diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d148220531f..25698ca6107 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -136,7 +136,7 @@ Enhancement suggestions are tracked as [GitHub issues](https://github.com/apache #### Environment Setup ##### 1. Forking the Code -One of the benefits of [GitHub](http://github.com) is the way that you can easily contribute to a project by [forking the repository](https://help.github.com/articles/fork-a-repo/) and [sending pull requests](https://help.github.com/articles/creating-a-pull-request/) with your changes. Please see GitHub's guides on how to create a fork and submit that fork. For easier illustration, the remainder of this document will use the `grails` repositories, but when working locally you should use your own fork. +One of the benefits of [GitHub](https://github.com) is the way that you can easily contribute to a project by [forking the repository](https://help.github.com/articles/fork-a-repo/) and [sending pull requests](https://help.github.com/articles/creating-a-pull-request/) with your changes. Please see GitHub's guides on how to create a fork and submit that fork. For easier illustration, the remainder of this document will use the `grails` repositories, but when working locally you should use your own fork. ##### 2. Tool Setup @@ -148,7 +148,7 @@ If you're interested in contributing fixes and features to any part of grails, y * A container runtime Once you have the pre-requisite packages installed, the next step is to download the Apache Grails source code, which is -hosted at [GitHub](http://github.com/apache/grails-core). This is a simple case of cloning the repository you're +hosted at [GitHub](https://github.com/apache/grails-core). This is a simple case of cloning the repository you're interested in. For example, to get the core framework run: git clone http://github.com/apache/grails-core.git @@ -202,7 +202,7 @@ There are many aspects to [Grail's documentation](https://docs.grails.org/) #### Improving the User Guide -The user guide is written using [Asciidoctor](http://asciidoctor.org/docs/user-manual/). The simplest way to contribute fixes is to simply click on the "Improve this doc" link that is to the right of each section of the documentation. +The user guide is written using [Asciidoctor](https://asciidoctor.org/docs/user-manual/). The simplest way to contribute fixes is to simply click on the "Improve this doc" link that is to the right of each section of the documentation. This will link to the GitHub edit screen where you can make changes, preview them and create a pull request. diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 993f2b8cfb9..f22cb0e8015 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -52,6 +52,8 @@ dependencies { implementation 'io.github.gradle-nexus:publish-plugin' implementation 'org.apache.grails:grails-docs-core' implementation 'org.apache.grails:grails-gradle-plugins' + implementation "com.diffplug.spotless:spotless-plugin-gradle:${gradleProperties.spotlessVersion}" + implementation "io.spring.nohttp:nohttp-gradle:${gradleProperties.nohttpGradleVersion}" implementation 'org.asciidoctor:asciidoctor-gradle-jvm' implementation 'org.springframework.boot:spring-boot-gradle-plugin' implementation 'org.nosphere.apache.rat:org.nosphere.apache.rat.gradle.plugin:0.8.1' diff --git a/etc/bin/Dockerfile b/etc/bin/Dockerfile index cd3e9696cd8..7ac7be67ece 100644 --- a/etc/bin/Dockerfile +++ b/etc/bin/Dockerfile @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-forge/config/checkstyle/checkstyle.xml b/etc/config/checkstyle/checkstyle.xml similarity index 96% rename from grails-forge/config/checkstyle/checkstyle.xml rename to etc/config/checkstyle/checkstyle.xml index 3e2e1ab9c38..3002c30d4d8 100644 --- a/grails-forge/config/checkstyle/checkstyle.xml +++ b/etc/config/checkstyle/checkstyle.xml @@ -103,6 +103,7 @@ + @@ -114,6 +115,8 @@ + + @@ -175,7 +178,9 @@ - + + + @@ -226,6 +231,8 @@ + + diff --git a/etc/config/checkstyle/suppressions.xml b/etc/config/checkstyle/suppressions.xml new file mode 100644 index 00000000000..5da56d946f9 --- /dev/null +++ b/etc/config/checkstyle/suppressions.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/grails-forge/config/spotless.license.java b/etc/config/spotless/license.java similarity index 100% rename from grails-forge/config/spotless.license.java rename to etc/config/spotless/license.java diff --git a/gradle.properties b/gradle.properties index 84a4d121d3e..504142de855 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, @@ -40,6 +40,8 @@ yakworksHibernateGroovyProxyVersion=1.1 picocliVersion=4.7.6 liquibaseHibernate5Version=4.27.0 hibernate5Version=5.6.15.Final +spotlessVersion=6.25.0 +nohttpGradleVersion=0.0.11 githubSlug=apache/grails-core githubBranch=7.0.x diff --git a/gradle/style-enforcement-config.gradle b/gradle/style-enforcement-config.gradle new file mode 100644 index 00000000000..f099e69f954 --- /dev/null +++ b/gradle/style-enforcement-config.gradle @@ -0,0 +1,88 @@ +import com.diffplug.gradle.spotless.SpotlessExtension +import io.spring.nohttp.gradle.NoHttpExtension + +/* + * 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. + */ + +apply plugin: 'checkstyle' +apply plugin: 'com.diffplug.spotless' +apply plugin: 'io.spring.nohttp' // enforce https everywhere + +extensions.configure(SpotlessExtension) { + // Explicit `it` required in extension configuration + it.java { + licenseHeaderFile(rootProject.layout.projectDirectory.file('etc/config/spotless/license.java')) + target( + 'grails-app/**/*.java', + 'src/main/groovy/**/*.java', + 'src/main/java/**/*.java' + ) + } + it.groovy { + licenseHeaderFile(rootProject.layout.projectDirectory.file('etc/config/spotless/license.java')) + target( + 'grails-app/**/*.groovy', + 'src/main/groovy/**/*.groovy' + ) + } + it.format('javaMisc') { + licenseHeaderFile(rootProject.layout.projectDirectory.file('etc/config/spotless/license.java'), '\\/\\*\\*') + target( + 'src/main/**/module-info.java', + 'src/main/**/package-info.java' + ) + } +} + +extensions.configure(CheckstyleExtension) { + // Explicit `it` required in extension configuration + it.configFile = rootProject.layout.projectDirectory.file('etc/config/checkstyle/checkstyle.xml').asFile + it.configDirectory = project.rootProject.layout.projectDirectory.dir('etc/config/checkstyle').asFile + it.maxErrors = 1 + it.maxWarnings = 10 + it.showViolations = true +} + +extensions.configure(NoHttpExtension) { + // Explicit `it` required in extension configuration + // TODO: xsd, xml, & doc files need looked at; this will at least make sure our POMs are correct + it.source.exclude( + 'build/**', + 'src/test/**', + 'LICENSE', '**/LICENSE', 'NOTICE', '**/NOTICE', 'licenses/**', 'INSTALL', + '**/*.xsd', '**/*.xml', '**/*.dtd', + '**/test/**', + '**/@grails.codegen.projectClassName@GrailsPlugin.groovy', + '**/grails-doc/**' // TODO: the grails doc still has a lot of work to do to remove https + ) +} + +if (tasks.names.contains('checkstyleTest')) { + tasks.named('checkstyleTest').configure { + it.group = 'verification' + it.enabled = false + } +} + +if (tasks.names.contains('checkstyleMain')) { + tasks.named('checkstyleMain').configure { + it.group = 'verification' + it.dependsOn('spotlessCheck') + } +} diff --git a/grails-async/core/build.gradle b/grails-async/core/build.gradle index 6a4f2b96791..bdeb790cb07 100644 --- a/grails-async/core/build.gradle +++ b/grails-async/core/build.gradle @@ -50,4 +50,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-async/core/src/main/groovy/grails/async/DelegateAsync.groovy b/grails-async/core/src/main/groovy/grails/async/DelegateAsync.groovy index 7fb5615fbea..bc5d80edd34 100644 --- a/grails-async/core/src/main/groovy/grails/async/DelegateAsync.groovy +++ b/grails-async/core/src/main/groovy/grails/async/DelegateAsync.groovy @@ -18,14 +18,14 @@ */ package grails.async +import org.codehaus.groovy.transform.GroovyASTTransformationClass + import java.lang.annotation.Documented import java.lang.annotation.ElementType import java.lang.annotation.Retention import java.lang.annotation.RetentionPolicy import java.lang.annotation.Target -import org.codehaus.groovy.transform.GroovyASTTransformationClass - /** * An AST transformation that takes each method in the given class and adds a delegate method that returns a {@link grails.async.Promise} and executes the method asynchronously. * For example given the following class: @@ -65,5 +65,6 @@ import org.codehaus.groovy.transform.GroovyASTTransformationClass @Target([ElementType.TYPE, ElementType.FIELD]) @GroovyASTTransformationClass("org.grails.async.transform.internal.DelegateAsyncTransformation") @interface DelegateAsync { + Class value() default DelegateAsync } diff --git a/grails-async/core/src/main/groovy/grails/async/PromiseFactory.groovy b/grails-async/core/src/main/groovy/grails/async/PromiseFactory.groovy index c6691ef95c7..1e1dcb4bca2 100644 --- a/grails-async/core/src/main/groovy/grails/async/PromiseFactory.groovy +++ b/grails-async/core/src/main/groovy/grails/async/PromiseFactory.groovy @@ -50,7 +50,7 @@ interface PromiseFactory { /** * Creates a promise with a value pre-bound to it * @param value The value - * @param The type of the value + * @param The type of the value * @return A Promise */ Promise createBoundPromise(T value) @@ -58,7 +58,7 @@ interface PromiseFactory { /** * Creates an unfulfilled promise that returns the given type * @param returnType The return type - * @param The type of the class + * @param The type of the class * @return The unfulfilled promise */ Promise createPromise(Class returnType) @@ -76,7 +76,7 @@ interface PromiseFactory { * @param map The map * @return A promise */ - Promise> createPromise(Map map) + Promise> createPromise(Map map) /** * Creates a promise from the given map where the values of the map are either closures or Promise instances @@ -84,7 +84,7 @@ interface PromiseFactory { * @param map The map * @return A promise */ - Promise> createPromise(Map map, List decorators) + Promise> createPromise(Map map, List decorators) /** * Creates a promise from one or more other promises @@ -92,7 +92,7 @@ interface PromiseFactory { * @param promises The promises * @return The promise */ - Promise> createPromise(Promise...promises) + Promise> createPromise(Promise... promises) /** * Creates a promise from one or many closures @@ -132,7 +132,7 @@ interface PromiseFactory { * @param promises The promises * @return The list of bound values */ - List waitAll(Promise...promises) + List waitAll(Promise... promises) /** * Synchronously waits for all promises to complete returning a list of values * diff --git a/grails-async/core/src/main/groovy/grails/async/PromiseList.groovy b/grails-async/core/src/main/groovy/grails/async/PromiseList.groovy index b19b1b2f8f0..8db692eefaf 100644 --- a/grails-async/core/src/main/groovy/grails/async/PromiseList.groovy +++ b/grails-async/core/src/main/groovy/grails/async/PromiseList.groovy @@ -138,7 +138,7 @@ class PromiseList implements Promise> { @Override boolean isDone() { - return promises.every {promise -> promise.isDone() } + return promises.every { promise -> promise.isDone() } } @Override diff --git a/grails-async/core/src/main/groovy/grails/async/PromiseMap.groovy b/grails-async/core/src/main/groovy/grails/async/PromiseMap.groovy index f367d961289..9bd07cb910b 100644 --- a/grails-async/core/src/main/groovy/grails/async/PromiseMap.groovy +++ b/grails-async/core/src/main/groovy/grails/async/PromiseMap.groovy @@ -32,14 +32,14 @@ import java.util.concurrent.TimeUnit */ @AutoFinal @CompileStatic -class PromiseMap implements Promise> { +class PromiseMap implements Promise> { protected LinkedHashMap> promises = [:] protected LinkedHashMap, K> promisesKeys = [:] PromiseMap() {} - PromiseMap(Map values) { + PromiseMap(Map values) { accept(values) } @@ -55,11 +55,11 @@ class PromiseMap implements Promise> { @Override boolean isDone() { - return promisesKeys.keySet().every {it.isDone() } + return promisesKeys.keySet().every { it.isDone() } } @Override - Promise> accept(Map values) { + Promise> accept(Map values) { values.each { K key, Object value -> if (value instanceof Promise) { put(key, value as Promise) @@ -210,10 +210,10 @@ class PromiseMap implements Promise> { * * @return A map where the values are obtained from the promises */ - Map get() throws Throwable { + Map get() throws Throwable { def promises = promises.values() - Map resultMap = [:] - for(Promise promise : promises) { + Map resultMap = [:] + for (Promise promise : promises) { V value = promise.get() resultMap.put(promisesKeys.get(promise), value) } @@ -224,15 +224,15 @@ class PromiseMap implements Promise> { * Synchronously return the populated map with all values obtained from promises used * inside the populated map * - * @param timeout The timeout period + * @param timeout The timeout period * @param units The timeout units * @return A map where the values are obtained from the promises */ - Map get(long timeout, TimeUnit units) throws Throwable { + Map get(long timeout, TimeUnit units) throws Throwable { List> promises = new ArrayList>(promises.values()) Promises.waitAll(promises, timeout, units) - Map resultMap = [:] - for(Promise promise : promises) { + Map resultMap = [:] + for (Promise promise : promises) { V value = promise.get() resultMap.put(promisesKeys.get(promise), value) } @@ -240,12 +240,12 @@ class PromiseMap implements Promise> { } @Override - Promise> onComplete(Closure> callable) { + Promise> onComplete(Closure> callable) { List> promises = new ArrayList>(promises.values()) Promises.onComplete(promises) { List values -> - Map resultMap = [:] + Map resultMap = [:] int i = 0 - for(V value in values) { + for (V value in values) { Promise promise = promises[i] K key = promisesKeys.get(promise) resultMap.put(key, value) @@ -258,13 +258,13 @@ class PromiseMap implements Promise> { } @Override - Promise> onError(Closure> callable) { + Promise> onError(Closure> callable) { Promises.onError(new ArrayList>(promises.values()), callable) return this } @Override - Promise> then(Closure> callable) { + Promise> then(Closure> callable) { return onComplete(callable) } diff --git a/grails-async/core/src/main/groovy/grails/async/Promises.groovy b/grails-async/core/src/main/groovy/grails/async/Promises.groovy index 6b3c209bf85..b46f99ad1d6 100644 --- a/grails-async/core/src/main/groovy/grails/async/Promises.groovy +++ b/grails-async/core/src/main/groovy/grails/async/Promises.groovy @@ -53,77 +53,77 @@ class Promises { /** * @see PromiseFactory#waitAll(grails.async.Promise[]) */ - static List waitAll(Promise... promises) { + static List waitAll(Promise... promises) { return getPromiseFactory().waitAll(promises) } /** * @see PromiseFactory#waitAll(java.util.List) */ - static List waitAll(List> promises) { + static List waitAll(List> promises) { return getPromiseFactory().waitAll(promises) } /** * @see PromiseFactory#waitAll(java.util.List) */ - static List waitAll(List> promises, long timeout, TimeUnit units) { + static List waitAll(List> promises, long timeout, TimeUnit units) { return getPromiseFactory().waitAll(promises, timeout, units) } /** * @see PromiseFactory#onComplete(java.util.List, groovy.lang.Closure) */ - static Promise> onComplete(List> promises, Closure callable) { + static Promise> onComplete(List> promises, Closure callable) { return getPromiseFactory().onComplete(promises, callable) } /** * @see PromiseFactory#onError(java.util.List, groovy.lang.Closure) */ - static Promise> onError(List> promises, Closure callable) { + static Promise> onError(List> promises, Closure callable) { return getPromiseFactory().onError(promises, callable) } /** * @see PromiseFactory#createPromise(java.util.Map) */ - static Promise> createPromise(Map map) { + static Promise> createPromise(Map map) { return getPromiseFactory().createPromise(map) } /** * @see PromiseFactory#createPromise(java.util.Map) */ - static Promise> createPromise(Map map, List decorators) { + static Promise> createPromise(Map map, List decorators) { return getPromiseFactory().createPromise(map, decorators) } /** - * @see PromiseFactory#createPromise(groovy.lang.Closure[]) + * @see PromiseFactory#createPromise(groovy.lang.Closure [ ]) */ - static Promise createPromise(Closure... closures) { + static Promise createPromise(Closure... closures) { return getPromiseFactory().createPromise(closures) } /** * @see PromiseFactory#createPromise(java.util.Map) */ - static Promise> tasks(Map map) { + static Promise> tasks(Map map) { return getPromiseFactory().createPromise(map) } /** - * @see PromiseFactory#createPromise(groovy.lang.Closure[]) + * @see PromiseFactory#createPromise(groovy.lang.Closure [ ]) */ - static Promise task(Closure closure) { + static Promise task(Closure closure) { return getPromiseFactory().createPromise(closure) } /** - * @see PromiseFactory#createPromise(groovy.lang.Closure[]) + * @see PromiseFactory#createPromise(groovy.lang.Closure [ ]) */ - static Promise tasks(Closure... closures) { + static Promise tasks(Closure... closures) { return getPromiseFactory().createPromise(closures) } /** - * @see PromiseFactory#createPromise(groovy.lang.Closure[]) + * @see PromiseFactory#createPromise(groovy.lang.Closure [ ]) */ - static Promise> tasks(List> closures) { + static Promise> tasks(List> closures) { return getPromiseFactory().createPromise(closures) } @@ -137,33 +137,33 @@ class Promises { /** * @see grails.async.PromiseFactory#createPromise(Class) */ - static Promise createPromise(Class returnType) { + static Promise createPromise(Class returnType) { return getPromiseFactory().createPromise(returnType) } /** * @see PromiseFactory#createPromise(groovy.lang.Closure, java.util.List) */ - static Promise createPromise(Closure closure, List decorators) { + static Promise createPromise(Closure closure, List decorators) { return getPromiseFactory().createPromise(closure, decorators) } /** * @see PromiseFactory#createPromise(java.util.List, java.util.List) */ - static Promise> createPromise(List> closures, List decorators) { + static Promise> createPromise(List> closures, List decorators) { return getPromiseFactory().createPromise(closures, decorators) } /** - * @see PromiseFactory#createPromise(grails.async.Promise[]) + * @see PromiseFactory#createPromise(grails.async.Promise [ ]) */ - static Promise> createPromise(Promise...promises) { + static Promise> createPromise(Promise... promises) { return getPromiseFactory().createPromise(promises) } /** * @see PromiseFactory#createBoundPromise(java.lang.Object) */ - static Promise createBoundPromise(T value) { - return getPromiseFactory().createBoundPromise(value) + static Promise createBoundPromise(T value) { + return getPromiseFactory().createBoundPromise(value) } } diff --git a/grails-async/core/src/main/groovy/grails/async/factory/AbstractPromiseFactory.groovy b/grails-async/core/src/main/groovy/grails/async/factory/AbstractPromiseFactory.groovy index bbd488348cd..03acae22996 100644 --- a/grails-async/core/src/main/groovy/grails/async/factory/AbstractPromiseFactory.groovy +++ b/grails-async/core/src/main/groovy/grails/async/factory/AbstractPromiseFactory.groovy @@ -59,13 +59,13 @@ abstract class AbstractPromiseFactory implements PromiseFactory { } Closure applyDecorators(Closure closure, List decorators) { - List allDecorators = decorators != null ? new ArrayList(decorators): new ArrayList() + List allDecorators = decorators != null ? new ArrayList(decorators) : new ArrayList() for (PromiseDecoratorLookupStrategy lookupStrategy : lookupStrategies) { allDecorators.addAll(lookupStrategy.findDecorators()) } def decoratedClosure = closure if (!allDecorators.empty) { - for(PromiseDecorator decorator : allDecorators) { + for (PromiseDecorator decorator : allDecorators) { decoratedClosure = decorator.decorate(decoratedClosure) } } @@ -76,7 +76,7 @@ abstract class AbstractPromiseFactory implements PromiseFactory { * @see PromiseFactory#createPromise(java.util.List) */ Promise> createPromise(List> closures) { - return createPromise(closures,null) + return createPromise(closures, null) } /** @@ -95,11 +95,11 @@ abstract class AbstractPromiseFactory implements PromiseFactory { } /** - * @see PromiseFactory#createPromise(grails.async.Promise[]) + * @see PromiseFactory#createPromise(grails.async.Promise [ ]) */ Promise> createPromise(Promise... promises) { PromiseList promiseList = new PromiseList<>() - for(Promise promise : promises) { + for (Promise promise : promises) { promiseList.add(promise) } return promiseList @@ -107,17 +107,15 @@ abstract class AbstractPromiseFactory implements PromiseFactory { @Override Promise> createPromise(Map map, List decorators) { - PromiseMap promiseMap = new PromiseMap<>() + PromiseMap promiseMap = new PromiseMap<>() map.forEach((K key, V value) -> { if (value instanceof Promise) { promiseMap.put(key, value as Promise) - } - else if (value instanceof Closure) { + } else if (value instanceof Closure) { Closure closure = value as Closure applyDecorators(closure, decorators) promiseMap.put(key, createPromiseInternal(closure)) - } - else { + } else { promiseMap.put(key, new BoundPromise(value)) } @@ -129,11 +127,11 @@ abstract class AbstractPromiseFactory implements PromiseFactory { * @see PromiseFactory#createPromise(java.util.Map) */ Promise> createPromise(Map map) { - return createPromise(map, Collections.emptyList()) + return createPromise(map, Collections. emptyList()) } protected Promise createPromiseInternal(Closure closure) { - return createPromise(closure) + return createPromise(closure) } /** diff --git a/grails-async/core/src/main/groovy/org/grails/async/factory/BoundPromise.groovy b/grails-async/core/src/main/groovy/org/grails/async/factory/BoundPromise.groovy index e693655567f..6759d6e9beb 100644 --- a/grails-async/core/src/main/groovy/org/grails/async/factory/BoundPromise.groovy +++ b/grails-async/core/src/main/groovy/org/grails/async/factory/BoundPromise.groovy @@ -91,8 +91,7 @@ class BoundPromise implements Promise { } catch (Throwable e) { return new BoundPromise(e) } - } - else { + } else { return this } } diff --git a/grails-async/core/src/main/groovy/org/grails/async/factory/PromiseFactoryBuilder.groovy b/grails-async/core/src/main/groovy/org/grails/async/factory/PromiseFactoryBuilder.groovy index 3ca1066012a..abdcfffabe2 100644 --- a/grails-async/core/src/main/groovy/org/grails/async/factory/PromiseFactoryBuilder.groovy +++ b/grails-async/core/src/main/groovy/org/grails/async/factory/PromiseFactoryBuilder.groovy @@ -16,11 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.async.factory import grails.async.PromiseFactory -import grails.async.Promises import groovy.transform.CompileStatic import groovy.util.logging.Slf4j import org.grails.async.factory.future.CachedThreadPoolPromiseFactory @@ -43,13 +41,12 @@ class PromiseFactoryBuilder { List promiseFactories = ServiceLoader.load(PromiseFactory).toList() PromiseFactory promiseFactory - if(promiseFactories.isEmpty()) { - log.debug 'No PromiseFactory implementation found. Using default ExecutorService promise factory.' + if (promiseFactories.isEmpty()) { + log.debug('No PromiseFactory implementation found. Using default ExecutorService promise factory.') promiseFactory = new CachedThreadPoolPromiseFactory() - } - else { + } else { promiseFactory = promiseFactories.first() - log.debug 'Found PromiseFactory implementation to use [{}]', promiseFactory + log.debug('Found PromiseFactory implementation to use [{}]', promiseFactory) } return promiseFactory diff --git a/grails-async/core/src/main/groovy/org/grails/async/factory/SynchronousPromise.groovy b/grails-async/core/src/main/groovy/org/grails/async/factory/SynchronousPromise.groovy index fe1dd1a989f..714fe0be409 100644 --- a/grails-async/core/src/main/groovy/org/grails/async/factory/SynchronousPromise.groovy +++ b/grails-async/core/src/main/groovy/org/grails/async/factory/SynchronousPromise.groovy @@ -58,8 +58,12 @@ class SynchronousPromise implements Promise { T get() throws Throwable { if (!executed) { executed = true - try { value = callable.call() } - catch (e) { value = e } + try { + value = callable.call() + } + catch (e) { + value = e + } } if (value instanceof Throwable) { throw value @@ -78,14 +82,21 @@ class SynchronousPromise implements Promise { } Promise onComplete(Closure callable) { - try { callable.call(get()) } - catch (Throwable ignored) {} + try { + callable.call(get()) + } + catch (Throwable ignored) { + } return this } Promise onError(Closure callable) { - try { get() } - catch (Throwable e) { callable.call(e) } + try { + get() + } + catch (Throwable e) { + callable.call(e) + } return this } diff --git a/grails-async/core/src/main/groovy/org/grails/async/factory/SynchronousPromiseFactory.groovy b/grails-async/core/src/main/groovy/org/grails/async/factory/SynchronousPromiseFactory.groovy index fe4d94e9ab4..cc15554db1b 100644 --- a/grails-async/core/src/main/groovy/org/grails/async/factory/SynchronousPromiseFactory.groovy +++ b/grails-async/core/src/main/groovy/org/grails/async/factory/SynchronousPromiseFactory.groovy @@ -54,14 +54,17 @@ class SynchronousPromiseFactory extends AbstractPromiseFactory { promise = new SynchronousPromise(closures[0]) } else { def promiseList = new PromiseList() - for(p in closures) { + for (p in closures) { promiseList << p } promise = promiseList } - try { promise.get() } - catch (Throwable ignored) {} + try { + promise.get() + } + catch (Throwable ignored) { + } return promise } diff --git a/grails-async/core/src/main/groovy/org/grails/async/factory/future/CachedThreadPoolPromiseFactory.groovy b/grails-async/core/src/main/groovy/org/grails/async/factory/future/CachedThreadPoolPromiseFactory.groovy index affba64fb2f..81fd1feb32a 100644 --- a/grails-async/core/src/main/groovy/org/grails/async/factory/future/CachedThreadPoolPromiseFactory.groovy +++ b/grails-async/core/src/main/groovy/org/grails/async/factory/future/CachedThreadPoolPromiseFactory.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.async.factory.future import grails.async.Promise @@ -24,10 +23,15 @@ import grails.async.PromiseList import grails.async.factory.AbstractPromiseFactory import groovy.transform.AutoFinal import groovy.transform.CompileStatic +import jakarta.annotation.PreDestroy import org.grails.async.factory.BoundPromise -import jakarta.annotation.PreDestroy -import java.util.concurrent.* +import java.util.concurrent.Callable +import java.util.concurrent.ExecutorService +import java.util.concurrent.RunnableFuture +import java.util.concurrent.SynchronousQueue +import java.util.concurrent.ThreadPoolExecutor +import java.util.concurrent.TimeUnit /** * A promise factory that uses an ExecutorService by default @@ -39,15 +43,18 @@ import java.util.concurrent.* @CompileStatic class CachedThreadPoolPromiseFactory extends AbstractPromiseFactory implements Closeable, ExecutorPromiseFactory { - final @Delegate ExecutorService executorService + @Delegate + final ExecutorService executorService CachedThreadPoolPromiseFactory(int maxPoolSize = Integer.MAX_VALUE, long timeout = 60L, TimeUnit unit = TimeUnit.SECONDS) { CachedThreadPoolPromiseFactory pf = this this.executorService = new ThreadPoolExecutor(0, maxPoolSize, timeout, unit, new SynchronousQueue()) { + @Override protected RunnableFuture newTaskFor(Callable callable) { return new FutureTaskPromise(pf, callable) } + @Override protected RunnableFuture newTaskFor(Runnable runnable, T value) { return new FutureTaskPromise(pf, runnable, value) @@ -71,8 +78,7 @@ class CachedThreadPoolPromiseFactory extends AbstractPromiseFactory implements C def callable = closures[0] def decoratedCallable = applyDecorators(callable, null) return executorService.submit(decoratedCallable as Callable) as Promise - } - else { + } else { PromiseList list = new PromiseList<>() for (Closure closure : closures) { list.add(closure) @@ -108,7 +114,11 @@ class CachedThreadPoolPromiseFactory extends AbstractPromiseFactory implements C while (promises.every { Promise promise -> !promise.isDone() }) { // wait (is this hogging the cpu?) } - try { for (Promise promise : promises) { promise.get() } } + try { + for (Promise promise : promises) { + promise.get() + } + } catch (Throwable e) { callable.call(e) return e diff --git a/grails-async/core/src/main/groovy/org/grails/async/factory/future/ExecutorPromiseFactory.groovy b/grails-async/core/src/main/groovy/org/grails/async/factory/future/ExecutorPromiseFactory.groovy index 7167d9e4eae..4172ada0f91 100644 --- a/grails-async/core/src/main/groovy/org/grails/async/factory/future/ExecutorPromiseFactory.groovy +++ b/grails-async/core/src/main/groovy/org/grails/async/factory/future/ExecutorPromiseFactory.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.async.factory.future import grails.async.PromiseFactory diff --git a/grails-async/core/src/main/groovy/org/grails/async/factory/future/FutureTaskChildPromise.groovy b/grails-async/core/src/main/groovy/org/grails/async/factory/future/FutureTaskChildPromise.groovy index d0ce580e97f..2d7b9b5e1c4 100644 --- a/grails-async/core/src/main/groovy/org/grails/async/factory/future/FutureTaskChildPromise.groovy +++ b/grails-async/core/src/main/groovy/org/grails/async/factory/future/FutureTaskChildPromise.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.async.factory.future import grails.async.Promise @@ -30,7 +29,6 @@ import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.ExecutionException import java.util.concurrent.TimeUnit import java.util.concurrent.TimeoutException -import java.util.concurrent.locks.ReentrantLock /** * A child promise of a {@link FutureTaskPromise} @@ -54,7 +52,7 @@ class FutureTaskChildPromise implements Promise { FutureTaskChildPromise(PromiseFactory promiseFactory, Promise parent, Closure callable) { this.parent = parent - this.callable = promiseFactory.applyDecorators(callable,null) + this.callable = promiseFactory.applyDecorators(callable, null) this.promiseFactory = promiseFactory } @@ -113,8 +111,7 @@ class FutureTaskChildPromise implements Promise { T get() throws InterruptedException, ExecutionException { if (bound != null) { return bound.get() - } - else { + } else { if (parent instanceof FutureTaskPromise) { def value = parent.get() if (bound == null) { @@ -122,8 +119,7 @@ class FutureTaskChildPromise implements Promise { bound = new BoundPromise<>(v) } return bound.get() - } - else { + } else { def v = callable.call(parent.get()) bound = new BoundPromise<>(v) return v @@ -135,8 +131,7 @@ class FutureTaskChildPromise implements Promise { T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { if (bound != null) { return bound.get() - } - else { + } else { if (parent instanceof FutureTaskPromise) { def value = parent.get(timeout, unit) if (bound == null) { @@ -144,8 +139,7 @@ class FutureTaskChildPromise implements Promise { bound = new BoundPromise<>(v) } return bound.get() - } - else { + } else { def v = callable.call(parent.get(timeout, unit)) bound = new BoundPromise<>(v) return v diff --git a/grails-async/core/src/main/groovy/org/grails/async/factory/future/FutureTaskPromise.groovy b/grails-async/core/src/main/groovy/org/grails/async/factory/future/FutureTaskPromise.groovy index 90cde682026..466fad6e00f 100644 --- a/grails-async/core/src/main/groovy/org/grails/async/factory/future/FutureTaskPromise.groovy +++ b/grails-async/core/src/main/groovy/org/grails/async/factory/future/FutureTaskPromise.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.async.factory.future import grails.async.Promise @@ -110,8 +109,7 @@ class FutureTaskPromise extends FutureTask implements Promise { } catch (Throwable ignored) { return this } - } - else { + } else { Promise newPromise = new FutureTaskChildPromise(promiseFactory, this as Promise, callable) successCallbacks.add(newPromise) return newPromise @@ -129,8 +127,7 @@ class FutureTaskPromise extends FutureTask implements Promise { } catch (Throwable e) { return new BoundPromise(callable.call(e)) } - } - else { + } else { Promise newPromise = new FutureTaskChildPromise(promiseFactory, this as Promise, callable) failureCallbacks.add(newPromise) return newPromise diff --git a/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransactionalMethodTransformer.java b/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransactionalMethodTransformer.java index 63c9e104197..f01caf4057c 100644 --- a/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransactionalMethodTransformer.java +++ b/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransactionalMethodTransformer.java @@ -29,5 +29,6 @@ * @since 2.3 */ public interface DelegateAsyncTransactionalMethodTransformer { + void transformTransactionalMethod(ClassNode classNode, ClassNode delegateClassNode, MethodNode methodNode, ListExpression promiseDecoratorLookupArguments); } diff --git a/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransformation.java b/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransformation.java index 74fd98d37d4..eec34eb86af 100644 --- a/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransformation.java +++ b/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransformation.java @@ -22,14 +22,6 @@ import grails.async.Promises; import groovy.lang.Closure; import groovy.lang.GroovyObjectSupport; - -import java.beans.Introspector; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - import org.apache.grails.common.compiler.GroovyTransformOrder; import org.codehaus.groovy.GroovyBugError; import org.codehaus.groovy.ast.ASTNode; @@ -59,6 +51,13 @@ import org.codehaus.groovy.transform.TransformWithPriority; import org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport; +import java.beans.Introspector; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + /** * Implementation of {@link grails.async.DelegateAsync} transformation * @@ -67,10 +66,11 @@ */ @GroovyASTTransformation public class DelegateAsyncTransformation implements ASTTransformation, TransformWithPriority { - private static final ArgumentListExpression NO_ARGS = new ArgumentListExpression(); - private static final String VOID = "void"; + public static final ClassNode GROOVY_OBJECT_CLASS_NODE = new ClassNode(GroovyObjectSupport.class); public static final ClassNode OBJECT_CLASS_NODE = new ClassNode(Object.class); + private static final ArgumentListExpression NO_ARGS = new ArgumentListExpression(); + private static final String VOID = "void"; public void visit(ASTNode[] nodes, SourceUnit source) { if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) { @@ -84,7 +84,7 @@ public void visit(ASTNode[] nodes, SourceUnit source) { Expression value = annotationNode.getMember("value"); if (value instanceof ClassExpression) { ClassNode targetApi = value.getType().getPlainNodeReference(); - ClassNode classNode = (ClassNode)parent; + ClassNode classNode = (ClassNode) parent; final String fieldName = '$' + Introspector.decapitalize(targetApi.getNameWithoutPackage()); FieldNode fieldNode = classNode.getField(fieldName); @@ -95,9 +95,8 @@ public void visit(ASTNode[] nodes, SourceUnit source) { applyDelegateAsyncTransform(classNode, targetApi, fieldName); } - } - else if(parent instanceof FieldNode) { - FieldNode fieldNode = (FieldNode)parent; + } else if (parent instanceof FieldNode) { + FieldNode fieldNode = (FieldNode) parent; ClassNode targetApi = fieldNode.getType().getPlainNodeReference(); ClassNode classNode = fieldNode.getOwner(); applyDelegateAsyncTransform(classNode, targetApi, fieldNode.getName()); @@ -112,27 +111,26 @@ private void applyDelegateAsyncTransform(ClassNode classNode, ClassNode targetAp MethodNode createPromiseMethodTargetWithDecorators = promisesClass.getDeclaredMethod("createPromise", new Parameter[]{new Parameter(new ClassNode(Closure.class), "c"), new Parameter(new ClassNode(List.class), "c")}); DelegateAsyncTransactionalMethodTransformer delegateAsyncTransactionalMethodTransformer = lookupAsyncTransactionalMethodTransformer(); - for(MethodNode m : methods) { + for (MethodNode m : methods) { if (isCandidateMethod(m)) { MethodNode existingMethod = classNode.getMethod(m.getName(), m.getParameters()); if (existingMethod == null) { ClassNode promiseNode = ClassHelper.make(Promise.class).getPlainNodeReference(); ClassNode originalReturnType = m.getReturnType(); - if(!originalReturnType.getNameWithoutPackage().equals(VOID)) { + if (!originalReturnType.getNameWithoutPackage().equals(VOID)) { ClassNode returnType; - if(ClassHelper.isPrimitiveType(originalReturnType.redirect())) { + if (ClassHelper.isPrimitiveType(originalReturnType.redirect())) { returnType = ClassHelper.getWrapper(originalReturnType.redirect()); } else { returnType = alignReturnType(classNode, originalReturnType); } - if(!OBJECT_CLASS_NODE.equals(returnType)) { + if (!OBJECT_CLASS_NODE.equals(returnType)) { promiseNode.setGenericsTypes(new GenericsType[]{new GenericsType(returnType)}); } } final BlockStatement methodBody = new BlockStatement(); final BlockStatement promiseBody = new BlockStatement(); - final ClosureExpression closureExpression = new ClosureExpression(new Parameter[0], promiseBody); VariableScope variableScope = new VariableScope(); closureExpression.setVariableScope(variableScope); @@ -147,8 +145,8 @@ private void applyDelegateAsyncTransform(ClassNode classNode, ClassNode targetAp MethodCallExpression getDecoratorsMethodCall = new MethodCallExpression(new ClassExpression(delegateAsyncUtilsClassNode), "getPromiseDecorators", getPromiseDecoratorsArguments); getDecoratorsMethodCall.setMethodTarget(getPromiseDecoratorsMethodNode); - MethodCallExpression createPromiseWithDecorators = new MethodCallExpression(new ClassExpression(promisesClass), "createPromise",new ArgumentListExpression( closureExpression, getDecoratorsMethodCall)); - if(createPromiseMethodTargetWithDecorators != null) { + MethodCallExpression createPromiseWithDecorators = new MethodCallExpression(new ClassExpression(promisesClass), "createPromise", new ArgumentListExpression(closureExpression, getDecoratorsMethodCall)); + if (createPromiseMethodTargetWithDecorators != null) { createPromiseWithDecorators.setMethodTarget(createPromiseMethodTargetWithDecorators); } methodBody.addStatement(new ExpressionStatement(createPromiseWithDecorators)); @@ -156,7 +154,7 @@ private void applyDelegateAsyncTransform(ClassNode classNode, ClassNode targetAp final ArgumentListExpression arguments = new ArgumentListExpression(); Parameter[] parameters = copyParameters(StaticTypeCheckingSupport.parameterizeArguments(classNode, m)); - for(Parameter p : parameters) { + for (Parameter p : parameters) { p.setClosureSharedVariable(true); variableScope.putReferencedLocalVariable(p); VariableExpression ve = new VariableExpression(p); @@ -165,7 +163,7 @@ private void applyDelegateAsyncTransform(ClassNode classNode, ClassNode targetAp } MethodCallExpression delegateMethodCall = new MethodCallExpression(new VariableExpression(fieldName), m.getName(), arguments); promiseBody.addStatement(new ExpressionStatement(delegateMethodCall)); - MethodNode newMethodNode = new MethodNode(m.getName(), Modifier.PUBLIC,promiseNode, parameters,null, methodBody); + MethodNode newMethodNode = new MethodNode(m.getName(), Modifier.PUBLIC, promiseNode, parameters, null, methodBody); classNode.addMethod(newMethodNode); } } @@ -183,7 +181,7 @@ private static ClassNode alignReturnType(final ClassNode receiver, final ClassNo GenericsType[] redirectReceiverTypes = redirectTypes.toArray(new GenericsType[0]); GenericsType[] receiverParameterizedTypes = receiver.getGenericsTypes(); - if (receiverParameterizedTypes==null) { + if (receiverParameterizedTypes == null) { receiverParameterizedTypes = redirectReceiverTypes; } @@ -210,9 +208,9 @@ protected DelegateAsyncTransactionalMethodTransformer lookupAsyncTransactionalMe private static boolean isCandidateMethod(MethodNode declaredMethod) { String methodName = declaredMethod.getName(); return !declaredMethod.isSynthetic() && - !methodName.contains("$") && - Modifier.isPublic(declaredMethod.getModifiers()) && - !GROOVY_OBJECT_CLASS_NODE.hasMethod(declaredMethod.getName(), declaredMethod.getParameters()); + !methodName.contains("$") && + Modifier.isPublic(declaredMethod.getModifiers()) && + !GROOVY_OBJECT_CLASS_NODE.hasMethod(declaredMethod.getName(), declaredMethod.getParameters()); } private static Parameter[] copyParameters(Parameter[] parameterTypes) { @@ -221,7 +219,7 @@ private static Parameter[] copyParameters(Parameter[] parameterTypes) { Parameter parameterType = parameterTypes[i]; ClassNode parameterTypeCN = parameterType.getType(); ClassNode newParameterTypeCN = parameterTypeCN.getPlainNodeReference(); - if(parameterTypeCN.isUsingGenerics() && !parameterTypeCN.isGenericsPlaceHolder()) { + if (parameterTypeCN.isUsingGenerics() && !parameterTypeCN.isGenericsPlaceHolder()) { newParameterTypeCN.setGenericsTypes(parameterTypeCN.getGenericsTypes()); } Parameter newParameter = new Parameter(newParameterTypeCN, parameterType.getName(), parameterType.getInitialExpression()); @@ -237,7 +235,8 @@ public int priority() { } private static class NoopDelegateAsyncTransactionalMethodTransformer implements DelegateAsyncTransactionalMethodTransformer { - public void transformTransactionalMethod(ClassNode classNode,ClassNode delegateClassNode, MethodNode methodNode, ListExpression promiseDecoratorLookupArguments) { + + public void transformTransactionalMethod(ClassNode classNode, ClassNode delegateClassNode, MethodNode methodNode, ListExpression promiseDecoratorLookupArguments) { // noop } } diff --git a/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncUtils.groovy b/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncUtils.groovy index 7041c066f12..17c0af8ed9a 100644 --- a/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncUtils.groovy +++ b/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncUtils.groovy @@ -18,9 +18,9 @@ */ package org.grails.async.transform.internal -import groovy.transform.CompileStatic import grails.async.decorator.PromiseDecorator import grails.async.decorator.PromiseDecoratorProvider +import groovy.transform.CompileStatic /** * Helps looking up the decorators @@ -37,10 +37,10 @@ class DelegateAsyncUtils { * @param additional The additional * @return The additional promise decorators */ - static Collection getPromiseDecorators(Object target, Collection additional ) { + static Collection getPromiseDecorators(Object target, Collection additional) { Collection decorators = [] if (target instanceof PromiseDecoratorProvider) { - decorators.addAll(((PromiseDecoratorProvider)target).getDecorators()) + decorators.addAll(((PromiseDecoratorProvider) target).getDecorators()) } if (additional) { decorators.addAll(additional) diff --git a/grails-async/gpars/build.gradle b/grails-async/gpars/build.gradle index ab599f3da30..335871bda09 100644 --- a/grails-async/gpars/build.gradle +++ b/grails-async/gpars/build.gradle @@ -50,4 +50,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-async/gpars/src/main/groovy/org/grails/async/factory/gpars/GparsPromise.groovy b/grails-async/gpars/src/main/groovy/org/grails/async/factory/gpars/GparsPromise.groovy index ed1731ea112..9d02d2e1b44 100644 --- a/grails-async/gpars/src/main/groovy/org/grails/async/factory/gpars/GparsPromise.groovy +++ b/grails-async/gpars/src/main/groovy/org/grails/async/factory/gpars/GparsPromise.groovy @@ -51,7 +51,7 @@ class GparsPromise implements Promise { @Override boolean cancel(boolean mayInterruptIfRunning) { - if(isDone()) return false + if (isDone()) return false throw new UnsupportedOperationException('Cancellation not supported') } @@ -77,7 +77,7 @@ class GparsPromise implements Promise { @Override Promise accept(T value) { - internalPromise = Dataflow.task({value}) + internalPromise = Dataflow.task({ value }) return this } @@ -87,7 +87,7 @@ class GparsPromise implements Promise { @Override Promise onComplete(Closure callable) { - def decoratedCallable= promiseFactory.applyDecorators(callable, null) + def decoratedCallable = promiseFactory.applyDecorators(callable, null) internalPromise.whenBound { T value -> if (!(value instanceof Throwable)) { return decoratedCallable.call(value) diff --git a/grails-async/gpars/src/main/groovy/org/grails/async/factory/gpars/GparsPromiseFactory.groovy b/grails-async/gpars/src/main/groovy/org/grails/async/factory/gpars/GparsPromiseFactory.groovy index 1782c75948f..915d389d87d 100644 --- a/grails-async/gpars/src/main/groovy/org/grails/async/factory/gpars/GparsPromiseFactory.groovy +++ b/grails-async/gpars/src/main/groovy/org/grails/async/factory/gpars/GparsPromiseFactory.groovy @@ -20,14 +20,13 @@ package org.grails.async.factory.gpars import grails.async.Promise import grails.async.PromiseList +import grails.async.factory.AbstractPromiseFactory import groovy.transform.AutoFinal import groovy.transform.CompileStatic import groovyx.gpars.GParsConfig import groovyx.gpars.dataflow.Dataflow import groovyx.gpars.dataflow.DataflowVariable -import grails.async.factory.AbstractPromiseFactory - import java.util.concurrent.TimeUnit /** @@ -42,16 +41,24 @@ class GparsPromiseFactory extends AbstractPromiseFactory { static final boolean GPARS_PRESENT static { - try { GPARS_PRESENT = Thread.currentThread().contextClassLoader.loadClass('groovyx.gpars.GParsConfig') } - catch (Throwable ignore) { GPARS_PRESENT = false } + try { + GPARS_PRESENT = Thread.currentThread().contextClassLoader.loadClass('groovyx.gpars.GParsConfig') + } + catch (Throwable ignore) { + GPARS_PRESENT = false + } } + static boolean isGparsAvailable() { GPARS_PRESENT } private static final Closure> originalValuesClosure = { List values -> values } as Closure> GparsPromiseFactory() { - try { GParsConfig.setPoolFactory(new LoggingPoolFactory()) } - catch (IllegalArgumentException ignore) {} + try { + GParsConfig.setPoolFactory(new LoggingPoolFactory()) + } + catch (IllegalArgumentException ignore) { + } } @Override @@ -75,7 +82,7 @@ class GparsPromiseFactory extends AbstractPromiseFactory { Promise createPromise(Closure... closures) { if (closures.length == 1) { def callable = closures[0] - return new GparsPromise(this, applyDecorators(callable,null)) + return new GparsPromise(this, applyDecorators(callable, null)) } PromiseList promiseList = new PromiseList<>() for (c in closures) { @@ -105,16 +112,16 @@ class GparsPromiseFactory extends AbstractPromiseFactory { @Override Promise onComplete(List> promises, Closure callable) { return new GparsPromise( - this, - Dataflow.whenAllBound(toGparsPromises(promises), callable as Closure) + this, + Dataflow.whenAllBound(toGparsPromises(promises), callable as Closure) ) } @Override Promise> onError(List> promises, Closure callable) { return new GparsPromise>( - this, - Dataflow.whenAllBound(toGparsPromises(promises), {} as Closure, callable as Closure) + this, + Dataflow.whenAllBound(toGparsPromises(promises), {} as Closure, callable as Closure) ) } } diff --git a/grails-async/gpars/src/main/groovy/org/grails/async/factory/gpars/LoggingPoolFactory.groovy b/grails-async/gpars/src/main/groovy/org/grails/async/factory/gpars/LoggingPoolFactory.groovy index c97b8cdc559..9058ba4b890 100644 --- a/grails-async/gpars/src/main/groovy/org/grails/async/factory/gpars/LoggingPoolFactory.groovy +++ b/grails-async/gpars/src/main/groovy/org/grails/async/factory/gpars/LoggingPoolFactory.groovy @@ -28,7 +28,11 @@ import org.slf4j.Logger import org.slf4j.LoggerFactory import java.lang.reflect.Method -import java.util.concurrent.* +import java.util.concurrent.RejectedExecutionHandler +import java.util.concurrent.SynchronousQueue +import java.util.concurrent.ThreadFactory +import java.util.concurrent.ThreadPoolExecutor +import java.util.concurrent.TimeUnit /** * A pool factory that logs error instead of printing them to standard err as is the default in GPars @@ -74,18 +78,20 @@ class LoggingPoolFactory implements PoolFactory { * Creates a fixed-thread pool of given size. Each thread will have the uncaught exception handler set * to print the unhandled exception to standard error output. * - * @param daemon Sets the daemon flag of threads in the pool. + * @param daemon Sets the daemon flag of threads in the pool. * @param poolSize The required pool size @return The created thread pool * @return The newly created thread pool */ private static ThreadPoolExecutor createResizeablePool(boolean daemon, int poolSize) { assert poolSize > 0; return new ThreadPoolExecutor(poolSize, 1000, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new SynchronousQueue(), new ThreadFactory() { + @Override Thread newThread(Runnable r) { Thread thread = new Thread(r, createThreadNameMethod.invoke(DefaultPool).toString()) thread.daemon = daemon thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + @Override void uncaughtException(Thread t, Throwable e) { LOG.error("Async execution error: ${e.message}", e) @@ -94,11 +100,12 @@ class LoggingPoolFactory implements PoolFactory { return thread } }, new RejectedExecutionHandler() { + @Override void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { throw new IllegalStateException("The thread pool executor cannot run the task. " + - "The upper limit of the thread pool size has probably been reached. " + - "Current pool size: $executor.poolSize Maximum pool size: $executor.maximumPoolSize") + "The upper limit of the thread pool size has probably been reached. " + + "Current pool size: $executor.poolSize Maximum pool size: $executor.maximumPoolSize") } }) } diff --git a/grails-async/plugin/build.gradle b/grails-async/plugin/build.gradle index f8ff94c033a..aaa17fcb752 100644 --- a/grails-async/plugin/build.gradle +++ b/grails-async/plugin/build.gradle @@ -60,4 +60,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-async/plugin/src/main/groovy/grails/async/services/PersistenceContextPromiseDecorator.groovy b/grails-async/plugin/src/main/groovy/grails/async/services/PersistenceContextPromiseDecorator.groovy index abbc3a8e65b..47d1fe88f2d 100644 --- a/grails-async/plugin/src/main/groovy/grails/async/services/PersistenceContextPromiseDecorator.groovy +++ b/grails-async/plugin/src/main/groovy/grails/async/services/PersistenceContextPromiseDecorator.groovy @@ -18,9 +18,9 @@ */ package grails.async.services -import groovy.transform.CompileStatic -import grails.persistence.support.PersistenceContextInterceptorExecutor import grails.async.decorator.PromiseDecorator +import grails.persistence.support.PersistenceContextInterceptorExecutor +import groovy.transform.CompileStatic /** * A {@link PromiseDecorator} that wraps a promise execution in a persistence context (example Hibernate session) @@ -29,7 +29,8 @@ import grails.async.decorator.PromiseDecorator * @since 2.3 */ @CompileStatic -class PersistenceContextPromiseDecorator implements PromiseDecorator{ +class PersistenceContextPromiseDecorator implements PromiseDecorator { + PersistenceContextInterceptorExecutor persistenceContextInterceptorExecutor PersistenceContextPromiseDecorator(PersistenceContextInterceptorExecutor persistenceContextInterceptorExecutor) { diff --git a/grails-async/plugin/src/main/groovy/grails/async/services/TransactionalPromiseDecorator.groovy b/grails-async/plugin/src/main/groovy/grails/async/services/TransactionalPromiseDecorator.groovy index 7032c4a247f..bcea7608fa2 100644 --- a/grails-async/plugin/src/main/groovy/grails/async/services/TransactionalPromiseDecorator.groovy +++ b/grails-async/plugin/src/main/groovy/grails/async/services/TransactionalPromiseDecorator.groovy @@ -18,9 +18,9 @@ */ package grails.async.services +import grails.async.decorator.PromiseDecorator import groovy.transform.AutoFinal import groovy.transform.CompileStatic -import grails.async.decorator.PromiseDecorator import org.springframework.beans.BeanWrapper import org.springframework.beans.PropertyAccessorFactory import org.springframework.transaction.PlatformTransactionManager @@ -45,7 +45,8 @@ import java.lang.reflect.Method class TransactionalPromiseDecorator implements PromiseDecorator, TransactionDefinition { PlatformTransactionManager transactionManager - @Delegate DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition() + @Delegate + DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition() TransactionalPromiseDecorator(PlatformTransactionManager transactionManager) { this.transactionManager = transactionManager @@ -78,7 +79,7 @@ class TransactionalPromiseDecorator implements PromiseDecorator, TransactionDefi @Override Closure decorate(Closure original) { if (transactionManager != null) { - return (Closure){ args -> + return (Closure) { args -> def transactionTemplate = transactionDefinition != null ? new TransactionTemplate(transactionManager, transactionDefinition) : new TransactionTemplate(transactionManager) transactionTemplate.execute({ original.call(args) diff --git a/grails-async/plugin/src/main/groovy/grails/async/web/AsyncController.groovy b/grails-async/plugin/src/main/groovy/grails/async/web/AsyncController.groovy index be3bbe2b0b4..6c7b94db769 100644 --- a/grails-async/plugin/src/main/groovy/grails/async/web/AsyncController.groovy +++ b/grails-async/plugin/src/main/groovy/grails/async/web/AsyncController.groovy @@ -16,10 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - package grails.async.web import groovy.transform.CompileStatic +import jakarta.servlet.AsyncContext +import jakarta.servlet.http.HttpServletRequest import org.grails.plugins.web.async.GrailsAsyncContext import org.grails.web.servlet.mvc.GrailsWebRequest import org.grails.web.util.GrailsApplicationAttributes @@ -28,9 +29,6 @@ import org.springframework.web.context.request.async.AsyncWebRequest import org.springframework.web.context.request.async.WebAsyncManager import org.springframework.web.context.request.async.WebAsyncUtils -import jakarta.servlet.AsyncContext -import jakarta.servlet.http.HttpServletRequest - /** * Exposes a startAsync() method for access to the Servlet 3.x API * @@ -45,7 +43,7 @@ trait AsyncController { * @return a new {@link javax.servlet.AsyncContext} */ AsyncContext startAsync() { - GrailsWebRequest webRequest = (GrailsWebRequest)RequestContextHolder.currentRequestAttributes() + GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes() HttpServletRequest request = webRequest.currentRequest WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request) diff --git a/grails-async/plugin/src/main/groovy/grails/async/web/AsyncGrailsWebRequest.groovy b/grails-async/plugin/src/main/groovy/grails/async/web/AsyncGrailsWebRequest.groovy index 7266d214039..c74c2876d4b 100644 --- a/grails-async/plugin/src/main/groovy/grails/async/web/AsyncGrailsWebRequest.groovy +++ b/grails-async/plugin/src/main/groovy/grails/async/web/AsyncGrailsWebRequest.groovy @@ -16,22 +16,21 @@ * specific language governing permissions and limitations * under the License. */ - package grails.async.web import groovy.transform.CompileStatic -import org.grails.web.util.GrailsApplicationAttributes -import org.grails.web.servlet.mvc.GrailsWebRequest -import org.springframework.context.ApplicationContext -import org.springframework.util.Assert -import org.springframework.web.context.request.async.AsyncWebRequest - import jakarta.servlet.AsyncContext import jakarta.servlet.AsyncEvent import jakarta.servlet.AsyncListener import jakarta.servlet.ServletContext import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse +import org.grails.web.servlet.mvc.GrailsWebRequest +import org.grails.web.util.GrailsApplicationAttributes +import org.springframework.context.ApplicationContext +import org.springframework.util.Assert +import org.springframework.web.context.request.async.AsyncWebRequest + import java.util.concurrent.atomic.AtomicBoolean import java.util.function.Consumer @@ -42,7 +41,8 @@ import java.util.function.Consumer * @since 3.0 */ @CompileStatic -class AsyncGrailsWebRequest extends GrailsWebRequest implements AsyncWebRequest, AsyncListener{ +class AsyncGrailsWebRequest extends GrailsWebRequest implements AsyncWebRequest, AsyncListener { + static final String WEB_REQUEST = "org.grails.ASYNC_WEB_REQUEST" Long timeout @@ -97,7 +97,7 @@ class AsyncGrailsWebRequest extends GrailsWebRequest implements AsyncWebRequest, @Override void startAsync() { Assert.state(request.asyncSupported, "The current request does not support Async processing") - if(!isAsyncStarted()) { + if (!isAsyncStarted()) { asyncContext = request.startAsync(request, response) asyncContext.addListener(this) } @@ -110,8 +110,8 @@ class AsyncGrailsWebRequest extends GrailsWebRequest implements AsyncWebRequest, @Override void dispatch() { - Assert.notNull this.asyncContext, "Cannot dispatch without an AsyncContext" - asyncContext.dispatch() + Assert.notNull this.asyncContext, "Cannot dispatch without an AsyncContext" + asyncContext.dispatch() } @Override @@ -121,7 +121,7 @@ class AsyncGrailsWebRequest extends GrailsWebRequest implements AsyncWebRequest, @Override void onComplete(AsyncEvent event) throws IOException { - for(handler in completionHandlers) { + for (handler in completionHandlers) { handler.run() } asyncContext = null @@ -130,7 +130,7 @@ class AsyncGrailsWebRequest extends GrailsWebRequest implements AsyncWebRequest, @Override void onTimeout(AsyncEvent event) throws IOException { - for(handler in timeoutHandlers) { + for (handler in timeoutHandlers) { handler.run() } } diff --git a/grails-async/plugin/src/main/groovy/grails/async/web/WebPromises.groovy b/grails-async/plugin/src/main/groovy/grails/async/web/WebPromises.groovy index 7a923d03d1b..4b19afa3453 100644 --- a/grails-async/plugin/src/main/groovy/grails/async/web/WebPromises.groovy +++ b/grails-async/plugin/src/main/groovy/grails/async/web/WebPromises.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package grails.async.web import grails.async.Promise @@ -32,7 +31,7 @@ import java.util.concurrent.TimeUnit * A specific promises factory class designed for use in controllers and other web contexts * * @since 3.2.7 - * @author Graeme Rocher + * @author Graeme Rocher */ @CompileStatic class WebPromises { @@ -57,73 +56,73 @@ class WebPromises { private WebPromises() {} /** - * @see grails.async.PromiseFactory#waitAll(grails.async.Promise[]) + * @see grails.async.PromiseFactory#waitAll(grails.async.Promise [ ]) */ - static List waitAll(Promise...promises) { + static List waitAll(Promise... promises) { return getPromiseFactory().waitAll(promises) } /** * @see grails.async.PromiseFactory#waitAll(java.util.List) */ - static List waitAll(List> promises) { + static List waitAll(List> promises) { return getPromiseFactory().waitAll(promises) } /** * @see grails.async.PromiseFactory#waitAll(java.util.List) */ - static List waitAll(List> promises, final long timeout, final TimeUnit units) { + static List waitAll(List> promises, final long timeout, final TimeUnit units) { return getPromiseFactory().waitAll(promises, timeout, units) } /** * @see grails.async.PromiseFactory#onComplete(java.util.List, groovy.lang.Closure) */ - static Promise> onComplete(List> promises, Closure callable) { + static Promise> onComplete(List> promises, Closure callable) { return getPromiseFactory().onComplete(promises, callable) } /** * @see grails.async.PromiseFactory#onError(java.util.List, groovy.lang.Closure) */ - static Promise> onError(List> promises, Closure callable) { + static Promise> onError(List> promises, Closure callable) { return getPromiseFactory().onError(promises, callable) } /** * @see grails.async.PromiseFactory#createPromise(java.util.Map) */ - static Promise> createPromise(Map map) { + static Promise> createPromise(Map map) { return getPromiseFactory().createPromise(map, DECORATOR_LOOKUP.findDecorators()) } /** - * @see grails.async.PromiseFactory#createPromise(groovy.lang.Closure[]) + * @see grails.async.PromiseFactory#createPromise(groovy.lang.Closure [ ]) */ - static Promise> createPromise(Closure... c) { + static Promise> createPromise(Closure... c) { return getPromiseFactory().createPromise(Arrays.asList(c), DECORATOR_LOOKUP.findDecorators()) } /** * @see grails.async.PromiseFactory#createPromise(java.util.Map) */ - static Promise> tasks(Map map) { + static Promise> tasks(Map map) { return createPromise(map) } /** - * @see grails.async.PromiseFactory#createPromise(groovy.lang.Closure[]) + * @see grails.async.PromiseFactory#createPromise(groovy.lang.Closure [ ]) */ - static Promise task(Closure c) { + static Promise task(Closure c) { return getPromiseFactory().createPromise(c, DECORATOR_LOOKUP.findDecorators()) } /** - * @see grails.async.PromiseFactory#createPromise(groovy.lang.Closure[]) + * @see grails.async.PromiseFactory#createPromise(groovy.lang.Closure [ ]) */ - static Promise> tasks(Closure... c) { + static Promise> tasks(Closure... c) { return createPromise(c) } /** - * @see grails.async.PromiseFactory#createPromise(groovy.lang.Closure[]) + * @see grails.async.PromiseFactory#createPromise(groovy.lang.Closure [ ]) */ - static Promise> tasks(List> closures) { + static Promise> tasks(List> closures) { return getPromiseFactory().createPromise(closures, DECORATOR_LOOKUP.findDecorators()) } @@ -137,33 +136,33 @@ class WebPromises { /** * @see grails.async.PromiseFactory#createPromise(Class) */ - static Promise createPromise(Class returnType) { + static Promise createPromise(Class returnType) { return getPromiseFactory().createPromise(returnType) } /** * @see grails.async.PromiseFactory#createPromise(groovy.lang.Closure, java.util.List) */ - static Promise createPromise(Closure c, List decorators) { + static Promise createPromise(Closure c, List decorators) { return getPromiseFactory().createPromise(c, DECORATOR_LOOKUP.findDecorators()) } /** * @see grails.async.PromiseFactory#createPromise(java.util.List, java.util.List) */ - static Promise> createPromise(List> closures, List decorators) { + static Promise> createPromise(List> closures, List decorators) { return getPromiseFactory().createPromise(closures, DECORATOR_LOOKUP.findDecorators()) } /** - * @see grails.async.PromiseFactory#createPromise(grails.async.Promise[]) + * @see grails.async.PromiseFactory#createPromise(grails.async.Promise [ ]) */ - static Promise> createPromise(Promise...promises) { + static Promise> createPromise(Promise... promises) { return getPromiseFactory().createPromise(promises) } /** * @see grails.async.PromiseFactory#createBoundPromise(java.lang.Object) */ - static Promise createBoundPromise(T value) { + static Promise createBoundPromise(T value) { return getPromiseFactory().createBoundPromise(value) } } diff --git a/grails-async/plugin/src/main/groovy/org/grails/async/transform/internal/DefaultDelegateAsyncTransactionalMethodTransformer.groovy b/grails-async/plugin/src/main/groovy/org/grails/async/transform/internal/DefaultDelegateAsyncTransactionalMethodTransformer.groovy index 2630bc9599b..f95dcf6826a 100644 --- a/grails-async/plugin/src/main/groovy/org/grails/async/transform/internal/DefaultDelegateAsyncTransactionalMethodTransformer.groovy +++ b/grails-async/plugin/src/main/groovy/org/grails/async/transform/internal/DefaultDelegateAsyncTransactionalMethodTransformer.groovy @@ -18,6 +18,7 @@ */ package org.grails.async.transform.internal +import grails.transaction.TransactionManagerAware import groovy.transform.CompileStatic import org.codehaus.groovy.ast.ClassHelper import org.codehaus.groovy.ast.ClassNode @@ -36,11 +37,10 @@ import org.codehaus.groovy.ast.expr.PropertyExpression import org.codehaus.groovy.ast.expr.VariableExpression import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.ExpressionStatement -import org.grails.compiler.injection.GrailsASTUtils -import org.grails.compiler.web.async.TransactionalAsyncTransformUtils -import grails.transaction.TransactionManagerAware import org.codehaus.groovy.syntax.Token import org.codehaus.groovy.syntax.Types +import org.grails.compiler.injection.GrailsASTUtils +import org.grails.compiler.web.async.TransactionalAsyncTransformUtils import org.springframework.transaction.PlatformTransactionManager import org.springframework.transaction.annotation.Transactional @@ -65,7 +65,7 @@ class DefaultDelegateAsyncTransactionalMethodTransformer implements DelegateAsyn private static final ClassNode CLASS_NODE_MAP = new ClassNode(Map.class).getPlainNodeReference() private static final String METHOD_NAME_SET_TRANSACTION_MANAGER = "setTransactionManager" private static final VariableExpression EXPRESSION_THIS = new VariableExpression("this") - private static final Token OPERATOR_ASSIGNMENT = new Token(Types.EQUAL,"=", -1,-1) + private static final Token OPERATOR_ASSIGNMENT = new Token(Types.EQUAL, "=", -1, -1) private static final String VARIABLE_TRANSACTION_MANAGER = "txMgr" private FieldNode transactionalField private boolean isTransactional = false @@ -73,14 +73,14 @@ class DefaultDelegateAsyncTransactionalMethodTransformer implements DelegateAsyn private int promiseDecoratorCount = 0 @Override - void transformTransactionalMethod(ClassNode classNode,ClassNode delegateClassNode, MethodNode methodNode, ListExpression promiseDecorators) { + void transformTransactionalMethod(ClassNode classNode, ClassNode delegateClassNode, MethodNode methodNode, ListExpression promiseDecorators) { if (transactionalField == null) { transactionalField = delegateClassNode.getField(TRANSACTIONAL_FIELD) isTransactional = false - if(transactionalField) { + if (transactionalField) { def ie = transactionalField.getInitialExpression() - if(ie instanceof ConstantExpression) { + if (ie instanceof ConstantExpression) { isTransactional = ie.isTrueExpression() } } @@ -92,30 +92,29 @@ class DefaultDelegateAsyncTransactionalMethodTransformer implements DelegateAsyn int currentIndex = promiseDecoratorCount++ - final methodLookupArguments = new ArgumentListExpression(new ConstantExpression(methodNode.getName())) - for(Parameter p in methodNode.getParameters()) { + for (Parameter p in methodNode.getParameters()) { methodLookupArguments.addExpression(new ClassExpression(p.getType().getPlainNodeReference())) } final promiseLookupExpression = new BinaryExpression(new PropertyExpression(EXPRESSION_THIS, FIELD_NAME_PROMISE_DECORATORS), Token.newSymbol(Types.LEFT_SQUARE_BRACKET, -1, -1), new ConstantExpression(currentIndex)) setTransactionManagerMethodBody.addStatement( - new ExpressionStatement( - new BinaryExpression( - promiseLookupExpression, - OPERATOR_ASSIGNMENT, - new MethodCallExpression( - new ClassExpression(new ClassNode(TransactionalAsyncTransformUtils).getPlainNodeReference()), - "createTransactionalPromiseDecorator", - new ArgumentListExpression(new VariableExpression(VARIABLE_TRANSACTION_MANAGER), - new MethodCallExpression( + new ExpressionStatement( + new BinaryExpression( + promiseLookupExpression, + OPERATOR_ASSIGNMENT, + new MethodCallExpression( + new ClassExpression(new ClassNode(TransactionalAsyncTransformUtils).getPlainNodeReference()), + "createTransactionalPromiseDecorator", + new ArgumentListExpression(new VariableExpression(VARIABLE_TRANSACTION_MANAGER), + new MethodCallExpression( new ClassExpression(delegateClassNode), "getDeclaredMethod", methodLookupArguments - ) - ) - ) + ) + ) + ) + ) ) - ) ) promiseDecorators.addExpression(promiseLookupExpression) @@ -137,7 +136,7 @@ class DefaultDelegateAsyncTransactionalMethodTransformer implements DelegateAsyn classNode.addField(new FieldNode(FIELD_NAME_TRANSACTION_MANAGER, Modifier.PRIVATE, INTERFACE_TRANSACTION_MANAGER, classNode, GrailsASTUtils.NULL_EXPRESSION)) } final promiseDecoratorsField = classNode.getField(FIELD_NAME_PROMISE_DECORATORS) - if(promiseDecoratorsField == null) { + if (promiseDecoratorsField == null) { classNode.addField(new FieldNode(FIELD_NAME_PROMISE_DECORATORS, Modifier.PRIVATE, CLASS_NODE_MAP, classNode, new MapExpression())) } @@ -146,28 +145,28 @@ class DefaultDelegateAsyncTransactionalMethodTransformer implements DelegateAsyn def parameters = [transactionManagerParameter] as Parameter[] final txMgrParam = new VariableExpression(transactionManagerParameter) methodBody.addStatement( - new ExpressionStatement( - new BinaryExpression( - new PropertyExpression(EXPRESSION_THIS, FIELD_NAME_TRANSACTION_MANAGER), - OPERATOR_ASSIGNMENT, - txMgrParam + new ExpressionStatement( + new BinaryExpression( + new PropertyExpression(EXPRESSION_THIS, FIELD_NAME_TRANSACTION_MANAGER), + OPERATOR_ASSIGNMENT, + txMgrParam + ) ) - ) ) methodBody.addStatement( - new ExpressionStatement( - new DeclarationExpression( - new VariableExpression(VARIABLE_TRANSACTION_MANAGER, INTERFACE_TRANSACTION_MANAGER), - OPERATOR_ASSIGNMENT, - txMgrParam + new ExpressionStatement( + new DeclarationExpression( + new VariableExpression(VARIABLE_TRANSACTION_MANAGER, INTERFACE_TRANSACTION_MANAGER), + OPERATOR_ASSIGNMENT, + txMgrParam + ) ) - ) ) method = new MethodNode(METHOD_NAME_SET_TRANSACTION_MANAGER, Modifier.PUBLIC, ClassHelper.VOID_TYPE, parameters, [] as ClassNode[], methodBody) classNode.addMethod(method) } - return (BlockStatement)method.getCode() + return (BlockStatement) method.getCode() } } diff --git a/grails-async/plugin/src/main/groovy/org/grails/compiler/web/async/TransactionalAsyncTransformUtils.groovy b/grails-async/plugin/src/main/groovy/org/grails/compiler/web/async/TransactionalAsyncTransformUtils.groovy index 7b2a25157ef..832981009e2 100644 --- a/grails-async/plugin/src/main/groovy/org/grails/compiler/web/async/TransactionalAsyncTransformUtils.groovy +++ b/grails-async/plugin/src/main/groovy/org/grails/compiler/web/async/TransactionalAsyncTransformUtils.groovy @@ -34,7 +34,6 @@ import java.lang.reflect.Method @CompileStatic class TransactionalAsyncTransformUtils { - /** * Creates a {@link TransactionalPromiseDecorator} for the given transactionManager and method to be invoked * diff --git a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/AsyncWebRequestPromiseDecorator.groovy b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/AsyncWebRequestPromiseDecorator.groovy index c63d86fd148..eb16ff01f55 100644 --- a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/AsyncWebRequestPromiseDecorator.groovy +++ b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/AsyncWebRequestPromiseDecorator.groovy @@ -16,22 +16,21 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.plugins.web.async +import grails.async.decorator.PromiseDecorator import grails.async.web.AsyncGrailsWebRequest import groovy.transform.CompileStatic import groovy.transform.TypeCheckingMode +import jakarta.servlet.AsyncContext +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse import org.grails.web.servlet.mvc.GrailsWebRequest import org.grails.web.util.WebUtils -import grails.async.decorator.PromiseDecorator import org.springframework.web.context.request.RequestContextHolder import org.springframework.web.context.request.async.WebAsyncManager import org.springframework.web.context.request.async.WebAsyncUtils -import jakarta.servlet.AsyncContext -import jakarta.servlet.http.HttpServletRequest -import jakarta.servlet.http.HttpServletResponse import java.util.concurrent.TimeoutException /** @@ -42,6 +41,7 @@ import java.util.concurrent.TimeoutException */ @CompileStatic class AsyncWebRequestPromiseDecorator implements PromiseDecorator { + GrailsWebRequest webRequest final AsyncGrailsWebRequest asyncRequest final AsyncContext asyncContext @@ -52,15 +52,14 @@ class AsyncWebRequestPromiseDecorator implements PromiseDecorator { HttpServletRequest currentServletRequest = webRequest.currentRequest WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(currentServletRequest) AsyncGrailsWebRequest newWebRequest - if(asyncManager.isConcurrentHandlingStarted()) { + if (asyncManager.isConcurrentHandlingStarted()) { newWebRequest = AsyncGrailsWebRequest.lookup(currentServletRequest) asyncContext = newWebRequest.asyncContext - if( newWebRequest == null || newWebRequest.isAsyncComplete() ) { + if (newWebRequest == null || newWebRequest.isAsyncComplete()) { throw new IllegalStateException("Cannot start a task once asynchronous request processing has completed") } - } - else { - newWebRequest = new AsyncGrailsWebRequest(currentServletRequest, webRequest.currentResponse, webRequest.servletContext,webRequest.applicationContext) + } else { + newWebRequest = new AsyncGrailsWebRequest(currentServletRequest, webRequest.currentResponse, webRequest.servletContext, webRequest.applicationContext) asyncManager.setAsyncWebRequest(newWebRequest) newWebRequest.startAsync() asyncContext = newWebRequest.asyncContext @@ -74,22 +73,21 @@ class AsyncWebRequestPromiseDecorator implements PromiseDecorator { @Override def Closure decorate(Closure c) { - return (Closure) { args -> - if(timeoutReached) { + return (Closure) { args -> + if (timeoutReached) { throw new TimeoutException("Asynchronous request processing timeout reached") } HttpServletRequest request = (HttpServletRequest) asyncContext.request - if(request.isAsyncStarted()) { + if (request.isAsyncStarted()) { - WebUtils.storeGrailsWebRequest(new GrailsWebRequest(request, (HttpServletResponse)asyncContext.response, webRequest.attributes)) + WebUtils.storeGrailsWebRequest(new GrailsWebRequest(request, (HttpServletResponse) asyncContext.response, webRequest.attributes)) try { return invokeClosure(c, args) } finally { RequestContextHolder.resetRequestAttributes() } - } - else { + } else { throw new IllegalStateException("Asynchronous request already terminated. Likely timeout reached") } } @@ -99,14 +97,11 @@ class AsyncWebRequestPromiseDecorator implements PromiseDecorator { def invokeClosure(Closure c, args) { if (args == null) { c.call(null) - } - else if(args && args.getClass().isArray()) { + } else if (args && args.getClass().isArray()) { c.call(*args) - } - else if (args instanceof List) { + } else if (args instanceof List) { c.call(*args) - } - else { + } else { c.call(args) } } diff --git a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/AsyncWebRequestPromiseDecoratorLookupStrategy.groovy b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/AsyncWebRequestPromiseDecoratorLookupStrategy.groovy index f43bc1ab065..42dea101daf 100644 --- a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/AsyncWebRequestPromiseDecoratorLookupStrategy.groovy +++ b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/AsyncWebRequestPromiseDecoratorLookupStrategy.groovy @@ -18,10 +18,10 @@ */ package org.grails.plugins.web.async -import groovy.transform.CompileStatic -import org.grails.web.servlet.mvc.GrailsWebRequest import grails.async.decorator.PromiseDecorator import grails.async.decorator.PromiseDecoratorLookupStrategy +import groovy.transform.CompileStatic +import org.grails.web.servlet.mvc.GrailsWebRequest /** * A promise decorated lookup strategy that binds a WebRequest to the promise thread @@ -31,6 +31,7 @@ import grails.async.decorator.PromiseDecoratorLookupStrategy */ @CompileStatic class AsyncWebRequestPromiseDecoratorLookupStrategy implements PromiseDecoratorLookupStrategy { + @Override List findDecorators() { final webRequest = GrailsWebRequest.lookup() diff --git a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/ControllersAsyncGrailsPlugin.groovy b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/ControllersAsyncGrailsPlugin.groovy index f6b20c98502..e004b64520f 100644 --- a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/ControllersAsyncGrailsPlugin.groovy +++ b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/ControllersAsyncGrailsPlugin.groovy @@ -30,10 +30,14 @@ import org.grails.plugins.web.async.spring.PromiseFactoryBean * @since 2.0 */ class ControllersAsyncGrailsPlugin extends Plugin { + def grailsVersion = "7.0.0 > *" def loadAfter = ['controllers'] - Closure doWithSpring() {{-> - asyncPromiseResponseActionResultTransformer(AsyncActionResultTransformer) - grailsPromiseFactory(PromiseFactoryBean) - }} + + Closure doWithSpring() { + { -> + asyncPromiseResponseActionResultTransformer(AsyncActionResultTransformer) + grailsPromiseFactory(PromiseFactoryBean) + } + } } diff --git a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/GrailsAsyncContext.groovy b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/GrailsAsyncContext.groovy index ebba8346d96..fb6d403e85f 100644 --- a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/GrailsAsyncContext.groovy +++ b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/GrailsAsyncContext.groovy @@ -37,7 +37,8 @@ class GrailsAsyncContext implements AsyncContext { private static final String PERSISTENCE_INTERCEPTORS = 'org.codehaus.groovy.grails.PERSISTENCE_INTERCEPTORS' - final @Delegate AsyncContext delegate + final @Delegate + AsyncContext delegate final GrailsWebRequest originalWebRequest final AsyncGrailsWebRequest asyncGrailsWebRequest @@ -53,7 +54,7 @@ class GrailsAsyncContext implements AsyncContext { void start(Runnable runnable) { delegate.start { - GrailsWebRequest webRequest = asyncGrailsWebRequest ?: new GrailsWebRequest((HttpServletRequest)request, (HttpServletResponse)response, request.getServletContext()) + GrailsWebRequest webRequest = asyncGrailsWebRequest ?: new GrailsWebRequest((HttpServletRequest) request, (HttpServletResponse) response, request.getServletContext()) WebUtils.storeGrailsWebRequest(webRequest) def interceptors = getPersistenceInterceptors(webRequest) @@ -74,11 +75,11 @@ class GrailsAsyncContext implements AsyncContext { void complete() { delegate.complete() - } + } protected Collection getPersistenceInterceptors(GrailsWebRequest webRequest) { def servletContext = webRequest.servletContext - Collection interceptors = (Collection)servletContext?.getAttribute(PERSISTENCE_INTERCEPTORS) + Collection interceptors = (Collection) servletContext?.getAttribute(PERSISTENCE_INTERCEPTORS) if (interceptors == null) { interceptors = webRequest.applicationContext?.getBeansOfType(PersistenceContextInterceptor)?.values() ?: [] servletContext.setAttribute(PERSISTENCE_INTERCEPTORS, interceptors) diff --git a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/mvc/AsyncActionResultTransformer.groovy b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/mvc/AsyncActionResultTransformer.groovy index df069f4285b..4233150f8ed 100644 --- a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/mvc/AsyncActionResultTransformer.groovy +++ b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/mvc/AsyncActionResultTransformer.groovy @@ -22,19 +22,18 @@ import grails.async.Promise import grails.async.PromiseList import grails.async.web.AsyncGrailsWebRequest import groovy.transform.CompileStatic +import jakarta.servlet.AsyncContext +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse import org.grails.plugins.web.async.GrailsAsyncContext import org.grails.web.errors.GrailsExceptionResolver -import org.grails.web.util.GrailsApplicationAttributes import org.grails.web.servlet.mvc.ActionResultTransformer import org.grails.web.servlet.mvc.GrailsWebRequest +import org.grails.web.util.GrailsApplicationAttributes import org.springframework.web.context.request.async.WebAsyncManager import org.springframework.web.context.request.async.WebAsyncUtils import org.springframework.web.servlet.ModelAndView -import jakarta.servlet.AsyncContext -import jakarta.servlet.http.HttpServletRequest -import jakarta.servlet.http.HttpServletResponse - /** * Handles an Async response from a controller * @@ -55,13 +54,12 @@ class AsyncActionResultTransformer implements ActionResultTransformer { final response = webRequest.getResponse() AsyncGrailsWebRequest asyncWebRequest - if(asyncManager.isConcurrentHandlingStarted()) { + if (asyncManager.isConcurrentHandlingStarted()) { asyncWebRequest = AsyncGrailsWebRequest.lookup(request) - if(asyncWebRequest == null) { + if (asyncWebRequest == null) { throw new IllegalStateException("Concurrency handling already started by another process") } - } - else { + } else { asyncWebRequest = new AsyncGrailsWebRequest(request, response, webRequest.servletContext) asyncManager.setAsyncWebRequest(asyncWebRequest) asyncWebRequest.startAsync() @@ -101,8 +99,7 @@ class AsyncActionResultTransformer implements ActionResultTransformer { def modelAndView = exceptionResolver.resolveException(request, response, this, (Exception) t) asyncContext.getRequest().setAttribute(GrailsApplicationAttributes.MODEL_AND_VIEW, modelAndView) asyncContext.dispatch() - } - else { + } else { asyncContext.complete() } } diff --git a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/spring/PromiseFactoryBean.groovy b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/spring/PromiseFactoryBean.groovy index 6bce2a57883..639548ffbff 100644 --- a/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/spring/PromiseFactoryBean.groovy +++ b/grails-async/plugin/src/main/groovy/org/grails/plugins/web/async/spring/PromiseFactoryBean.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.plugins.web.async.spring import grails.async.PromiseFactory @@ -33,6 +32,7 @@ import org.springframework.beans.factory.FactoryBean */ @CompileStatic class PromiseFactoryBean extends PromiseFactoryBuilder implements FactoryBean { + @Override PromiseFactory getObject() throws Exception { PromiseFactory promiseFactory = build() diff --git a/grails-async/rxjava/build.gradle b/grails-async/rxjava/build.gradle index b15111a3952..363846c1ce0 100644 --- a/grails-async/rxjava/build.gradle +++ b/grails-async/rxjava/build.gradle @@ -46,4 +46,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-async/rxjava/src/main/groovy/org/grails/async/factory/rxjava/RxPromise.groovy b/grails-async/rxjava/src/main/groovy/org/grails/async/factory/rxjava/RxPromise.groovy index f44de3fab5e..71358ca0b2d 100644 --- a/grails-async/rxjava/src/main/groovy/org/grails/async/factory/rxjava/RxPromise.groovy +++ b/grails-async/rxjava/src/main/groovy/org/grails/async/factory/rxjava/RxPromise.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.async.factory.rxjava import grails.async.Promise @@ -47,21 +46,21 @@ import java.util.concurrent.TimeoutException @AutoFinal @CompileStatic @PackageScope -class RxPromise implements Promise { +class RxPromise implements Promise { - final Subject subject + final Subject subject final RxPromiseFactory promiseFactory protected Subscription subscription RxPromise(RxPromiseFactory promiseFactory, Closure callable, Scheduler scheduler) { - this(promiseFactory, Single.create( { SingleSubscriber singleSubscriber -> + this(promiseFactory, Single.create({ SingleSubscriber singleSubscriber -> try { - singleSubscriber.onSuccess((T)callable.call()) + singleSubscriber.onSuccess((T) callable.call()) } catch (Throwable t) { singleSubscriber.onError(t) } } as Single.OnSubscribe) - .subscribeOn(scheduler)) + .subscribeOn(scheduler)) } RxPromise(RxPromiseFactory promiseFactory, Observable single) { @@ -78,7 +77,7 @@ class RxPromise implements Promise { this.subject = subject } - RxPromise(RxPromiseFactory promiseFactory,Observable observable, Subject subject) { + RxPromise(RxPromiseFactory promiseFactory, Observable observable, Subject subject) { this.promiseFactory = promiseFactory this.subscription = observable.subscribe(subject) this.subject = subject @@ -92,13 +91,13 @@ class RxPromise implements Promise { @Override Promise onComplete(Closure callable) { def decoratedCallable = promiseFactory.applyDecorators(callable, null) - return new RxPromise(promiseFactory,subject.map(decoratedCallable as Func1)) + return new RxPromise(promiseFactory, subject.map(decoratedCallable as Func1)) } @Override Promise onError(Closure callable) { def decoratedCallable = promiseFactory.applyDecorators(callable, null) - return new RxPromise(promiseFactory,subject.doOnError(decoratedCallable as Action1)) + return new RxPromise(promiseFactory, subject.doOnError(decoratedCallable as Action1)) } @Override @@ -108,7 +107,7 @@ class RxPromise implements Promise { @Override boolean cancel(boolean mayInterruptIfRunning) { - if(subscription != null) { + if (subscription != null) { subscription.unsubscribe() return subscription.isUnsubscribed() } @@ -117,10 +116,9 @@ class RxPromise implements Promise { @Override boolean isCancelled() { - if(subscription == null) { + if (subscription == null) { return false - } - else { + } else { return subscription.isUnsubscribed() } } @@ -140,10 +138,9 @@ class RxPromise implements Promise { try { return subject.timeout(timeout, unit).toBlocking().first() } catch (Throwable e) { - if(e.cause instanceof TimeoutException) { + if (e.cause instanceof TimeoutException) { throw e.cause - } - else { + } else { throw e } } diff --git a/grails-async/rxjava/src/main/groovy/org/grails/async/factory/rxjava/RxPromiseFactory.groovy b/grails-async/rxjava/src/main/groovy/org/grails/async/factory/rxjava/RxPromiseFactory.groovy index 6248acc299f..0785de57a1e 100644 --- a/grails-async/rxjava/src/main/groovy/org/grails/async/factory/rxjava/RxPromiseFactory.groovy +++ b/grails-async/rxjava/src/main/groovy/org/grails/async/factory/rxjava/RxPromiseFactory.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.async.factory.rxjava import grails.async.Promise @@ -53,10 +52,9 @@ class RxPromiseFactory extends AbstractPromiseFactory { @Override Promise createPromise(Closure[] closures) { - if(closures.length == 1) { - return new RxPromise(this,closures[0], Schedulers.io()) - } - else { + if (closures.length == 1) { + return new RxPromise(this, closures[0], Schedulers.io()) + } else { def promiseList = new PromiseList() for (Closure closure : closures) { promiseList.add(closure) @@ -79,22 +77,21 @@ class RxPromiseFactory extends AbstractPromiseFactory { Promise onComplete(List> promises, Closure callable) { new RxPromise(this, Observable.concat( promises.collect() { Promise p -> - if(p instanceof BoundPromise) { - return Observable.just(((BoundPromise)p).value) - } - else { - return ((RxPromise)p).subject as Observable + if (p instanceof BoundPromise) { + return Observable.just(((BoundPromise) p).value) + } else { + return ((RxPromise) p).subject as Observable } } ).toList()) - .onComplete(callable) + .onComplete(callable) } @Override Promise onError(List> promises, Closure callable) { new RxPromise(this, Observable.concat( - promises.collect() { Promise p -> ((RxPromise)p).subject as Observable } + promises.collect() { Promise p -> ((RxPromise) p).subject as Observable } ).toList()) - .onError(callable) + .onError(callable) } } diff --git a/grails-async/rxjava/src/test/groovy/org/grails/async/factory/rxjava/RxJavaPromiseListSpec.groovy b/grails-async/rxjava/src/test/groovy/org/grails/async/factory/rxjava/RxJavaPromiseListSpec.groovy index 91409810b1d..0fba6d90afe 100644 --- a/grails-async/rxjava/src/test/groovy/org/grails/async/factory/rxjava/RxJavaPromiseListSpec.groovy +++ b/grails-async/rxjava/src/test/groovy/org/grails/async/factory/rxjava/RxJavaPromiseListSpec.groovy @@ -27,7 +27,6 @@ import spock.util.concurrent.PollingConditions */ class RxJavaPromiseListSpec extends Specification{ - void 'Test promise list handling'() { when: 'a list of promises is created' diff --git a/grails-async/rxjava/src/test/groovy/org/grails/async/factory/rxjava/RxJavaPromiseMapSpec.groovy b/grails-async/rxjava/src/test/groovy/org/grails/async/factory/rxjava/RxJavaPromiseMapSpec.groovy index 894c70ae336..7a940767614 100644 --- a/grails-async/rxjava/src/test/groovy/org/grails/async/factory/rxjava/RxJavaPromiseMapSpec.groovy +++ b/grails-async/rxjava/src/test/groovy/org/grails/async/factory/rxjava/RxJavaPromiseMapSpec.groovy @@ -82,7 +82,6 @@ class RxJavaPromiseMapSpec extends Specification{ } } - void 'Test that a PromiseMap triggers onError for an exception and ignores onComplete'() { when: 'a promise map is used with an onComplete handler' diff --git a/grails-async/rxjava/src/test/groovy/org/grails/async/factory/rxjava/RxJavaPromiseSpec.groovy b/grails-async/rxjava/src/test/groovy/org/grails/async/factory/rxjava/RxJavaPromiseSpec.groovy index 7108caafa8a..f8f3f2a62f5 100644 --- a/grails-async/rxjava/src/test/groovy/org/grails/async/factory/rxjava/RxJavaPromiseSpec.groovy +++ b/grails-async/rxjava/src/test/groovy/org/grails/async/factory/rxjava/RxJavaPromiseSpec.groovy @@ -153,4 +153,3 @@ class RxJavaPromiseSpec extends Specification { } } - diff --git a/grails-async/rxjava2/build.gradle b/grails-async/rxjava2/build.gradle index 41732df8d9b..cb6afbeebf1 100644 --- a/grails-async/rxjava2/build.gradle +++ b/grails-async/rxjava2/build.gradle @@ -46,4 +46,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-async/rxjava2/src/main/groovy/org/grails/async/factory/rxjava2/RxPromise.groovy b/grails-async/rxjava2/src/main/groovy/org/grails/async/factory/rxjava2/RxPromise.groovy index a0f1bdf3242..f573973c9ab 100644 --- a/grails-async/rxjava2/src/main/groovy/org/grails/async/factory/rxjava2/RxPromise.groovy +++ b/grails-async/rxjava2/src/main/groovy/org/grails/async/factory/rxjava2/RxPromise.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.async.factory.rxjava2 import grails.async.Promise @@ -28,7 +27,6 @@ import io.reactivex.Observer import io.reactivex.Scheduler import io.reactivex.Single import io.reactivex.SingleEmitter -import io.reactivex.SingleObserver import io.reactivex.SingleOnSubscribe import io.reactivex.disposables.Disposable import io.reactivex.functions.Consumer @@ -50,7 +48,7 @@ import java.util.concurrent.TimeoutException @AutoFinal @CompileStatic @PackageScope -class RxPromise implements Promise { +class RxPromise implements Promise { protected final Subject subject protected final RxPromiseFactory promiseFactory @@ -61,9 +59,9 @@ class RxPromise implements Promise { RxPromise(RxPromiseFactory promiseFactory, Closure callable, Scheduler scheduler) { - this(promiseFactory, Single.create( { SingleEmitter singleSubscriber -> + this(promiseFactory, Single.create({ SingleEmitter singleSubscriber -> try { - singleSubscriber.onSuccess((T)runCallable(callable)) + singleSubscriber.onSuccess((T) runCallable(callable)) } catch (Throwable t) { singleSubscriber.onError(t) } @@ -87,6 +85,7 @@ class RxPromise implements Promise { this.observable = observable this.promiseFactory = promiseFactory observable.subscribe(new Observer() { + @Override void onSubscribe(Disposable d) { subscription = d @@ -138,7 +137,7 @@ class RxPromise implements Promise { @Override boolean cancel(boolean mayInterruptIfRunning) { - if(subscription != null) { + if (subscription != null) { subscription.dispose() return subscription.isDisposed() } @@ -147,10 +146,9 @@ class RxPromise implements Promise { @Override boolean isCancelled() { - if(subscription == null) { + if (subscription == null) { return false - } - else { + } else { return subscription.isDisposed() } } @@ -170,10 +168,9 @@ class RxPromise implements Promise { try { return subject.timeout(timeout, unit).blockingFirst() } catch (Throwable e) { - if(e.cause instanceof TimeoutException) { + if (e.cause instanceof TimeoutException) { throw e.cause - } - else { + } else { throw e } } @@ -181,7 +178,7 @@ class RxPromise implements Promise { static Object runCallable(Closure callable) { Object rtn = callable.call() - if(rtn == null) { + if (rtn == null) { return Void } else { return rtn diff --git a/grails-async/rxjava2/src/main/groovy/org/grails/async/factory/rxjava2/RxPromiseFactory.groovy b/grails-async/rxjava2/src/main/groovy/org/grails/async/factory/rxjava2/RxPromiseFactory.groovy index c527d26d2b8..2ec3611516a 100644 --- a/grails-async/rxjava2/src/main/groovy/org/grails/async/factory/rxjava2/RxPromiseFactory.groovy +++ b/grails-async/rxjava2/src/main/groovy/org/grails/async/factory/rxjava2/RxPromiseFactory.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.async.factory.rxjava2 import grails.async.Promise @@ -53,10 +52,9 @@ class RxPromiseFactory extends AbstractPromiseFactory { @Override Promise createPromise(Closure[] closures) { - if(closures.length == 1) { + if (closures.length == 1) { return new RxPromise(this, closures[0], Schedulers.io()) - } - else { + } else { def promiseList = new PromiseList() for (Closure closure : closures) { promiseList.add(closure) @@ -78,23 +76,22 @@ class RxPromiseFactory extends AbstractPromiseFactory { @Override Promise onComplete(List> promises, Closure callable) { new RxPromise(this, Observable.concat( - promises.collect { Promise p -> - if(p instanceof BoundPromise) { - return Observable.just(((BoundPromise)p).value) as Observable + promises.collect { Promise p -> + if (p instanceof BoundPromise) { + return Observable.just(((BoundPromise) p).value) as Observable + } else { + return ((RxPromise) p).toObservable() as Observable + } } - else { - return ((RxPromise)p).toObservable() as Observable - } - } ).toList()) - .onComplete(callable) + .onComplete(callable) } @Override Promise> onError(List> promises, Closure callable) { new RxPromise(this, Observable.concat( - promises.collect { ((RxPromise)it).toObservable() } + promises.collect { ((RxPromise) it).toObservable() } ).toList()) - .onError(callable) as Promise> + .onError(callable) as Promise> } } diff --git a/grails-async/rxjava2/src/test/groovy/org/grails/async/factory/rxjava2/RxPromiseSpec.groovy b/grails-async/rxjava2/src/test/groovy/org/grails/async/factory/rxjava2/RxPromiseSpec.groovy index 30b3c3bfd23..6d9f31f72cf 100644 --- a/grails-async/rxjava2/src/test/groovy/org/grails/async/factory/rxjava2/RxPromiseSpec.groovy +++ b/grails-async/rxjava2/src/test/groovy/org/grails/async/factory/rxjava2/RxPromiseSpec.groovy @@ -167,4 +167,3 @@ class RxPromiseSpec extends Specification { } } - diff --git a/grails-async/rxjava3/build.gradle b/grails-async/rxjava3/build.gradle index 3c62cff0dd9..5c647a42b28 100644 --- a/grails-async/rxjava3/build.gradle +++ b/grails-async/rxjava3/build.gradle @@ -46,4 +46,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-async/rxjava3/src/main/groovy/org/grails/async/factory/rxjava3/RxPromise.groovy b/grails-async/rxjava3/src/main/groovy/org/grails/async/factory/rxjava3/RxPromise.groovy index 187da074108..f21cc7c4aec 100644 --- a/grails-async/rxjava3/src/main/groovy/org/grails/async/factory/rxjava3/RxPromise.groovy +++ b/grails-async/rxjava3/src/main/groovy/org/grails/async/factory/rxjava3/RxPromise.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.async.factory.rxjava3 import grails.async.Promise @@ -48,7 +47,7 @@ import java.util.concurrent.TimeoutException @AutoFinal @CompileStatic @PackageScope -class RxPromise implements Promise { +class RxPromise implements Promise { protected final Subject subject protected final RxPromiseFactory promiseFactory @@ -58,9 +57,9 @@ class RxPromise implements Promise { protected boolean finished = false RxPromise(RxPromiseFactory promiseFactory, Closure callable, Scheduler scheduler) { - this(promiseFactory, Single.create( { SingleEmitter singleSubscriber -> + this(promiseFactory, Single.create({ SingleEmitter singleSubscriber -> try { - singleSubscriber.onSuccess((T)runCallable(callable)) + singleSubscriber.onSuccess((T) runCallable(callable)) } catch (Throwable t) { singleSubscriber.onError(t) } @@ -84,6 +83,7 @@ class RxPromise implements Promise { this.observable = observable this.promiseFactory = promiseFactory observable.subscribe(new Observer() { + @Override void onSubscribe(Disposable d) { subscription = d @@ -135,7 +135,7 @@ class RxPromise implements Promise { @Override boolean cancel(boolean mayInterruptIfRunning) { - if(subscription != null) { + if (subscription != null) { subscription.dispose() return subscription.isDisposed() } @@ -144,10 +144,9 @@ class RxPromise implements Promise { @Override boolean isCancelled() { - if(subscription == null) { + if (subscription == null) { return false - } - else { + } else { return subscription.isDisposed() } } @@ -167,10 +166,9 @@ class RxPromise implements Promise { try { return subject.timeout(timeout, unit).blockingFirst() } catch (Throwable e) { - if(e.cause instanceof TimeoutException) { + if (e.cause instanceof TimeoutException) { throw e.cause - } - else { + } else { throw e } } @@ -178,7 +176,7 @@ class RxPromise implements Promise { static Object runCallable(Closure callable) { Object rtn = callable.call() - if(rtn == null) { + if (rtn == null) { return Void } else { return rtn diff --git a/grails-async/rxjava3/src/main/groovy/org/grails/async/factory/rxjava3/RxPromiseFactory.groovy b/grails-async/rxjava3/src/main/groovy/org/grails/async/factory/rxjava3/RxPromiseFactory.groovy index f93dab19255..1512b468522 100644 --- a/grails-async/rxjava3/src/main/groovy/org/grails/async/factory/rxjava3/RxPromiseFactory.groovy +++ b/grails-async/rxjava3/src/main/groovy/org/grails/async/factory/rxjava3/RxPromiseFactory.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.async.factory.rxjava3 import grails.async.Promise @@ -50,10 +49,9 @@ class RxPromiseFactory extends AbstractPromiseFactory { @Override Promise createPromise(Closure[] closures) { - if(closures.length == 1) { + if (closures.length == 1) { return new RxPromise(this, closures[0], Schedulers.io()) - } - else { + } else { def promiseList = new PromiseList() for (Closure closure : closures) { promiseList.add(closure) @@ -75,23 +73,22 @@ class RxPromiseFactory extends AbstractPromiseFactory { @Override Promise onComplete(List> promises, Closure callable) { new RxPromise(this, Observable.concat( - promises.collect { Promise p -> - if(p instanceof BoundPromise) { - return Observable.just(((BoundPromise)p).value) as Observable + promises.collect { Promise p -> + if (p instanceof BoundPromise) { + return Observable.just(((BoundPromise) p).value) as Observable + } else { + return ((RxPromise) p).toObservable() as Observable + } } - else { - return ((RxPromise)p).toObservable() as Observable - } - } ).toList()) - .onComplete(callable) + .onComplete(callable) } @Override Promise> onError(List> promises, Closure callable) { new RxPromise(this, Observable.concat( - promises.collect { ((RxPromise)it).toObservable() } + promises.collect { ((RxPromise) it).toObservable() } ).toList()) - .onError(callable) as Promise> + .onError(callable) as Promise> } } diff --git a/grails-async/rxjava3/src/test/groovy/org/grails/async/factory/rxjava3/RxPromiseSpec.groovy b/grails-async/rxjava3/src/test/groovy/org/grails/async/factory/rxjava3/RxPromiseSpec.groovy index 77cfd92dfa6..8e42cee8702 100644 --- a/grails-async/rxjava3/src/test/groovy/org/grails/async/factory/rxjava3/RxPromiseSpec.groovy +++ b/grails-async/rxjava3/src/test/groovy/org/grails/async/factory/rxjava3/RxPromiseSpec.groovy @@ -164,4 +164,3 @@ class RxPromiseSpec extends Specification { } } - diff --git a/grails-bom/build.gradle b/grails-bom/build.gradle index 7d23c614494..99c6261b33c 100644 --- a/grails-bom/build.gradle +++ b/grails-bom/build.gradle @@ -200,4 +200,5 @@ ext { apply { from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-bootstrap/build.gradle b/grails-bootstrap/build.gradle index b42df191c80..d8ac8a4b040 100644 --- a/grails-bootstrap/build.gradle +++ b/grails-bootstrap/build.gradle @@ -84,4 +84,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-bootstrap/src/main/groovy/grails/build/logging/ConsoleLogger.java b/grails-bootstrap/src/main/groovy/grails/build/logging/ConsoleLogger.java index b83f5b95406..1cb417e3aa0 100644 --- a/grails-bootstrap/src/main/groovy/grails/build/logging/ConsoleLogger.java +++ b/grails-bootstrap/src/main/groovy/grails/build/logging/ConsoleLogger.java @@ -25,6 +25,7 @@ * @since 3.0 */ public interface ConsoleLogger { + /** * Indicates progress with the default progress indicator */ @@ -91,7 +92,7 @@ public interface ConsoleLogger { /** * Use to log an error * - * @param msg The message + * @param msg The message * @param error The error */ void error(String msg, Throwable error); @@ -99,7 +100,7 @@ public interface ConsoleLogger { /** * Log an error with a specific error label * - * @param label The label + * @param label The label * @param message The message */ void error(String label, String message); @@ -127,9 +128,9 @@ public interface ConsoleLogger { /** * Outputs a verbose message + * * @param msg The message */ void verbose(String msg); - } diff --git a/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsConsole.java b/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsConsole.java index fe3de1607e3..1aa0ebe5c8a 100644 --- a/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsConsole.java +++ b/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsConsole.java @@ -40,12 +40,21 @@ import org.grails.build.logging.GrailsConsoleErrorPrintStream; import org.grails.build.logging.GrailsConsolePrintStream; -import java.io.*; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.Flushable; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; import java.util.Collection; import java.util.List; import java.util.Stack; -import static org.fusesource.jansi.Ansi.Color.*; +import static org.fusesource.jansi.Ansi.Color.DEFAULT; +import static org.fusesource.jansi.Ansi.Color.RED; +import static org.fusesource.jansi.Ansi.Color.YELLOW; import static org.fusesource.jansi.Ansi.Erase.FORWARD; import static org.fusesource.jansi.Ansi.ansi; @@ -57,8 +66,6 @@ */ public class GrailsConsole implements ConsoleLogger { - private static GrailsConsole instance; - public static final String ENABLE_TERMINAL = "grails.console.enable.terminal"; public static final String ENABLE_INTERACTIVE = "grails.console.enable.interactive"; public static final String LINE_SEPARATOR = System.getProperty("line.separator"); @@ -71,24 +78,8 @@ public class GrailsConsole implements ConsoleLogger { public static final String STACKTRACE_FILTERED_MESSAGE = " (NOTE: Stack trace has been filtered. Use --verbose to see entire trace.)"; public static final String STACKTRACE_MESSAGE = " (Use --stacktrace to see the full trace)"; public static final Character SECURE_MASK_CHAR = Character.valueOf('*'); - private PrintStream originalSystemOut; - private PrintStream originalSystemErr; - private StringBuilder maxIndicatorString; - private int cursorMove; - private Thread shutdownHookThread; - private Character defaultInputMask = null; - - /** - * Whether to enable verbose mode - */ - private boolean verbose = Boolean.getBoolean("grails.verbose"); - - /** - * Whether to show stack traces - */ - private boolean stacktrace = Boolean.getBoolean("grails.show.stacktrace"); - private boolean progressIndicatorActive = false; + private static GrailsConsole instance; /** * The progress indicator to use @@ -119,11 +110,32 @@ public class GrailsConsole implements ConsoleLogger { Stack category = new Stack() { @Override public String toString() { - if (size() == 1) return peek() + CATEGORY_SEPARATOR; - return DefaultGroovyMethods.join((Iterable) this, CATEGORY_SEPARATOR) + CATEGORY_SEPARATOR; + if (size() == 1) { + return peek() + CATEGORY_SEPARATOR; + } + return DefaultGroovyMethods.join(this, CATEGORY_SEPARATOR) + CATEGORY_SEPARATOR; } }; + private PrintStream originalSystemOut; + private PrintStream originalSystemErr; + private StringBuilder maxIndicatorString; + private int cursorMove; + private Thread shutdownHookThread; + private Character defaultInputMask = null; + + /** + * Whether to enable verbose mode + */ + private boolean verbose = Boolean.getBoolean("grails.verbose"); + + /** + * Whether to show stack traces + */ + private boolean stacktrace = Boolean.getBoolean("grails.show.stacktrace"); + + private boolean progressIndicatorActive = false; + /** * Whether ANSI should be enabled for output */ @@ -134,6 +146,23 @@ public String toString() { */ private boolean userInputActive; + /** + * Logs a message below the current status message + * + * @param msg The message to log + */ + private boolean appendCalled = false; + + protected GrailsConsole() throws IOException { + cursorMove = 1; + + initialize(System.in, System.out, System.err); + + // bit of a WTF this, but see no other way to allow a customization indicator + maxIndicatorString = new StringBuilder(indicator).append(indicator).append(indicator).append(indicator).append(indicator); + + } + public void addShutdownHook() { if (!Environment.isFork()) { shutdownHookThread = new Thread(new Runnable() { @@ -152,17 +181,6 @@ public void removeShutdownHook() { } } - - protected GrailsConsole() throws IOException { - cursorMove = 1; - - initialize(System.in, System.out, System.err); - - // bit of a WTF this, but see no other way to allow a customization indicator - maxIndicatorString = new StringBuilder(indicator).append(indicator).append(indicator).append(indicator).append(indicator); - - } - /** * Use in testing when System.out, System.err or System.in change * @@ -571,7 +589,9 @@ public void updateStatus(String msg) { private void outputMessage(String msg, int replaceCount) { verifySystemOut(); - if (msg == null || msg.trim().length() == 0) return; + if (msg == null || msg.trim().length() == 0) { + return; + } try { if (isAnsiEnabled()) { if (replaceCount > 0) { @@ -584,7 +604,9 @@ private void outputMessage(String msg, int replaceCount) { cursorMove = replaceCount; } } else { - if (lastMessage != null && lastMessage.equals(msg)) return; + if (lastMessage != null && lastMessage.equals(msg)) { + return; + } if (progressIndicatorActive) { out.println(); @@ -745,13 +767,6 @@ private void erasePrompt(PrintStream printStream) { .eraseLine(Ansi.Erase.BACKWARD).cursorLeft(PROMPT.length())); } - /** - * Logs a message below the current status message - * - * @param msg The message to log - */ - private boolean appendCalled = false; - public void append(String msg) { verifySystemOut(); PrintStream printStream = out; @@ -956,7 +971,9 @@ private Ansi outputErrorLabel(Ansi ansi, String label) { private Ansi erasePreviousLine(String categoryName) { int cursorMove = this.cursorMove; - if (userInputActive) cursorMove++; + if (userInputActive) { + cursorMove++; + } if (cursorMove > 0) { int moveLeftLength = categoryName.length() + lastMessage.length(); if (userInputActive) { diff --git a/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsEclipseConsole.java b/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsEclipseConsole.java index 72153378aed..9bcddd72e84 100644 --- a/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsEclipseConsole.java +++ b/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsEclipseConsole.java @@ -36,7 +36,6 @@ * anticipated needs. * * @author Kris De Volder - * * @since 2.0.0.M2 */ public class GrailsEclipseConsole extends GrailsConsole { @@ -65,7 +64,7 @@ private boolean eclipseSupportsAnsi() { private static Boolean boolProp(String propName) { try { - String prop = System.getProperty(propName); + String prop = System.getProperty(propName); return prop != null && Boolean.valueOf(prop); } catch (Exception e) { return false; diff --git a/grails-bootstrap/src/main/groovy/grails/build/proxy/SystemPropertiesAuthenticator.groovy b/grails-bootstrap/src/main/groovy/grails/build/proxy/SystemPropertiesAuthenticator.groovy index 9fac0165c1f..d005afe4106 100644 --- a/grails-bootstrap/src/main/groovy/grails/build/proxy/SystemPropertiesAuthenticator.groovy +++ b/grails-bootstrap/src/main/groovy/grails/build/proxy/SystemPropertiesAuthenticator.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package grails.build.proxy import grails.util.BuildSettings @@ -33,7 +32,7 @@ class SystemPropertiesAuthenticator extends Authenticator { @Override protected PasswordAuthentication getPasswordAuthentication() { - if(getRequestorType() == RequestorType.PROXY) { + if (getRequestorType() == RequestorType.PROXY) { return new PasswordAuthentication( System.getProperty(BuildSettings.PROXY_HTTP_USER, ""), System.getProperty(BuildSettings.PROXY_HTTP_PASSWORD, "").toCharArray()); diff --git a/grails-bootstrap/src/main/groovy/grails/build/support/MetaClassRegistryCleaner.java b/grails-bootstrap/src/main/groovy/grails/build/support/MetaClassRegistryCleaner.java index bedb6357264..91923f5f768 100644 --- a/grails-bootstrap/src/main/groovy/grails/build/support/MetaClassRegistryCleaner.java +++ b/grails-bootstrap/src/main/groovy/grails/build/support/MetaClassRegistryCleaner.java @@ -18,11 +18,20 @@ */ package grails.build.support; -import groovy.lang.*; +import groovy.lang.ExpandoMetaClass; +import groovy.lang.GroovySystem; +import groovy.lang.MetaClass; +import groovy.lang.MetaClassRegistry; +import groovy.lang.MetaClassRegistryChangeEvent; +import groovy.lang.MetaClassRegistryChangeEventListener; import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl; import java.lang.ref.WeakReference; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** @@ -32,13 +41,13 @@ * @since 2.0 */ @SuppressWarnings("rawtypes") -public class MetaClassRegistryCleaner implements MetaClassRegistryChangeEventListener { +public final class MetaClassRegistryCleaner implements MetaClassRegistryChangeEventListener { - private Map alteredClasses = new ConcurrentHashMap (); - private Map alteredInstances = new ConcurrentHashMap(); private static final Object NO_CUSTOM_METACLASS = new Object(); - private static boolean cleaning; private static final MetaClassRegistryCleaner INSTANCE = new MetaClassRegistryCleaner(); + private static boolean cleaning; + private Map alteredClasses = new ConcurrentHashMap(); + private Map alteredInstances = new ConcurrentHashMap(); private MetaClassRegistryCleaner() { } @@ -50,7 +59,8 @@ public static MetaClassRegistryCleaner createAndRegister() { boolean registered = false; for (MetaClassRegistryChangeEventListener listener : listeners) { if (listener == INSTANCE) { - registered = true;break; + registered = true; + break; } } if (!registered) { @@ -96,11 +106,10 @@ private void updateMetaClassOfInstance(MetaClass oldMetaClass, Object instanceTo private void updateMetaClassOfClass(MetaClass oldMetaClass, Class classToUpdate) { if (oldMetaClass != null && !(oldMetaClass.getClass().getName().equals("groovy.mock.interceptor.MockProxyMetaClass"))) { Object current = alteredClasses.get(classToUpdate); - if (current == null ) { + if (current == null) { alteredClasses.put(classToUpdate, oldMetaClass); } - } - else { + } else { alteredClasses.put(classToUpdate, NO_CUSTOM_METACLASS); } } @@ -137,8 +146,7 @@ private void cleanMetaClassOfClass(MetaClassRegistryImpl registry) { Object alteredMetaClass = alteredClasses.get(aClass); if (alteredMetaClass == NO_CUSTOM_METACLASS) { registry.removeMetaClass(aClass); - } - else { + } else { registry.setMetaClass(aClass, (MetaClass) alteredMetaClass); } } @@ -164,7 +172,7 @@ public boolean equals(Object obj) { if (this == obj) { return true; } - return get() == ((IdentityWeakReference)obj).get(); + return get() == ((IdentityWeakReference) obj).get(); } } } diff --git a/grails-bootstrap/src/main/groovy/grails/codegen/model/Model.groovy b/grails-bootstrap/src/main/groovy/grails/codegen/model/Model.groovy index 7f68ac8a883..cea898d1791 100644 --- a/grails-bootstrap/src/main/groovy/grails/codegen/model/Model.groovy +++ b/grails-bootstrap/src/main/groovy/grails/codegen/model/Model.groovy @@ -58,7 +58,6 @@ interface Model { */ String getPropertyName() - /** * A property name version of the class name. For example 'FooBar' becomes 'fooBar' * diff --git a/grails-bootstrap/src/main/groovy/grails/codegen/model/ModelBuilder.groovy b/grails-bootstrap/src/main/groovy/grails/codegen/model/ModelBuilder.groovy index 31c023aac21..6d941c9596f 100644 --- a/grails-bootstrap/src/main/groovy/grails/codegen/model/ModelBuilder.groovy +++ b/grails-bootstrap/src/main/groovy/grails/codegen/model/ModelBuilder.groovy @@ -52,10 +52,9 @@ trait ModelBuilder { * @return The {@link Model} instance */ Model model(String className) { - if(defaultPackage && !className.contains('.')) { + if (defaultPackage && !className.contains('.')) { return new ModelImpl("${defaultPackage}.$className") - } - else { + } else { return new ModelImpl(className) } } @@ -83,6 +82,7 @@ trait ModelBuilder { @CompileStatic private static class ModelImpl implements Model { + final String className final String fullName final String propertyName @@ -114,13 +114,13 @@ trait ModelBuilder { @Override Map asMap() { - [className: className, - fullName: fullName, + [className : className, + fullName : fullName, propertyName: propertyName, - modelName: propertyName, + modelName : propertyName, packageName: packageName, packagePath: packagePath, - simpleName: simpleName, + simpleName : simpleName, lowerCaseName: lowerCaseName] as Map } } diff --git a/grails-bootstrap/src/main/groovy/grails/io/ResourceUtils.groovy b/grails-bootstrap/src/main/groovy/grails/io/ResourceUtils.groovy index b8e7dcd3981..202ef56c5f7 100644 --- a/grails-bootstrap/src/main/groovy/grails/io/ResourceUtils.groovy +++ b/grails-bootstrap/src/main/groovy/grails/io/ResourceUtils.groovy @@ -23,7 +23,6 @@ import groovy.transform.CompileStatic import groovy.transform.Memoized import org.grails.io.support.GrailsResourceUtils - /** * Utility methods for interacting with resources * @@ -52,7 +51,7 @@ class ResourceUtils extends GrailsResourceUtils { def dirName = dir.name if (!dir.hidden && !dirName.startsWith('.') && !['conf', 'i18n', 'assets', 'views', 'migrations'].contains(dirName)) { File[] files = dir.listFiles() - populatePackages(dir,files, packageNames, "") + populatePackages(dir, files, packageNames, "") } } } @@ -62,28 +61,26 @@ class ResourceUtils extends GrailsResourceUtils { protected static populatePackages(File rootDir, File[] files, Collection packageNames, String prefix) { - if(files != null) { - for(dir in files ) { - if(dir.isDirectory()) { + if (files != null) { + for (dir in files) { + if (dir.isDirectory()) { String dirName = dir.name if (!dir.hidden && !dirName.startsWith('.')) { def dirFiles = dir.listFiles() - if(dirFiles != null) { + if (dirFiles != null) { boolean hasGroovySources = dirFiles?.find() { File f -> f.name.endsWith('.groovy') } - if(hasGroovySources) { + if (hasGroovySources) { // if there are Groovy sources stop here, no need to add child packages packageNames.add "${prefix}${dirName}".toString() - } - else { + } else { // otherwise recurse into a child package populatePackages(dir, dirFiles, packageNames, "${prefix}${dirName}.") } } } - } - else { - if(dir.name.endsWith('.groovy') && prefix == "") { + } else { + if (dir.name.endsWith('.groovy') && prefix == "") { packageNames.add("") } } diff --git a/grails-bootstrap/src/main/groovy/grails/io/support/SystemOutErrCapturer.groovy b/grails-bootstrap/src/main/groovy/grails/io/support/SystemOutErrCapturer.groovy index 4cec2bb5643..af3da1a91c9 100644 --- a/grails-bootstrap/src/main/groovy/grails/io/support/SystemOutErrCapturer.groovy +++ b/grails-bootstrap/src/main/groovy/grails/io/support/SystemOutErrCapturer.groovy @@ -25,17 +25,18 @@ import groovy.transform.CompileStatic */ @CompileStatic class SystemOutErrCapturer { + ByteArrayOutputStream out ByteArrayOutputStream err SystemStreamsRedirector previousState - + SystemOutErrCapturer capture() { out = new ByteArrayOutputStream() err = new ByteArrayOutputStream() previousState = SystemStreamsRedirector.create(null, new PrintStream(out, true), new PrintStream(err, true)).redirect() this } - + SystemOutErrCapturer redirectToNull() { out = null err = null @@ -43,14 +44,14 @@ class SystemOutErrCapturer { previousState = SystemStreamsRedirector.create(null, new PrintStream(nullStream, true), new PrintStream(nullStream, true)).redirect() this } - + void close() { - if(previousState != null) { + if (previousState != null) { previousState.redirect() previousState = null } } - + public static T withCapturedOutput(Closure closure) { SystemOutErrCapturer capturer = new SystemOutErrCapturer().capture() try { @@ -59,7 +60,7 @@ class SystemOutErrCapturer { capturer.close() } } - + public static T withNullOutput(Closure closure) { SystemOutErrCapturer capturer = new SystemOutErrCapturer().redirectToNull() try { @@ -68,22 +69,23 @@ class SystemOutErrCapturer { capturer.close() } } - + @CompileStatic public static class NullOutputStream extends OutputStream { + @Override public void write(byte[] b) throws IOException { - - } - + + } + @Override public void write(int b) throws IOException { - + } - + @Override public void write(byte[] b, int off, int len) throws IOException { - + } } } diff --git a/grails-bootstrap/src/main/groovy/grails/io/support/SystemStreamsRedirector.groovy b/grails-bootstrap/src/main/groovy/grails/io/support/SystemStreamsRedirector.groovy index 6bdbd8b7a39..322b90af15f 100644 --- a/grails-bootstrap/src/main/groovy/grails/io/support/SystemStreamsRedirector.groovy +++ b/grails-bootstrap/src/main/groovy/grails/io/support/SystemStreamsRedirector.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package grails.io.support import groovy.transform.CompileStatic @@ -25,33 +24,34 @@ import groovy.transform.ToString @ToString @CompileStatic class SystemStreamsRedirector { + private static final SystemStreamsRedirector original = current() final InputStream input final PrintStream out final PrintStream err - + private SystemStreamsRedirector(InputStream input, PrintStream out, PrintStream err) { this.input = input this.out = out this.err = err } - + static SystemStreamsRedirector create(InputStream input, PrintStream out, PrintStream err) { new SystemStreamsRedirector(input, out, err) } - + static SystemStreamsRedirector current() { create(System.in, System.out, System.err) } - + static SystemStreamsRedirector original() { original } - + static T withOriginalIO(Closure closure) { original().withRedirectedIO(closure) } - + public T withRedirectedIO(Closure closure) { SystemStreamsRedirector previous = redirect() try { @@ -60,27 +60,26 @@ class SystemStreamsRedirector { previous.redirect() } } - - + SystemStreamsRedirector redirect() { InputStream prevInput = null PrintStream prevOut = null PrintStream prevErr = null - if(input != null) { + if (input != null) { prevInput = System.in - if(!(prevInput.is(input))) { + if (!(prevInput.is(input))) { System.setIn(input) } } - if(out != null) { + if (out != null) { prevOut = System.out - if(!(prevOut.is(out))) { + if (!(prevOut.is(out))) { System.setOut(out) } } - if(err != null) { + if (err != null) { prevErr = System.err - if(!(prevErr.is(err))) { + if (!(prevErr.is(err))) { System.setErr(err) } } diff --git a/grails-bootstrap/src/main/groovy/grails/plugins/GrailsPluginInfo.java b/grails-bootstrap/src/main/groovy/grails/plugins/GrailsPluginInfo.java index 40b87beb3eb..2e7967c3cce 100644 --- a/grails-bootstrap/src/main/groovy/grails/plugins/GrailsPluginInfo.java +++ b/grails-bootstrap/src/main/groovy/grails/plugins/GrailsPluginInfo.java @@ -18,12 +18,13 @@ */ package grails.plugins; -import java.util.Map; - import org.grails.io.support.Resource; +import java.util.Map; + /** * Base interface that just contains information about a particular plugin. + * * @author Graeme Rocher * @since 1.3 */ @@ -61,6 +62,7 @@ public interface GrailsPluginInfo { /** * Returns the location of the Resource that represents the plugin descriptor (the *GrailsPlugin.groovy file) + * * @return The resource */ Resource getDescriptor(); @@ -72,6 +74,7 @@ public interface GrailsPluginInfo { /** * Gets the properties of the plugin as a map + * * @return A map of the properties */ @SuppressWarnings("rawtypes") diff --git a/grails-bootstrap/src/main/groovy/grails/plugins/GrailsVersionUtils.groovy b/grails-bootstrap/src/main/groovy/grails/plugins/GrailsVersionUtils.groovy index f09d6616f86..3538ed87f58 100644 --- a/grails-bootstrap/src/main/groovy/grails/plugins/GrailsVersionUtils.groovy +++ b/grails-bootstrap/src/main/groovy/grails/plugins/GrailsVersionUtils.groovy @@ -18,8 +18,8 @@ */ package grails.plugins -import groovy.transform.CompileStatic import grails.plugins.metadata.GrailsPlugin +import groovy.transform.CompileStatic @CompileStatic class GrailsVersionUtils { @@ -53,7 +53,7 @@ class GrailsVersionUtils { def vc = new VersionComparator() pluginVersion = trimTag(pluginVersion) - if (requiredVersion.indexOf('>') >- 1) { + if (requiredVersion.indexOf('>') > -1) { def tokens = requiredVersion.split(">")*.trim() tokens = tokens.stream().collect({ String it -> trimTag(it) }) tokens << pluginVersion @@ -62,8 +62,7 @@ class GrailsVersionUtils { if (tokens[1] == pluginVersion) { return true } - } - else if (pluginVersion.equals(trimTag(requiredVersion))) { + } else if (pluginVersion.equals(trimTag(requiredVersion))) { return true } @@ -112,13 +111,12 @@ class GrailsVersionUtils { private static String trimTag(String pluginVersion) { def i = pluginVersion.indexOf('-') - if (i >- 1) { - pluginVersion = pluginVersion[0..i-1] + if (i > -1) { + pluginVersion = pluginVersion[0..i - 1] } def tokens = pluginVersion.split(/\./) - return tokens.findAll { String it -> it ==~ /\d+/ || it =='*'}.join(".") + return tokens.findAll { String it -> it ==~ /\d+/ || it == '*' }.join(".") } } - diff --git a/grails-bootstrap/src/main/groovy/grails/plugins/VersionComparator.groovy b/grails-bootstrap/src/main/groovy/grails/plugins/VersionComparator.groovy index fcec1cc82a0..2f2886a6210 100644 --- a/grails-bootstrap/src/main/groovy/grails/plugins/VersionComparator.groovy +++ b/grails-bootstrap/src/main/groovy/grails/plugins/VersionComparator.groovy @@ -32,11 +32,9 @@ class VersionComparator implements Comparator { int result = 0 if (o1 == '*') { result = 1 - } - else if (o2 == '*') { + } else if (o2 == '*') { result = -1 - } - else { + } else { def nums1 try { def tokens = deSnapshot(o1).split(/\./) @@ -63,12 +61,11 @@ class VersionComparator implements Comparator { if (result != 0) { break } - if (i == (nums1.size()-1) && bigRight) { - if (nums2[i+1] != 0) + if (i == (nums1.size() - 1) && bigRight) { + if (nums2[i + 1] != 0) result = -1; break } - } - else if (bigLeft) { + } else if (bigLeft) { if (nums1[i] != 0) result = 1; break } diff --git a/grails-bootstrap/src/main/groovy/grails/plugins/metadata/GrailsPlugin.java b/grails-bootstrap/src/main/groovy/grails/plugins/metadata/GrailsPlugin.java index c5b0258c0ed..fec5205f3d7 100644 --- a/grails-bootstrap/src/main/groovy/grails/plugins/metadata/GrailsPlugin.java +++ b/grails-bootstrap/src/main/groovy/grails/plugins/metadata/GrailsPlugin.java @@ -18,10 +18,10 @@ */ package grails.plugins.metadata; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import java.lang.annotation.ElementType; /** * Annotation that appears on classes of a particular plugin. @@ -32,6 +32,8 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface GrailsPlugin { + String name(); + String version(); } diff --git a/grails-bootstrap/src/main/groovy/grails/plugins/metadata/PluginSource.java b/grails-bootstrap/src/main/groovy/grails/plugins/metadata/PluginSource.java index 202ed16d84c..5e0a5e0691e 100644 --- a/grails-bootstrap/src/main/groovy/grails/plugins/metadata/PluginSource.java +++ b/grails-bootstrap/src/main/groovy/grails/plugins/metadata/PluginSource.java @@ -32,4 +32,5 @@ @Retention(RetentionPolicy.SOURCE) @Target({ElementType.TYPE}) public @interface PluginSource { + } diff --git a/grails-bootstrap/src/main/groovy/grails/util/CosineSimilarity.groovy b/grails-bootstrap/src/main/groovy/grails/util/CosineSimilarity.groovy index 96721ebf5bd..1152796795f 100644 --- a/grails-bootstrap/src/main/groovy/grails/util/CosineSimilarity.groovy +++ b/grails-bootstrap/src/main/groovy/grails/util/CosineSimilarity.groovy @@ -20,7 +20,6 @@ package grails.util /** * Uses cosine similarity to find matches from a candidate set for a specified input. - * Based on code from http://www.nearinfinity.com/blogs/seth_schroeder/groovy_cosine_similarity_in_grails.html * * @author Burt Beckwith */ @@ -28,9 +27,9 @@ class CosineSimilarity { /** * Sort the candidates by their similarity to the specified input. - * @param pattern the input string - * @param candidates the possible matches - * @return the ordered candidates + * @param pattern the input string + * @param candidates the possible matches + * @return the ordered candidates */ static List mostSimilar(String pattern, candidates, double threshold = 0) { SortedMap sorted = new TreeMap() diff --git a/grails-bootstrap/src/main/groovy/grails/util/Described.groovy b/grails-bootstrap/src/main/groovy/grails/util/Described.groovy index d7febf70d25..a0311669fea 100644 --- a/grails-bootstrap/src/main/groovy/grails/util/Described.groovy +++ b/grails-bootstrap/src/main/groovy/grails/util/Described.groovy @@ -16,10 +16,8 @@ * specific language governing permissions and limitations * under the License. */ - package grails.util - /** * Interface for classes that are described * diff --git a/grails-bootstrap/src/main/groovy/org/grails/build/interactive/CandidateListCompletionHandler.java b/grails-bootstrap/src/main/groovy/org/grails/build/interactive/CandidateListCompletionHandler.java index e09740b679e..831fcad2bfb 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/build/interactive/CandidateListCompletionHandler.java +++ b/grails-bootstrap/src/main/groovy/org/grails/build/interactive/CandidateListCompletionHandler.java @@ -18,7 +18,6 @@ */ package org.grails.build.interactive; - import jline.console.ConsoleReader; import jline.console.CursorBuffer; import jline.console.completer.CompletionHandler; @@ -82,7 +81,7 @@ public boolean complete(ConsoleReader reader, @SuppressWarnings("rawtypes") List * foobar, foobaz, foobuz, the * method will return foob. */ - private final String getUnambiguousCompletions(final List candidates) { + private String getUnambiguousCompletions(final List candidates) { if (candidates == null || candidates.isEmpty()) { return null; } @@ -106,9 +105,9 @@ private final String getUnambiguousCompletions(final List candidates) { /** * @return true is all the elements of candidates - * start with starts + * start with starts */ - private final boolean startsWith(final String starts, final String[] candidates) { + private boolean startsWith(final String starts, final String[] candidates) { for (int i = 0; i < candidates.length; i++) { if (!candidates[i].startsWith(starts)) { return false; diff --git a/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsoleAntBuilder.java b/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsoleAntBuilder.java index 63d4f70c3b9..681281c1fd9 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsoleAntBuilder.java +++ b/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsoleAntBuilder.java @@ -20,7 +20,12 @@ import grails.build.logging.GrailsConsole; import groovy.ant.AntBuilder; -import org.apache.tools.ant.*; +import org.apache.tools.ant.BuildEvent; +import org.apache.tools.ant.BuildLogger; +import org.apache.tools.ant.DefaultLogger; +import org.apache.tools.ant.MagicNames; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.ProjectHelper; import org.apache.tools.ant.types.LogLevel; import org.apache.tools.ant.util.StringUtils; @@ -73,13 +78,14 @@ public static void addGrailsConsoleBuildListener(Project project) { if (!instance.isVerbose()) { for (Object buildListener : project.getBuildListeners()) { if (buildListener instanceof BuildLogger) { - ((BuildLogger)buildListener).setMessageOutputLevel(LogLevel.ERR.getLevel()); + ((BuildLogger) buildListener).setMessageOutputLevel(LogLevel.ERR.getLevel()); } } } } private static class GrailsConsoleLogger extends DefaultLogger { + /** * Name of the current target, if it should * be displayed on the next message. This is diff --git a/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsoleBuildListener.java b/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsoleBuildListener.java index f5075391011..4a2d2fd5a21 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsoleBuildListener.java +++ b/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsoleBuildListener.java @@ -53,8 +53,7 @@ public final void buildStarted(final BuildEvent start) { * will still be fired if an error occurred during the build.

* * @param finish An event with any relevant extra information. - * Must not be null. - * + * Must not be null. * @see BuildEvent#getException() */ public final void buildFinished(final BuildEvent finish) { @@ -66,7 +65,6 @@ public final void buildFinished(final BuildEvent finish) { * * @param start An event with any relevant extra information. * Must not be null. - * * @see BuildEvent#getTarget() */ public final void targetStarted(final BuildEvent start) { @@ -78,8 +76,7 @@ public final void targetStarted(final BuildEvent start) { * still be fired if an error occurred during the build.

* * @param finish An event with any relevant extra information. - * Must not be null. - * + * Must not be null. * @see BuildEvent#getException() */ public final void targetFinished(final BuildEvent finish) { @@ -91,7 +88,6 @@ public final void targetFinished(final BuildEvent finish) { * * @param start An event with any relevant extra information. * Must not be null. - * * @see BuildEvent#getTask() */ public final void taskStarted(final BuildEvent start) { @@ -103,18 +99,18 @@ public final void taskStarted(final BuildEvent start) { * be fired if an error occurred during the build.

* * @param finish An event with any relevant extra information. - * Must not be null. - * + * Must not be null. * @see BuildEvent#getException() */ public final void taskFinished(final BuildEvent finish) { ui.indicateProgress(); } - /**

When a message is sent to this logger, Ant calls this method.

+ /** + *

When a message is sent to this logger, Ant calls this method.

+ * * @param event An event with any relevant extra information. * Must not be null. - * * @see BuildEvent#getMessage() * @see BuildEvent#getPriority() */ diff --git a/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsoleErrorPrintStream.java b/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsoleErrorPrintStream.java index 20400d3986d..377aa396314 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsoleErrorPrintStream.java +++ b/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsoleErrorPrintStream.java @@ -35,7 +35,7 @@ public GrailsConsoleErrorPrintStream(PrintStream out) { } public PrintStream getTargetOut() { - return (PrintStream)out; + return (PrintStream) out; } @Override diff --git a/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsolePrintStream.java b/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsolePrintStream.java index 69ab0972aff..e7c10e57ce4 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsolePrintStream.java +++ b/grails-bootstrap/src/main/groovy/org/grails/build/logging/GrailsConsolePrintStream.java @@ -35,7 +35,7 @@ public GrailsConsolePrintStream(PrintStream out) { } public PrintStream getTargetOut() { - return (PrintStream)out; + return (PrintStream) out; } @Override diff --git a/grails-bootstrap/src/main/groovy/org/grails/build/parsing/ScriptNameResolver.groovy b/grails-bootstrap/src/main/groovy/org/grails/build/parsing/ScriptNameResolver.groovy index 872e3452c2e..f055dad705a 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/build/parsing/ScriptNameResolver.groovy +++ b/grails-bootstrap/src/main/groovy/org/grails/build/parsing/ScriptNameResolver.groovy @@ -33,7 +33,7 @@ class ScriptNameResolver { * The following scriptNames match FooBar: FB, FoB, FBa */ static boolean resolvesTo(String scriptName, String scriptFileName) { - def scriptFileNameTokens = GrailsNameUtils.getNameFromScript( scriptFileName ).findAll(/[A-Z][a-z]+/) + def scriptFileNameTokens = GrailsNameUtils.getNameFromScript(scriptFileName).findAll(/[A-Z][a-z]+/) def scriptNameTokens = GrailsNameUtils.getNameFromScript(scriptName).findAll(/[A-Z][a-z]*/) if (scriptFileNameTokens.size() != scriptNameTokens.size()) return false diff --git a/grails-bootstrap/src/main/groovy/org/grails/config/CodeGenConfig.groovy b/grails-bootstrap/src/main/groovy/org/grails/config/CodeGenConfig.groovy index 232717bf778..5de2bbbfc26 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/config/CodeGenConfig.groovy +++ b/grails-bootstrap/src/main/groovy/org/grails/config/CodeGenConfig.groovy @@ -40,6 +40,7 @@ import org.yaml.snakeyaml.constructor.SafeConstructor @CompileStatic @Canonical class CodeGenConfig implements Cloneable, ConfigMap { + final NavigableMap configMap GroovyClassLoader groovyClassLoader = new GroovyClassLoader(CodeGenConfig.getClassLoader()) @@ -125,7 +126,7 @@ class CodeGenConfig implements Cloneable, ConfigMap { @Override def T getRequiredProperty(String key, Class targetType) throws IllegalStateException { def value = getProperty(key, targetType) - if(value == null) { + if (value == null) { throw new IllegalStateException("Property [$key] not found") } return value @@ -138,15 +139,15 @@ class CodeGenConfig implements Cloneable, ConfigMap { def envName = Environment.current.name def environmentSpecific = getProperty("environments.${envName}", Map.class) - if(environmentSpecific != null) { - if(!environmentSpecific.isEmpty()) { + if (environmentSpecific != null) { + if (!environmentSpecific.isEmpty()) { mergeMap(environmentSpecific, false) } } } void loadGroovy(File groovyConfig) { - if(groovyConfig.exists()) { + if (groovyConfig.exists()) { def envName = Environment.current.name def configSlurper = new ConfigSlurper(envName) configSlurper.classLoader = groovyClassLoader @@ -155,68 +156,68 @@ class CodeGenConfig implements Cloneable, ConfigMap { } } - @CompileDynamic // fails with CompileStatic! + @CompileDynamic + // fails with CompileStatic! void loadYml(InputStream input) { Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions())) - for(Object yamlObject : yaml.loadAll(input)) { - if(yamlObject instanceof Map) { // problem here with CompileStatic - mergeMap((Map)yamlObject) + for (Object yamlObject : yaml.loadAll(input)) { + if (yamlObject instanceof Map) { // problem here with CompileStatic + mergeMap((Map) yamlObject) } } } - - void mergeMap(Map sourceMap, boolean parseFlatKeys =false) { + + void mergeMap(Map sourceMap, boolean parseFlatKeys = false) { configMap.merge(sourceMap, parseFlatKeys) } - + public T navigate(Class requiredType, String... path) { Object result = configMap.navigate(path) - if(result == null) { + if (result == null) { return null } return convertToType(result, requiredType) } - + protected T convertToType(Object value, Class requiredType) { - if(value == null || value instanceof NavigableMap.NullSafeNavigator) { + if (value == null || value instanceof NavigableMap.NullSafeNavigator) { return null + } else if (requiredType.isInstance(value)) { + return (T) value } - else if(requiredType.isInstance(value)) { - return (T)value - } - if(requiredType==String.class) { + if (requiredType == String.class) { return String.valueOf(value) - } else if(requiredType==Boolean.class) { + } else if (requiredType == Boolean.class) { Boolean booleanObject = toBooleanObject(String.valueOf(value)) return booleanObject != null ? booleanObject : Boolean.FALSE - } else if (requiredType==boolean) { + } else if (requiredType == boolean) { Boolean booleanObject = toBooleanObject(String.valueOf(value)) return booleanObject != null ? booleanObject.booleanValue() : Boolean.FALSE.booleanValue() - } else if(requiredType==Integer.class) { - if(value instanceof Number) { - return Integer.valueOf(((Number)value).intValue()) + } else if (requiredType == Integer.class) { + if (value instanceof Number) { + return Integer.valueOf(((Number) value).intValue()) } else { return Integer.valueOf(String.valueOf(value)) } - } else if(requiredType==Long.class) { - if(value instanceof Number) { - return Long.valueOf(((Number)value).longValue()) + } else if (requiredType == Long.class) { + if (value instanceof Number) { + return Long.valueOf(((Number) value).longValue()) } else { return Long.valueOf(String.valueOf(value)) } - } else if(requiredType==Double.class) { - if(value instanceof Number) { - return Double.valueOf(((Number)value).doubleValue()) + } else if (requiredType == Double.class) { + if (value instanceof Number) { + return Double.valueOf(((Number) value).doubleValue()) } else { return Double.valueOf(String.valueOf(value)) } - } else if(requiredType==BigDecimal.class) { + } else if (requiredType == BigDecimal.class) { return new BigDecimal(String.valueOf(value)) } else { return convertToOtherTypes(value, requiredType) } } - + protected T convertToOtherTypes(Object value, Class requiredType) { throw new RuntimeException("conversion of $value to $requiredType.name not implemented") } @@ -224,33 +225,33 @@ class CodeGenConfig implements Cloneable, ConfigMap { public Object navigate(String... path) { return navigate(Object, path) } - + public boolean asBoolean() { return !configMap.isEmpty() } public Object asType(Class type) { - if(type==Boolean || type==boolean) { + if (type == Boolean || type == boolean) { return asBoolean() - } else if (type==String) { + } else if (type == String) { return toString() - } else if (type==Map) { + } else if (type == Map) { return this - } else if (type==CodeGenConfig) { + } else if (type == CodeGenConfig) { return new CodeGenConfig(this) } else { throw new GroovyCastException(this, type) } } - + public Object getAt(Object key) { getProperty(String.valueOf(key)) } - + public void setAt(Object key, Object value) { setProperty(String.valueOf(key), value) } - + public Object getProperty(String name) { if ("configMap".equals(name)) return this.configMap @@ -269,13 +270,13 @@ class CodeGenConfig implements Cloneable, ConfigMap { } public T getProperty(String name, Class requiredType) { - return convertToType( configMap.get(name), requiredType ) + return convertToType(configMap.get(name), requiredType) } @Override def T getProperty(String key, Class targetType, T defaultValue) { def v = getProperty(key, targetType) - if(v == null) { + if (v == null) { return defaultValue } return v @@ -284,8 +285,7 @@ class CodeGenConfig implements Cloneable, ConfigMap { public void setProperty(String name, Object value) { configMap.setProperty(name, value) } - - + /** * toBooleanObject method ported from org.apache.commons.lang.BooleanUtils.toBooleanObject to Groovy code * @param str @@ -299,27 +299,27 @@ class CodeGenConfig implements Cloneable, ConfigMap { return null } int strlen = str.length() - if (strlen==0) { + if (strlen == 0) { return null } else if (strlen == 1) { char ch0 = str.charAt(0) if ((ch0 == 'y' || ch0 == 'Y') || - (ch0 == 't' || ch0 == 'T')) { + (ch0 == 't' || ch0 == 'T')) { return Boolean.TRUE } if ((ch0 == 'n' || ch0 == 'N') || - (ch0 == 'f' || ch0 == 'F')) { + (ch0 == 'f' || ch0 == 'F')) { return Boolean.FALSE } } else if (strlen == 2) { char ch0 = str.charAt(0) char ch1 = str.charAt(1) if ((ch0 == 'o' || ch0 == 'O') && - (ch1 == 'n' || ch1 == 'N') ) { + (ch1 == 'n' || ch1 == 'N')) { return Boolean.TRUE } if ((ch0 == 'n' || ch0 == 'N') && - (ch1 == 'o' || ch1 == 'O') ) { + (ch1 == 'o' || ch1 == 'O')) { return Boolean.FALSE } } else if (strlen == 3) { @@ -327,13 +327,13 @@ class CodeGenConfig implements Cloneable, ConfigMap { char ch1 = str.charAt(1) char ch2 = str.charAt(2) if ((ch0 == 'y' || ch0 == 'Y') && - (ch1 == 'e' || ch1 == 'E') && - (ch2 == 's' || ch2 == 'S') ) { + (ch1 == 'e' || ch1 == 'E') && + (ch2 == 's' || ch2 == 'S')) { return Boolean.TRUE } if ((ch0 == 'o' || ch0 == 'O') && - (ch1 == 'f' || ch1 == 'F') && - (ch2 == 'f' || ch2 == 'F') ) { + (ch1 == 'f' || ch1 == 'F') && + (ch2 == 'f' || ch2 == 'F')) { return Boolean.FALSE } } else if (strlen == 4) { @@ -342,9 +342,9 @@ class CodeGenConfig implements Cloneable, ConfigMap { char ch2 = str.charAt(2) char ch3 = str.charAt(3) if ((ch0 == 't' || ch0 == 'T') && - (ch1 == 'r' || ch1 == 'R') && - (ch2 == 'u' || ch2 == 'U') && - (ch3 == 'e' || ch3 == 'E') ) { + (ch1 == 'r' || ch1 == 'R') && + (ch2 == 'u' || ch2 == 'U') && + (ch3 == 'e' || ch3 == 'E')) { return Boolean.TRUE } } else if (strlen == 5) { @@ -354,10 +354,10 @@ class CodeGenConfig implements Cloneable, ConfigMap { char ch3 = str.charAt(3) char ch4 = str.charAt(4) if ((ch0 == 'f' || ch0 == 'F') && - (ch1 == 'a' || ch1 == 'A') && - (ch2 == 'l' || ch2 == 'L') && - (ch3 == 's' || ch3 == 'S') && - (ch4 == 'e' || ch4 == 'E') ) { + (ch1 == 'a' || ch1 == 'A') && + (ch2 == 'l' || ch2 == 'L') && + (ch3 == 's' || ch3 == 'S') && + (ch4 == 'e' || ch4 == 'E')) { return Boolean.FALSE } } diff --git a/grails-bootstrap/src/main/groovy/org/grails/config/NavigableMap.groovy b/grails-bootstrap/src/main/groovy/org/grails/config/NavigableMap.groovy index 94a2a9c3521..fde5adc0614 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/config/NavigableMap.groovy +++ b/grails-bootstrap/src/main/groovy/org/grails/config/NavigableMap.groovy @@ -70,7 +70,7 @@ class NavigableMap implements Map, Cloneable { this.rootConfig = rootConfig this.path = path dottedPath = path.join('.') - this.delegateMap= delegateMap + this.delegateMap = delegateMap } @Override @@ -148,7 +148,7 @@ class NavigableMap implements Map, Cloneable { delegateMap.entrySet() } - void merge(Map sourceMap, boolean parseFlatKeys=false) { + void merge(Map sourceMap, boolean parseFlatKeys = false) { mergeMaps(this, "", this, sourceMap, parseFlatKeys) } @@ -158,7 +158,7 @@ class NavigableMap implements Map, Cloneable { Map sourceMap, boolean parseFlatKeys) { - if(springProfileExclude(sourceMap, path)) { + if (springProfileExclude(sourceMap, path)) { return } @@ -189,7 +189,7 @@ class NavigableMap implements Map, Cloneable { def activeSpringProfile = System.getProperty(SPRING_PROFILES) // Is there a 'spring.config.activate.on-profile' property defined in the source map? - def sourceMapProfile1 = ((Map)((Map)((Map)sourceMap?.get(SPRING))?.get(CONFIG))?.get(ACTIVATE))?.get(ON_PROFILE) + def sourceMapProfile1 = ((Map) ((Map) ((Map) sourceMap?.get(SPRING))?.get(CONFIG))?.get(ACTIVATE))?.get(ON_PROFILE) if (!sourceMapProfile1 && path == "$SPRING.$CONFIG.$ACTIVATE") { sourceMapProfile1 = sourceMap?.get(ON_PROFILE) } @@ -206,7 +206,7 @@ class NavigableMap implements Map, Cloneable { } // Is there a 'spring.profiles' property defined in the source map? (Old way of Spring profiles activation) - def sourceMapProfile2 = ((Map)sourceMap?.get(SPRING))?.get(PROFILES) + def sourceMapProfile2 = ((Map) sourceMap?.get(SPRING))?.get(PROFILES) if (!sourceMapProfile2 && path == SPRING) { sourceMapProfile2 = sourceMap?.get(PROFILES) } @@ -235,106 +235,105 @@ class NavigableMap implements Map, Cloneable { int subscriptStart = sourceKey.indexOf('[') int subscriptEnd = sourceKey.indexOf(']') if (subscriptEnd > subscriptStart) { - if(subscriptStart > -1) { - String k = sourceKey[0.. i) { - def v = list.get(i) - if (v instanceof Map) { - ((Map)v).put(remainder, sourceValue) - } else { - Map newMap = [:] - newMap.put(remainder, sourceValue) - fill(list, i, null) - list.set(i, newMap) - } - } else { - Map newMap = [:] - newMap.put(remainder, sourceValue) - fill(list, i, null) - list.set(i, newMap) - } - targetMap.put(k, list) - } else { - def currentValue = targetMap.get(k) - Map nestedMap = currentValue instanceof Map ? currentValue : [:] - targetMap.put(k, nestedMap) - - def v = nestedMap.get(index) - if (v instanceof Map) { - ((Map)v).put(remainder, sourceValue) - } else { - Map newMap = [:] - newMap.put(remainder, sourceValue) - nestedMap.put(index, newMap) - } - } - } else { - def currentValue = targetMap.get(k) - if (index.isNumber()) { - List list = currentValue instanceof List ? currentValue : [] - int i = index.toInteger() - fill(list, i, null) - list.set(i, sourceValue) - targetMap.put(k, list) - } else { - Map nestedMap = currentValue instanceof Map ? currentValue : [:] - targetMap.put(k, nestedMap) - nestedMap.put(index, sourceValue) - } - targetMap.put(sourceKey, sourceValue) - } - - } + if (subscriptStart > -1) { + String k = sourceKey[0.. i) { + def v = list.get(i) + if (v instanceof Map) { + ((Map) v).put(remainder, sourceValue) + } else { + Map newMap = [:] + newMap.put(remainder, sourceValue) + fill(list, i, null) + list.set(i, newMap) + } + } else { + Map newMap = [:] + newMap.put(remainder, sourceValue) + fill(list, i, null) + list.set(i, newMap) + } + targetMap.put(k, list) + } else { + def currentValue = targetMap.get(k) + Map nestedMap = currentValue instanceof Map ? currentValue : [:] + targetMap.put(k, nestedMap) + + def v = nestedMap.get(index) + if (v instanceof Map) { + ((Map) v).put(remainder, sourceValue) + } else { + Map newMap = [:] + newMap.put(remainder, sourceValue) + nestedMap.put(index, newMap) + } + } + } else { + def currentValue = targetMap.get(k) + if (index.isNumber()) { + List list = currentValue instanceof List ? currentValue : [] + int i = index.toInteger() + fill(list, i, null) + list.set(i, sourceValue) + targetMap.put(k, list) + } else { + Map nestedMap = currentValue instanceof Map ? currentValue : [:] + targetMap.put(k, nestedMap) + nestedMap.put(index, sourceValue) + } + targetMap.put(sourceKey, sourceValue) + } + + } } else { Object currentValue = targetMap.containsKey(sourceKey) ? targetMap.get(sourceKey) : null Object newValue - if(sourceValue instanceof Map) { + if (sourceValue instanceof Map) { List newPathList = [] - newPathList.addAll( targetMap.getPath() ) + newPathList.addAll(targetMap.getPath()) newPathList.add(sourceKey) NavigableMap subMap - if(currentValue instanceof NavigableMap) { - subMap = (NavigableMap)currentValue - } - else { + if (currentValue instanceof NavigableMap) { + subMap = (NavigableMap) currentValue + } else { subMap = new NavigableMap(targetMap.getRootConfig(), newPathList.asImmutable()) - if(currentValue instanceof Map) { - subMap.putAll((Map)currentValue) + if (currentValue instanceof Map) { + subMap.putAll((Map) currentValue) } } String newPath = path ? "${path}.${sourceKey}" : sourceKey - mergeMaps(rootMap, newPath , subMap, (Map)sourceValue, parseFlatKeys) + mergeMaps(rootMap, newPath, subMap, (Map) sourceValue, parseFlatKeys) newValue = subMap } else { newValue = sourceValue } if (isNestedSet && newValue == null) { - if(path) { + if (path) { def subMap = rootMap.get(path) - if(subMap instanceof Map) { + if (subMap instanceof Map) { subMap.remove(sourceKey) } def keysToRemove = rootMap.keySet().findAll() { String key -> key.startsWith("${path}.") } - for(key in keysToRemove) { + for (key in keysToRemove) { rootMap.remove(key) } } targetMap.remove(sourceKey) } else { - if(path) { - rootMap.put( "${path}.${sourceKey}".toString(), newValue ) + if (path) { + rootMap.put("${path}.${sourceKey}".toString(), newValue) } mergeMapEntry(targetMap, sourceKey, newValue) } @@ -373,16 +372,16 @@ class NavigableMap implements Map, Cloneable { Object navigate(String... path) { return navigateMap(this, path) } - + private Object navigateMap(Map map, String... path) { - if(map==null || path == null) return null - if(path.length == 0) { + if (map == null || path == null) return null + if (path.length == 0) { return map } else if (path.length == 1) { return map.get(path[0]) } else { def submap = map.get(path[0]) - if(submap instanceof Map) { + if (submap instanceof Map) { return navigateMap((Map) submap, path.tail()) } return submap @@ -402,28 +401,27 @@ class NavigableMap implements Map, Cloneable { NavigableMap currentMap = this StringBuilder accumulatedPath = new StringBuilder() boolean isFirst = true - for(String pathElement : path) { - if(!isFirst) { + for (String pathElement : path) { + if (!isFirst) { accumulatedPath.append(".").append(pathElement) - } - else { + } else { isFirst = false accumulatedPath.append(pathElement) } - Object currentItem = currentMap.get(pathElement) - if(currentItem instanceof NavigableMap) { - currentMap = (NavigableMap)currentItem + Object currentItem = currentMap.get(pathElement) + if (currentItem instanceof NavigableMap) { + currentMap = (NavigableMap) currentItem } else if (createMissing) { List newPathList = [] - newPathList.addAll( currentMap.getPath() ) + newPathList.addAll(currentMap.getPath()) newPathList.add(pathElement) Map newMap = new NavigableMap(currentMap.getRootConfig(), newPathList.asImmutable()) currentMap.put(pathElement, newMap) def fullPath = accumulatedPath.toString() - if(!rootMap.containsKey(fullPath)) { + if (!rootMap.containsKey(fullPath)) { rootMap.put(fullPath, newMap) } currentMap = newMap @@ -433,44 +431,44 @@ class NavigableMap implements Map, Cloneable { } currentMap } - + Map toFlatConfig() { Map flatConfig = [:] flattenKeys(flatConfig, this, [], false) flatConfig } - + Properties toProperties() { Properties properties = new Properties() flattenKeys((Map) properties, this, [], true) properties } - + private void flattenKeys(Map flatConfig, Map currentMap, List path, boolean forceStrings) { currentMap.each { key, value -> String stringKey = String.valueOf(key) - if(value != null) { - if(value instanceof Map) { + if (value != null) { + if (value instanceof Map) { List newPathList = [] - newPathList.addAll( path ) - newPathList.add( stringKey ) + newPathList.addAll(path) + newPathList.add(stringKey) - flattenKeys(flatConfig, (Map)value, newPathList.asImmutable(), forceStrings) + flattenKeys(flatConfig, (Map) value, newPathList.asImmutable(), forceStrings) } else { String fullKey - if(path) { + if (path) { fullKey = path.join('.') + '.' + stringKey } else { fullKey = stringKey } - if(value instanceof Collection) { - if(forceStrings) { - flatConfig.put(fullKey, ((Collection)value).join(",")) + if (value instanceof Collection) { + if (forceStrings) { + flatConfig.put(fullKey, ((Collection) value).join(",")) } else { flatConfig.put(fullKey, value) } int index = 0 - for(Object item: (Collection)value) { + for (Object item : (Collection) value) { String collectionKey = "${fullKey}[${index}]".toString() flatConfig.put(collectionKey, forceStrings ? String.valueOf(item) : item) index++ @@ -480,7 +478,7 @@ class NavigableMap implements Map, Cloneable { } } } - } + } } @Override @@ -498,7 +496,8 @@ class NavigableMap implements Map, Cloneable { */ @Deprecated @CompileStatic - static class NullSafeNavigator implements Map{ + static class NullSafeNavigator implements Map { + final NavigableMap parent final List path @@ -521,7 +520,7 @@ class NavigableMap implements Map, Cloneable { @Override int size() { NavigableMap parentMap = parent.navigateSubMap(path, false) - if(parentMap != null) { + if (parentMap != null) { return parentMap.size() } return 0 @@ -530,7 +529,7 @@ class NavigableMap implements Map, Cloneable { @Override boolean isEmpty() { NavigableMap parentMap = parent.navigateSubMap(path, false) - if(parentMap != null) { + if (parentMap != null) { return parentMap.isEmpty() } return true @@ -538,7 +537,7 @@ class NavigableMap implements Map, Cloneable { boolean containsKey(Object key) { NavigableMap parentMap = parent.navigateSubMap(path, false) - if(parentMap == null) return false + if (parentMap == null) return false else { return parentMap.containsKey(key) } @@ -547,7 +546,7 @@ class NavigableMap implements Map, Cloneable { @Override boolean containsValue(Object value) { NavigableMap parentMap = parent.navigateSubMap(path, false) - if(parentMap != null) { + if (parentMap != null) { return parentMap.containsValue(value) } return false @@ -581,7 +580,7 @@ class NavigableMap implements Map, Cloneable { @Override Set keySet() { NavigableMap parentMap = parent.navigateSubMap(path, false) - if(parentMap != null) { + if (parentMap != null) { return parentMap.keySet() } return Collections.emptySet() @@ -590,7 +589,7 @@ class NavigableMap implements Map, Cloneable { @Override Collection values() { NavigableMap parentMap = parent.navigateSubMap(path, false) - if(parentMap != null) { + if (parentMap != null) { return parentMap.values() } return Collections.emptySet() @@ -599,7 +598,7 @@ class NavigableMap implements Map, Cloneable { @Override Set> entrySet() { NavigableMap parentMap = parent.navigateSubMap(path, false) - if(parentMap != null) { + if (parentMap != null) { return parentMap.entrySet() } return Collections.emptySet() @@ -607,7 +606,7 @@ class NavigableMap implements Map, Cloneable { Object getProperty(String name) { NavigableMap parentMap = parent.navigateSubMap(path, false) - if(parentMap == null) { + if (parentMap == null) { return new NullSafeNavigator(parent, ((path + [name]) as List).asImmutable()) } else { return parentMap.get(name) @@ -648,7 +647,7 @@ class NavigableMap implements Map, Cloneable { } Object asType(Class c) { - if(c==Boolean || c==boolean) return false + if (c == Boolean || c == boolean) return false return null } diff --git a/grails-bootstrap/src/main/groovy/org/grails/exceptions/ExceptionUtils.groovy b/grails-bootstrap/src/main/groovy/org/grails/exceptions/ExceptionUtils.groovy index 6e733ffd518..815418617ce 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/exceptions/ExceptionUtils.groovy +++ b/grails-bootstrap/src/main/groovy/org/grails/exceptions/ExceptionUtils.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.exceptions import groovy.transform.CompileStatic @@ -35,7 +34,6 @@ class ExceptionUtils { public static final String EXCEPTION_ATTRIBUTE = "exception"; - static RuntimeException getFirstRuntimeException(Throwable e) { if (e instanceof RuntimeException) return (RuntimeException) e @@ -61,10 +59,10 @@ class ExceptionUtils { static int extractLineNumber(CompilationFailedException e) { int lineNumber = -1 if (e instanceof MultipleCompilationErrorsException) { - MultipleCompilationErrorsException mcee = (MultipleCompilationErrorsException)e + MultipleCompilationErrorsException mcee = (MultipleCompilationErrorsException) e Object message = mcee.errorCollector.errors.iterator().next() if (message instanceof SyntaxErrorMessage) { - SyntaxErrorMessage sem = (SyntaxErrorMessage)message + SyntaxErrorMessage sem = (SyntaxErrorMessage) message lineNumber = sem.cause.line } } diff --git a/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/DefaultStackTraceFilterer.java b/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/DefaultStackTraceFilterer.java index 95215b5e829..05b994d94b9 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/DefaultStackTraceFilterer.java +++ b/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/DefaultStackTraceFilterer.java @@ -28,31 +28,32 @@ /** * Default implementation of StackTraceFilterer. * - * @since 2.0 * @author Graeme Rocher + * @since 2.0 */ public class DefaultStackTraceFilterer implements StackTraceFilterer { + public static final String STACK_LOG_NAME = "StackTrace"; public static final Log STACK_LOG = LogFactory.getLog(STACK_LOG_NAME); - private static final String[] DEFAULT_INTERNAL_PACKAGES = new String[] { - "org.codehaus.groovy.runtime.", - "org.codehaus.groovy.reflection.", - "org.codehaus.groovy.ast.", - "org.springframework.web.filter", - "org.springframework.boot.actuate", - "org.mortbay.", - "groovy.lang.", - "org.apache.catalina.", - "org.apache.coyote.", - "org.apache.tomcat.", - "net.sf.cglib.proxy.", - "sun.", - "java.lang.reflect.", - "org.springframework.boot.devtools.", - "org.springsource.loaded.", - "com.opensymphony.", - "jakarta.servlet." + private static final String[] DEFAULT_INTERNAL_PACKAGES = new String[]{ + "org.codehaus.groovy.runtime.", + "org.codehaus.groovy.reflection.", + "org.codehaus.groovy.ast.", + "org.springframework.web.filter", + "org.springframework.boot.actuate", + "org.mortbay.", + "groovy.lang.", + "org.apache.catalina.", + "org.apache.coyote.", + "org.apache.tomcat.", + "net.sf.cglib.proxy.", + "sun.", + "java.lang.reflect.", + "org.springframework.boot.devtools.", + "org.springsource.loaded.", + "com.opensymphony.", + "jakarta.servlet." }; private List packagesToFilter = new ArrayList(); @@ -69,7 +70,9 @@ public DefaultStackTraceFilterer(boolean shouldFilter) { } public void addInternalPackage(String name) { - if (name == null) throw new IllegalArgumentException("Package name cannot be null"); + if (name == null) { + throw new IllegalArgumentException("Package name cannot be null"); + } packagesToFilter.add(name); } @@ -120,7 +123,9 @@ private List filterTraceWithCutOff(StackTraceElement[] trace, if (!foundGroovy && fileName != null && fileName.endsWith(".groovy")) { foundGroovy = true; } - if (endPackage != null && className.startsWith(endPackage) && foundGroovy) break; + if (endPackage != null && className.startsWith(endPackage) && foundGroovy) { + break; + } if (isApplicationClass(className)) { if (stackTraceElement.getLineNumber() > -1) { newTrace.add(stackTraceElement); @@ -132,12 +137,15 @@ private List filterTraceWithCutOff(StackTraceElement[] trace, /** * Whether the given class name is an internal class and should be filtered + * * @param className The class name * @return true if is internal */ protected boolean isApplicationClass(String className) { for (String packageName : packagesToFilter) { - if (className.startsWith(packageName)) return false; + if (className.startsWith(packageName)) { + return false; + } } return true; } diff --git a/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/DefaultStackTracePrinter.groovy b/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/DefaultStackTracePrinter.groovy index 1673bc7d60d..b80dfa606cd 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/DefaultStackTracePrinter.groovy +++ b/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/DefaultStackTracePrinter.groovy @@ -62,23 +62,21 @@ class DefaultStackTracePrinter implements StackTracePrinter { printCausedByMessage(sb, e) } if (e instanceof MultipleCompilationErrorsException) break - if(last > 0) { + if (last > 0) { stackTrace[0..-1].eachWithIndex { te, idx -> def fileName = getFileName(te) def lineNumber if (e instanceof SourceCodeAware) { if (e.lineNumber && e.lineNumber > -1) { lineNumber = e.lineNumber.toString().padLeft(lineNumWidth) - } - else { + } else { lineNumber = te.lineNumber.toString().padLeft(lineNumWidth) } if (e.fileName) { fileName = e.fileName fileName = makeRelativeIfPossible(fileName) } - } - else { + } else { lineNumber = te.lineNumber.toString().padLeft(lineNumWidth) } diff --git a/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/SourceCodeAware.java b/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/SourceCodeAware.java index a826fd04f2c..10abd7b27ac 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/SourceCodeAware.java +++ b/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/SourceCodeAware.java @@ -27,6 +27,7 @@ * @since 1.0 */ public interface SourceCodeAware extends Serializable { + String getFileName(); int getLineNumber(); diff --git a/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/StackTraceFilterer.java b/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/StackTraceFilterer.java index ff0d9b6786f..cb6e61c0b5e 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/StackTraceFilterer.java +++ b/grails-bootstrap/src/main/groovy/org/grails/exceptions/reporting/StackTraceFilterer.java @@ -21,8 +21,8 @@ /** * Improves the output of stack traces produced by exceptions in a Grails application. * - * @since 2.0 * @author Graeme Rocher + * @since 2.0 */ public interface StackTraceFilterer { @@ -38,6 +38,7 @@ public interface StackTraceFilterer { /** * Sets the package where the stack trace should end + * * @param cutOffPackage The cut off package */ void setCutOffPackage(String cutOffPackage); @@ -45,7 +46,8 @@ public interface StackTraceFilterer { /** *

Remove all apparently Grails-internal trace entries from the exception instance

*

This modifies the original instance and returns it, it does not clone

- * @param source The source exception + * + * @param source The source exception * @param recursive Whether to recursively filter the cause * @return The exception passed in, after cleaning the stack trace */ @@ -54,6 +56,7 @@ public interface StackTraceFilterer { /** *

Remove all apparently Grails-internal trace entries from the exception instance

*

This modifies the original instance and returns it, it does not clone

+ * * @param source The source exception * @return The exception passed in, after cleaning the stack trace */ diff --git a/grails-bootstrap/src/main/groovy/org/grails/io/support/AntPathMatcher.java b/grails-bootstrap/src/main/groovy/org/grails/io/support/AntPathMatcher.java index d92fcccb0f7..54242897cf8 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/io/support/AntPathMatcher.java +++ b/grails-bootstrap/src/main/groovy/org/grails/io/support/AntPathMatcher.java @@ -18,6 +18,8 @@ */ package org.grails.io.support; +import org.codehaus.groovy.runtime.StringGroovyMethods; + import java.util.Comparator; import java.util.LinkedHashMap; import java.util.LinkedList; @@ -26,12 +28,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.codehaus.groovy.runtime.StringGroovyMethods; - /** * PathMatcher implementation for Ant-style path patterns. Examples are provided below. * - *

Part of this mapping code has been kindly borrowed from Apache Ant. + *

Part of this mapping code has been kindly borrowed from Apache Ant. * *

The mapping matches URLs using the following rules:

  • ? matches one character
  • * matches zero * or more characters
  • ** matches zero or more 'directories' in a path
@@ -50,16 +50,20 @@ * @author Arjen Poutsma * @since 16.07.2003 */ -public class AntPathMatcher { - - private static final Pattern VARIABLE_PATTERN = Pattern.compile("\\{[^/]+?\\}"); +public final class AntPathMatcher { - /** Default path separator: "/" */ + /** + * Default path separator: "/" + */ public static final String DEFAULT_PATH_SEPARATOR = "/"; + private static final Pattern VARIABLE_PATTERN = Pattern.compile("\\{[^/]+?\\}"); + private String pathSeparator = DEFAULT_PATH_SEPARATOR; - /** Set the path separator to use for pattern parsing. Default is "/", as in Ant. */ + /** + * Set the path separator to use for pattern parsing. Default is "/", as in Ant. + */ public void setPathSeparator(String pathSeparator) { this.pathSeparator = pathSeparator == null ? DEFAULT_PATH_SEPARATOR : pathSeparator; } @@ -78,10 +82,11 @@ public boolean matchStart(String pattern, String path) { /** * Actually match the given path against the given pattern. - * @param pattern the pattern to match against - * @param path the path String to test + * + * @param pattern the pattern to match against + * @param path the path String to test * @param fullMatch whether a full pattern match is required (else a pattern match - * as far as the given base path goes is sufficient) + * as far as the given base path goes is sufficient) * @return true if the supplied path matched, false if it didn't */ protected boolean doMatch(String pattern, String path, boolean fullMatch, @@ -130,12 +135,10 @@ protected boolean doMatch(String pattern, String path, boolean fullMatch, } } return true; - } - else if (pattIdxStart > pattIdxEnd) { + } else if (pattIdxStart > pattIdxEnd) { // String not exhausted, but pattern is. Failure. return false; - } - else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) { + } else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) { // Path start definitely matches due to "**" part in pattern. return true; } @@ -212,15 +215,16 @@ else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) { } private String[] tokenize(String pattern) { - List list = StringGroovyMethods.tokenize((CharSequence)pattern, (CharSequence)pathSeparator); + List list = StringGroovyMethods.tokenize((CharSequence) pattern, (CharSequence) pathSeparator); return list.toArray(new String[list.size()]); } /** * Tests whether or not a string matches against a pattern. The pattern may contain two special characters:
'*' * means zero or more characters
'?' means one and only one character + * * @param pattern pattern to match against. Must not be null. - * @param str string which must be matched against the pattern. Must not be null. + * @param str string which must be matched against the pattern. Must not be null. * @return true if the string matches against the pattern, or false otherwise. */ private boolean matchStrings(String pattern, String str, Map uriTemplateVariables) { @@ -273,7 +277,8 @@ public String extractPathWithinPattern(String pattern, String path) { public Map extractUriTemplateVariables(String pattern, String path) { Map variables = new LinkedHashMap(); - /*boolean result =*/ doMatch(pattern, path, true, variables); + /*boolean result =*/ + doMatch(pattern, path, true, variables); return variables; } @@ -291,6 +296,7 @@ public Map extractUriTemplateVariables(String pattern, String pa * /hotels/**{hotel}/hotels/**/{hotel} * /*.html/hotels.html/hotels.html /*.html/hotels/hotels.html * /*.html/*.txtIllegalArgumentException + * * @param pattern1 the first pattern * @param pattern2 the second pattern * @return the combination of the two patterns @@ -341,8 +347,7 @@ public String combine(String pattern1, String pattern2) { if (dotPos2 != -1) { fileName2 = pattern2.substring(0, dotPos2); extension2 = pattern2.substring(dotPos2); - } - else { + } else { fileName2 = pattern2; extension2 = ""; } @@ -353,7 +358,7 @@ public String combine(String pattern1, String pattern2) { } private boolean hasText(String txt) { - return txt != null && txt.length()>0; + return txt != null && txt.length() > 0; } /** @@ -365,6 +370,7 @@ private boolean hasText(String txt) { * list so that the order will be as indicated. *

The full path given as parameter is used to test for exact matches. So when the given path is {@code /hotels/2}, * the pattern {@code /hotels/2} will be sorted before {@code /hotels/1}. + * * @param path the full path to use for comparison * @return a comparator capable of sorting patterns in order of explicitness */ @@ -372,86 +378,24 @@ public Comparator getPatternComparator(String path) { return new AntPatternComparator(path); } - private static class AntPatternComparator implements Comparator { - - private final String path; - - private AntPatternComparator(String path) { - this.path = path; - } - - public int compare(String pattern1, String pattern2) { - if (pattern1 == null && pattern2 == null) { - return 0; - } - else if (pattern1 == null) { - return 1; - } - else if (pattern2 == null) { - return -1; - } - boolean pattern1EqualsPath = pattern1.equals(path); - boolean pattern2EqualsPath = pattern2.equals(path); - if (pattern1EqualsPath && pattern2EqualsPath) { - return 0; - } - else if (pattern1EqualsPath) { - return -1; - } - else if (pattern2EqualsPath) { - return 1; - } - int wildCardCount1 = getWildCardCount(pattern1); - int wildCardCount2 = getWildCardCount(pattern2); - - int bracketCount1 = countOccurrencesOf(pattern1, "{"); - int bracketCount2 = countOccurrencesOf(pattern2, "{"); - - int totalCount1 = wildCardCount1 + bracketCount1; - int totalCount2 = wildCardCount2 + bracketCount2; - - if (totalCount1 != totalCount2) { - return totalCount1 - totalCount2; - } - - int pattern1Length = getPatternLength(pattern1); - int pattern2Length = getPatternLength(pattern2); - - if (pattern1Length != pattern2Length) { - return pattern2Length - pattern1Length; - } - - if (wildCardCount1 < wildCardCount2) { - return -1; - } - else if (wildCardCount2 < wildCardCount1) { - return 1; - } - - if (bracketCount1 < bracketCount2) { - return -1; - } - else if (bracketCount2 < bracketCount1) { - return 1; - } - + /** + * Count the occurrences of the substring in string s. + * + * @param str string to search in. Return 0 if this is null. + * @param sub string to search for. Return 0 if this is null. + */ + public static int countOccurrencesOf(String str, String sub) { + if (str == null || sub == null || str.length() == 0 || sub.length() == 0) { return 0; } - - private int getWildCardCount(String pattern) { - if (pattern.endsWith(".*")) { - pattern = pattern.substring(0, pattern.length() - 2); - } - return countOccurrencesOf(pattern, "*"); - } - - /** - * Returns the length of the given pattern, where template variables are considered to be 1 long. - */ - private int getPatternLength(String pattern) { - Matcher m = VARIABLE_PATTERN.matcher(pattern); - return m.replaceAll("#").length(); + int count = 0; + int pos = 0; + int idx; + while ((idx = str.indexOf(sub, pos)) != -1) { + ++count; + pos = idx + sub.length(); } + return count; } /** @@ -465,7 +409,7 @@ private int getPatternLength(String pattern) { * @author Rossen Stoyanchev * @since 3.0 */ - static class AntPathStringMatcher { + static class AntPathStringMatcher { private static final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*|\\{((?:\\{[^/]+?\\}|[^/{}]|\\\\[{}])+?)\\}"); @@ -479,7 +423,9 @@ static class AntPathStringMatcher { private final Map uriTemplateVariables; - /** Construct a new instance of the AntPatchStringMatcher. */ + /** + * Construct a new instance of the AntPatchStringMatcher. + */ AntPathStringMatcher(String pattern, String str, Map uriTemplateVariables) { this.str = str; this.uriTemplateVariables = uriTemplateVariables; @@ -495,17 +441,14 @@ private Pattern createPattern(String p) { String match = m.group(); if ("?".equals(match)) { patternBuilder.append('.'); - } - else if ("*".equals(match)) { + } else if ("*".equals(match)) { patternBuilder.append(".*"); - } - else if (match.startsWith("{") && match.endsWith("}")) { + } else if (match.startsWith("{") && match.endsWith("}")) { int colonIdx = match.indexOf(':'); if (colonIdx == -1) { patternBuilder.append(DEFAULT_VARIABLE_PATTERN); variableNames.add(m.group(1)); - } - else { + } else { String variablePattern = match.substring(colonIdx + 1, match.length() - 1); patternBuilder.append('('); patternBuilder.append(variablePattern); @@ -548,22 +491,79 @@ public boolean matchStrings() { } } - /** - * Count the occurrences of the substring in string s. - * @param str string to search in. Return 0 if this is null. - * @param sub string to search for. Return 0 if this is null. - */ - public static int countOccurrencesOf(String str, String sub) { - if (str == null || sub == null || str.length() == 0 || sub.length() == 0) { + private static final class AntPatternComparator implements Comparator { + + private final String path; + + private AntPatternComparator(String path) { + this.path = path; + } + + public int compare(String pattern1, String pattern2) { + if (pattern1 == null && pattern2 == null) { + return 0; + } else if (pattern1 == null) { + return 1; + } else if (pattern2 == null) { + return -1; + } + boolean pattern1EqualsPath = pattern1.equals(path); + boolean pattern2EqualsPath = pattern2.equals(path); + if (pattern1EqualsPath && pattern2EqualsPath) { + return 0; + } else if (pattern1EqualsPath) { + return -1; + } else if (pattern2EqualsPath) { + return 1; + } + int wildCardCount1 = getWildCardCount(pattern1); + int wildCardCount2 = getWildCardCount(pattern2); + + int bracketCount1 = countOccurrencesOf(pattern1, "{"); + int bracketCount2 = countOccurrencesOf(pattern2, "{"); + + int totalCount1 = wildCardCount1 + bracketCount1; + int totalCount2 = wildCardCount2 + bracketCount2; + + if (totalCount1 != totalCount2) { + return totalCount1 - totalCount2; + } + + int pattern1Length = getPatternLength(pattern1); + int pattern2Length = getPatternLength(pattern2); + + if (pattern1Length != pattern2Length) { + return pattern2Length - pattern1Length; + } + + if (wildCardCount1 < wildCardCount2) { + return -1; + } else if (wildCardCount2 < wildCardCount1) { + return 1; + } + + if (bracketCount1 < bracketCount2) { + return -1; + } else if (bracketCount2 < bracketCount1) { + return 1; + } + return 0; } - int count = 0; - int pos = 0; - int idx; - while ((idx = str.indexOf(sub, pos)) != -1) { - ++count; - pos = idx + sub.length(); + + private int getWildCardCount(String pattern) { + if (pattern.endsWith(".*")) { + pattern = pattern.substring(0, pattern.length() - 2); + } + return countOccurrencesOf(pattern, "*"); + } + + /** + * Returns the length of the given pattern, where template variables are considered to be 1 long. + */ + private int getPatternLength(String pattern) { + Matcher m = VARIABLE_PATTERN.matcher(pattern); + return m.replaceAll("#").length(); } - return count; } } diff --git a/grails-bootstrap/src/main/groovy/org/grails/io/support/DevNullPrintStream.groovy b/grails-bootstrap/src/main/groovy/org/grails/io/support/DevNullPrintStream.groovy index 3017de89a79..fdd05df47ba 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/io/support/DevNullPrintStream.groovy +++ b/grails-bootstrap/src/main/groovy/org/grails/io/support/DevNullPrintStream.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.io.support import groovy.transform.CompileStatic diff --git a/grails-bootstrap/src/main/groovy/org/grails/io/support/FileSystemResourceLoader.java b/grails-bootstrap/src/main/groovy/org/grails/io/support/FileSystemResourceLoader.java index 6b791c3e631..c3e0b3c4883 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/io/support/FileSystemResourceLoader.java +++ b/grails-bootstrap/src/main/groovy/org/grails/io/support/FileSystemResourceLoader.java @@ -27,13 +27,13 @@ * to the current VM working directory, even if they start with a slash. * (This is consistent with the semantics in a Servlet container.) * Use an explicit "file:" prefix to enforce an absolute file path. - * + *

* is a full-fledged ApplicationContext implementation that provides * the same resource path resolution strategy. * * @author Juergen Hoeller - * @since 1.1.3 * @see DefaultResourceLoader + * @since 1.1.3 */ public class FileSystemResourceLoader extends DefaultResourceLoader { @@ -41,6 +41,7 @@ public class FileSystemResourceLoader extends DefaultResourceLoader { * Resolve resource paths as file system paths. *

Note: Even if a given path starts with a slash, it will get * interpreted as relative to the current VM working directory. + * * @param path the path to the resource * @return the corresponding Resource handle * @see FileSystemResource diff --git a/grails-bootstrap/src/main/groovy/org/grails/io/support/PathMatchingResourcePatternResolver.java b/grails-bootstrap/src/main/groovy/org/grails/io/support/PathMatchingResourcePatternResolver.java index 7205754f750..744db9b3df1 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/io/support/PathMatchingResourcePatternResolver.java +++ b/grails-bootstrap/src/main/groovy/org/grails/io/support/PathMatchingResourcePatternResolver.java @@ -31,7 +31,6 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; - /** * A ResourcePatternResolver implementation that is able to resolve a * specified resource location path into one or more matching Resources. @@ -142,14 +141,13 @@ * @author Colin Sampaleanu * @author Marius Bogoevici * @author Costin Leau - * @since 1.0.2 * @see java.lang.ClassLoader#getResources(String) + * @since 1.0.2 */ public class PathMatchingResourcePatternResolver { private static final String CLASSPATH_ALL_URL_PREFIX = "classpath*:"; - private final ResourceLoader resourceLoader; private AntPathMatcher pathMatcher = new AntPathMatcher(); @@ -164,9 +162,10 @@ public PathMatchingResourcePatternResolver() { /** * Create a new PathMatchingResourcePatternResolver with a DefaultResourceLoader. + * * @param classLoader the ClassLoader to load classpath resources with, - * or null for using the thread context class loader - * at the time of actual resource access + * or null for using the thread context class loader + * at the time of actual resource access */ public PathMatchingResourcePatternResolver(ClassLoader classLoader) { resourceLoader = new DefaultResourceLoader(classLoader); @@ -175,8 +174,9 @@ public PathMatchingResourcePatternResolver(ClassLoader classLoader) { /** * Create a new PathMatchingResourcePatternResolver. *

ClassLoader access will happen via the thread context class loader. + * * @param resourceLoader the ResourceLoader to load root directories and - * actual resources with + * actual resources with */ public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; @@ -234,11 +234,12 @@ public Resource[] getResources(String locationPattern) throws IOException { return findPathMatchingResources(locationPattern); } // a single resource with the given name - return new Resource[] {getResourceLoader().getResource(locationPattern)}; + return new Resource[]{getResourceLoader().getResource(locationPattern)}; } /** * Find all class location resources with the given location via the ClassLoader. + * * @param location the absolute path within the classpath * @return the result as Resource array * @throws IOException in case of I/O errors @@ -262,6 +263,7 @@ protected Resource[] findAllClassPathResources(String location) throws IOExcepti /** * Convert the given URL as returned from the ClassLoader into a Resource object. *

The default implementation simply creates a UrlResource instance. + * * @param url a URL as returned from the ClassLoader * @return the corresponding Resource object * @see java.lang.ClassLoader#getResources @@ -274,6 +276,7 @@ protected Resource convertClassLoaderURL(URL url) { * Find all resources that match the given location pattern via the * Ant-style PathMatcher. Supports resources in jar files and zip files * and in the file system. + * * @param locationPattern the location pattern to match * @return the result as Resource array * @throws IOException in case of I/O errors @@ -289,8 +292,7 @@ protected Resource[] findPathMatchingResources(String locationPattern) throws IO rootDirResource = resolveRootDirResource(rootDirResource); if (isJarResource(rootDirResource)) { result.addAll(doFindPathMatchingJarResources(rootDirResource, subPattern)); - } - else { + } else { result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern)); } } @@ -305,6 +307,7 @@ protected Resource[] findPathMatchingResources(String locationPattern) throws IO * remainder of the location as pattern. *

Will return "/WEB-INF/" for the pattern "/WEB-INF/*.xml", * for example. + * * @param location the location to check * @return the part of the location that denotes the root directory * @see #retrieveMatchingFiles @@ -326,6 +329,7 @@ protected String determineRootDir(String location) { *

The default implementation detects an Equinox OSGi "bundleresource:" * / "bundleentry:" URL and resolves it into a standard jar file URL that * can be traversed using Spring's standard jar file traversal algorithm. + * * @param original the resource to resolve * @return the resolved resource (may be identical to the passed-in resource) * @throws IOException in case of resolution failure @@ -340,8 +344,9 @@ protected Resource resolveRootDirResource(Resource original) throws IOException *

The default implementation checks against the URL protocols * "jar", "zip" and "wsjar" (the latter are used by BEA WebLogic Server * and IBM WebSphere, respectively, but can be treated like jar files). + * * @param resource the resource handle to check - * (usually the root directory to start path matching from) + * (usually the root directory to start path matching from) * @see #doFindPathMatchingJarResources */ protected boolean isJarResource(Resource resource) throws IOException { @@ -351,8 +356,9 @@ protected boolean isJarResource(Resource resource) throws IOException { /** * Find all resources in jar files that match the given location pattern * via the Ant-style PathMatcher. + * * @param rootDirResource the root directory as Resource - * @param subPattern the sub pattern to match (below the root directory) + * @param subPattern the sub pattern to match (below the root directory) * @return the Set of matching Resource instances * @throws IOException in case of I/O errors * @see java.net.JarURLConnection @@ -374,8 +380,7 @@ protected Set doFindPathMatchingJarResources(Resource rootDirResource, jarFileUrl = jarCon.getJarFileURL().toExternalForm(); JarEntry jarEntry = jarCon.getJarEntry(); rootEntryPath = (jarEntry != null ? jarEntry.getName() : ""); - } - else { + } else { // No JarURLConnection -> need to resort to URL file parsing. // We'll assume URLs of the format "jar:path!/entry", with the protocol // being arbitrary as long as following the entry format. @@ -386,8 +391,7 @@ protected Set doFindPathMatchingJarResources(Resource rootDirResource, jarFileUrl = urlFile.substring(0, separatorIndex); rootEntryPath = urlFile.substring(separatorIndex + GrailsResourceUtils.JAR_URL_SEPARATOR.length()); jarFile = getJarFile(jarFileUrl); - } - else { + } else { jarFile = new JarFile(urlFile); jarFileUrl = urlFile; rootEntryPath = ""; @@ -402,7 +406,7 @@ protected Set doFindPathMatchingJarResources(Resource rootDirResource, rootEntryPath = rootEntryPath + "/"; } Set result = new LinkedHashSet(8); - for (Enumeration entries = jarFile.entries(); entries.hasMoreElements();) { + for (Enumeration entries = jarFile.entries(); entries.hasMoreElements(); ) { JarEntry entry = entries.nextElement(); String entryPath = entry.getName(); if (entryPath.startsWith(rootEntryPath)) { @@ -413,8 +417,7 @@ protected Set doFindPathMatchingJarResources(Resource rootDirResource, } } return result; - } - finally { + } finally { // Close jar file, but only if freshly obtained - // not from JarURLConnection, which might cache the file reference. if (newJarFile) { @@ -430,8 +433,7 @@ protected JarFile getJarFile(String jarFileUrl) throws IOException { if (jarFileUrl.startsWith(GrailsResourceUtils.FILE_URL_PREFIX)) { try { return new JarFile(GrailsResourceUtils.toURI(jarFileUrl).getSchemeSpecificPart()); - } - catch (URISyntaxException ex) { + } catch (URISyntaxException ex) { // Fallback for URLs that are not valid URIs (should hardly ever happen). return new JarFile(jarFileUrl.substring(GrailsResourceUtils.FILE_URL_PREFIX.length())); } @@ -442,8 +444,9 @@ protected JarFile getJarFile(String jarFileUrl) throws IOException { /** * Find all resources in the file system that match the given location pattern * via the Ant-style PathMatcher. + * * @param rootDirResource the root directory as Resource - * @param subPattern the sub pattern to match (below the root directory) + * @param subPattern the sub pattern to match (below the root directory) * @return the Set of matching Resource instances * @throws IOException in case of I/O errors * @see #retrieveMatchingFiles @@ -454,8 +457,7 @@ protected Set doFindPathMatchingFileResources(Resource rootDirResource File rootDir; try { rootDir = rootDirResource.getFile().getAbsoluteFile(); - } - catch (IOException ex) { + } catch (IOException ex) { return Collections.emptySet(); } return doFindMatchingFileSystemResources(rootDir, subPattern); @@ -464,7 +466,8 @@ protected Set doFindPathMatchingFileResources(Resource rootDirResource /** * Find all resources in the file system that match the given location pattern * via the Ant-style PathMatcher. - * @param rootDir the root directory in the file system + * + * @param rootDir the root directory in the file system * @param subPattern the sub pattern to match (below the root directory) * @return the Set of matching Resource instances * @throws IOException in case of I/O errors @@ -482,9 +485,10 @@ protected Set doFindMatchingFileSystemResources(File rootDir, String s /** * Retrieve files that match the given path pattern, * checking the given directory and its subdirectories. + * * @param rootDir the directory to start from * @param pattern the pattern to match against, - * relative to the root directory + * relative to the root directory * @return the Set of matching File instances * @throws IOException if directory contents could not be retrieved */ @@ -500,7 +504,7 @@ protected Set retrieveMatchingFiles(File rootDir, String pattern) throws I if (!rootDir.canRead()) { return Collections.emptySet(); } - String fullPattern = rootDir.getAbsolutePath().replace( File.separator, "/"); + String fullPattern = rootDir.getAbsolutePath().replace(File.separator, "/"); if (!pattern.startsWith("/")) { fullPattern += "/"; } @@ -513,10 +517,11 @@ protected Set retrieveMatchingFiles(File rootDir, String pattern) throws I /** * Recursively retrieve files that match the given pattern, * adding them to the given result list. + * * @param fullPattern the pattern to match against, - * with prepended root directory path - * @param dir the current directory - * @param result the Set of matching File instances to add to + * with prepended root directory path + * @param dir the current directory + * @param result the Set of matching File instances to add to * @throws IOException if directory contents could not be retrieved */ protected void doRetrieveMatchingFiles(String fullPattern, File dir, Set result) throws IOException { @@ -525,7 +530,7 @@ protected void doRetrieveMatchingFiles(String fullPattern, File dir, Set r return; } for (File content : dirContents) { - String currPath = content.getAbsolutePath().replace( File.separator, "/"); + String currPath = content.getAbsolutePath().replace(File.separator, "/"); if (content.isDirectory() && getPathMatcher().matchStart(fullPattern, currPath + "/")) { if (content.canRead()) { doRetrieveMatchingFiles(fullPattern, content, result); diff --git a/grails-bootstrap/src/main/groovy/org/grails/io/support/ResourceLocator.java b/grails-bootstrap/src/main/groovy/org/grails/io/support/ResourceLocator.java index cc753ad6581..6b3e4267cce 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/io/support/ResourceLocator.java +++ b/grails-bootstrap/src/main/groovy/org/grails/io/support/ResourceLocator.java @@ -36,6 +36,7 @@ * @since 3.0 */ public class ResourceLocator { + public static final String WILDCARD = "*"; public static final String FILE_SEPARATOR = File.separator; public static final String CLOSURE_MARKER = "$"; @@ -48,7 +49,7 @@ public class ResourceLocator { protected List resourceSearchDirectories = new ArrayList(); protected Map classNameToResourceCache = new ConcurrentHashMap(); protected Map uriToResourceCache = new ConcurrentHashMap(); - protected ResourceLoader defaultResourceLoader = new FileSystemResourceLoader(); + protected ResourceLoader defaultResourceLoader = new FileSystemResourceLoader(); protected boolean warDeployed = Environment.isWarDeployed(); public void setSearchLocation(String searchLocation) { @@ -100,16 +101,14 @@ public Resource findResourceForURI(String uri) { if (defaultResource != null && defaultResource.exists()) { resource = defaultResource; } - } - else { + } else { String uriWebAppRelative = WEB_APP_DIR + uri; for (String resourceSearchDirectory : resourceSearchDirectories) { Resource res = resolveExceptionSafe(resourceSearchDirectory + uriWebAppRelative); if (res.exists()) { resource = res; - } - else if (!warDeployed) { + } else if (!warDeployed) { Resource dir = resolveExceptionSafe(resourceSearchDirectory); if (dir.exists() && info != null) { String filename = dir.getFilename(); @@ -124,7 +123,6 @@ else if (!warDeployed) { } } - if (resource == null || !resource.exists()) { Resource tmp = defaultResourceLoader != null ? defaultResourceLoader.getResource(uri) : null; if (tmp != null && tmp.exists()) { @@ -134,15 +132,13 @@ else if (!warDeployed) { if (resource != null) { uriToResourceCache.put(uri, resource); - } - else if (warDeployed) { + } else if (warDeployed) { uriToResourceCache.put(uri, NULL_RESOURCE); } } return resource == NULL_RESOURCE ? null : resource; } - private PluginResourceInfo inferPluginNameFromURI(String uri) { if (uri.startsWith("/plugins/")) { String withoutPluginsPath = uri.substring("/plugins/".length(), uri.length()); @@ -173,7 +169,7 @@ public Resource findResourceForClassName(String className) { } } if (resource == null || !resource.exists()) { - for(String ext : new String[]{".groovy", ".java"}) { + for (String ext : new String[]{".groovy", ".java"}) { resource = resolveExceptionSafe(GrailsResourceUtils.DOMAIN_DIR_PATH + "**/" + className + ext); if (resource != null && resource.exists()) { classNameToResourceCache.put(className, resource); @@ -214,8 +210,8 @@ public void setResourceLoader(ResourceLoader resourceLoader) { defaultResourceLoader = resourceLoader; } - class PluginResourceInfo { + String pluginName; String uri; } diff --git a/grails-bootstrap/src/main/groovy/org/grails/io/support/StaticResourceLoader.java b/grails-bootstrap/src/main/groovy/org/grails/io/support/StaticResourceLoader.java index 08630df9357..39f9e19ae3f 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/io/support/StaticResourceLoader.java +++ b/grails-bootstrap/src/main/groovy/org/grails/io/support/StaticResourceLoader.java @@ -18,7 +18,6 @@ */ package org.grails.io.support; - /** * Loads relative to a static base resource * diff --git a/grails-bootstrap/src/main/groovy/org/grails/io/watch/AbstractDirectoryWatcher.java b/grails-bootstrap/src/main/groovy/org/grails/io/watch/AbstractDirectoryWatcher.java index 83ff54b689d..e6b57acde82 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/io/watch/AbstractDirectoryWatcher.java +++ b/grails-bootstrap/src/main/groovy/org/grails/io/watch/AbstractDirectoryWatcher.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.io.watch; import java.io.File; @@ -24,19 +23,20 @@ import java.util.Collection; import java.util.List; - /** * Backend for {@link DirectoryWatcher} + * * @author Craig Andrews - * @since 2.4 * @see WatchServiceDirectoryWatcher * @see PollingDirectoryWatcher * @see DirectoryWatcher + * @since 2.4 */ abstract class AbstractDirectoryWatcher implements Runnable { - private List listeners = new ArrayList(); - volatile protected boolean active = true; //must be volatile as it's read by multiple threads and the value should be reflected in all of them + protected long sleepTime = 1000; + protected volatile boolean active = true; //must be volatile as it's read by multiple threads and the value should be reflected in all of them + private List listeners = new ArrayList(); /** * Sets whether to stop the directory watcher @@ -44,7 +44,7 @@ abstract class AbstractDirectoryWatcher implements Runnable { * @param active False if you want to stop watching */ public void setActive(boolean active) { - this.active = active; + this.active = active; } /** @@ -85,7 +85,7 @@ public void removeListener(DirectoryWatcher.FileChangeListener listener) { * Adds a directory to watch for the given file and extensions. * No String in the fileExtensions list can start with a dot (DirectoryWatcher guarantees that) * - * @param dir The directory + * @param dir The directory * @param fileExtensions The extensions */ public abstract void addWatchDirectory(File dir, List fileExtensions); @@ -102,8 +102,8 @@ protected void fireOnNew(File file) { } } - protected boolean isValidDirectoryToMonitor(File file){ - return file.isDirectory() && ! file.isHidden() && !file.getName().startsWith("."); + protected boolean isValidDirectoryToMonitor(File file) { + return file.isDirectory() && !file.isHidden() && !file.getName().startsWith("."); } protected boolean isValidFileToMonitor(File file, Collection fileExtensions) { @@ -111,7 +111,7 @@ protected boolean isValidFileToMonitor(File file, Collection fileExtensi String path = file.getAbsolutePath(); boolean isSvnFile = path.indexOf(File.separator + DirectoryWatcher.SVN_DIR_NAME + File.separator) > 0; return !isSvnFile && - !file.isDirectory() && + !file.isDirectory() && !file.isHidden() && !file.getName().startsWith(".") && (fileExtensions.contains("*") || fileExtensions.contains(getFilenameExtension(name))); @@ -120,6 +120,7 @@ protected boolean isValidFileToMonitor(File file, Collection fileExtensi /** * Extract the filename extension from the given path, * e.g. "mypath/myfile.txt" -> "txt". + * * @param path the file path (may be {@code null}) * @return the extracted filename extension, or {@code null} if none */ diff --git a/grails-bootstrap/src/main/groovy/org/grails/io/watch/DirectoryWatcher.java b/grails-bootstrap/src/main/groovy/org/grails/io/watch/DirectoryWatcher.java index 52a56dfd8d3..6fc68d44596 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/io/watch/DirectoryWatcher.java +++ b/grails-bootstrap/src/main/groovy/org/grails/io/watch/DirectoryWatcher.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.io.watch; import org.slf4j.Logger; @@ -34,11 +33,9 @@ */ public class DirectoryWatcher extends Thread { - private static final Logger LOG = LoggerFactory.getLogger(DirectoryWatcher.class); - - private final AbstractDirectoryWatcher directoryWatcherDelegate; - public static final String SVN_DIR_NAME = ".svn"; + private static final Logger LOG = LoggerFactory.getLogger(DirectoryWatcher.class); + private final AbstractDirectoryWatcher directoryWatcherDelegate; /** * Constructor. Automatically selects the best means of watching for file system changes. @@ -47,29 +44,29 @@ public DirectoryWatcher() { setDaemon(true); AbstractDirectoryWatcher directoryWatcherDelegate; try { - if(System.getProperty("os.name").equals("Mac OS X")) { + if (System.getProperty("os.name").equals("Mac OS X")) { Boolean jnaAvailable = false; try { - Class.forName( "com.sun.jna.Pointer" ); + Class.forName("com.sun.jna.Pointer"); jnaAvailable = true; - } catch( ClassNotFoundException e ) { - if(LOG.isWarnEnabled()) { - LOG.warn("Error Initializing Native OS X File Event Watcher. Add JNA to classpath for Faster File Watching performance."); + } catch (ClassNotFoundException e) { + if (LOG.isWarnEnabled()) { + LOG.warn("Error Initializing Native OS X File Event Watcher. Add JNA to classpath for Faster File Watching performance."); } - + } - if(jnaAvailable) { + if (jnaAvailable) { directoryWatcherDelegate = (AbstractDirectoryWatcher) Class.forName("org.grails.io.watch.MacOsWatchServiceDirectoryWatcher").newInstance(); } else { - directoryWatcherDelegate = (AbstractDirectoryWatcher) Class.forName("org.grails.io.watch.WatchServiceDirectoryWatcher").newInstance(); + directoryWatcherDelegate = (AbstractDirectoryWatcher) Class.forName("org.grails.io.watch.WatchServiceDirectoryWatcher").newInstance(); } } else { - directoryWatcherDelegate = (AbstractDirectoryWatcher) Class.forName("org.grails.io.watch.WatchServiceDirectoryWatcher").newInstance(); + directoryWatcherDelegate = (AbstractDirectoryWatcher) Class.forName("org.grails.io.watch.WatchServiceDirectoryWatcher").newInstance(); } - } catch (Throwable e) { - LOG.info("Exception while trying to load WatchServiceDirectoryWatcher (this is probably Java 6 and WatchService isn't available). Falling back to PollingDirectoryWatcher.", e); - directoryWatcherDelegate = new PollingDirectoryWatcher(); - } + } catch (Throwable e) { + LOG.info("Exception while trying to load WatchServiceDirectoryWatcher (this is probably Java 6 and WatchService isn't available). Falling back to PollingDirectoryWatcher.", e); + directoryWatcherDelegate = new PollingDirectoryWatcher(); + } this.directoryWatcherDelegate = directoryWatcherDelegate; } @@ -79,7 +76,7 @@ public DirectoryWatcher() { * @param active False if you want to stop watching */ public void setActive(boolean active) { - directoryWatcherDelegate.setActive(active); + directoryWatcherDelegate.setActive(active); } /** @@ -88,7 +85,7 @@ public void setActive(boolean active) { * @param sleepTime The sleep time */ public void setSleepTime(long sleepTime) { - directoryWatcherDelegate.setSleepTime(sleepTime); + directoryWatcherDelegate.setSleepTime(sleepTime); } /** @@ -97,7 +94,7 @@ public void setSleepTime(long sleepTime) { * @param listener The file listener */ public void addListener(FileChangeListener listener) { - directoryWatcherDelegate.addListener(listener); + directoryWatcherDelegate.addListener(listener); } /** @@ -115,36 +112,36 @@ public void removeListener(FileChangeListener listener) { * @param fileToWatch The file to watch */ public void addWatchFile(File fileToWatch) { - directoryWatcherDelegate.addWatchFile(fileToWatch); + directoryWatcherDelegate.addWatchFile(fileToWatch); } /** * Adds a directory to watch for the given file and extensions. * - * @param dir The directory + * @param dir The directory * @param fileExtensions The extensions */ public void addWatchDirectory(File dir, List fileExtensions) { - List fileExtensionsWithoutDot = new ArrayList(fileExtensions.size()); - for(String fileExtension : fileExtensions){ - fileExtensionsWithoutDot.add(removeStartingDotIfPresent(fileExtension)); - } - directoryWatcherDelegate.addWatchDirectory(dir, fileExtensions); + List fileExtensionsWithoutDot = new ArrayList(fileExtensions.size()); + for (String fileExtension : fileExtensions) { + fileExtensionsWithoutDot.add(removeStartingDotIfPresent(fileExtension)); + } + directoryWatcherDelegate.addWatchDirectory(dir, fileExtensions); } /** - * Adds a directory to watch for the given file. All files and subdirectories in the directory will be watched. + * Adds a directory to watch for the given file. All files and subdirectories in the directory will be watched. * * @param dir The directory */ public void addWatchDirectory(File dir) { - addWatchDirectory(dir, "*"); + addWatchDirectory(dir, "*"); } /** * Adds a directory to watch for the given file and extensions. * - * @param dir The directory + * @param dir The directory * @param extension The extension */ public void addWatchDirectory(File dir, String extension) { @@ -152,21 +149,33 @@ public void addWatchDirectory(File dir, String extension) { List fileExtensions = new ArrayList(); if (extension != null && extension.length() > 0) { int i = extension.lastIndexOf('.'); - if(i > -1) { + if (i > -1) { extension = extension.substring(i + 1); } fileExtensions.add(extension); - } - else { + } else { fileExtensions.add("*"); } addWatchDirectory(dir, fileExtensions); } + @Override + public void run() { + directoryWatcherDelegate.run(); + } + + private String removeStartingDotIfPresent(String extension) { + if (extension.startsWith(".")) { + extension = extension.substring(1); + } + return extension; + } + /** * Interface for FileChangeListeners */ public static interface FileChangeListener { + /** * Fired when a file changes * @@ -181,16 +190,4 @@ public static interface FileChangeListener { */ void onNew(File file); } - - @Override - public void run() { - directoryWatcherDelegate.run(); - } - - private String removeStartingDotIfPresent(String extension) { - if (extension.startsWith(".")) { - extension = extension.substring(1); - } - return extension; - } } diff --git a/grails-bootstrap/src/main/groovy/org/grails/io/watch/FileExtensionFileChangeListener.groovy b/grails-bootstrap/src/main/groovy/org/grails/io/watch/FileExtensionFileChangeListener.groovy index 8e38c2cadf9..47ad0fe301f 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/io/watch/FileExtensionFileChangeListener.groovy +++ b/grails-bootstrap/src/main/groovy/org/grails/io/watch/FileExtensionFileChangeListener.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.io.watch import groovy.transform.CompileStatic @@ -38,7 +37,7 @@ abstract class FileExtensionFileChangeListener implements DirectoryWatcher.FileC @Override final void onChange(File file) { - if(file && extensions.any() { String ext -> file.name.endsWith( ext ) } ) { + if (file && extensions.any() { String ext -> file.name.endsWith(ext) }) { onChange(file, extensions) } } @@ -47,7 +46,7 @@ abstract class FileExtensionFileChangeListener implements DirectoryWatcher.FileC @Override final void onNew(File file) { - if(file && extensions.any() { String ext -> file.name.endsWith( ext ) } ) { + if (file && extensions.any() { String ext -> file.name.endsWith(ext) }) { onNew(file, extensions) } } diff --git a/grails-bootstrap/src/main/groovy/org/grails/io/watch/MacOsWatchServiceDirectoryWatcher.java b/grails-bootstrap/src/main/groovy/org/grails/io/watch/MacOsWatchServiceDirectoryWatcher.java index 9120c534c54..963cf194cb1 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/io/watch/MacOsWatchServiceDirectoryWatcher.java +++ b/grails-bootstrap/src/main/groovy/org/grails/io/watch/MacOsWatchServiceDirectoryWatcher.java @@ -16,55 +16,68 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.io.watch; -import java.nio.file.WatchEvent.Kind; import io.methvin.watchservice.MacOSXListeningWatchService; import io.methvin.watchservice.WatchablePath; -import static io.methvin.watcher.DirectoryChangeEvent.EventType.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import java.io.File; import java.io.IOException; -import java.nio.file.*; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.WatchEvent; +import java.nio.file.WatchEvent.Kind; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; import java.nio.file.attribute.BasicFileAttributes; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** * Implementation of a {@link AbstractDirectoryWatcher} that uses {@link java.nio.WatchService}. * This implementation is used for Java 7 and later. + * * @author Eric Helgeson * @author David Estes - * @since 3.2 * @see DirectoryWatcher + * @since 3.2 */ class MacOsWatchServiceDirectoryWatcher extends AbstractDirectoryWatcher { - private static final Logger LOG = LoggerFactory.getLogger(MacOsWatchServiceDirectoryWatcher.class); + private static final Logger LOG = LoggerFactory.getLogger(MacOsWatchServiceDirectoryWatcher.class); private Map> watchKeyToExtensionsMap = new ConcurrentHashMap>(); private Set individualWatchedFiles = new HashSet(); - private final WatchService watchService; + private final WatchService watchService; + + public MacOsWatchServiceDirectoryWatcher() { + try { + watchService = new MacOSXListeningWatchService(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } @SuppressWarnings("unchecked") private static WatchEvent cast(WatchEvent event) { - return (WatchEvent)event; + return (WatchEvent) event; } - public MacOsWatchServiceDirectoryWatcher(){ - try { - watchService = new MacOSXListeningWatchService(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - public void run() { + @Override + public void run() { while (active) { - try { + try { WatchKey watchKey; try { watchKey = watchService.take(); @@ -81,17 +94,16 @@ public void run() { WatchEvent pathWatchEvent = cast(watchEvent); Path child = pathWatchEvent.context(); File childFile = child.toFile(); - if(individualWatchedFiles.contains(child) || individualWatchedFiles.contains(child.normalize())){ - if(kind == StandardWatchEventKinds.ENTRY_CREATE){ + if (individualWatchedFiles.contains(child) || individualWatchedFiles.contains(child.normalize())) { + if (kind == StandardWatchEventKinds.ENTRY_CREATE) { fireOnNew(childFile); - }else if(kind == StandardWatchEventKinds.ENTRY_MODIFY){ + } else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) { fireOnChange(childFile); - }else if(kind == StandardWatchEventKinds.ENTRY_DELETE){ - // do nothing... there's no way to communicate deletions - } - }else{ + } // else if (kind == StandardWatchEventKinds.ENTRY_DELETE) + // do nothing... there's no way to communicate deletions + } else { List fileExtensions = watchKeyToExtensionsMap.get(watchKey); - if(fileExtensions==null){ + if (fileExtensions == null) { // this event didn't match a file in individualWatchedFiles so it's a not an individual file we're interested in // this event also didn't match a directory that we're interested in (if it did, fileExtentions wouldn't be null) // so it must be event for a file we're not interested in. An example of how this can happen is: @@ -102,98 +114,100 @@ public void run() { // Now, /images/b.png is changed. Because java.nio.file.WatchService watches directories, it gets a WatchEvent // for /images/b.png. But we aren't interested in that. LOG.debug("WatchService received an event for a file/directory that it's not interested in."); - }else{ - if(kind==StandardWatchEventKinds.ENTRY_CREATE){ + } else { + if (kind == StandardWatchEventKinds.ENTRY_CREATE) { // new directory created, so watch its contents - addWatchDirectory(child,fileExtensions); - if(childFile.isDirectory() && childFile.exists()) { + addWatchDirectory(child, fileExtensions); + if (childFile.isDirectory() && childFile.exists()) { final File[] files = childFile.listFiles(); - if(files != null) { + if (files != null) { for (File newFile : files) { - if(isValidFileToMonitor(newFile, fileExtensions)) { + if (isValidFileToMonitor(newFile, fileExtensions)) { fireOnNew(newFile); } } } } } - if(isValidFileToMonitor(childFile,fileExtensions)){ - if(kind == StandardWatchEventKinds.ENTRY_CREATE){ + if (isValidFileToMonitor(childFile, fileExtensions)) { + if (kind == StandardWatchEventKinds.ENTRY_CREATE) { fireOnNew(childFile); - }else if(kind == StandardWatchEventKinds.ENTRY_MODIFY){ + } else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) { fireOnChange(childFile); - }else if(kind == StandardWatchEventKinds.ENTRY_DELETE){ - // do nothing... there's no way to communicate deletions - } + } // else if (kind == StandardWatchEventKinds.ENTRY_DELETE) + // do nothing... there's no way to communicate deletions } } } } watchKey.reset(); - } catch (Exception e) { + } catch (Exception e) { LOG.error(e.toString()); // ignore - } + } } try { - watchService.close(); - } catch (IOException e) { - LOG.debug("Exception while closing watchService", e); - } - } + watchService.close(); + } catch (IOException e) { + LOG.debug("Exception while closing watchService", e); + } + } - @Override - public void addWatchFile(File fileToWatch) { - if(!isValidFileToMonitor(fileToWatch, Arrays.asList("*"))) return; - try { - if(!fileToWatch.exists()) return; - Path pathToWatch = fileToWatch.toPath().toAbsolutePath(); - individualWatchedFiles.add(pathToWatch); + @Override + public void addWatchFile(File fileToWatch) { + if (!isValidFileToMonitor(fileToWatch, Arrays.asList("*"))) { + return; + } + try { + if (!fileToWatch.exists()) { + return; + } + Path pathToWatch = fileToWatch.toPath().toAbsolutePath(); + individualWatchedFiles.add(pathToWatch); WatchablePath watchPath = new WatchablePath(pathToWatch); - Kind[] events = new Kind[] { StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY }; - watchPath.register(watchService, events); - } catch (IOException e) { - throw new RuntimeException(e); - } - } + Kind[] events = new Kind[]{StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY}; + watchPath.register(watchService, events); + } catch (IOException e) { + throw new RuntimeException(e); + } + } - @Override - public void addWatchDirectory(File dir, final List fileExtensions) { - Path dirPath = dir.toPath(); - addWatchDirectory(dirPath, fileExtensions); - } + @Override + public void addWatchDirectory(File dir, final List fileExtensions) { + Path dirPath = dir.toPath(); + addWatchDirectory(dirPath, fileExtensions); + } - private void addWatchDirectory(Path dir, final List fileExtensions) { - if(!isValidDirectoryToMonitor(dir.toFile())){ - return; - } - try { - //add the subdirectories too - Files.walkFileTree(dir, new SimpleFileVisitor() { - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) - throws IOException - { - if(!isValidDirectoryToMonitor(dir.toFile())){ - return FileVisitResult.SKIP_SUBTREE; - } + private void addWatchDirectory(Path dir, final List fileExtensions) { + if (!isValidDirectoryToMonitor(dir.toFile())) { + return; + } + try { + //add the subdirectories too + Files.walkFileTree(dir, new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) + throws IOException { + if (!isValidDirectoryToMonitor(dir.toFile())) { + return FileVisitResult.SKIP_SUBTREE; + } WatchablePath watchPath = new WatchablePath(dir); - Kind[] events = new Kind[] { StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY }; - WatchKey watchKey = watchPath.register(watchService, events); - final List originalFileExtensions = watchKeyToExtensionsMap.get(watchKey); - if(originalFileExtensions==null){ - watchKeyToExtensionsMap.put(watchKey, fileExtensions); - }else{ - final HashSet newFileExtensions = new HashSet(originalFileExtensions); - newFileExtensions.addAll(fileExtensions); - watchKeyToExtensionsMap.put(watchKey, Collections.unmodifiableList(new ArrayList(newFileExtensions))); - } - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - throw new RuntimeException(e); - } - } + Kind[] events = new Kind[]{StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY}; + WatchKey watchKey = watchPath.register(watchService, events); + final List originalFileExtensions = watchKeyToExtensionsMap.get(watchKey); + if (originalFileExtensions == null) { + watchKeyToExtensionsMap.put(watchKey, fileExtensions); + } else { + final HashSet newFileExtensions = new HashSet(originalFileExtensions); + newFileExtensions.addAll(fileExtensions); + watchKeyToExtensionsMap.put(watchKey, Collections.unmodifiableList(new ArrayList(newFileExtensions))); + } + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/grails-bootstrap/src/main/groovy/org/grails/io/watch/PollingDirectoryWatcher.java b/grails-bootstrap/src/main/groovy/org/grails/io/watch/PollingDirectoryWatcher.java index 94090900f8c..bb169aa709e 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/io/watch/PollingDirectoryWatcher.java +++ b/grails-bootstrap/src/main/groovy/org/grails/io/watch/PollingDirectoryWatcher.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.io.watch; import java.io.File; @@ -31,10 +30,11 @@ /** * Implementation of a {@link AbstractDirectoryWatcher} that uses polling. * This implementation is used where {@link java.nio.WatchService} isn't available (pre Java 7). + * * @author Craig Andrews - * @since 2.4 * @see WatchServiceDirectoryWatcher * @see DirectoryWatcher + * @since 2.4 */ class PollingDirectoryWatcher extends AbstractDirectoryWatcher { @@ -44,8 +44,8 @@ class PollingDirectoryWatcher extends AbstractDirectoryWatcher { private Map> directoryToExtensionsMap = new ConcurrentHashMap>(); private Map directoryWatch = new ConcurrentHashMap(); - @Override - public void run() { + @Override + public void run() { int count = 0; while (active) { Set files = lastModifiedMap.keySet(); @@ -68,28 +68,27 @@ public void run() { // ignore } } - } + } - @Override - public void addWatchFile(File fileToWatch) { + @Override + public void addWatchFile(File fileToWatch) { lastModifiedMap.put(fileToWatch, fileToWatch.lastModified()); - } + } - @Override - public void addWatchDirectory(File dir, List fileExtensions) { - if(!isValidDirectoryToMonitor(dir)){ - return; - } + @Override + public void addWatchDirectory(File dir, List fileExtensions) { + if (!isValidDirectoryToMonitor(dir)) { + return; + } trackDirectoryExtensions(dir, fileExtensions); cacheFilesForDirectory(dir, fileExtensions, false); - } + } private void trackDirectoryExtensions(File dir, List fileExtensions) { Collection existingExtensions = directoryToExtensionsMap.get(dir); - if(existingExtensions == null) { + if (existingExtensions == null) { directoryToExtensionsMap.put(dir, new ArrayList(fileExtensions)); - } - else { + } else { existingExtensions.addAll(fileExtensions); } } @@ -100,7 +99,7 @@ private void checkForNewFiles() { if (currentTimestamp < directory.lastModified()) { Collection extensions = directoryToExtensionsMap.get(directory); - if(extensions == null) { + if (extensions == null) { extensions = this.extensions; } cacheFilesForDirectory(directory, extensions, true); @@ -118,10 +117,9 @@ private void cacheFilesForDirectory(File directory, Collection fileExten } for (File file : files) { - if(isValidDirectoryToMonitor(file)) { + if (isValidDirectoryToMonitor(file)) { cacheFilesForDirectory(file, fileExtensions, fireEvent); - } - else if (isValidFileToMonitor(file, fileExtensions)) { + } else if (isValidFileToMonitor(file, fileExtensions)) { if (!lastModifiedMap.containsKey(file) && fireEvent) { fireOnNew(file); } diff --git a/grails-bootstrap/src/main/groovy/org/grails/io/watch/WatchServiceDirectoryWatcher.java b/grails-bootstrap/src/main/groovy/org/grails/io/watch/WatchServiceDirectoryWatcher.java index 60dc0bb8b99..072dcdec41f 100644 --- a/grails-bootstrap/src/main/groovy/org/grails/io/watch/WatchServiceDirectoryWatcher.java +++ b/grails-bootstrap/src/main/groovy/org/grails/io/watch/WatchServiceDirectoryWatcher.java @@ -16,9 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.io.watch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.File; import java.io.IOException; import java.nio.file.FileSystems; @@ -31,8 +33,8 @@ import java.nio.file.WatchKey; import java.nio.file.WatchService; import java.nio.file.attribute.BasicFileAttributes; -import java.util.Arrays; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -41,166 +43,165 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * Implementation of a {@link AbstractDirectoryWatcher} that uses {@link java.nio.WatchService}. * This implementation is used for Java 7 and later. + * * @author Craig Andrews - * @since 2.4 * @see WatchServiceDirectoryWatcher * @see DirectoryWatcher + * @since 2.4 */ class WatchServiceDirectoryWatcher extends AbstractDirectoryWatcher { - private static final Logger LOG = LoggerFactory.getLogger(WatchServiceDirectoryWatcher.class); + private static final Logger LOG = LoggerFactory.getLogger(WatchServiceDirectoryWatcher.class); private Map> watchKeyToExtensionsMap = new ConcurrentHashMap>(); private Set individualWatchedFiles = new HashSet(); - private final WatchService watchService; + private final WatchService watchService; + + public WatchServiceDirectoryWatcher() { + try { + watchService = FileSystems.getDefault().newWatchService(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } @SuppressWarnings("unchecked") private static WatchEvent cast(WatchEvent event) { - return (WatchEvent)event; + return (WatchEvent) event; } - public WatchServiceDirectoryWatcher(){ - try { - watchService = FileSystems.getDefault().newWatchService(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public void run() { + @Override + public void run() { while (active) { - try { - WatchKey watchKey = watchService.poll(sleepTime, TimeUnit.MILLISECONDS); - if(watchKey!=null){ - List> watchEvents = watchKey.pollEvents(); - for(WatchEvent watchEvent : watchEvents){ - WatchEvent.Kind kind = watchEvent.kind(); - if (kind == StandardWatchEventKinds.OVERFLOW) { - // TODO how is this supposed to be handled? I think the best thing to do is ignore it, but I'm not positive - LOG.warn("WatchService Overflow occurred"); - continue; - } - WatchEvent pathWatchEvent = cast(watchEvent); - Path name = pathWatchEvent.context(); - Path dir = (Path) watchKey.watchable(); - Path child = dir.resolve(name).toAbsolutePath(); - File childFile = child.toFile(); - if(individualWatchedFiles.contains(child) || individualWatchedFiles.contains(child.normalize())){ - if(kind == StandardWatchEventKinds.ENTRY_CREATE){ - fireOnNew(childFile); - }else if(kind == StandardWatchEventKinds.ENTRY_MODIFY){ - fireOnChange(childFile); - }else if(kind == StandardWatchEventKinds.ENTRY_DELETE){ - // do nothing... there's no way to communicate deletions - } - }else{ - List fileExtensions = watchKeyToExtensionsMap.get(watchKey); - if(fileExtensions==null){ - // this event didn't match a file in individualWatchedFiles so it's a not an individual file we're interested in - // this event also didn't match a directory that we're interested in (if it did, fileExtentions wouldn't be null) - // so it must be event for a file we're not interested in. An example of how this can happen is: - // there's a directory with files in it like this: - // /images/a.png - // /images/b.png - // by using the addWatchFile method, /images/a.png is watched. - // Now, /images/b.png is changed. Because java.nio.file.WatchService watches directories, it gets a WatchEvent - // for /images/b.png. But we aren't interested in that. - LOG.debug("WatchService received an event for a file/directory that it's not interested in."); - }else{ - if(kind==StandardWatchEventKinds.ENTRY_CREATE){ - // new directory created, so watch its contents - addWatchDirectory(child,fileExtensions); - if(childFile.isDirectory() && childFile.exists()) { - final File[] files = childFile.listFiles(); - if(files != null) { - for (File newFile : files) { - if(isValidFileToMonitor(newFile, fileExtensions)) { - fireOnNew(newFile); - } - } - } - } - } - if(isValidFileToMonitor(childFile,fileExtensions)){ - if(kind == StandardWatchEventKinds.ENTRY_CREATE){ - fireOnNew(childFile); - }else if(kind == StandardWatchEventKinds.ENTRY_MODIFY){ - fireOnChange(childFile); - }else if(kind == StandardWatchEventKinds.ENTRY_DELETE){ - // do nothing... there's no way to communicate deletions - } - } - } - } - } - watchKey.reset(); - } - } catch (InterruptedException e) { - // ignore - } + try { + WatchKey watchKey = watchService.poll(sleepTime, TimeUnit.MILLISECONDS); + if (watchKey != null) { + List> watchEvents = watchKey.pollEvents(); + for (WatchEvent watchEvent : watchEvents) { + WatchEvent.Kind kind = watchEvent.kind(); + if (kind == StandardWatchEventKinds.OVERFLOW) { + // TODO how is this supposed to be handled? I think the best thing to do is ignore it, but I'm not positive + LOG.warn("WatchService Overflow occurred"); + continue; + } + WatchEvent pathWatchEvent = cast(watchEvent); + Path name = pathWatchEvent.context(); + Path dir = (Path) watchKey.watchable(); + Path child = dir.resolve(name).toAbsolutePath(); + File childFile = child.toFile(); + if (individualWatchedFiles.contains(child) || individualWatchedFiles.contains(child.normalize())) { + if (kind == StandardWatchEventKinds.ENTRY_CREATE) { + fireOnNew(childFile); + } else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) { + fireOnChange(childFile); + } // else if (kind == StandardWatchEventKinds.ENTRY_DELETE) { + // do nothing... there's no way to communicate deletions + } else { + List fileExtensions = watchKeyToExtensionsMap.get(watchKey); + if (fileExtensions == null) { + // this event didn't match a file in individualWatchedFiles so it's a not an individual file we're interested in + // this event also didn't match a directory that we're interested in (if it did, fileExtentions wouldn't be null) + // so it must be event for a file we're not interested in. An example of how this can happen is: + // there's a directory with files in it like this: + // /images/a.png + // /images/b.png + // by using the addWatchFile method, /images/a.png is watched. + // Now, /images/b.png is changed. Because java.nio.file.WatchService watches directories, it gets a WatchEvent + // for /images/b.png. But we aren't interested in that. + LOG.debug("WatchService received an event for a file/directory that it's not interested in."); + } else { + if (kind == StandardWatchEventKinds.ENTRY_CREATE) { + // new directory created, so watch its contents + addWatchDirectory(child, fileExtensions); + if (childFile.isDirectory() && childFile.exists()) { + final File[] files = childFile.listFiles(); + if (files != null) { + for (File newFile : files) { + if (isValidFileToMonitor(newFile, fileExtensions)) { + fireOnNew(newFile); + } + } + } + } + } + if (isValidFileToMonitor(childFile, fileExtensions)) { + if (kind == StandardWatchEventKinds.ENTRY_CREATE) { + fireOnNew(childFile); + } else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) { + fireOnChange(childFile); + } // else if (kind == StandardWatchEventKinds.ENTRY_DELETE) { + // do nothing... there's no way to communicate deletions + } + } + } + } + watchKey.reset(); + } + } catch (InterruptedException e) { + // ignore + } } try { - watchService.close(); - } catch (IOException e) { - LOG.debug("Exception while closing watchService", e); - } - } + watchService.close(); + } catch (IOException e) { + LOG.debug("Exception while closing watchService", e); + } + } - @Override - public void addWatchFile(File fileToWatch) { - if(!isValidFileToMonitor(fileToWatch, Arrays.asList("*"))) return; - try { - if(!fileToWatch.exists()) return; - Path pathToWatch = fileToWatch.toPath().toAbsolutePath(); - individualWatchedFiles.add(pathToWatch); - pathToWatch.getParent().register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); - } catch (IOException e) { - throw new RuntimeException(e); - } - } + @Override + public void addWatchFile(File fileToWatch) { + if (!isValidFileToMonitor(fileToWatch, Arrays.asList("*"))) { + return; + } + try { + if (!fileToWatch.exists()) { + return; + } + Path pathToWatch = fileToWatch.toPath().toAbsolutePath(); + individualWatchedFiles.add(pathToWatch); + pathToWatch.getParent().register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); + } catch (IOException e) { + throw new RuntimeException(e); + } + } - @Override - public void addWatchDirectory(File dir, final List fileExtensions) { - Path dirPath = dir.toPath(); - addWatchDirectory(dirPath, fileExtensions); - } + @Override + public void addWatchDirectory(File dir, final List fileExtensions) { + Path dirPath = dir.toPath(); + addWatchDirectory(dirPath, fileExtensions); + } - private void addWatchDirectory(Path dir, final List fileExtensions) { - if(!isValidDirectoryToMonitor(dir.toFile())){ - return; - } - try { - //add the subdirectories too - Files.walkFileTree(dir, new SimpleFileVisitor() { - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) - throws IOException - { - if(!isValidDirectoryToMonitor(dir.toFile())){ - return FileVisitResult.SKIP_SUBTREE; - } - WatchKey watchKey = dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); - final List originalFileExtensions = watchKeyToExtensionsMap.get(watchKey); - if(originalFileExtensions==null){ - watchKeyToExtensionsMap.put(watchKey, fileExtensions); - }else{ - final HashSet newFileExtensions = new HashSet(originalFileExtensions); - newFileExtensions.addAll(fileExtensions); - watchKeyToExtensionsMap.put(watchKey, Collections.unmodifiableList(new ArrayList(newFileExtensions))); - } - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - throw new RuntimeException(e); - } - } + private void addWatchDirectory(Path dir, final List fileExtensions) { + if (!isValidDirectoryToMonitor(dir.toFile())) { + return; + } + try { + //add the subdirectories too + Files.walkFileTree(dir, new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) + throws IOException { + if (!isValidDirectoryToMonitor(dir.toFile())) { + return FileVisitResult.SKIP_SUBTREE; + } + WatchKey watchKey = dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); + final List originalFileExtensions = watchKeyToExtensionsMap.get(watchKey); + if (originalFileExtensions == null) { + watchKeyToExtensionsMap.put(watchKey, fileExtensions); + } else { + final HashSet newFileExtensions = new HashSet(originalFileExtensions); + newFileExtensions.addAll(fileExtensions); + watchKeyToExtensionsMap.put(watchKey, Collections.unmodifiableList(new ArrayList(newFileExtensions))); + } + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/grails-bootstrap/src/main/resources/grails.build.properties b/grails-bootstrap/src/main/resources/grails.build.properties index 26135d62d52..bc2eba68f17 100644 --- a/grails-bootstrap/src/main/resources/grails.build.properties +++ b/grails-bootstrap/src/main/resources/grails.build.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-bootstrap/src/main/resources/springloaded.properties b/grails-bootstrap/src/main/resources/springloaded.properties index c321a1ae12e..21805ace279 100644 --- a/grails-bootstrap/src/main/resources/springloaded.properties +++ b/grails-bootstrap/src/main/resources/springloaded.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-cache/build.gradle b/grails-cache/build.gradle index 2575e34f182..e4fa085e697 100644 --- a/grails-cache/build.gradle +++ b/grails-cache/build.gradle @@ -64,4 +64,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/grails-extension-gradle-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-cache/grails-app/taglib/grails/plugin/cache/CacheTagLib.groovy b/grails-cache/grails-app/taglib/grails/plugin/cache/CacheTagLib.groovy index 6d57ea3b3d4..37310a24601 100644 --- a/grails-cache/grails-app/taglib/grails/plugin/cache/CacheTagLib.groovy +++ b/grails-cache/grails-app/taglib/grails/plugin/cache/CacheTagLib.groovy @@ -31,7 +31,6 @@ import org.springframework.web.context.request.RequestContextHolder @Slf4j class CacheTagLib { - static namespace = 'cache' GrailsCacheManager grailsCacheManager diff --git a/grails-cache/src/ast/groovy/grails/plugin/cache/CacheEvict.java b/grails-cache/src/ast/groovy/grails/plugin/cache/CacheEvict.java index 4d289f41fe5..bf3fd379c97 100644 --- a/grails-cache/src/ast/groovy/grails/plugin/cache/CacheEvict.java +++ b/grails-cache/src/ast/groovy/grails/plugin/cache/CacheEvict.java @@ -20,7 +20,12 @@ import org.codehaus.groovy.transform.GroovyASTTransformationClass; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Indicates that a method (or all methods on a class) trigger(s) @@ -36,30 +41,30 @@ @GroovyASTTransformationClass("org.grails.plugin.cache.compiler.CacheEvictTransformation") public @interface CacheEvict { - /** - * Qualifier value for the specified cached operation. - *

May be used to determine the target cache (or caches), matching the qualifier - * value. - */ - String[] value(); + /** + * Qualifier value for the specified cached operation. + *

May be used to determine the target cache (or caches), matching the qualifier + * value. + */ + String[] value(); - /** - * A closure for computing the key dynamically. - *

Default is null, meaning all method parameters are considered as a key. - */ - Class[] key() default {}; + /** + * A closure for computing the key dynamically. + *

Default is null, meaning all method parameters are considered as a key. + */ + Class[] key() default {}; - /** - * A closure used for conditioning the method caching. - *

Default is null, meaning the method is always cached. - */ - Class[] condition() default {}; + /** + * A closure used for conditioning the method caching. + *

Default is null, meaning the method is always cached. + */ + Class[] condition() default {}; - /** - * Whether or not all the entries inside the cache(s) are removed or not. By - * default, only the value under the associated key is removed. - *

Note that specifying setting this parameter to true and specifying a - * CacheKey is not allowed. - */ - boolean allEntries() default false; + /** + * Whether or not all the entries inside the cache(s) are removed or not. By + * default, only the value under the associated key is removed. + *

Note that specifying setting this parameter to true and specifying a + * CacheKey is not allowed. + */ + boolean allEntries() default false; } diff --git a/grails-cache/src/ast/groovy/grails/plugin/cache/CachePut.java b/grails-cache/src/ast/groovy/grails/plugin/cache/CachePut.java index 4be40c52739..c053ca2dcaf 100644 --- a/grails-cache/src/ast/groovy/grails/plugin/cache/CachePut.java +++ b/grails-cache/src/ast/groovy/grails/plugin/cache/CachePut.java @@ -20,7 +20,12 @@ import org.codehaus.groovy.transform.GroovyASTTransformationClass; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Indicates that a method (or all methods on a class) trigger(s) @@ -31,23 +36,23 @@ * @author Jeff Brown * @author Graeme Rocher */ -@Target({ ElementType.METHOD, ElementType.TYPE }) +@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @GroovyASTTransformationClass("org.grails.plugin.cache.compiler.CachePutTransformation") public @interface CachePut { - /** - * Name of the caches in which the update takes place. - *

May be used to determine the target cache (or caches), matching the - * qualifier value. - */ - String[] value(); + /** + * Name of the caches in which the update takes place. + *

May be used to determine the target cache (or caches), matching the + * qualifier value. + */ + String[] value(); - /** - * A closure for computing the key dynamically. - *

Default is null, meaning all method parameters are considered as a key. - */ - Class[] key() default {}; + /** + * A closure for computing the key dynamically. + *

Default is null, meaning all method parameters are considered as a key. + */ + Class[] key() default {}; } diff --git a/grails-cache/src/ast/groovy/grails/plugin/cache/Cacheable.java b/grails-cache/src/ast/groovy/grails/plugin/cache/Cacheable.java index a6b1454727d..74bbd8c03ca 100644 --- a/grails-cache/src/ast/groovy/grails/plugin/cache/Cacheable.java +++ b/grails-cache/src/ast/groovy/grails/plugin/cache/Cacheable.java @@ -18,6 +18,8 @@ */ package grails.plugin.cache; +import org.codehaus.groovy.transform.GroovyASTTransformationClass; + import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; @@ -25,8 +27,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.codehaus.groovy.transform.GroovyASTTransformationClass; - /** * Indicates that a method (or all the methods on a class) can be cached. * diff --git a/grails-cache/src/ast/groovy/grails/plugin/cache/CustomCacheKeyGenerator.groovy b/grails-cache/src/ast/groovy/grails/plugin/cache/CustomCacheKeyGenerator.groovy index e67226f8b35..a301fca14e2 100644 --- a/grails-cache/src/ast/groovy/grails/plugin/cache/CustomCacheKeyGenerator.groovy +++ b/grails-cache/src/ast/groovy/grails/plugin/cache/CustomCacheKeyGenerator.groovy @@ -125,7 +125,6 @@ class CustomCacheKeyGenerator implements KeyGenerator, GrailsCacheKeyGenerator { return new TemporaryGrailsCacheKey(className, methodName, objHashCode, simpleKey) } - @CompileStatic private static class TemporaryGrailsCacheKey implements Serializable { final String targetClassName diff --git a/grails-cache/src/ast/groovy/org/grails/plugin/cache/GrailsCacheManager.java b/grails-cache/src/ast/groovy/org/grails/plugin/cache/GrailsCacheManager.java index 0b5a4fa0007..116b4eb7cd2 100644 --- a/grails-cache/src/ast/groovy/org/grails/plugin/cache/GrailsCacheManager.java +++ b/grails-cache/src/ast/groovy/org/grails/plugin/cache/GrailsCacheManager.java @@ -25,18 +25,19 @@ */ public interface GrailsCacheManager extends CacheManager { - /** - * Whether the cache for the given name exits - * - * @param name The name of the cache - * @return True if it does - */ - boolean cacheExists(String name); + /** + * Whether the cache for the given name exits + * + * @param name The name of the cache + * @return True if it does + */ + boolean cacheExists(String name); - /** - * Destroys the given named cache - * @param name The name of the cache - * @return True if it was destroyed - */ - boolean destroyCache(String name); + /** + * Destroys the given named cache + * + * @param name The name of the cache + * @return True if it was destroyed + */ + boolean destroyCache(String name); } diff --git a/grails-cache/src/ast/groovy/org/grails/plugin/cache/compiler/AbstractCacheTransformation.groovy b/grails-cache/src/ast/groovy/org/grails/plugin/cache/compiler/AbstractCacheTransformation.groovy index 09fd88b450f..73f15ce7a58 100644 --- a/grails-cache/src/ast/groovy/org/grails/plugin/cache/compiler/AbstractCacheTransformation.groovy +++ b/grails-cache/src/ast/groovy/org/grails/plugin/cache/compiler/AbstractCacheTransformation.groovy @@ -22,8 +22,21 @@ package org.grails.plugin.cache.compiler import grails.gorm.multitenancy.Tenants import grails.plugin.cache.GrailsCacheKeyGenerator import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.* -import org.codehaus.groovy.ast.expr.* +import org.codehaus.groovy.ast.AnnotationNode +import org.codehaus.groovy.ast.ClassCodeExpressionTransformer +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.DynamicVariable +import org.codehaus.groovy.ast.MethodNode +import org.codehaus.groovy.ast.Parameter +import org.codehaus.groovy.ast.Variable +import org.codehaus.groovy.ast.VariableScope +import org.codehaus.groovy.ast.expr.ArgumentListExpression +import org.codehaus.groovy.ast.expr.ClosureExpression +import org.codehaus.groovy.ast.expr.ConstantExpression +import org.codehaus.groovy.ast.expr.Expression +import org.codehaus.groovy.ast.expr.MapExpression +import org.codehaus.groovy.ast.expr.MethodCallExpression +import org.codehaus.groovy.ast.expr.VariableExpression import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.ExpressionStatement import org.codehaus.groovy.ast.stmt.Statement @@ -37,9 +50,24 @@ import org.grails.plugin.cache.GrailsCacheManagerAware import org.springframework.cache.Cache import org.springframework.cache.CacheManager -import static org.codehaus.groovy.ast.ClassHelper.* -import static org.codehaus.groovy.ast.tools.GeneralUtils.* -import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.* +import static org.codehaus.groovy.ast.ClassHelper.CLOSURE_TYPE +import static org.codehaus.groovy.ast.ClassHelper.MAP_TYPE +import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE +import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE +import static org.codehaus.groovy.ast.ClassHelper.int_TYPE +import static org.codehaus.groovy.ast.ClassHelper.make +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS +import static org.codehaus.groovy.ast.tools.GeneralUtils.notX +import static org.codehaus.groovy.ast.tools.GeneralUtils.param +import static org.codehaus.groovy.ast.tools.GeneralUtils.params +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX +import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.callD /** * Abstract implementation for implementers of cache annotations @@ -175,7 +203,6 @@ abstract class AbstractCacheTransformation extends AbstractMethodDecoratingTrans return cacheKeyVariableExpression } - @Override protected Object getAppliedMarker() { return APPLIED_MARKER diff --git a/grails-cache/src/ast/groovy/org/grails/plugin/cache/compiler/CachePutTransformation.groovy b/grails-cache/src/ast/groovy/org/grails/plugin/cache/compiler/CachePutTransformation.groovy index 40aa18c3ac9..54e416eedd6 100644 --- a/grails-cache/src/ast/groovy/org/grails/plugin/cache/compiler/CachePutTransformation.groovy +++ b/grails-cache/src/ast/groovy/org/grails/plugin/cache/compiler/CachePutTransformation.groovy @@ -33,7 +33,14 @@ import org.codehaus.groovy.control.SourceUnit import org.codehaus.groovy.transform.GroovyASTTransformation import static org.codehaus.groovy.ast.ClassHelper.make -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.block +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS +import static org.codehaus.groovy.ast.tools.GeneralUtils.notNullX +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.callD /** @@ -54,7 +61,6 @@ class CachePutTransformation extends AbstractCacheTransformation { VariableExpression cacheManagerVariableExpression = varX(GRAILS_CACHE_MANAGER_PROPERTY_NAME) BlockStatement cachingBlock = block() - // Cache $_cache_cacheVariable = this.grailsCacheManager.getCache("..."); VariableExpression cacheDeclaration = declareCache(annotationNode, cacheManagerVariableExpression, cachingBlock) diff --git a/grails-cache/src/ast/groovy/org/grails/plugin/cache/compiler/CacheableTransformation.groovy b/grails-cache/src/ast/groovy/org/grails/plugin/cache/compiler/CacheableTransformation.groovy index 9f98c7c2a09..bd851abb009 100644 --- a/grails-cache/src/ast/groovy/org/grails/plugin/cache/compiler/CacheableTransformation.groovy +++ b/grails-cache/src/ast/groovy/org/grails/plugin/cache/compiler/CacheableTransformation.groovy @@ -35,8 +35,17 @@ import org.codehaus.groovy.transform.GroovyASTTransformation import org.grails.core.artefact.ControllerArtefactHandler import org.springframework.cache.Cache -import static org.codehaus.groovy.ast.ClassHelper.* -import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.* +import static org.codehaus.groovy.ast.ClassHelper.make +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.block +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifElseS +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS +import static org.codehaus.groovy.ast.tools.GeneralUtils.notNullX +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX +import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.callD /** * @since 4.0.0 @@ -81,7 +90,6 @@ class CacheableTransformation extends AbstractCacheTransformation { // def $_cache_cacheKey = customCacheKeyGenerator.generate(className, methodName, hashCode, $_method_parameter_map) VariableExpression cacheKeyDeclaration = declareCacheKey(sourceUnit, annotationNode, classNode, methodNode , cachingBlock) - // ValueWrapper $_cache_valueWrapper = $_cache_cacheVariable.get($_cache_cacheKey); VariableExpression cacheValueWrapper = varX(CACHE_VALUE_WRAPPER_LOCAL_VARIABLE_NAME, make(Cache.ValueWrapper)) cachingBlock.addStatement( diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/CacheException.groovy b/grails-cache/src/main/groovy/grails/plugin/cache/CacheException.groovy index b17b721b55f..b3c0a8e6ec0 100644 --- a/grails-cache/src/main/groovy/grails/plugin/cache/CacheException.groovy +++ b/grails-cache/src/main/groovy/grails/plugin/cache/CacheException.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package grails.plugin.cache import groovy.transform.CompileStatic diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy b/grails-cache/src/main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy index 86d57e20291..b2d4a17a617 100644 --- a/grails-cache/src/main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy +++ b/grails-cache/src/main/groovy/grails/plugin/cache/CacheGrailsPlugin.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package grails.plugin.cache import grails.plugins.Plugin @@ -53,7 +52,6 @@ class CacheGrailsPlugin extends Plugin { customCacheKeyGenerator(CustomCacheKeyGenerator) - Class cacheClazz = GrailsConcurrentMapCacheManager // Selects cache manager from config if (config.getProperty("grails.cache.cacheManager", String, null) == "GrailsConcurrentLinkedMapCacheManager") { diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/CachePluginConfiguration.groovy b/grails-cache/src/main/groovy/grails/plugin/cache/CachePluginConfiguration.groovy index 87e800d16d3..e9b632f9a8a 100644 --- a/grails-cache/src/main/groovy/grails/plugin/cache/CachePluginConfiguration.groovy +++ b/grails-cache/src/main/groovy/grails/plugin/cache/CachePluginConfiguration.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package grails.plugin.cache import groovy.transform.CompileStatic diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsCache.java b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsCache.java index da62b521c75..d19389f5160 100644 --- a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsCache.java +++ b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsCache.java @@ -18,15 +18,15 @@ */ package grails.plugin.cache; -import java.util.Collection; - import org.springframework.cache.Cache; +import java.util.Collection; + /** * @author Burt Beckwith * @since 1.0 */ public interface GrailsCache extends Cache { - Collection getAllKeys(); + Collection getAllKeys(); } diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsCacheAdminService.groovy b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsCacheAdminService.groovy index e0cb95104b2..7587008e42b 100644 --- a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsCacheAdminService.groovy +++ b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsCacheAdminService.groovy @@ -24,20 +24,20 @@ import org.grails.plugin.cache.GrailsCacheManagerAware @CompileStatic class GrailsCacheAdminService implements GrailsCacheManagerAware { - @CacheEvict(value="grailsBlocksCache", allEntries = true) + @CacheEvict(value = "grailsBlocksCache", allEntries = true) void clearBlocksCache() {} - @CacheEvict(value="grailsTemplatesCache", allEntries = true) + @CacheEvict(value = "grailsTemplatesCache", allEntries = true) void clearTemplatesCache() {} void clearCache(CharSequence cacheName) { - if(cacheName) { + if (cacheName) { grailsCacheManager.getCache(cacheName.toString())?.clear() } } void clearAllCaches() { - for(CharSequence cacheName in grailsCacheManager.cacheNames) { + for (CharSequence cacheName in grailsCacheManager.cacheNames) { clearCache(cacheName) } } diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentLinkedMapCache.java b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentLinkedMapCache.java index f7530e86f01..897902bf8f6 100644 --- a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentLinkedMapCache.java +++ b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentLinkedMapCache.java @@ -31,76 +31,78 @@ */ public class GrailsConcurrentLinkedMapCache implements GrailsCache { - private static final Object NULL_HOLDER = new NullHolder(); - private String name; - private long capacity; - private final ConcurrentLinkedHashMap store; - private final boolean allowNullValues; - - /** - * Create a new GrailsConcurrentLinkedMapCache with the specified name - * and capacity - * @param name the name of the cache - * @param capacity of the map - * @param allowNullValues null values (default is true) - */ - public GrailsConcurrentLinkedMapCache(String name, long capacity, boolean allowNullValues) { - this.name = name; - this.capacity = capacity; - this.allowNullValues = allowNullValues; - // Workaround: using explicit type arguments to prevent groovydoc error (#53) - // Replace with diamond operator once a fix for GROOVY-8628 is included in groovy dependency - this.store = new ConcurrentLinkedHashMap.Builder() - .maximumWeightedCapacity(capacity) - .build(); - } - - /** - * Create a new GrailsConcurrentLinkedMapCache with the specified name - * and capacity - * @param name the name of the cache - * @param capacity of the map - */ - public GrailsConcurrentLinkedMapCache(String name, long capacity) { - this(name, capacity, true); - } - - public final long getCapacity() { - return this.store.capacity(); - } - - @Override - public final String getName() { - return this.name; - } - - @Override - public final ConcurrentMap getNativeCache() { - return this.store; - } - - public final int getSize() { - return this.store.size(); - } - - public final boolean isAllowNullValues() { - return this.allowNullValues; - } - - @Override - public GrailsValueWrapper get(Object key) { - Object value = getNativeCache().get(key); - return value == null ? null : new GrailsValueWrapper(fromStoreValue(value), null); - } - - @Override - public T get(Object key, Class type) { - Object value = getNativeCache().get(key); - if (value != null && type != null && !type.isInstance(value)) { - throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value); - } - return (T) value; - } + private static final Object NULL_HOLDER = new NullHolder(); + private String name; + private long capacity; + private final ConcurrentLinkedHashMap store; + private final boolean allowNullValues; + + /** + * Create a new GrailsConcurrentLinkedMapCache with the specified name + * and capacity + * + * @param name the name of the cache + * @param capacity of the map + * @param allowNullValues null values (default is true) + */ + public GrailsConcurrentLinkedMapCache(String name, long capacity, boolean allowNullValues) { + this.name = name; + this.capacity = capacity; + this.allowNullValues = allowNullValues; + // Workaround: using explicit type arguments to prevent groovydoc error (#53) + // Replace with diamond operator once a fix for GROOVY-8628 is included in groovy dependency + this.store = new ConcurrentLinkedHashMap.Builder() + .maximumWeightedCapacity(capacity) + .build(); + } + + /** + * Create a new GrailsConcurrentLinkedMapCache with the specified name + * and capacity + * + * @param name the name of the cache + * @param capacity of the map + */ + public GrailsConcurrentLinkedMapCache(String name, long capacity) { + this(name, capacity, true); + } + + public final long getCapacity() { + return this.store.capacity(); + } + + @Override + public final String getName() { + return this.name; + } + + @Override + public final ConcurrentMap getNativeCache() { + return this.store; + } + + public final int getSize() { + return this.store.size(); + } + + public final boolean isAllowNullValues() { + return this.allowNullValues; + } + + @Override + public GrailsValueWrapper get(Object key) { + Object value = getNativeCache().get(key); + return value == null ? null : new GrailsValueWrapper(fromStoreValue(value), null); + } + + @Override + public T get(Object key, Class type) { + Object value = getNativeCache().get(key); + if (value != null && type != null && !type.isInstance(value)) { + throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value); + } + return (T) value; + } @Override public T get(Object key, Callable valueLoader) { @@ -108,66 +110,69 @@ public T get(Object key, Callable valueLoader) { } @SuppressWarnings("unchecked") - public Collection getAllKeys() { - return getNativeCache().keySet(); - } - - public Collection getHottestKeys() { - return this.store.descendingKeySet(); - } - - @Override - public void put(Object key, Object value) { - this.store.put(key, toStoreValue(value)); - } - - public ValueWrapper putIfAbsent(Object key, Object value) { - Object existing = this.store.putIfAbsent(key, value); - return toWrapper(existing); - } - - @Override - public void evict(Object key) { - this.store.remove(key); - } - - @Override - public void clear() { - this.store.clear(); - } - - /** - * Convert the given value from the internal store to a user value - * returned from the get method (adapting {@code null}). - * @param storeValue the store value - * @return the value to return to the user - */ - protected Object fromStoreValue(Object storeValue) { - if (this.allowNullValues && storeValue == NULL_HOLDER) { - return null; - } - return storeValue; - } - - /** - * Convert the given user value, as passed into the put method, - * to a value in the internal store (adapting {@code null}). - * @param userValue the given user value - * @return the value to store - */ - protected Object toStoreValue(Object userValue) { - if (this.allowNullValues && userValue == null) { - return NULL_HOLDER; - } - return userValue; - } - - private ValueWrapper toWrapper(Object value) { - return (value != null ? new SimpleValueWrapper(fromStoreValue(value)) : null); - } - - @SuppressWarnings("serial") - - private static class NullHolder implements Serializable { - } + public Collection getAllKeys() { + return getNativeCache().keySet(); + } + + public Collection getHottestKeys() { + return this.store.descendingKeySet(); + } + + @Override + public void put(Object key, Object value) { + this.store.put(key, toStoreValue(value)); + } + + public ValueWrapper putIfAbsent(Object key, Object value) { + Object existing = this.store.putIfAbsent(key, value); + return toWrapper(existing); + } + + @Override + public void evict(Object key) { + this.store.remove(key); + } + + @Override + public void clear() { + this.store.clear(); + } + + /** + * Convert the given value from the internal store to a user value + * returned from the get method (adapting {@code null}). + * + * @param storeValue the store value + * @return the value to return to the user + */ + protected Object fromStoreValue(Object storeValue) { + if (this.allowNullValues && storeValue == NULL_HOLDER) { + return null; + } + return storeValue; + } + + /** + * Convert the given user value, as passed into the put method, + * to a value in the internal store (adapting {@code null}). + * + * @param userValue the given user value + * @return the value to store + */ + protected Object toStoreValue(Object userValue) { + if (this.allowNullValues && userValue == null) { + return NULL_HOLDER; + } + return userValue; + } + + private ValueWrapper toWrapper(Object value) { + return (value != null ? new SimpleValueWrapper(fromStoreValue(value)) : null); + } + + @SuppressWarnings("serial") + + private static class NullHolder implements Serializable { + + } } diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentLinkedMapCacheManager.groovy b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentLinkedMapCacheManager.groovy index ab7cc818bf5..6b5b9b433df 100644 --- a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentLinkedMapCacheManager.groovy +++ b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentLinkedMapCacheManager.groovy @@ -33,43 +33,43 @@ import java.util.concurrent.ConcurrentMap @CompileStatic class GrailsConcurrentLinkedMapCacheManager implements GrailsCacheManager { - protected final ConcurrentMap cacheMap = new ConcurrentHashMap() + protected final ConcurrentMap cacheMap = new ConcurrentHashMap() - Collection getCacheNames() { - return Collections.unmodifiableSet(cacheMap.keySet()) - } + Collection getCacheNames() { + return Collections.unmodifiableSet(cacheMap.keySet()) + } - Cache getCache(String name) { - return getCache(name, 10000) - } + Cache getCache(String name) { + return getCache(name, 10000) + } - Cache getCache(String name, int capacity) { - Cache cache = cacheMap.get(name) - if (cache == null) { - cache = createConcurrentLinkedMapCache(name, capacity) - Cache existing = cacheMap.putIfAbsent(name, cache) - if (existing != null) { - cache = existing - } - } - return cache - } + Cache getCache(String name, int capacity) { + Cache cache = cacheMap.get(name) + if (cache == null) { + cache = createConcurrentLinkedMapCache(name, capacity) + Cache existing = cacheMap.putIfAbsent(name, cache) + if (existing != null) { + cache = existing + } + } + return cache + } - boolean cacheExists(String name) { - getCacheNames().contains(name) - } + boolean cacheExists(String name) { + getCacheNames().contains(name) + } - boolean destroyCache(String name) { - cacheMap.remove(name) != null - } + boolean destroyCache(String name) { + cacheMap.remove(name) != null + } - protected GrailsConcurrentLinkedMapCache createConcurrentLinkedMapCache(String name, long capacity) { - return new GrailsConcurrentLinkedMapCache(name, capacity) - } + protected GrailsConcurrentLinkedMapCache createConcurrentLinkedMapCache(String name, long capacity) { + return new GrailsConcurrentLinkedMapCache(name, capacity) + } - void setConfiguration(CachePluginConfiguration configuration) { - configuration.caches.each { String key, CachePluginConfiguration.CacheConfig value -> - getCache(key, value.maxCapacity) - } - } + void setConfiguration(CachePluginConfiguration configuration) { + configuration.caches.each { String key, CachePluginConfiguration.CacheConfig value -> + getCache(key, value.maxCapacity) + } + } } diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentMapCache.java b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentMapCache.java index 67421ec98fe..d545951f512 100644 --- a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentMapCache.java +++ b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentMapCache.java @@ -18,11 +18,11 @@ */ package grails.plugin.cache; +import org.springframework.cache.concurrent.ConcurrentMapCache; + import java.util.Collection; import java.util.concurrent.ConcurrentMap; -import org.springframework.cache.concurrent.ConcurrentMapCache; - /** * Extends the default implementation to return GrailsValueWrapper instances instead of * SimpleValueWrapper. This isn't useful for this implementation but is for others where @@ -34,26 +34,26 @@ */ public class GrailsConcurrentMapCache extends ConcurrentMapCache implements GrailsCache { - public GrailsConcurrentMapCache(String name) { - super(name); - } + public GrailsConcurrentMapCache(String name) { + super(name); + } - public GrailsConcurrentMapCache(String name, boolean allowNullValues) { - super(name, allowNullValues); - } + public GrailsConcurrentMapCache(String name, boolean allowNullValues) { + super(name, allowNullValues); + } - public GrailsConcurrentMapCache(String name, ConcurrentMap store, boolean allowNullValues) { - super(name, store, allowNullValues); - } + public GrailsConcurrentMapCache(String name, ConcurrentMap store, boolean allowNullValues) { + super(name, store, allowNullValues); + } - @Override - public GrailsValueWrapper get(Object key) { - Object value = getNativeCache().get(key); - return value == null ? null : new GrailsValueWrapper(fromStoreValue(value), null); - } + @Override + public GrailsValueWrapper get(Object key) { + Object value = getNativeCache().get(key); + return value == null ? null : new GrailsValueWrapper(fromStoreValue(value), null); + } - @SuppressWarnings("unchecked") - public Collection getAllKeys() { - return getNativeCache().keySet(); - } + @SuppressWarnings("unchecked") + public Collection getAllKeys() { + return getNativeCache().keySet(); + } } diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentMapCacheManager.groovy b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentMapCacheManager.groovy index 6a6d7a5ab92..aa43a9456db 100644 --- a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentMapCacheManager.groovy +++ b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsConcurrentMapCacheManager.groovy @@ -19,11 +19,11 @@ package grails.plugin.cache import groovy.transform.CompileStatic -import org.grails.plugin.cache.GrailsCacheManager; +import org.grails.plugin.cache.GrailsCacheManager +import org.springframework.cache.Cache import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentMap -import org.springframework.cache.Cache /** * Based on org.springframework.cache.concurrent.ConcurrentMapCacheManager. @@ -34,39 +34,39 @@ import org.springframework.cache.Cache @CompileStatic class GrailsConcurrentMapCacheManager implements GrailsCacheManager { - protected final ConcurrentMap cacheMap = new ConcurrentHashMap() + protected final ConcurrentMap cacheMap = new ConcurrentHashMap() - Collection getCacheNames() { - Collections.unmodifiableSet(cacheMap.keySet()) - } + Collection getCacheNames() { + Collections.unmodifiableSet(cacheMap.keySet()) + } - Cache getCache(String name) { - Cache cache = cacheMap.get(name) - if (cache == null) { - cache = createConcurrentMapCache(name) - Cache existing = cacheMap.putIfAbsent(name, cache) - if (existing != null) { - cache = existing - } - } - cache - } + Cache getCache(String name) { + Cache cache = cacheMap.get(name) + if (cache == null) { + cache = createConcurrentMapCache(name) + Cache existing = cacheMap.putIfAbsent(name, cache) + if (existing != null) { + cache = existing + } + } + cache + } - boolean cacheExists(String name) { - getCacheNames().contains(name) - } + boolean cacheExists(String name) { + getCacheNames().contains(name) + } - boolean destroyCache(String name) { - cacheMap.remove(name) != null - } + boolean destroyCache(String name) { + cacheMap.remove(name) != null + } - protected GrailsConcurrentMapCache createConcurrentMapCache(String name) { - new GrailsConcurrentMapCache(name) - } + protected GrailsConcurrentMapCache createConcurrentMapCache(String name) { + new GrailsConcurrentMapCache(name) + } - void setConfiguration(CachePluginConfiguration configuration) { - configuration.caches.each { String key, CachePluginConfiguration.CacheConfig value -> - getCache(key) - } - } + void setConfiguration(CachePluginConfiguration configuration) { + configuration.caches.each { String key, CachePluginConfiguration.CacheConfig value -> + getCache(key) + } + } } diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsValueWrapper.java b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsValueWrapper.java index 6b74a361e67..8ff0708b918 100644 --- a/grails-cache/src/main/groovy/grails/plugin/cache/GrailsValueWrapper.java +++ b/grails-cache/src/main/groovy/grails/plugin/cache/GrailsValueWrapper.java @@ -27,14 +27,14 @@ */ public class GrailsValueWrapper extends SimpleValueWrapper { - protected Object nativeWrapper; + protected Object nativeWrapper; - public GrailsValueWrapper(Object value, Object nativeWrapper) { - super(value); - this.nativeWrapper = nativeWrapper; - } + public GrailsValueWrapper(Object value, Object nativeWrapper) { + super(value); + this.nativeWrapper = nativeWrapper; + } - public Object getNativeWrapper() { - return nativeWrapper; - } + public Object getNativeWrapper() { + return nativeWrapper; + } } diff --git a/grails-cache/src/main/groovy/grails/plugin/cache/util/ClassUtils.java b/grails-cache/src/main/groovy/grails/plugin/cache/util/ClassUtils.java index 5a6df4b1854..a4da98e2ddc 100644 --- a/grails-cache/src/main/groovy/grails/plugin/cache/util/ClassUtils.java +++ b/grails-cache/src/main/groovy/grails/plugin/cache/util/ClassUtils.java @@ -19,12 +19,11 @@ package grails.plugin.cache.util; import grails.util.GrailsNameUtils; +import org.springframework.util.ReflectionUtils; import java.lang.reflect.Field; import java.lang.reflect.Method; -import org.springframework.util.ReflectionUtils; - /** * @author Jeff Brown */ @@ -35,7 +34,7 @@ public class ClassUtils { * object using a corresponding getter method. If no getter method is found * then this method will look for the corresponding field and return its value. * - * @param object object to inspect + * @param object object to inspect * @param propertyOrFieldName the name of the field or property to retrieve * @return the value of the field or property, null if neither is found */ diff --git a/grails-codecs-core/build.gradle b/grails-codecs-core/build.gradle index 4fa52b2bb49..970f96a6ea6 100644 --- a/grails-codecs-core/build.gradle +++ b/grails-codecs-core/build.gradle @@ -57,4 +57,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/DigestUtils.groovy b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/DigestUtils.groovy index fccb6489a10..0960e45b1d6 100644 --- a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/DigestUtils.groovy +++ b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/DigestUtils.groovy @@ -33,12 +33,10 @@ abstract class DigestUtils { def src if (data instanceof Byte[] || data instanceof byte[]) { src = data - } - else if (data instanceof List || data.getClass().isArray()) { + } else if (data instanceof List || data.getClass().isArray()) { src = new byte[data.size()] data.eachWithIndex { v, i -> src[i] = v } - } - else { + } else { src = data.toString().getBytes(StandardCharsets.UTF_8) } md.update(src) // This probably needs to use the thread's Locale encoding diff --git a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/HexCodecExtensionMethods.groovy b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/HexCodecExtensionMethods.groovy index 7dda93f99a2..0944166cd1d 100644 --- a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/HexCodecExtensionMethods.groovy +++ b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/HexCodecExtensionMethods.groovy @@ -57,8 +57,7 @@ class HexCodecExtensionMethods { str.eachWithIndex { val, idx -> if (!(idx % 2)) { currentByte = HEXDIGITS.indexOf(val) << 4 - } - else { + } else { output << (currentByte | HEXDIGITS.indexOf(val)) currentByte = 0 } diff --git a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/MD5BytesCodecExtensionMethods.groovy b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/MD5BytesCodecExtensionMethods.groovy index 4b5fdeccc6a..8422367f87d 100644 --- a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/MD5BytesCodecExtensionMethods.groovy +++ b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/MD5BytesCodecExtensionMethods.groovy @@ -24,7 +24,7 @@ class MD5BytesCodecExtensionMethods { // Returns the byte[] of the digest, taken from UTF-8 of the string representation // or the raw data coerced to bytes static encodeAsMD5Bytes(theTarget) { - if(theTarget == null || theTarget instanceof NullObject) { + if (theTarget == null || theTarget instanceof NullObject) { return null } DigestUtils.digest("MD5", theTarget) diff --git a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA1BytesCodecExtensionMethods.groovy b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA1BytesCodecExtensionMethods.groovy index 398dac6c9f5..967db854b77 100644 --- a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA1BytesCodecExtensionMethods.groovy +++ b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA1BytesCodecExtensionMethods.groovy @@ -23,7 +23,7 @@ import org.codehaus.groovy.runtime.NullObject class SHA1BytesCodecExtensionMethods { // Returns the byte[] of the digest static encodeAsSHA1Bytes(theTarget) { - if(theTarget == null || theTarget instanceof NullObject) { + if (theTarget == null || theTarget instanceof NullObject) { return null } DigestUtils.digest("SHA-1", theTarget) diff --git a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA1CodecExtensionMethods.groovy b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA1CodecExtensionMethods.groovy index f952e003250..0eb9d8f138d 100644 --- a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA1CodecExtensionMethods.groovy +++ b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA1CodecExtensionMethods.groovy @@ -23,7 +23,7 @@ import org.codehaus.groovy.runtime.NullObject class SHA1CodecExtensionMethods { // Returns the byte[] of the digest static encodeAsSHA1(theTarget) { - if(theTarget == null || theTarget instanceof NullObject) { + if (theTarget == null || theTarget instanceof NullObject) { return null } theTarget.encodeAsSHA1Bytes().encodeAsHex() diff --git a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA256BytesCodecExtensionMethods.groovy b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA256BytesCodecExtensionMethods.groovy index d3aab53f5cd..05de30348da 100644 --- a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA256BytesCodecExtensionMethods.groovy +++ b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA256BytesCodecExtensionMethods.groovy @@ -23,7 +23,7 @@ import org.codehaus.groovy.runtime.NullObject class SHA256BytesCodecExtensionMethods { // Returns the byte[] of the digest static encodeAsSHA256Bytes(theTarget) { - if(theTarget == null || theTarget instanceof NullObject) { + if (theTarget == null || theTarget instanceof NullObject) { return null } DigestUtils.digest("SHA-256", theTarget) diff --git a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA256CodecExtensionMethods.groovy b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA256CodecExtensionMethods.groovy index a34298e1a9c..1034ba090bb 100644 --- a/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA256CodecExtensionMethods.groovy +++ b/grails-codecs-core/src/main/groovy/org/grails/plugins/codecs/SHA256CodecExtensionMethods.groovy @@ -23,7 +23,7 @@ import org.codehaus.groovy.runtime.NullObject class SHA256CodecExtensionMethods extends DigestUtils { // Returns the byte[] of the digest static encodeAsSHA256(theTarget) { - if(theTarget == null || theTarget instanceof NullObject) { + if (theTarget == null || theTarget instanceof NullObject) { return null } theTarget.encodeAsSHA256Bytes()?.encodeAsHex() diff --git a/grails-codecs/build.gradle b/grails-codecs/build.gradle index a109b376add..c8802f4b83f 100644 --- a/grails-codecs/build.gradle +++ b/grails-codecs/build.gradle @@ -67,4 +67,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-codecs/src/main/groovy/org/grails/commons/CodecArtefactHandler.java b/grails-codecs/src/main/groovy/org/grails/commons/CodecArtefactHandler.java index bcf4cc69eab..b34e9461e8a 100644 --- a/grails-codecs/src/main/groovy/org/grails/commons/CodecArtefactHandler.java +++ b/grails-codecs/src/main/groovy/org/grails/commons/CodecArtefactHandler.java @@ -34,7 +34,9 @@ public CodecArtefactHandler() { @Override public boolean isArtefactClass(@SuppressWarnings("rawtypes") Class clazz) { - if (clazz == null) return false; + if (clazz == null) { + return false; + } return clazz.getName().endsWith(DefaultGrailsCodecClass.CODEC) && !DomainClassArtefactHandler.isDomainClass(clazz); } diff --git a/grails-codecs/src/main/groovy/org/grails/commons/DefaultGrailsCodecClass.java b/grails-codecs/src/main/groovy/org/grails/commons/DefaultGrailsCodecClass.java index 1e815ae11eb..b186a3a3cb1 100644 --- a/grails-codecs/src/main/groovy/org/grails/commons/DefaultGrailsCodecClass.java +++ b/grails-codecs/src/main/groovy/org/grails/commons/DefaultGrailsCodecClass.java @@ -18,13 +18,8 @@ */ package org.grails.commons; -import org.grails.core.AbstractInjectableGrailsClass; import groovy.lang.Closure; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - +import org.grails.core.AbstractInjectableGrailsClass; import org.grails.encoder.CodecFactory; import org.grails.encoder.CodecIdentifier; import org.grails.encoder.CodecMetaClassSupport; @@ -38,20 +33,25 @@ import org.grails.encoder.EncodingStateRegistryLookup; import org.grails.encoder.EncodingStateRegistryLookupHolder; import org.grails.encoder.StreamingEncoder; -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.core.Ordered; import org.springframework.util.ReflectionUtils; +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + /** * @author Jeff Brown * @since 0.4 */ public class DefaultGrailsCodecClass extends AbstractInjectableGrailsClass implements InitializingBean, GrailsCodecClass, Ordered { + public static final String CODEC = CodecArtefactHandler.TYPE; + private static int instantionCounter = 0; private Encoder encoder; private Decoder decoder; - private static int instantionCounter=0; private int order = 100 + instantionCounter++; private boolean initialized = false; @@ -64,7 +64,9 @@ public void afterPropertiesSet() { } private void initializeCodec() { - if (initialized) return; + if (initialized) { + return; + } initialized = true; Integer orderSetting = getStaticPropertyValue("order", Integer.class); if (orderSetting != null) { @@ -73,42 +75,42 @@ private void initializeCodec() { Object instance = getReferenceInstance(); if (Encoder.class.isAssignableFrom(getClazz())) { encoder = (Encoder) instance; - encoder = (Encoder)autowireCodecBean(encoder); + encoder = (Encoder) autowireCodecBean(encoder); if (encoder instanceof Ordered) { - order = ((Ordered)encoder).getOrder(); + order = ((Ordered) encoder).getOrder(); } } if (Decoder.class.isAssignableFrom(getClazz())) { decoder = (Decoder) instance; - decoder = (Decoder)autowireCodecBean(decoder); + decoder = (Decoder) autowireCodecBean(decoder); if (decoder instanceof Ordered) { - order = ((Ordered)decoder).getOrder(); + order = ((Ordered) decoder).getOrder(); } } - if (encoder==null && decoder==null) { - CodecFactory codecFactory=null; + if (encoder == null && decoder == null) { + CodecFactory codecFactory = null; if (CodecFactory.class.isAssignableFrom(getClazz())) { - codecFactory=(CodecFactory) instance; - codecFactory=(CodecFactory)autowireCodecBean(codecFactory); + codecFactory = (CodecFactory) instance; + codecFactory = (CodecFactory) autowireCodecBean(codecFactory); } - if (codecFactory==null) { - codecFactory=getStaticPropertyValue("codecFactory", CodecFactory.class); - codecFactory=(CodecFactory)autowireCodecBean(codecFactory); + if (codecFactory == null) { + codecFactory = getStaticPropertyValue("codecFactory", CodecFactory.class); + codecFactory = (CodecFactory) autowireCodecBean(codecFactory); } - if (codecFactory==null) { - codecFactory=new ClosureCodecFactory(instance); + if (codecFactory == null) { + codecFactory = new ClosureCodecFactory(instance); } - encoder=codecFactory.getEncoder(); - decoder=codecFactory.getDecoder(); + encoder = codecFactory.getEncoder(); + decoder = codecFactory.getDecoder(); if (codecFactory instanceof Ordered) { - order = ((Ordered)codecFactory).getOrder(); + order = ((Ordered) codecFactory).getOrder(); } } if (encoder != null) { if (encoder instanceof StreamingEncoder) { - encoder=new StreamingStateAwareEncoderWrapper((StreamingEncoder)encoder); + encoder = new StreamingStateAwareEncoderWrapper((StreamingEncoder) encoder); } else { - encoder=new StateAwareEncoderWrapper(encoder); + encoder = new StateAwareEncoderWrapper(encoder); } } } @@ -123,7 +125,28 @@ protected Object autowireCodecBean(Object existingBean) { return existingBean; } + public Encoder getEncoder() { + return encoder; + } + + public Decoder getDecoder() { + return decoder; + } + + public void configureCodecMethods() { + // for compatibility. Not everything (especially unit tests written by existing Grails applications) call afterPropertiesSet(), but everything calls + // configureCodecMethods() at least once + initializeCodec(); + + new CodecMetaClassSupport().configureCodecMethods(this); + } + + public int getOrder() { + return order; + } + private class ClosureCodecFactory implements CodecFactory { + private Encoder encoder; private Decoder decoder; private final Object codecInstance; @@ -132,11 +155,11 @@ private class ClosureCodecFactory implements CodecFactory { this.codecInstance = codecInstance; Closure encoderClosure = getMethodOrClosureMethod(getClazz(), "encode"); if (encoderClosure != null) { - encoder=new ClosureEncoder(getName(), encoderClosure); + encoder = new ClosureEncoder(getName(), encoderClosure); } Closure decoderClosure = getMethodOrClosureMethod(getClazz(), "decode"); if (decoderClosure != null) { - decoder=new ClosureDecoder(getName(), decoderClosure); + decoder = new ClosureDecoder(getName(), decoderClosure); } } @@ -152,13 +175,13 @@ private Closure getMethodOrClosureMethod(Class clazz, String methodNa @SuppressWarnings("unchecked") Closure closure = getStaticPropertyValue(methodName, Closure.class); if (closure == null) { - Method method = ReflectionUtils.findMethod(clazz, methodName, (Class[])null); + Method method = ReflectionUtils.findMethod(clazz, methodName, (Class[]) null); if (method != null) { Object owner; if (Modifier.isStatic(method.getModifiers())) { - owner=clazz; + owner = clazz; } else { - owner=codecInstance; + owner = codecInstance; } return new MethodCallingClosure(owner, method); } @@ -170,12 +193,13 @@ private Closure getMethodOrClosureMethod(Class clazz, String methodNa } private static class ClosureDecoder implements Decoder { + private CodecIdentifier codecIdentifier; private Closure closure; public ClosureDecoder(String codecName, Closure closure) { - this.codecIdentifier=new DefaultCodecIdentifier(codecName); - this.closure=closure; + this.codecIdentifier = new DefaultCodecIdentifier(codecName); + this.closure = closure; } public CodecIdentifier getCodecIdentifier() { @@ -188,10 +212,11 @@ public Object decode(Object o) { } private static class StateAwareEncoderWrapper implements Encoder { + private Encoder delegate; public StateAwareEncoderWrapper(Encoder delegate) { - this.delegate=delegate; + this.delegate = delegate; } public CodecIdentifier getCodecIdentifier() { @@ -200,18 +225,19 @@ public CodecIdentifier getCodecIdentifier() { public Object encode(Object target) { if (target instanceof Encodeable) { - return ((Encodeable)target).encode(this); + return ((Encodeable) target).encode(this); } - EncodingStateRegistry encodingState=lookupEncodingState(); + EncodingStateRegistry encodingState = lookupEncodingState(); if (encodingState != null && target instanceof CharSequence) { - if (!encodingState.shouldEncodeWith(this, (CharSequence)target)) { + if (!encodingState.shouldEncodeWith(this, (CharSequence) target)) { return target; } } Object encoded = delegate.encode(target); - if (encodingState != null && encoded instanceof CharSequence) - encodingState.registerEncodedWith(this, (CharSequence)encoded); + if (encodingState != null && encoded instanceof CharSequence) { + encodingState.registerEncodedWith(this, (CharSequence) encoded); + } return encoded; } @@ -221,7 +247,7 @@ protected EncodingStateRegistry lookupEncodingState() { } public void markEncoded(CharSequence string) { - EncodingStateRegistry encodingState=lookupEncodingState(); + EncodingStateRegistry encodingState = lookupEncodingState(); if (encodingState != null) { encodingState.registerEncodedWith(this, string); } @@ -237,24 +263,28 @@ public boolean isApplyToSafelyEncoded() { } private static class StreamingStateAwareEncoderWrapper extends StateAwareEncoderWrapper implements StreamingEncoder { + private StreamingEncoder delegate; + public StreamingStateAwareEncoderWrapper(StreamingEncoder delegate) { super(delegate); - this.delegate=delegate; + this.delegate = delegate; } + public void encodeToStream(Encoder thisInstance, CharSequence source, int offset, int len, EncodedAppender appender, - EncodingState encodingState) throws IOException { + EncodingState encodingState) throws IOException { delegate.encodeToStream(this, source, offset, len, appender, encodingState); } } private static class ClosureEncoder implements Encoder { + private CodecIdentifier codecIdentifier; private Closure closure; public ClosureEncoder(String codecName, Closure closure) { - this.codecIdentifier=new DefaultCodecIdentifier(codecName); - this.closure=closure; + this.codecIdentifier = new DefaultCodecIdentifier(codecName); + this.closure = closure; } public CodecIdentifier getCodecIdentifier() { @@ -262,7 +292,9 @@ public CodecIdentifier getCodecIdentifier() { } public Object encode(Object target) { - if (target==null) return null; + if (target == null) { + return null; + } return closure.call(target); } @@ -280,6 +312,7 @@ public boolean isApplyToSafelyEncoded() { } private static class MethodCallingClosure extends Closure { + private static final long serialVersionUID = 1L; private Method method; @@ -287,7 +320,7 @@ public MethodCallingClosure(Object owner, Method method) { super(owner); maximumNumberOfParameters = 1; parameterTypes = new Class[]{Object.class}; - this.method=method; + this.method = method; } protected Object callMethod(Object argument) { @@ -300,33 +333,14 @@ public Object call(Object... args) { } protected Object doCall(Object[] args) { - Object target=null; - if (args != null && args.length > 0) - target=args[0]; - if (target==null) { + Object target = null; + if (args != null && args.length > 0) { + target = args[0]; + } + if (target == null) { return null; } return callMethod(target); } } - - public Encoder getEncoder() { - return encoder; - } - - public Decoder getDecoder() { - return decoder; - } - - public void configureCodecMethods() { - // for compatibility. Not everything (especially unit tests written by existing Grails applications) call afterPropertiesSet(), but everything calls - // configureCodecMethods() at least once - initializeCodec(); - - new CodecMetaClassSupport().configureCodecMethods(this); - } - - public int getOrder() { - return order; - } } diff --git a/grails-codecs/src/main/groovy/org/grails/commons/GrailsCodecClass.java b/grails-codecs/src/main/groovy/org/grails/commons/GrailsCodecClass.java index f3456bcb679..1591be02d1e 100644 --- a/grails-codecs/src/main/groovy/org/grails/commons/GrailsCodecClass.java +++ b/grails-codecs/src/main/groovy/org/grails/commons/GrailsCodecClass.java @@ -29,5 +29,6 @@ * @since 0.4 */ public interface GrailsCodecClass extends InjectableGrailsClass, CodecFactory { - public void configureCodecMethods(); + + void configureCodecMethods(); } diff --git a/grails-codecs/src/main/groovy/org/grails/plugins/codecs/CodecsGrailsPlugin.groovy b/grails-codecs/src/main/groovy/org/grails/plugins/codecs/CodecsGrailsPlugin.groovy index 403897ba7f8..af29028a5ee 100644 --- a/grails-codecs/src/main/groovy/org/grails/plugins/codecs/CodecsGrailsPlugin.groovy +++ b/grails-codecs/src/main/groovy/org/grails/plugins/codecs/CodecsGrailsPlugin.groovy @@ -32,6 +32,7 @@ import org.grails.encoder.impl.RawCodec * @since 0.4 */ class CodecsGrailsPlugin extends Plugin { + def version = GrailsUtil.getGrailsVersion() def dependsOn = [core: version] def watchedResources = "file:./grails-app/utils/**/*Codec.groovy" diff --git a/grails-codecs/src/main/groovy/org/grails/plugins/codecs/DefaultCodecLookup.java b/grails-codecs/src/main/groovy/org/grails/plugins/codecs/DefaultCodecLookup.java index 519ba504e2a..2596e89bf16 100644 --- a/grails-codecs/src/main/groovy/org/grails/plugins/codecs/DefaultCodecLookup.java +++ b/grails-codecs/src/main/groovy/org/grails/plugins/codecs/DefaultCodecLookup.java @@ -18,25 +18,26 @@ */ package org.grails.plugins.codecs; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import org.grails.commons.CodecArtefactHandler; import grails.core.GrailsApplication; import grails.core.GrailsClass; -import org.grails.commons.GrailsCodecClass; import grails.core.support.GrailsApplicationAware; +import org.grails.commons.CodecArtefactHandler; +import org.grails.commons.GrailsCodecClass; import org.grails.encoder.impl.BasicCodecLookup; import org.springframework.context.ApplicationContext; import org.springframework.core.OrderComparator; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + /** * @author Lari Hotari * @since 2.3 */ public class DefaultCodecLookup extends BasicCodecLookup implements GrailsApplicationAware { + protected ApplicationContext applicationContext; protected GrailsApplication grailsApplication; @@ -54,7 +55,7 @@ protected void registerCodecs() { Collections.sort(codecs, OrderComparator.INSTANCE); Collections.reverse(codecs); for (GrailsClass grailsClass : codecs) { - registerCodec((GrailsCodecClass)grailsClass); + registerCodec((GrailsCodecClass) grailsClass); } } diff --git a/grails-codecs/src/main/groovy/org/grails/plugins/codecs/HTMLCodec.java b/grails-codecs/src/main/groovy/org/grails/plugins/codecs/HTMLCodec.java index dc1366099f9..6e0a96ebfea 100644 --- a/grails-codecs/src/main/groovy/org/grails/plugins/codecs/HTMLCodec.java +++ b/grails-codecs/src/main/groovy/org/grails/plugins/codecs/HTMLCodec.java @@ -27,7 +27,6 @@ import org.grails.encoder.impl.HTML4Decoder; import org.grails.encoder.impl.HTML4Encoder; import org.grails.encoder.impl.HTMLEncoder; - import org.springframework.beans.factory.InitializingBean; /** @@ -38,23 +37,24 @@ * @since 1.1 */ public final class HTMLCodec implements CodecFactory, GrailsApplicationAware, InitializingBean { + public static final String CONFIG_PROPERTY_GSP_HTMLCODEC = "grails.views.gsp.htmlcodec"; static final String CODEC_NAME = "HTML"; - private GrailsApplication grailsApplication; - private Encoder encoder; - static final Encoder xml_encoder = new HTMLEncoder(); - static final Encoder html4_encoder = new HTML4Encoder() { + static final Encoder XML_ENCODER = new HTMLEncoder(); + static final Encoder HTML_4_ENCODER = new HTML4Encoder() { @Override public CodecIdentifier getCodecIdentifier() { return HTMLEncoder.HTML_CODEC_IDENTIFIER; } }; - static final Decoder decoder = new HTML4Decoder() { + static final Decoder DECODER = new HTML4Decoder() { @Override public CodecIdentifier getCodecIdentifier() { return HTMLEncoder.HTML_CODEC_IDENTIFIER; } }; + private GrailsApplication grailsApplication; + private Encoder encoder; public HTMLCodec() { setUseLegacyEncoder(true); @@ -65,7 +65,7 @@ public Encoder getEncoder() { } public Decoder getDecoder() { - return decoder; + return DECODER; } public void setGrailsApplication(GrailsApplication grailsApplication) { @@ -89,6 +89,6 @@ public void afterPropertiesSet() { } public void setUseLegacyEncoder(boolean useLegacyEncoder) { - encoder = useLegacyEncoder ? html4_encoder : xml_encoder; + encoder = useLegacyEncoder ? HTML_4_ENCODER : XML_ENCODER; } } diff --git a/grails-codecs/src/main/groovy/org/grails/plugins/codecs/URLCodec.groovy b/grails-codecs/src/main/groovy/org/grails/plugins/codecs/URLCodec.groovy index c25d3efd88f..835443579a5 100644 --- a/grails-codecs/src/main/groovy/org/grails/plugins/codecs/URLCodec.groovy +++ b/grails-codecs/src/main/groovy/org/grails/plugins/codecs/URLCodec.groovy @@ -28,6 +28,7 @@ import org.springframework.web.context.request.RequestContextHolder * @since 0.5 */ class URLCodec extends URLCodecFactory { + protected String resolveEncoding() { RequestContextHolder.getRequestAttributes()?.request?.characterEncoding ?: 'UTF-8' } diff --git a/grails-common/build.gradle b/grails-common/build.gradle index 3dadf85c547..66de40dc014 100644 --- a/grails-common/build.gradle +++ b/grails-common/build.gradle @@ -56,4 +56,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AbstractRecursiveAnnotationVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AbstractRecursiveAnnotationVisitor.java index a810868fd4f..e764b2c5aa2 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AbstractRecursiveAnnotationVisitor.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AbstractRecursiveAnnotationVisitor.java @@ -1,26 +1,25 @@ /* - * Copyright 2002-2024 the original author or authors. + * 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 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.apache.grails.common.annotation; -import java.lang.reflect.Field; -import java.security.AccessControlException; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.springframework.asm.AnnotationVisitor; import org.springframework.asm.SpringAsmInfo; import org.springframework.asm.Type; @@ -29,9 +28,12 @@ import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; +import java.lang.reflect.Field; +import java.security.AccessControlException; + /** * {@link AnnotationVisitor} to recursively visit annotations. - + * *

Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was * removed in Spring 6 without a public replacement. * @@ -54,14 +56,12 @@ abstract class AbstractRecursiveAnnotationVisitor extends AnnotationVisitor { @Nullable protected final ClassLoader classLoader; - public AbstractRecursiveAnnotationVisitor(@Nullable ClassLoader classLoader, AnnotationAttributes attributes) { super(SpringAsmInfo.ASM_VERSION); this.classLoader = classLoader; this.attributes = attributes; } - @Override public void visit(String attributeName, Object attributeValue) { this.attributes.put(attributeName, attributeValue); @@ -95,11 +95,9 @@ protected Object getEnumValue(String asmTypeDescriptor, String attributeValue) { ReflectionUtils.makeAccessible(enumConstant); valueToUse = enumConstant.get(null); } - } - catch (ClassNotFoundException | NoClassDefFoundError ex) { + } catch (ClassNotFoundException | NoClassDefFoundError ex) { logger.debug("Failed to classload enum type while reading annotation metadata", ex); - } - catch (IllegalAccessException | AccessControlException ex) { + } catch (IllegalAccessException | AccessControlException ex) { logger.debug("Could not access enum value while reading annotation metadata", ex); } return valueToUse; diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationAttributesReadingVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationAttributesReadingVisitor.java index 91e4bad1d05..e8506ce619b 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationAttributesReadingVisitor.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationAttributesReadingVisitor.java @@ -1,20 +1,29 @@ /* - * Copyright 2002-2024 the original author or authors. + * 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 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.apache.grails.common.annotation; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.lang.Nullable; +import org.springframework.util.MultiValueMap; +import org.springframework.util.ObjectUtils; + import java.lang.annotation.Annotation; import java.lang.reflect.Modifier; import java.util.LinkedHashSet; @@ -22,12 +31,6 @@ import java.util.Map; import java.util.Set; -import org.springframework.core.annotation.AnnotationAttributes; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.lang.Nullable; -import org.springframework.util.MultiValueMap; -import org.springframework.util.ObjectUtils; - /** * ASM visitor which looks for annotations defined on a class or method, * including meta-annotations. @@ -54,7 +57,6 @@ final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttrib private final Map> metaAnnotationMap; - public AnnotationAttributesReadingVisitor(String annotationType, MultiValueMap attributesMap, Map> metaAnnotationMap, @Nullable ClassLoader classLoader) { @@ -64,7 +66,6 @@ public AnnotationAttributesReadingVisitor(String annotationType, this.metaAnnotationMap = metaAnnotationMap; } - @Override public void visitEnd() { super.visitEnd(); @@ -74,8 +75,7 @@ public void visitEnd() { List attributeList = this.attributesMap.get(this.annotationType); if (attributeList == null) { this.attributesMap.add(this.annotationType, this.attributes); - } - else { + } else { attributeList.add(0, this.attributes); } if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationClass.getName())) { @@ -94,8 +94,7 @@ public void visitEnd() { this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames); } } - } - catch (Throwable ex) { + } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to introspect meta-annotations on " + annotationClass + ": " + ex); } @@ -119,8 +118,7 @@ private void recursivelyCollectMetaAnnotations(Set visited, Annotati for (Annotation metaMetaAnnotation : annotationType.getAnnotations()) { recursivelyCollectMetaAnnotations(visited, metaMetaAnnotation); } - } - catch (Throwable ex) { + } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to introspect meta-annotations on " + annotation + ": " + ex); } diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationMetadataReadingVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationMetadataReadingVisitor.java index 664ba4afd20..b2da940a6ec 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationMetadataReadingVisitor.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationMetadataReadingVisitor.java @@ -1,28 +1,23 @@ /* - * Copyright 2002-2024 the original author or authors. + * 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 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.apache.grails.common.annotation; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.springframework.asm.AnnotationVisitor; import org.springframework.asm.MethodVisitor; import org.springframework.asm.Opcodes; @@ -36,6 +31,14 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * ASM class visitor which looks for the class name and implemented types as * well as for the annotations defined on the class, exposing them through @@ -68,18 +71,17 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito /** * Declared as a {@link LinkedMultiValueMap} instead of a {@link MultiValueMap} * to ensure that the hierarchical ordering of the entries is preserved. + * * @see AnnotationReadingVisitorUtils#getMergedAnnotationAttributes */ protected final LinkedMultiValueMap attributesMap = new LinkedMultiValueMap<>(3); protected final Set methodMetadataSet = new LinkedHashSet<>(4); - public AnnotationMetadataReadingVisitor(@Nullable ClassLoader classLoader) { this.classLoader = classLoader; } - @Override public MergedAnnotations getAnnotations() { throw new UnsupportedOperationException(); @@ -111,7 +113,6 @@ public AnnotationVisitor visitAnnotation(String desc, boolean visible) { className, this.attributesMap, this.metaAnnotationMap, this.classLoader); } - @Override public Set getAnnotationTypes() { return this.annotationSet; diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationReadingVisitorUtils.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationReadingVisitorUtils.java index 7b20f290afc..40b2db3f1e5 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationReadingVisitorUtils.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/annotation/AnnotationReadingVisitorUtils.java @@ -1,27 +1,23 @@ /* - * Copyright 2002-2024 the original author or authors. + * 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 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.apache.grails.common.annotation; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.springframework.asm.Type; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.annotation.AnnotationUtils; @@ -31,6 +27,13 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.ObjectUtils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * Internal utility class used when reading annotations via ASM. * @@ -62,19 +65,16 @@ public static AnnotationAttributes convertClassValues(Object annotatedElement, if (value instanceof AnnotationAttributes) { value = convertClassValues( annotatedElement, classLoader, (AnnotationAttributes) value, classValuesAsString); - } - else if (value instanceof AnnotationAttributes[]) { + } else if (value instanceof AnnotationAttributes[]) { AnnotationAttributes[] values = (AnnotationAttributes[]) value; for (int i = 0; i < values.length; i++) { values[i] = convertClassValues(annotatedElement, classLoader, values[i], classValuesAsString); } value = values; - } - else if (value instanceof Type) { + } else if (value instanceof Type) { value = (classValuesAsString ? ((Type) value).getClassName() : ClassUtils.forName(((Type) value).getClassName(), classLoader)); - } - else if (value instanceof Type[]) { + } else if (value instanceof Type[]) { Type[] array = (Type[]) value; Object[] convArray = (classValuesAsString ? new String[array.length] : new Class[array.length]); @@ -83,12 +83,10 @@ else if (value instanceof Type[]) { ClassUtils.forName(array[i].getClassName(), classLoader)); } value = convArray; - } - else if (classValuesAsString) { + } else if (classValuesAsString) { if (value instanceof Class) { value = ((Class) value).getName(); - } - else if (value instanceof Class[]) { + } else if (value instanceof Class[]) { Class[] clazzArray = (Class[]) value; String[] newValue = new String[clazzArray.length]; for (int i = 0; i < clazzArray.length; i++) { @@ -98,8 +96,7 @@ else if (value instanceof Class[]) { } } entry.setValue(value); - } - catch (Throwable ex) { + } catch (Throwable ex) { // Class not found - can't resolve class reference in annotation attribute. result.put(entry.getKey(), ex); } @@ -114,12 +111,13 @@ else if (value instanceof Class[]) { *

Annotation attribute values appearing lower in the annotation * hierarchy (i.e., closer to the declaring class) will override those * defined higher in the annotation hierarchy. - * @param attributesMap the map of annotation attribute lists, keyed by - * annotation type name + * + * @param attributesMap the map of annotation attribute lists, keyed by + * annotation type name * @param metaAnnotationMap the map of meta annotation relationships, - * keyed by annotation type name - * @param annotationName the fully qualified class name of the annotation - * type to look for + * keyed by annotation type name + * @param annotationName the fully qualified class name of the annotation + * type to look for * @return the merged annotation attributes, or {@code null} if no * matching annotation is present in the {@code attributesMap} * @since 4.0.3 diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/ClassMetadataReadingVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/ClassMetadataReadingVisitor.java index c51cf9414ee..ca8934d4b49 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/ClassMetadataReadingVisitor.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/annotation/ClassMetadataReadingVisitor.java @@ -1,23 +1,23 @@ /* - * Copyright 2002-2024 the original author or authors. + * 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 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.apache.grails.common.annotation; -import java.util.LinkedHashSet; -import java.util.Set; - import org.springframework.asm.AnnotationVisitor; import org.springframework.asm.Attribute; import org.springframework.asm.ClassVisitor; @@ -30,6 +30,9 @@ import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; +import java.util.LinkedHashSet; +import java.util.Set; + /** * ASM class visitor which looks only for the class name and implemented types, * exposing them through the {@link org.springframework.core.type.ClassMetadata} @@ -73,12 +76,10 @@ class ClassMetadataReadingVisitor extends ClassVisitor implements ClassMetadata private Set memberClassNames = new LinkedHashSet<>(4); - public ClassMetadataReadingVisitor() { super(SpringAsmInfo.ASM_VERSION); } - @Override public void visit( int version, int access, String name, String signature, @Nullable String supername, String[] interfaces) { @@ -110,8 +111,7 @@ public void visitInnerClass(String name, @Nullable String outerName, String inne if (this.className.equals(fqName)) { this.enclosingClassName = fqOuterName; this.independentInnerClass = ((access & Opcodes.ACC_STATIC) != 0); - } - else if (this.className.equals(fqOuterName)) { + } else if (this.className.equals(fqOuterName)) { this.memberClassNames.add(fqName); } } @@ -151,7 +151,6 @@ public void visitEnd() { // no-op } - @Override public String getClassName() { return this.className; @@ -209,7 +208,6 @@ public String[] getMemberClassNames() { return StringUtils.toStringArray(this.memberClassNames); } - private static class EmptyAnnotationVisitor extends AnnotationVisitor { public EmptyAnnotationVisitor() { @@ -227,7 +225,6 @@ public AnnotationVisitor visitArray(String name) { } } - private static class EmptyMethodVisitor extends MethodVisitor { public EmptyMethodVisitor() { @@ -235,7 +232,6 @@ public EmptyMethodVisitor() { } } - private static class EmptyFieldVisitor extends FieldVisitor { public EmptyFieldVisitor() { diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/MethodMetadataReadingVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/MethodMetadataReadingVisitor.java index 9e06949c6af..962e058504b 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/MethodMetadataReadingVisitor.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/annotation/MethodMetadataReadingVisitor.java @@ -1,25 +1,23 @@ /* - * Copyright 2002-2024 the original author or authors. + * 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 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.apache.grails.common.annotation; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.springframework.asm.AnnotationVisitor; import org.springframework.asm.MethodVisitor; import org.springframework.asm.Opcodes; @@ -32,6 +30,11 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * ASM method visitor which looks for the annotations defined on a method, * exposing them through the {@link org.springframework.core.type.MethodMetadata} @@ -70,7 +73,6 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho protected final LinkedMultiValueMap attributesMap = new LinkedMultiValueMap<>(3); - public MethodMetadataReadingVisitor(String methodName, int access, String declaringClassName, String returnTypeName, @Nullable ClassLoader classLoader, Set methodMetadataSet) { @@ -83,7 +85,6 @@ public MethodMetadataReadingVisitor(String methodName, int access, String declar this.methodMetadataSet = methodMetadataSet; } - @Override public MergedAnnotations getAnnotations() { throw new UnsupportedOperationException(); @@ -101,7 +102,6 @@ public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { className, this.attributesMap, this.metaAnnotationMap, this.classLoader); } - @Override public String getMethodName() { return this.methodName; diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationArrayVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationArrayVisitor.java index d7ee022739c..e97077b16bf 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationArrayVisitor.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationArrayVisitor.java @@ -1,31 +1,34 @@ /* - * Copyright 2002-2024 the original author or authors. + * 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 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.apache.grails.common.annotation; -import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.List; - import org.springframework.asm.AnnotationVisitor; import org.springframework.asm.Type; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; +import java.lang.annotation.Annotation; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; + /** * {@link AnnotationVisitor} to recursively visit annotation arrays. * @@ -46,7 +49,6 @@ class RecursiveAnnotationArrayVisitor extends AbstractRecursiveAnnotationVisitor private final List allNestedAttributes = new ArrayList<>(); - public RecursiveAnnotationArrayVisitor( String attributeName, AnnotationAttributes attributes, @Nullable ClassLoader classLoader) { @@ -54,15 +56,13 @@ public RecursiveAnnotationArrayVisitor( this.attributeName = attributeName; } - @Override public void visit(String attributeName, Object attributeValue) { Object newValue = attributeValue; Object existingValue = this.attributes.get(this.attributeName); if (existingValue != null) { newValue = ObjectUtils.addObjectToArray((Object[]) existingValue, newValue); - } - else { + } else { Class arrayClass = newValue.getClass(); if (Enum.class.isAssignableFrom(arrayClass)) { while (arrayClass.getSuperclass() != null && !arrayClass.isEnum()) { @@ -88,8 +88,7 @@ public AnnotationVisitor visitAnnotation(String attributeName, String asmTypeDes public void visitEnd() { if (!this.allNestedAttributes.isEmpty()) { this.attributes.put(this.attributeName, this.allNestedAttributes.toArray(new AnnotationAttributes[0])); - } - else if (!this.attributes.containsKey(this.attributeName)) { + } else if (!this.attributes.containsKey(this.attributeName)) { Class annotationType = this.attributes.annotationType(); if (annotationType != null) { try { @@ -101,8 +100,7 @@ else if (!this.attributes.containsKey(this.attributeName)) { } this.attributes.put(this.attributeName, Array.newInstance(elementType, 0)); } - } - catch (NoSuchMethodException ex) { + } catch (NoSuchMethodException ex) { // Corresponding attribute method not found: cannot expose empty array. } } diff --git a/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationAttributesVisitor.java b/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationAttributesVisitor.java index dc8b935d1a6..ae233a0b2fb 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationAttributesVisitor.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/annotation/RecursiveAnnotationAttributesVisitor.java @@ -1,27 +1,29 @@ /* - * Copyright 2002-2024 the original author or authors. + * 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 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.apache.grails.common.annotation; -import org.springframework.asm.AnnotationVisitor; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.lang.Nullable; /** - * {@link AnnotationVisitor} to recursively visit annotation attributes. + * {@link org.springframework.asm.AnnotationVisitor} to recursively visit annotation attributes. * *

Note: This class was ported to Grails 7 from Spring Framework 5.3 as it was * removed in Spring 6 without a public replacement. @@ -38,7 +40,6 @@ class RecursiveAnnotationAttributesVisitor extends AbstractRecursiveAnnotationVi protected final String annotationType; - public RecursiveAnnotationAttributesVisitor( String annotationType, AnnotationAttributes attributes, @Nullable ClassLoader classLoader) { @@ -46,7 +47,6 @@ public RecursiveAnnotationAttributesVisitor( this.annotationType = annotationType; } - @Override public void visitEnd() { AnnotationUtils.registerDefaultValues(this.attributes); diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/GroovyTransformOrder.groovy b/grails-common/src/main/groovy/org/apache/grails/common/compiler/GroovyTransformOrder.groovy index 88804912f30..9e1bf73eebc 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/GroovyTransformOrder.groovy +++ b/grails-common/src/main/groovy/org/apache/grails/common/compiler/GroovyTransformOrder.groovy @@ -1,18 +1,20 @@ /* - * 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.apache.grails.common.compiler @@ -23,6 +25,7 @@ import groovy.transform.CompileStatic */ @CompileStatic interface GroovyTransformOrder { + static final int HIGHEST_PRIORITY = Integer.MAX_VALUE static final int HIGHEST_STARTING_PRIORITY = HIGHEST_PRIORITY - 1000000 static final int DECREMENT_PRIORITY = -5 diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/AnnotationMetadataReader.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/AnnotationMetadataReader.java index 98a5342bdec..e7e536e02c4 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/AnnotationMetadataReader.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/AnnotationMetadataReader.java @@ -1,18 +1,20 @@ /* - * 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.apache.grails.common.compiler.asm; @@ -36,6 +38,7 @@ * @since 3.1.13 */ public class AnnotationMetadataReader implements MetadataReader { + private final Resource resource; private final ClassMetadata classMetadata; @@ -44,18 +47,20 @@ public class AnnotationMetadataReader implements MetadataReader { /** * Reads only the annotation names from a class resource - * @param resource The resource + * + * @param resource The resource * @param classLoader The classloader * @throws IOException */ public AnnotationMetadataReader(Resource resource, ClassLoader classLoader) throws IOException { this(resource, classLoader, false); } + /** * Constructs a new annotation metadata reader * - * @param resource The resource - * @param classLoader The classloader + * @param resource The resource + * @param classLoader The classloader * @param readAttributeValues Whether to read the attributes in addition or just the annotation class names * @throws IOException */ @@ -64,22 +69,18 @@ public AnnotationMetadataReader(Resource resource, ClassLoader classLoader, bool ClassReader classReader; try { classReader = new ClassReader(is); - } - catch (IllegalArgumentException ex) { + } catch (IllegalArgumentException ex) { throw new IOException("ASM ClassReader failed to parse class file - " + "probably due to a new Java class file version that isn't supported yet: " + resource, ex); - } - finally { + } finally { is.close(); } - AnnotationMetadataReadingVisitor visitor; - if(readAttributeValues) { + if (readAttributeValues) { visitor = new AnnotationMetadataReadingVisitor(classLoader); - } - else { + } else { visitor = new AnnotationMetadataReadingVisitor(classLoader) { @Override public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { @@ -97,7 +98,6 @@ public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { this.resource = resource; } - @Override public Resource getResource() { return this.resource; diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Attribute.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Attribute.java index 356d618d192..d57befba9be 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Attribute.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Attribute.java @@ -1,31 +1,20 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. +/* + * 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 * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * https://www.apache.org/licenses/LICENSE-2.0 * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. + * 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.common.compiler.asm; @@ -40,11 +29,6 @@ */ class Attribute { - /** - * The type of this attribute. - */ - public final String type; - /** * The raw value of this attribute, used only for unknown attributes. */ @@ -55,11 +39,15 @@ class Attribute { */ Attribute next; + /** + * The type of this attribute. + */ + private final String type; + /** * Constructs a new empty attribute. * - * @param type - * the type of the attribute. + * @param type the type of the attribute. */ protected Attribute(final String type) { this.type = type; @@ -88,7 +76,7 @@ public boolean isCodeAttribute() { * Returns the labels corresponding to this attribute. * * @return the labels corresponding to this attribute, or null if - * this attribute is not a code attribute that contains labels. + * this attribute is not a code attribute that contains labels. */ protected Label[] getLabels() { return null; @@ -100,63 +88,56 @@ protected Label[] getLabels() { * corresponding to the len bytes starting at the given offset, in * the given class reader. * - * @param cr - * the class that contains the attribute to be read. - * @param off - * index of the first byte of the attribute's content in - * {@link ClassReader#b cr.b}. The 6 attribute header bytes, - * containing the type and the length of the attribute, are not - * taken into account here. - * @param len - * the length of the attribute's content. - * @param buf - * buffer to be used to call {@link ClassReader#readUTF8 - * readUTF8}, {@link ClassReader#readClass(int,char[]) readClass} - * or {@link ClassReader#readConst readConst}. - * @param codeOff - * index of the first byte of code's attribute content in - * {@link ClassReader#b cr.b}, or -1 if the attribute to be read - * is not a code attribute. The 6 attribute header bytes, - * containing the type and the length of the attribute, are not - * taken into account here. - * @param labels - * the labels of the method's code, or null if the - * attribute to be read is not a code attribute. + * @param cr the class that contains the attribute to be read. + * @param off index of the first byte of the attribute's content in + * {@link ClassReader#b cr.b}. The 6 attribute header bytes, + * containing the type and the length of the attribute, are not + * taken into account here. + * @param len the length of the attribute's content. + * @param buf buffer to be used to call {@link ClassReader#readUTF8 + * readUTF8}, {@link ClassReader#readClass(int, char[]) readClass} + * or {@link ClassReader#readConst readConst}. + * @param codeOff index of the first byte of code's attribute content in + * {@link ClassReader#b cr.b}, or -1 if the attribute to be read + * is not a code attribute. The 6 attribute header bytes, + * containing the type and the length of the attribute, are not + * taken into account here. + * @param labels the labels of the method's code, or null if the + * attribute to be read is not a code attribute. * @return a new {@link Attribute} object corresponding to the given - * bytes. + * bytes. */ protected Attribute read(final ClassReader cr, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) { Attribute attr = new Attribute(type); attr.value = new byte[len]; - System.arraycopy(cr.b, off, attr.value, 0, len); + System.arraycopy(cr.getB(), off, attr.value, 0, len); return attr; } + public String getType() { + return type; + } + /** * Returns the byte array form of this attribute. * - * @param cw - * the class to which this attribute must be added. This - * parameter can be used to add to the constant pool of this - * class the items that corresponds to this attribute. - * @param code - * the bytecode of the method corresponding to this code - * attribute, or null if this attribute is not a code - * attributes. - * @param len - * the length of the bytecode of the method corresponding to this - * code attribute, or null if this attribute is not a - * code attribute. - * @param maxStack - * the maximum stack size of the method corresponding to this - * code attribute, or -1 if this attribute is not a code - * attribute. - * @param maxLocals - * the maximum number of local variables of the method - * corresponding to this code attribute, or -1 if this attribute - * is not a code attribute. + * @param cw the class to which this attribute must be added. This + * parameter can be used to add to the constant pool of this + * class the items that corresponds to this attribute. + * @param code the bytecode of the method corresponding to this code + * attribute, or null if this attribute is not a code + * attributes. + * @param len the length of the bytecode of the method corresponding to this + * code attribute, or null if this attribute is not a + * code attribute. + * @param maxStack the maximum stack size of the method corresponding to this + * code attribute, or -1 if this attribute is not a code + * attribute. + * @param maxLocals the maximum number of local variables of the method + * corresponding to this code attribute, or -1 if this attribute + * is not a code attribute. * @return the byte array form of this attribute. */ protected ByteVector write(final ClassWriter cw, final byte[] code, @@ -185,27 +166,22 @@ final int getCount() { /** * Returns the size of all the attributes in this attribute list. * - * @param cw - * the class writer to be used to convert the attributes into - * byte arrays, with the {@link #write write} method. - * @param code - * the bytecode of the method corresponding to these code - * attributes, or null if these attributes are not code - * attributes. - * @param len - * the length of the bytecode of the method corresponding to - * these code attributes, or null if these attributes - * are not code attributes. - * @param maxStack - * the maximum stack size of the method corresponding to these - * code attributes, or -1 if these attributes are not code - * attributes. - * @param maxLocals - * the maximum number of local variables of the method - * corresponding to these code attributes, or -1 if these - * attributes are not code attributes. + * @param cw the class writer to be used to convert the attributes into + * byte arrays, with the {@link #write write} method. + * @param code the bytecode of the method corresponding to these code + * attributes, or null if these attributes are not code + * attributes. + * @param len the length of the bytecode of the method corresponding to + * these code attributes, or null if these attributes + * are not code attributes. + * @param maxStack the maximum stack size of the method corresponding to these + * code attributes, or -1 if these attributes are not code + * attributes. + * @param maxLocals the maximum number of local variables of the method + * corresponding to these code attributes, or -1 if these + * attributes are not code attributes. * @return the size of all the attributes in this attribute list. This size - * includes the size of the attribute headers. + * includes the size of the attribute headers. */ final int getSize(final ClassWriter cw, final byte[] code, final int len, final int maxStack, final int maxLocals) { @@ -223,27 +199,21 @@ final int getSize(final ClassWriter cw, final byte[] code, final int len, * Writes all the attributes of this attribute list in the given byte * vector. * - * @param cw - * the class writer to be used to convert the attributes into - * byte arrays, with the {@link #write write} method. - * @param code - * the bytecode of the method corresponding to these code - * attributes, or null if these attributes are not code - * attributes. - * @param len - * the length of the bytecode of the method corresponding to - * these code attributes, or null if these attributes - * are not code attributes. - * @param maxStack - * the maximum stack size of the method corresponding to these - * code attributes, or -1 if these attributes are not code - * attributes. - * @param maxLocals - * the maximum number of local variables of the method - * corresponding to these code attributes, or -1 if these - * attributes are not code attributes. - * @param out - * where the attributes must be written. + * @param cw the class writer to be used to convert the attributes into + * byte arrays, with the {@link #write write} method. + * @param code the bytecode of the method corresponding to these code + * attributes, or null if these attributes are not code + * attributes. + * @param len the length of the bytecode of the method corresponding to + * these code attributes, or null if these attributes + * are not code attributes. + * @param maxStack the maximum stack size of the method corresponding to these + * code attributes, or -1 if these attributes are not code + * attributes. + * @param maxLocals the maximum number of local variables of the method + * corresponding to these code attributes, or -1 if these + * attributes are not code attributes. + * @param out where the attributes must be written. */ final void put(final ClassWriter cw, final byte[] code, final int len, final int maxStack, final int maxLocals, final ByteVector out) { diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ByteVector.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ByteVector.java index d3f08fdb14a..f035c2d74fb 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ByteVector.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ByteVector.java @@ -1,31 +1,20 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. +/* + * 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 * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * https://www.apache.org/licenses/LICENSE-2.0 * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. + * 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.common.compiler.asm; @@ -59,8 +48,7 @@ public ByteVector() { * Constructs a new {@link ByteVector ByteVector} with the given initial * size. * - * @param initialSize - * the initial size of the byte vector to be constructed. + * @param initialSize the initial size of the byte vector to be constructed. */ public ByteVector(final int initialSize) { data = new byte[initialSize]; @@ -70,8 +58,7 @@ public ByteVector(final int initialSize) { * Puts a byte into this byte vector. The byte vector is automatically * enlarged if necessary. * - * @param b - * a byte. + * @param b a byte. * @return this byte vector. */ public ByteVector putByte(final int b) { @@ -88,10 +75,8 @@ public ByteVector putByte(final int b) { * Puts two bytes into this byte vector. The byte vector is automatically * enlarged if necessary. * - * @param b1 - * a byte. - * @param b2 - * another byte. + * @param b1 a byte. + * @param b2 another byte. * @return this byte vector. */ ByteVector put11(final int b1, final int b2) { @@ -110,8 +95,7 @@ ByteVector put11(final int b1, final int b2) { * Puts a short into this byte vector. The byte vector is automatically * enlarged if necessary. * - * @param s - * a short. + * @param s a short. * @return this byte vector. */ public ByteVector putShort(final int s) { @@ -130,10 +114,8 @@ public ByteVector putShort(final int s) { * Puts a byte and a short into this byte vector. The byte vector is * automatically enlarged if necessary. * - * @param b - * a byte. - * @param s - * a short. + * @param b a byte. + * @param s a short. * @return this byte vector. */ ByteVector put12(final int b, final int s) { @@ -153,8 +135,7 @@ ByteVector put12(final int b, final int s) { * Puts an int into this byte vector. The byte vector is automatically * enlarged if necessary. * - * @param i - * an int. + * @param i an int. * @return this byte vector. */ public ByteVector putInt(final int i) { @@ -175,8 +156,7 @@ public ByteVector putInt(final int i) { * Puts a long into this byte vector. The byte vector is automatically * enlarged if necessary. * - * @param l - * a long. + * @param l a long. * @return this byte vector. */ public ByteVector putLong(final long l) { @@ -203,8 +183,7 @@ public ByteVector putLong(final long l) { * Puts an UTF8 string into this byte vector. The byte vector is * automatically enlarged if necessary. * - * @param s - * a String whose UTF8 encoded length must be less than 65536. + * @param s a String whose UTF8 encoded length must be less than 65536. * @return this byte vector. */ public ByteVector putUTF8(final String s) { @@ -244,15 +223,12 @@ public ByteVector putUTF8(final String s) { * bytes before the encoded characters, if there is space for that (i.e. if * this.length - i - 2 >= 0). * - * @param s - * the String to encode. - * @param i - * the index of the first character to encode. The previous - * characters are supposed to have already been encoded, using - * only one byte per character. - * @param maxByteLength - * the maximum byte length of the encoded string, including the - * already encoded characters. + * @param s the String to encode. + * @param i the index of the first character to encode. The previous + * characters are supposed to have already been encoded, using + * only one byte per character. + * @param maxByteLength the maximum byte length of the encoded string, including the + * already encoded characters. * @return this byte vector. */ ByteVector encodeUTF8(final String s, int i, int maxByteLength) { @@ -302,13 +278,10 @@ ByteVector encodeUTF8(final String s, int i, int maxByteLength) { * Puts an array of bytes into this byte vector. The byte vector is * automatically enlarged if necessary. * - * @param b - * an array of bytes. May be null to put len + * @param b an array of bytes. May be null to put len * null bytes into this byte vector. - * @param off - * index of the fist byte of b that must be copied. - * @param len - * number of bytes of b that must be copied. + * @param off index of the fist byte of b that must be copied. + * @param len number of bytes of b that must be copied. * @return this byte vector. */ public ByteVector putByteArray(final byte[] b, final int off, final int len) { @@ -325,9 +298,8 @@ public ByteVector putByteArray(final byte[] b, final int off, final int len) { /** * Enlarge this byte vector so that it can receive n more bytes. * - * @param size - * number of additional bytes that this byte vector should be - * able to receive. + * @param size number of additional bytes that this byte vector should be + * able to receive. */ private void enlarge(final int size) { int length1 = 2 * data.length; diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ClassReader.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ClassReader.java index e7afd738836..c228582bb1b 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ClassReader.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/ClassReader.java @@ -1,35 +1,31 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. +/* + * 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 * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * https://www.apache.org/licenses/LICENSE-2.0 * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. + * 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.common.compiler.asm; -import org.springframework.asm.*; +import org.springframework.asm.AnnotationVisitor; +import org.springframework.asm.ClassVisitor; +import org.springframework.asm.Handle; +import org.springframework.asm.Label; +import org.springframework.asm.MethodVisitor; +import org.springframework.asm.Opcodes; +import org.springframework.asm.Type; + import java.io.IOException; import java.io.InputStream; @@ -43,13 +39,22 @@ * @author Eugene Kuleshov */ class ClassReader { + + /** + * Flag to skip the debug information in the class. If this flag is set the + * debug information of the class is not visited, i.e. the + * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and + * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be + * called. + */ + public static final int SKIP_DEBUG = 2; + /** * Pseudo access flag to distinguish between the synthetic attribute and the * synthetic access flag. */ static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000; - /** * The type of CONSTANT_Class constant pool items. */ @@ -130,22 +135,18 @@ class ClassReader { */ static final boolean ANNOTATIONS = true; - - /** - * Flag to skip the debug information in the class. If this flag is set the - * debug information of the class is not visited, i.e. the - * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and - * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be - * called. - */ - public static final int SKIP_DEBUG = 2; - /** * The class to be parsed. The content of this array must not be * modified. This field is intended for {@link Attribute} sub classes, and * is normally not needed by class generators or adapters. */ - public final byte[] b; + private final byte[] b; + + /** + * Start index of the class header information (access, name...) in + * {@link #b b}. + */ + private final int header; /** * The start index of each constant pool item in {@link #b b}, plus one. The @@ -170,43 +171,49 @@ class ClassReader { private final int maxStringLength; /** - * Start index of the class header information (access, name...) in - * {@link #b b}. + * Constructs a new {@link ClassReader} object. + * + * @param b the bytecode of the class to be read. */ - public final int header; + private ClassReader(final byte[] b) { + this(b, 0, b.length); + } - // ------------------------------------------------------------------------ - // Constructors - // ------------------------------------------------------------------------ + /** + * Constructs a new {@link ClassReader} object. + * + * @param is an input stream from which to read the class. + * @throws IOException if a problem occurs during reading. + */ + public ClassReader(final InputStream is) throws IOException { + this(readClass(is, false)); + } /** * Constructs a new {@link ClassReader} object. * - * @param b - * the bytecode of the class to be read. + * @param name the binary qualified name of the class to be read. + * @throws IOException if an exception occurs during reading. */ - private ClassReader(final byte[] b) { - this(b, 0, b.length); + public ClassReader(final String name) throws IOException { + this(readClass(ClassLoader.getSystemResourceAsStream(name.replace('.', '/') + ".class"), true)); } /** * Constructs a new {@link ClassReader} object. * - * @param b - * the bytecode of the class to be read. - * @param off - * the start offset of the class data. - * @param len - * the length of the class data. + * @param b the bytecode of the class to be read. + * @param off the start offset of the class data. + * @param len the length of the class data. */ public ClassReader(final byte[] b, final int off, final int len) { this.b = b; // checks the class version - /* SPRING PATCH: REMOVED FOR FORWARD COMPATIBILITY WITH JDK 9 + /* SPRING PATCH: REMOVED FOR FORWARD COMPATIBILITY WITH JDK 9 if (readShort(off + 6) > Opcodes.V1_8) { throw new IllegalArgumentException(); } - */ + */ // parses the constant pool items = new int[readUnsignedShort(off + 8)]; int n = items.length; @@ -254,13 +261,20 @@ public ClassReader(final byte[] b, final int off, final int len) { header = index; } + public byte[] getB() { + return b; + } + + public int getHeader() { + return header; + } + /** * Returns the class's access flags (see {@link Opcodes}). This value may * not reflect Deprecated and Synthetic flags when bytecode is before 1.5 * and those flags are represented by attributes. * * @return the class access flags - * * @see ClassVisitor#visit(int, int, String, String, String, String[]) */ public int getAccess() { @@ -272,7 +286,6 @@ public int getAccess() { * {@link Type#getInternalName() getInternalName}). * * @return the internal class name - * * @see ClassVisitor#visit(int, int, String, String, String, String[]) */ public String getClassName() { @@ -285,8 +298,7 @@ public String getClassName() { * super class is {@link Object}. * * @return the internal name of super class, or null for - * {@link Object} class. - * + * {@link Object} class. * @see ClassVisitor#visit(int, int, String, String, String, String[]) */ public String getSuperName() { @@ -298,8 +310,7 @@ public String getSuperName() { * {@link Type#getInternalName() getInternalName}). * * @return the array of internal names for all implemented interfaces or - * null. - * + * null. * @see ClassVisitor#visit(int, int, String, String, String, String[]) */ public String[] getInterfaces() { @@ -316,49 +327,15 @@ public String[] getInterfaces() { return interfaces; } - - - - - /** - * Constructs a new {@link ClassReader} object. - * - * @param is - * an input stream from which to read the class. - * @throws IOException - * if a problem occurs during reading. - */ - public ClassReader(final InputStream is) throws IOException { - this(readClass(is, false)); - } - - /** - * Constructs a new {@link ClassReader} object. - * - * @param name - * the binary qualified name of the class to be read. - * @throws IOException - * if an exception occurs during reading. - */ - public ClassReader(final String name) throws IOException { - this(readClass( - ClassLoader.getSystemResourceAsStream(name.replace('.', '/') - + ".class"), true)); - } - /** * Reads the bytecode of a class. * - * @param is - * an input stream from which to read the class. - * @param close - * true to close the input stream after reading. + * @param is an input stream from which to read the class. + * @param close true to close the input stream after reading. * @return the bytecode read from the given input stream. - * @throws IOException - * if a problem occurs during reading. + * @throws IOException if a problem occurs during reading. */ - private static byte[] readClass(final InputStream is, boolean close) - throws IOException { + private static byte[] readClass(final InputStream is, boolean close) throws IOException { if (is == null) { throw new IOException("Class not found"); } @@ -403,8 +380,7 @@ private static byte[] readClass(final InputStream is, boolean close) * . This class is the one specified in the constructor (see * {@link #ClassReader(byte[]) ClassReader}). * - * @param classVisitor - * the visitor that must visit this class. + * @param classVisitor the visitor that must visit this class. */ public void accept(final ClassVisitor classVisitor, final int flags) { accept(classVisitor, new Attribute[0], flags); @@ -415,20 +391,17 @@ public void accept(final ClassVisitor classVisitor, final int flags) { * This class is the one specified in the constructor (see * {@link #ClassReader(byte[]) ClassReader}). * - * @param classVisitor - * the visitor that must visit this class. - * @param attrs - * prototypes of the attributes that must be parsed during the - * visit of the class. Any attribute whose type is not equal to - * the type of one the prototypes will not be parsed: its byte - * array value will be passed unchanged to the ClassWriter. - * This may corrupt it if this value contains references to - * the constant pool, or has syntactic or semantic links with a - * class element that has been transformed by a class adapter - * between the reader and the writer. - */ - public void accept(final ClassVisitor classVisitor, - final Attribute[] attrs, final int flags) { + * @param classVisitor the visitor that must visit this class. + * @param attrs prototypes of the attributes that must be parsed during the + * visit of the class. Any attribute whose type is not equal to + * the type of one the prototypes will not be parsed: its byte + * array value will be passed unchanged to the ClassWriter. + * This may corrupt it if this value contains references to + * the constant pool, or has syntactic or semantic links with a + * class element that has been transformed by a class adapter + * between the reader and the writer. + */ + public void accept(final ClassVisitor classVisitor, final Attribute[] attrs, final int flags) { int u = header; // current offset in the class file char[] c = new char[maxStringLength]; // buffer used to read strings @@ -480,25 +453,20 @@ public void accept(final ClassVisitor classVisitor, } } else if (SIGNATURES && "Signature".equals(attrName)) { signature = readUTF8(u + 8, c); - } else if (ANNOTATIONS - && "RuntimeVisibleAnnotations".equals(attrName)) { + } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) { anns = u + 8; - } else if (ANNOTATIONS - && "RuntimeVisibleTypeAnnotations".equals(attrName)) { + } else if (ANNOTATIONS && "RuntimeVisibleTypeAnnotations".equals(attrName)) { tanns = u + 8; } else if ("Deprecated".equals(attrName)) { access |= Opcodes.ACC_DEPRECATED; } else if ("Synthetic".equals(attrName)) { - access |= Opcodes.ACC_SYNTHETIC - | ACC_SYNTHETIC_ATTRIBUTE; + access |= Opcodes.ACC_SYNTHETIC | ACC_SYNTHETIC_ATTRIBUTE; } else if ("SourceDebugExtension".equals(attrName)) { int len = readInt(u + 4); sourceDebug = readUTF(u + 8, len, new char[len]); - } else if (ANNOTATIONS - && "RuntimeInvisibleAnnotations".equals(attrName)) { + } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) { ianns = u + 8; - } else if (ANNOTATIONS - && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { + } else if (ANNOTATIONS && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { itanns = u + 8; } else if ("BootstrapMethods".equals(attrName)) { int[] bootstrapMethods = new int[readUnsignedShort(u + 8)]; @@ -508,8 +476,7 @@ public void accept(final ClassVisitor classVisitor, } context.bootstrapMethods = bootstrapMethods; } else { - Attribute attr = readAttribute(attrs, attrName, u + 8, - readInt(u + 4), c, -1, null); + Attribute attr = readAttribute(attrs, attrName, u + 8, readInt(u + 4), c, -1, null); if (attr != null) { attr.next = attributes; attributes = attr; @@ -519,32 +486,27 @@ public void accept(final ClassVisitor classVisitor, } // visits the class declaration - classVisitor.visit(readInt(items[1] - 7), access, name, signature, - superClass, interfaces); + classVisitor.visit(readInt(items[1] - 7), access, name, signature, superClass, interfaces); // visits the source and debug info - if ((flags & SKIP_DEBUG) == 0 - && (sourceFile != null || sourceDebug != null)) { + if ((flags & SKIP_DEBUG) == 0 && (sourceFile != null || sourceDebug != null)) { classVisitor.visitSource(sourceFile, sourceDebug); } // visits the outer class if (enclosingOwner != null) { - classVisitor.visitOuterClass(enclosingOwner, enclosingName, - enclosingDesc); + classVisitor.visitOuterClass(enclosingOwner, enclosingName, enclosingDesc); } // visits the class annotations and type annotations if (ANNOTATIONS && anns != 0) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - classVisitor.visitAnnotation(readUTF8(v, c), true)); + v = readAnnotationValues(v + 2, c, true, classVisitor.visitAnnotation(readUTF8(v, c), true)); } } if (ANNOTATIONS && ianns != 0) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { - v = readAnnotationValues(v + 2, c, true, - classVisitor.visitAnnotation(readUTF8(v, c), false)); + v = readAnnotationValues(v + 2, c, true, classVisitor.visitAnnotation(readUTF8(v, c), false)); } } @@ -555,22 +517,17 @@ public void accept(final ClassVisitor classVisitor, /** * Reads the values of an annotation and makes the given visitor visit them. * - * @param v - * the start offset in {@link #b b} of the values to be read - * (including the unsigned short that gives the number of - * values). - * @param buf - * buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or {@link #readConst - * readConst}. - * @param named - * if the annotation values are named or not. - * @param av - * the visitor that must visit the values. + * @param v the start offset in {@link #b b} of the values to be read + * (including the unsigned short that gives the number of + * values). + * @param buf buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int, char[]) readClass} or {@link #readConst + * readConst}. + * @param named if the annotation values are named or not. + * @param av the visitor that must visit the values. * @return the end offset of the annotation values. */ - private int readAnnotationValues(int v, final char[] buf, - final boolean named, final AnnotationVisitor av) { + private int readAnnotationValues(int v, final char[] buf, final boolean named, final AnnotationVisitor av) { int i = readUnsignedShort(v); v += 2; if (named) { @@ -591,21 +548,16 @@ private int readAnnotationValues(int v, final char[] buf, /** * Reads a value of an annotation and makes the given visitor visit it. * - * @param v - * the start offset in {@link #b b} of the value to be read - * (not including the value name constant pool index). - * @param buf - * buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or {@link #readConst - * readConst}. - * @param name - * the name of the value to be read. - * @param av - * the visitor that must visit the value. + * @param v the start offset in {@link #b b} of the value to be read + * (not including the value name constant pool index). + * @param buf buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int, char[]) readClass} or {@link #readConst + * readConst}. + * @param name the name of the value to be read. + * @param av the visitor that must visit the value. * @return the end offset of the annotation value. */ - private int readAnnotationValue(int v, final char[] buf, final String name, - final AnnotationVisitor av) { + private int readAnnotationValue(int v, final char[] buf, final String name, final AnnotationVisitor av) { int i; if (av == null) { switch (b[v] & 0xFF) { @@ -656,15 +608,13 @@ private int readAnnotationValue(int v, final char[] buf, final String name, v += 2; break; case '@': // annotation_value - v = readAnnotationValues(v + 2, buf, true, - av.visitAnnotation(name, readUTF8(v, buf))); + v = readAnnotationValues(v + 2, buf, true, av.visitAnnotation(name, readUTF8(v, buf))); break; case '[': // array_value int size = readUnsignedShort(v); v += 2; if (size == 0) { - return readAnnotationValues(v - 2, buf, false, - av.visitArray(name)); + return readAnnotationValues(v - 2, buf, false, av.visitArray(name)); } switch (this.b[v++] & 0xFF) { case 'B': @@ -724,8 +674,7 @@ private int readAnnotationValue(int v, final char[] buf, final String name, case 'F': float[] fv = new float[size]; for (i = 0; i < size; i++) { - fv[i] = Float - .intBitsToFloat(readInt(items[readUnsignedShort(v)])); + fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)])); v += 3; } av.visit(name, fv); @@ -734,8 +683,7 @@ private int readAnnotationValue(int v, final char[] buf, final String name, case 'D': double[] dv = new double[size]; for (i = 0; i < size; i++) { - dv[i] = Double - .longBitsToDouble(readLong(items[readUnsignedShort(v)])); + dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)])); v += 3; } av.visit(name, dv); @@ -744,22 +692,22 @@ private int readAnnotationValue(int v, final char[] buf, final String name, default: v = readAnnotationValues(v - 3, buf, false, av.visitArray(name)); } + default: + // do nothing + break; } return v; } - /** * Returns the label corresponding to the given offset. The default * implementation of this method creates a label for the given offset if it * has not been already created. * - * @param offset - * a bytecode offset in a method. - * @param labels - * the already created labels, indexed by their offset. If a - * label already exists for offset this method must not create a - * new one. Otherwise it must store the new label in this array. + * @param offset a bytecode offset in a method. + * @param labels the already created labels, indexed by their offset. If a + * label already exists for offset this method must not create a + * new one. Otherwise it must store the new label in this array. * @return a non null Label, which must be equal to labels[offset]. */ protected Label readLabel(int offset, Label[] labels) { @@ -803,55 +751,44 @@ private int getAttributes() { /** * Reads an attribute in {@link #b b}. * - * @param attrs - * prototypes of the attributes that must be parsed during the - * visit of the class. Any attribute whose type is not equal to - * the type of one the prototypes is ignored (i.e. an empty - * {@link Attribute} instance is returned). - * @param type - * the type of the attribute. - * @param off - * index of the first byte of the attribute's content in - * {@link #b b}. The 6 attribute header bytes, containing the - * type and the length of the attribute, are not taken into - * account here (they have already been read). - * @param len - * the length of the attribute's content. - * @param buf - * buffer to be used to call {@link #readUTF8 readUTF8}, - * {@link #readClass(int,char[]) readClass} or {@link #readConst - * readConst}. - * @param codeOff - * index of the first byte of code's attribute content in - * {@link #b b}, or -1 if the attribute to be read is not a code - * attribute. The 6 attribute header bytes, containing the type - * and the length of the attribute, are not taken into account - * here. - * @param labels - * the labels of the method's code, or null if the - * attribute to be read is not a code attribute. + * @param attrs prototypes of the attributes that must be parsed during the + * visit of the class. Any attribute whose type is not equal to + * the type of one the prototypes is ignored (i.e. an empty + * {@link Attribute} instance is returned). + * @param type the type of the attribute. + * @param off index of the first byte of the attribute's content in + * {@link #b b}. The 6 attribute header bytes, containing the + * type and the length of the attribute, are not taken into + * account here (they have already been read). + * @param len the length of the attribute's content. + * @param buf buffer to be used to call {@link #readUTF8 readUTF8}, + * {@link #readClass(int, char[]) readClass} or {@link #readConst + * readConst}. + * @param codeOff index of the first byte of code's attribute content in + * {@link #b b}, or -1 if the attribute to be read is not a code + * attribute. The 6 attribute header bytes, containing the type + * and the length of the attribute, are not taken into account + * here. + * @param labels the labels of the method's code, or null if the + * attribute to be read is not a code attribute. * @return the attribute that has been read, or null to skip this - * attribute. + * attribute. */ - private Attribute readAttribute(final Attribute[] attrs, final String type, - final int off, final int len, final char[] buf, final int codeOff, - final Label[] labels) { + private Attribute readAttribute(final Attribute[] attrs, final String type, final int off, final int len, final char[] buf, final int codeOff, final Label[] labels) { for (int i = 0; i < attrs.length; ++i) { - if (attrs[i].type.equals(type)) { + if (attrs[i].getType().equals(type)) { return attrs[i].read(this, off, len, buf, codeOff, labels); } } return new Attribute(type).read(this, off, len, null, -1, null); } - /** * Reads a byte value in {@link #b b}. This method is intended for * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. * - * @param index - * the start index of the value to be read in {@link #b b}. + * @param index the start index of the value to be read in {@link #b b}. * @return the read value. */ public int readByte(final int index) { @@ -863,8 +800,7 @@ public int readByte(final int index) { * for {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. * - * @param index - * the start index of the value to be read in {@link #b b}. + * @param index the start index of the value to be read in {@link #b b}. * @return the read value. */ public int readUnsignedShort(final int index) { @@ -877,8 +813,7 @@ public int readUnsignedShort(final int index) { * for {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. * - * @param index - * the start index of the value to be read in {@link #b b}. + * @param index the start index of the value to be read in {@link #b b}. * @return the read value. */ public short readShort(final int index) { @@ -891,14 +826,12 @@ public short readShort(final int index) { * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. * - * @param index - * the start index of the value to be read in {@link #b b}. + * @param index the start index of the value to be read in {@link #b b}. * @return the read value. */ public int readInt(final int index) { byte[] b = this.b; - return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) - | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); + return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); } /** @@ -906,8 +839,7 @@ public int readInt(final int index) { * {@link Attribute} sub classes, and is normally not needed by class * generators or adapters. * - * @param index - * the start index of the value to be read in {@link #b b}. + * @param index the start index of the value to be read in {@link #b b}. * @return the read value. */ public long readLong(final int index) { @@ -921,12 +853,10 @@ public long readLong(final int index) { * is intended for {@link Attribute} sub classes, and is normally not needed * by class generators or adapters. * - * @param index - * the start index of an unsigned short value in {@link #b b}, - * whose value is the index of an UTF8 constant pool item. - * @param buf - * buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. + * @param index the start index of an unsigned short value in {@link #b b}, + * whose value is the index of an UTF8 constant pool item. + * @param buf buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. * @return the String corresponding to the specified UTF8 item. */ public String readUTF8(int index, final char[] buf) { @@ -939,19 +869,18 @@ public String readUTF8(int index, final char[] buf) { return s; } index = items[item]; - return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf); + String utf8Item = readUTF(index + 2, readUnsignedShort(index), buf); + strings[item] = utf8Item; + return utf8Item; } /** * Reads UTF8 string in {@link #b b}. * - * @param index - * start offset of the UTF8 string to be read. - * @param utfLen - * length of the UTF8 string to be read. - * @param buf - * buffer to be used to read the string. This buffer must be - * sufficiently large. It is not automatically resized. + * @param index start offset of the UTF8 string to be read. + * @param utfLen length of the UTF8 string to be read. + * @param buf buffer to be used to read the string. This buffer must be + * sufficiently large. It is not automatically resized. * @return the String corresponding to the specified UTF8 string. */ private String readUTF(int index, final int utfLen, final char[] buf) { @@ -986,6 +915,10 @@ private String readUTF(int index, final int utfLen, final char[] buf) { cc = (char) ((cc << 6) | (c & 0x3F)); st = 1; break; + + default: + // do nothing + break; } } return new String(buf, 0, strLen); @@ -996,12 +929,10 @@ private String readUTF(int index, final int utfLen, final char[] buf) { * intended for {@link Attribute} sub classes, and is normally not needed by * class generators or adapters. * - * @param index - * the start index of an unsigned short value in {@link #b b}, - * whose value is the index of a class constant pool item. - * @param buf - * buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. + * @param index the start index of an unsigned short value in {@link #b b}, + * whose value is the index of a class constant pool item. + * @param buf buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. * @return the String corresponding to the specified class item. */ public String readClass(final int index, final char[] buf) { @@ -1016,14 +947,12 @@ public String readClass(final int index, final char[] buf) { * method is intended for {@link Attribute} sub classes, and is normally not * needed by class generators or adapters. * - * @param item - * the index of a constant pool item. - * @param buf - * buffer to be used to read the item. This buffer must be - * sufficiently large. It is not automatically resized. + * @param item the index of a constant pool item. + * @param buf buffer to be used to read the item. This buffer must be + * sufficiently large. It is not automatically resized. * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double}, - * {@link String}, {@link Type} or {@link Handle} corresponding to - * the given constant pool item. + * {@link String}, {@link Type} or {@link Handle} corresponding to + * the given constant pool item. */ public Object readConst(final int item, final char[] buf) { int index = items[item]; diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Context.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Context.java index 2ad9692aa05..004cb36c04c 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Context.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/Context.java @@ -1,31 +1,20 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. +/* + * 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 * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * https://www.apache.org/licenses/LICENSE-2.0 * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. + * 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.common.compiler.asm; @@ -143,4 +132,4 @@ class Context { * The stack values of the latest stack map frame that has been parsed. */ Object[] stack; -} \ No newline at end of file +} diff --git a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/TypePath.java b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/TypePath.java index f2510b12aac..5c71a2f7026 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/TypePath.java +++ b/grails-common/src/main/groovy/org/apache/grails/common/compiler/asm/TypePath.java @@ -1,35 +1,23 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. +/* + * 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 * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * https://www.apache.org/licenses/LICENSE-2.0 * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. + * 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.common.compiler.asm; - /** * The path to a type argument, wildcard bound, array element type, or static * inner type within an enclosing type. @@ -42,25 +30,25 @@ class TypePath { * A type path step that steps into the element type of an array type. See * {@link #getStep getStep}. */ - public final static int ARRAY_ELEMENT = 0; + public static final int ARRAY_ELEMENT = 0; /** * A type path step that steps into the nested type of a class type. See * {@link #getStep getStep}. */ - public final static int INNER_TYPE = 1; + public static final int INNER_TYPE = 1; /** * A type path step that steps into the bound of a wildcard type. See * {@link #getStep getStep}. */ - public final static int WILDCARD_BOUND = 2; + public static final int WILDCARD_BOUND = 2; /** * A type path step that steps into a type argument of a generic type. See * {@link #getStep getStep}. */ - public final static int TYPE_ARGUMENT = 3; + public static final int TYPE_ARGUMENT = 3; /** * The byte array where the path is stored, in Java class file format. @@ -75,11 +63,9 @@ class TypePath { /** * Creates a new type path. * - * @param b - * the byte array containing the type path in Java class file - * format. - * @param offset - * the offset of the first byte of the type path in 'b'. + * @param b the byte array containing the type path in Java class file + * format. + * @param offset the offset of the first byte of the type path in 'b'. */ TypePath(byte[] b, int offset) { this.b = b; @@ -98,11 +84,10 @@ public int getLength() { /** * Returns the value of the given step of this path. * - * @param index - * an index between 0 and {@link #getLength()}, exclusive. + * @param index an index between 0 and {@link #getLength()}, exclusive. * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE - * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or - * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. + * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or + * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. */ public int getStep(int index) { return b[offset + 2 * index + 1]; @@ -113,10 +98,9 @@ public int getStep(int index) { * into. This method should only be used for steps whose value is * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. * - * @param index - * an index between 0 and {@link #getLength()}, exclusive. + * @param index an index between 0 and {@link #getLength()}, exclusive. * @return the index of the type argument that the given step is stepping - * into. + * into. */ public int getStepArgument(int index) { return b[offset + 2 * index + 2]; @@ -126,9 +110,8 @@ public int getStepArgument(int index) { * Converts a type path in string form, in the format used by * {@link #toString()}, into a TypePath object. * - * @param typePath - * a type path in string form, in the format used by - * {@link #toString()}. May be null or empty. + * @param typePath a type path in string form, in the format used by + * {@link #toString()}. May be null or empty. * @return the corresponding TypePath object, or null if the path is empty. */ public static TypePath fromString(final String typePath) { @@ -138,7 +121,7 @@ public static TypePath fromString(final String typePath) { int n = typePath.length(); ByteVector out = new ByteVector(n); out.putByte(0); - for (int i = 0; i < n;) { + for (int i = 0; i < n; ) { char c = typePath.charAt(i++); if (c == '[') { out.put11(ARRAY_ELEMENT, 0); diff --git a/grails-common/src/main/groovy/org/apache/grails/common/properties/PropertyFileUtils.groovy b/grails-common/src/main/groovy/org/apache/grails/common/properties/PropertyFileUtils.groovy index 24a0fb7f1d4..deeb3fa277b 100644 --- a/grails-common/src/main/groovy/org/apache/grails/common/properties/PropertyFileUtils.groovy +++ b/grails-common/src/main/groovy/org/apache/grails/common/properties/PropertyFileUtils.groovy @@ -1,18 +1,20 @@ /* - * 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.apache.grails.common.properties diff --git a/grails-common/src/main/resources/META-INF/NOTICE b/grails-common/src/main/resources/META-INF/NOTICE index d524ab7e3e7..151ca988414 100644 --- a/grails-common/src/main/resources/META-INF/NOTICE +++ b/grails-common/src/main/resources/META-INF/NOTICE @@ -2,7 +2,7 @@ Apache Grails Copyright 2005-2025 The Apache Software Foundation This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). +The Apache Software Foundation (https://www.apache.org/). Additional Licenses diff --git a/grails-console/build.gradle b/grails-console/build.gradle index e2d0cc792da..49191ea8691 100644 --- a/grails-console/build.gradle +++ b/grails-console/build.gradle @@ -69,4 +69,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/java-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-console/src/main/groovy/grails/ui/command/GrailsApplicationContextCommandRunner.groovy b/grails-console/src/main/groovy/grails/ui/command/GrailsApplicationContextCommandRunner.groovy index 7f28f5024af..353e881e81c 100644 --- a/grails-console/src/main/groovy/grails/ui/command/GrailsApplicationContextCommandRunner.groovy +++ b/grails-console/src/main/groovy/grails/ui/command/GrailsApplicationContextCommandRunner.groovy @@ -1,18 +1,20 @@ /* - * 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 grails.ui.command @@ -26,7 +28,6 @@ import org.grails.build.parsing.CommandLineParser import org.springframework.beans.factory.config.AutowireCapableBeanFactory import org.springframework.context.ConfigurableApplicationContext - /** * @author Graeme Rocher * @since 3.0 @@ -89,7 +90,7 @@ class GrailsApplicationContextCommandRunner extends DevelopmentGrailsApplication * * @param args The first argument is the Command name, the last argument is the Application class name */ - public static void main(String[] args) { + static void main(String[] args) { if(args.size() > 1) { Class applicationClass = null String className = args.last() diff --git a/grails-console/src/main/groovy/grails/ui/console/GrailsSwingConsole.groovy b/grails-console/src/main/groovy/grails/ui/console/GrailsSwingConsole.groovy index 6846ee5e2f0..ece40afdc60 100644 --- a/grails-console/src/main/groovy/grails/ui/console/GrailsSwingConsole.groovy +++ b/grails-console/src/main/groovy/grails/ui/console/GrailsSwingConsole.groovy @@ -27,7 +27,6 @@ import org.springframework.context.ConfigurableApplicationContext import org.springframework.core.io.ResourceLoader import org.springframework.util.ClassUtils - /** * The Grails console runs Grails embedded within a Swing console instead of within a container like Tomcat * @@ -38,7 +37,7 @@ import org.springframework.util.ClassUtils class GrailsSwingConsole extends GrailsApp { static { - System.setProperty("java.awt.headless", "false"); + System.setProperty("java.awt.headless", "false") } GrailsSwingConsole(Class... sources) { @@ -59,7 +58,6 @@ class GrailsSwingConsole extends GrailsApp { } } - /** * Static helper that can be used to run a {@link GrailsApp} from the * specified source using default settings. @@ -67,8 +65,8 @@ class GrailsSwingConsole extends GrailsApp { * @param args the application arguments (usually passed from a Java main method) * @return the running {@link org.springframework.context.ApplicationContext} */ - public static ConfigurableApplicationContext run(Class source, String... args) { - return run([ source ] as Class[], args); + static ConfigurableApplicationContext run(Class source, String... args) { + return run([source] as Class[], args) } /** @@ -78,8 +76,8 @@ class GrailsSwingConsole extends GrailsApp { * @param args the application arguments (usually passed from a Java main method) * @return the running {@link org.springframework.context.ApplicationContext} */ - public static ConfigurableApplicationContext run(Class[] sources, String[] args) { - return new GrailsSwingConsole(sources).run(args); + static ConfigurableApplicationContext run(Class[] sources, String[] args) { + return new GrailsSwingConsole(sources).run(args) } /** @@ -87,7 +85,7 @@ class GrailsSwingConsole extends GrailsApp { * * @param args The first argument is the Application class name */ - public static void main(String[] args) { + static void main(String[] args) { if(args) { def applicationClass = Thread.currentThread().contextClassLoader.loadClass(args[0]) new GrailsSwingConsole(applicationClass).run(args) diff --git a/grails-console/src/main/groovy/grails/ui/console/support/GroovyConsoleApplicationContext.groovy b/grails-console/src/main/groovy/grails/ui/console/support/GroovyConsoleApplicationContext.groovy index b0a2b05e62c..a37a6737baa 100644 --- a/grails-console/src/main/groovy/grails/ui/console/support/GroovyConsoleApplicationContext.groovy +++ b/grails-console/src/main/groovy/grails/ui/console/support/GroovyConsoleApplicationContext.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package grails.ui.console.support import grails.core.GrailsApplication diff --git a/grails-console/src/main/groovy/grails/ui/console/support/GroovyConsoleWebApplicationContext.groovy b/grails-console/src/main/groovy/grails/ui/console/support/GroovyConsoleWebApplicationContext.groovy index 5910d1b36ac..b86bce5cbf0 100644 --- a/grails-console/src/main/groovy/grails/ui/console/support/GroovyConsoleWebApplicationContext.groovy +++ b/grails-console/src/main/groovy/grails/ui/console/support/GroovyConsoleWebApplicationContext.groovy @@ -16,18 +16,13 @@ * specific language governing permissions and limitations * under the License. */ - package grails.ui.console.support import grails.core.GrailsApplication import grails.persistence.support.PersistenceContextInterceptor import grails.ui.support.DevelopmentWebApplicationContext -import grails.util.BuildSettings import groovy.transform.CompileStatic import groovy.transform.InheritConstructors -import org.springframework.mock.web.MockServletConfig -import org.springframework.mock.web.MockServletContext -import org.springframework.web.context.support.GenericWebApplicationContext /** * A {@org.springframework.web.context.WebApplicationContext} for use in the embedded Grails console diff --git a/grails-console/src/main/groovy/grails/ui/script/GrailsApplicationScriptRunner.groovy b/grails-console/src/main/groovy/grails/ui/script/GrailsApplicationScriptRunner.groovy index 7cb9467c5ba..d42ba2050e3 100644 --- a/grails-console/src/main/groovy/grails/ui/script/GrailsApplicationScriptRunner.groovy +++ b/grails-console/src/main/groovy/grails/ui/script/GrailsApplicationScriptRunner.groovy @@ -93,7 +93,6 @@ class GrailsApplicationScriptRunner extends DevelopmentGrailsApplication { } } - return ctx } /** @@ -101,7 +100,7 @@ class GrailsApplicationScriptRunner extends DevelopmentGrailsApplication { * * @param args The last argument is the Application class name. All other args are script names */ - public static void main(String[] args) { + static void main(String[] args) { if(args.size() > 1) { Class applicationClass = null String className = args.last() diff --git a/grails-console/src/main/groovy/grails/ui/shell/GrailsShell.groovy b/grails-console/src/main/groovy/grails/ui/shell/GrailsShell.groovy index d41ab4a8581..0c4390b3e89 100644 --- a/grails-console/src/main/groovy/grails/ui/shell/GrailsShell.groovy +++ b/grails-console/src/main/groovy/grails/ui/shell/GrailsShell.groovy @@ -46,7 +46,7 @@ class GrailsShell extends GrailsApp { configureApplicationContextClass() } - public configureApplicationContextClass() { + def configureApplicationContextClass() { if (ClassUtils.isPresent("jakarta.servlet.ServletContext", Thread.currentThread().contextClassLoader)) { setApplicationContextFactory(ApplicationContextFactory.ofContextClass(GroovyshWebApplicationContext)) } else { @@ -54,7 +54,6 @@ class GrailsShell extends GrailsApp { } } - /** * Static helper that can be used to run a {@link GrailsApp} from the * specified source using default settings. @@ -62,8 +61,8 @@ class GrailsShell extends GrailsApp { * @param args the application arguments (usually passed from a Java main method) * @return the running {@link org.springframework.context.ApplicationContext} */ - public static ConfigurableApplicationContext run(Class source, String... args) { - return run([ source ] as Class[], args); + static ConfigurableApplicationContext run(Class source, String... args) { + return run([source] as Class[], args) } /** @@ -73,8 +72,8 @@ class GrailsShell extends GrailsApp { * @param args the application arguments (usually passed from a Java main method) * @return the running {@link org.springframework.context.ApplicationContext} */ - public static ConfigurableApplicationContext run(Class[] sources, String[] args) { - return new GrailsShell(sources).run(args); + static ConfigurableApplicationContext run(Class[] sources, String[] args) { + return new GrailsShell(sources).run(args) } /** @@ -82,7 +81,7 @@ class GrailsShell extends GrailsApp { * * @param args The first argument is the Application class name */ - public static void main(String[] args) { + static void main(String[] args) { if(args) { def applicationClass = Thread.currentThread().contextClassLoader.loadClass(args[0]) new GrailsShell(applicationClass).run(args) diff --git a/grails-console/src/main/groovy/grails/ui/support/DevelopmentGrailsApplication.groovy b/grails-console/src/main/groovy/grails/ui/support/DevelopmentGrailsApplication.groovy index bf59f109429..37ea780c5ea 100644 --- a/grails-console/src/main/groovy/grails/ui/support/DevelopmentGrailsApplication.groovy +++ b/grails-console/src/main/groovy/grails/ui/support/DevelopmentGrailsApplication.groovy @@ -24,7 +24,6 @@ import org.springframework.boot.ApplicationContextFactory import org.springframework.util.ClassUtils import org.springframework.web.context.support.GenericWebApplicationContext - /** * @author Graeme Rocher * @since 3.0 diff --git a/grails-console/src/main/groovy/grails/ui/support/DevelopmentWebApplicationContext.groovy b/grails-console/src/main/groovy/grails/ui/support/DevelopmentWebApplicationContext.groovy index 402c3d31ed1..3f4796ecf69 100644 --- a/grails-console/src/main/groovy/grails/ui/support/DevelopmentWebApplicationContext.groovy +++ b/grails-console/src/main/groovy/grails/ui/support/DevelopmentWebApplicationContext.groovy @@ -24,7 +24,6 @@ import org.springframework.mock.web.MockServletConfig import org.springframework.mock.web.MockServletContext import org.springframework.web.context.support.GenericWebApplicationContext - /** * A {@link org.springframework.web.context.WebApplicationContext} used during development * for things like running scripts and loading the console UI diff --git a/grails-controllers/build.gradle b/grails-controllers/build.gradle index 457a8f9748b..8a898037e30 100644 --- a/grails-controllers/build.gradle +++ b/grails-controllers/build.gradle @@ -77,4 +77,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-controllers/src/main/groovy/grails/artefact/Controller.groovy b/grails-controllers/src/main/groovy/grails/artefact/Controller.groovy index ee32c1c1782..b4a4be41e6f 100644 --- a/grails-controllers/src/main/groovy/grails/artefact/Controller.groovy +++ b/grails-controllers/src/main/groovy/grails/artefact/Controller.groovy @@ -32,6 +32,9 @@ import grails.web.databinding.DataBinder import grails.web.databinding.DataBindingUtils import groovy.transform.CompileStatic import groovy.transform.Generated +import jakarta.servlet.ServletRequest +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse import org.codehaus.groovy.runtime.InvokerHelper import org.grails.compiler.web.ControllerActionTransformer import org.grails.core.artefact.DomainClassArtefactHandler @@ -55,9 +58,6 @@ import org.springframework.web.context.request.RequestAttributes import org.springframework.web.context.request.RequestContextHolder import org.springframework.web.servlet.ModelAndView -import jakarta.servlet.ServletRequest -import jakarta.servlet.http.HttpServletRequest -import jakarta.servlet.http.HttpServletResponse import java.lang.reflect.Method /** @@ -74,7 +74,6 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward private MimeTypesApiSupport mimeTypesSupport = new MimeTypesApiSupport() - /** *

The withFormat method is used to allow controllers to handle different types of * request formats such as HTML, XML and so on. Example usage:

@@ -89,12 +88,12 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward * * * @param callable - * @return The result of the closure execution selected + * @return The result of the closure execution selected */ @Generated def withFormat(Closure callable) { HttpServletResponse response = GrailsWebRequest.lookup().currentResponse - mimeTypesSupport.withFormat((HttpServletResponse)response, callable) + mimeTypesSupport.withFormat((HttpServletResponse) response, callable) } /** @@ -143,7 +142,6 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward setErrorsInternal(webRequest, errors) } - /** * Obtains the errors instance for the current controller * @@ -155,7 +153,6 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward getErrorsInternal(webRequest) } - /** * Obtains the ModelAndView for the currently executing controller * @@ -163,7 +160,7 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward */ @Generated ModelAndView getModelAndView() { - (ModelAndView)currentRequestAttributes().getAttribute(GrailsApplicationAttributes.MODEL_AND_VIEW, 0) + (ModelAndView) currentRequestAttributes().getAttribute(GrailsApplicationAttributes.MODEL_AND_VIEW, 0) } /** @@ -230,18 +227,17 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward throw new IllegalArgumentException("Invalid arguments to method 'redirect': $argMap") } - GrailsWebRequest webRequest = (GrailsWebRequest)RequestContextHolder.currentRequestAttributes() + GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes() - if(this instanceof GroovyObject) { - GroovyObject controller = (GroovyObject)this + if (this instanceof GroovyObject) { + GroovyObject controller = (GroovyObject) this // if there are errors add it to the list of errors Errors controllerErrors = getErrorsInternal(webRequest) - Errors errors = (Errors)argMap.get(GormProperties.ERRORS) + Errors errors = (Errors) argMap.get(GormProperties.ERRORS) if (controllerErrors != null && errors != null) { controllerErrors.addAllErrors errors - } - else { + } else { setErrorsInternal webRequest, errors } def action = argMap.get(GrailsControllerClass.ACTION) @@ -289,8 +285,7 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward if (isTokenValid(webRequest)) { resetToken(webRequest) handler = new ValidResponseHandler(callable?.call()) - } - else { + } else { handler = new InvalidResponseHandler() } @@ -305,7 +300,7 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward */ private synchronized boolean isTokenValid(GrailsWebRequest webRequest) { final request = webRequest.getCurrentRequest() - SynchronizerTokensHolder tokensHolderInSession = (SynchronizerTokensHolder)request.getSession(false)?.getAttribute(SynchronizerTokensHolder.HOLDER) + SynchronizerTokensHolder tokensHolderInSession = (SynchronizerTokensHolder) request.getSession(false)?.getAttribute(SynchronizerTokensHolder.HOLDER) if (!tokensHolderInSession) return false String tokenInRequest = webRequest.params[SynchronizerTokensHolder.TOKEN_KEY] @@ -327,7 +322,7 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward */ private synchronized resetToken(GrailsWebRequest webRequest) { final request = webRequest.getCurrentRequest() - SynchronizerTokensHolder tokensHolderInSession = (SynchronizerTokensHolder)request.getSession(false)?.getAttribute(SynchronizerTokensHolder.HOLDER) + SynchronizerTokensHolder tokensHolderInSession = (SynchronizerTokensHolder) request.getSession(false)?.getAttribute(SynchronizerTokensHolder.HOLDER) String urlInRequest = webRequest.params[SynchronizerTokensHolder.TOKEN_URI] String tokenInRequest = webRequest.params[SynchronizerTokensHolder.TOKEN_KEY] @@ -339,14 +334,13 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward @Generated public static ApplicationContext getStaticApplicationContext() { - RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes() - if (!(requestAttributes instanceof GrailsWebRequest)) { - return ContextLoader.getCurrentWebApplicationContext() - } - ((GrailsWebRequest)requestAttributes).getApplicationContext() + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes() + if (!(requestAttributes instanceof GrailsWebRequest)) { + return ContextLoader.getCurrentWebApplicationContext() + } + ((GrailsWebRequest) requestAttributes).getApplicationContext() } - /** * Initializes a command object. * @@ -369,13 +363,13 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward try { final DataBindingSource dataBindingSource = DataBindingUtils .createDataBindingSource( - getGrailsApplication(), type, - request) + getGrailsApplication(), type, + request) final DataBindingSource commandObjectBindingSource = getCommandObjectBindingSourceForPrefix( commandObjectParameterName, dataBindingSource) def entityIdentifierValue = null final boolean isDomainClass - if(GroovyObject.isAssignableFrom(type)) { + if (GroovyObject.isAssignableFrom(type)) { isDomainClass = DomainClass.isAssignableFrom(type) } else { isDomainClass = DomainClassArtefactHandler @@ -440,20 +434,20 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward } } catch (Exception e) { final exceptionHandlerMethodFor = getExceptionHandlerMethodFor(e.getClass()) - if(exceptionHandlerMethodFor != null) { + if (exceptionHandlerMethodFor != null) { throw e } commandObjectInstance = type.getDeclaredConstructor().newInstance() final o = GrailsMetaClassUtils.invokeMethodIfExists(commandObjectInstance, "getErrors") - if(o instanceof BindingResult) { - final BindingResult errors = (BindingResult)o + if (o instanceof BindingResult) { + final BindingResult errors = (BindingResult) o String msg = "Error occurred initializing command object [" + commandObjectParameterName + "]. " + e.getMessage() ObjectError error = new ObjectError(commandObjectParameterName, msg) errors.addError(error) } } - if(commandObjectInstance != null) { + if (commandObjectInstance != null) { final ApplicationContext applicationContext = getApplicationContext() final AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory() autowireCapableBeanFactory.autowireBeanProperties(commandObjectInstance, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false) @@ -475,9 +469,9 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward DataBindingSource commandParams = params if (params != null && prefix != null) { def innerValue = params[prefix] - if(innerValue instanceof DataBindingSource) { - commandParams = (DataBindingSource)innerValue - } else if(innerValue instanceof Map) { + if (innerValue instanceof DataBindingSource) { + commandParams = (DataBindingSource) innerValue + } else if (innerValue instanceof Map) { commandParams = new SimpleMapDataBindingSource(innerValue) } } @@ -487,26 +481,26 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward @Generated @SuppressWarnings("unchecked") Method getExceptionHandlerMethodFor(final Class exceptionType) throws Exception { - if(!Exception.class.isAssignableFrom(exceptionType)) { + if (!Exception.class.isAssignableFrom(exceptionType)) { throw new IllegalArgumentException("exceptionType [${exceptionType.getName()}] argument must be Exception or a subclass of Exception") } Method handlerMethod - final List exceptionHandlerMetaDataInstances = (List)GrailsClassUtils.getStaticFieldValue(this.getClass(), ControllerActionTransformer.EXCEPTION_HANDLER_META_DATA_FIELD_NAME) - if(exceptionHandlerMetaDataInstances) { + final List exceptionHandlerMetaDataInstances = (List) GrailsClassUtils.getStaticFieldValue(this.getClass(), ControllerActionTransformer.EXCEPTION_HANDLER_META_DATA_FIELD_NAME) + if (exceptionHandlerMetaDataInstances) { // find all of the handler methods which could accept this exception type - final List matches = (List)exceptionHandlerMetaDataInstances.findAll { ControllerExceptionHandlerMetaData cemd -> + final List matches = (List) exceptionHandlerMetaDataInstances.findAll { ControllerExceptionHandlerMetaData cemd -> cemd.exceptionType.isAssignableFrom(exceptionType) } - if(matches.size() > 0) { + if (matches.size() > 0) { ControllerExceptionHandlerMetaData theOne = matches.get(0) // if there are more than 1, find the one that is farthest down the inheritance hierarchy - for(int i = 1; i < matches.size(); i++) { + for (int i = 1; i < matches.size(); i++) { final ControllerExceptionHandlerMetaData nextMatch = matches.get(i) - if(theOne.getExceptionType().isAssignableFrom(nextMatch.getExceptionType())) { + if (theOne.getExceptionType().isAssignableFrom(nextMatch.getExceptionType())) { theOne = nextMatch } } @@ -517,8 +511,6 @@ trait Controller implements ResponseRenderer, ResponseRedirector, RequestForward handlerMethod } - - private Errors getErrorsInternal(GrailsWebRequest webRequest) { (Errors) webRequest.getAttribute(GrailsApplicationAttributes.ERRORS, 0) } diff --git a/grails-controllers/src/main/groovy/grails/artefact/controller/support/AllowedMethodsHelper.groovy b/grails-controllers/src/main/groovy/grails/artefact/controller/support/AllowedMethodsHelper.groovy index fcd7df92271..22b3993ada3 100644 --- a/grails-controllers/src/main/groovy/grails/artefact/controller/support/AllowedMethodsHelper.groovy +++ b/grails-controllers/src/main/groovy/grails/artefact/controller/support/AllowedMethodsHelper.groovy @@ -19,12 +19,11 @@ package grails.artefact.controller.support import groovy.transform.CompileStatic - import jakarta.servlet.http.HttpServletRequest /** * A helper class for interrogating the allowedMethods property. - * + * * @author Jeff Brown * @since 3.0 * @@ -34,10 +33,10 @@ class AllowedMethodsHelper { static boolean isAllowed(final String actionName, final HttpServletRequest request, final Map allowedMethods) { boolean isAllowed = true - if(allowedMethods?.containsKey(actionName)) { + if (allowedMethods?.containsKey(actionName)) { def method = request.method def value = allowedMethods[actionName] - if(value instanceof String) { + if (value instanceof String) { isAllowed = method.equalsIgnoreCase(value) } else if (value instanceof List) { isAllowed = value.find { s -> method.equalsIgnoreCase((String) s) } diff --git a/grails-controllers/src/main/groovy/grails/artefact/controller/support/RequestForwarder.groovy b/grails-controllers/src/main/groovy/grails/artefact/controller/support/RequestForwarder.groovy index 365215dccfd..590034435ef 100644 --- a/grails-controllers/src/main/groovy/grails/artefact/controller/support/RequestForwarder.groovy +++ b/grails-controllers/src/main/groovy/grails/artefact/controller/support/RequestForwarder.groovy @@ -23,6 +23,9 @@ import grails.web.api.WebAttributes import grails.web.mapping.LinkGenerator import groovy.transform.CompileStatic import groovy.transform.Generated +import jakarta.servlet.RequestDispatcher +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse import org.grails.web.mapping.UrlMappingUtils import org.grails.web.mapping.mvc.UrlMappingsHandlerMapping import org.grails.web.servlet.mvc.GrailsWebRequest @@ -32,10 +35,6 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.web.context.request.WebRequest import org.springframework.web.filter.OncePerRequestFilter -import jakarta.servlet.RequestDispatcher -import jakarta.servlet.http.HttpServletRequest -import jakarta.servlet.http.HttpServletResponse - /** * A Trait for classes that forward the request * @@ -44,17 +43,18 @@ import jakarta.servlet.http.HttpServletResponse */ @CompileStatic trait RequestForwarder implements WebAttributes { + private UrlConverter urlConverter private LinkGenerator linkGenerator @Generated - @Autowired(required=false) + @Autowired(required = false) void setUrlConverter(UrlConverter urlConverter) { this.urlConverter = urlConverter } private LinkGenerator lookupLinkGenerator() { - if(this.linkGenerator == null) { + if (this.linkGenerator == null) { this.linkGenerator = webRequest.getApplicationContext().getBean(LinkGenerator) } return this.linkGenerator @@ -73,39 +73,39 @@ trait RequestForwarder implements WebAttributes { if (webRequest) { def controllerName - if(params.controller) { + if (params.controller) { controllerName = params.controller } else { controllerName = webRequest.controllerName } - if(controllerName) { + if (controllerName) { def convertedControllerName = convert(controllerName.toString()) webRequest.controllerName = convertedControllerName } params.controller = webRequest.controllerName - if(params.action) { + if (params.action) { params.action = convert(params.action.toString()) } - if(params.namespace) { + if (params.namespace) { params.namespace = params.namespace } - if(params.plugin) { + if (params.plugin) { params.plugin = params.plugin } - if ( !params.params ) { - params.params = UrlMappingUtils.findAllParamsNotInKeys( + if (!params.params) { + params.params = UrlMappingUtils.findAllParamsNotInKeys( UrlMappingUtils.findAllParamsNotInUrlMappingKeywords(webRequest.params), webRequest.originalParams.keySet() ) } } - Map model = params.model instanceof Map ? (Map)params.model : Collections.EMPTY_MAP + Map model = params.model instanceof Map ? (Map) params.model : Collections.EMPTY_MAP HttpServletRequest request = webRequest.currentRequest HttpServletResponse response = webRequest.currentResponse @@ -118,7 +118,6 @@ trait RequestForwarder implements WebAttributes { params.includeContext = false String fowardURI = lookupLinkGenerator().link(params) - RequestDispatcher dispatcher = request.getRequestDispatcher(fowardURI) int requestScope = WebRequest.SCOPE_REQUEST @@ -141,7 +140,6 @@ trait RequestForwarder implements WebAttributes { return fowardURI } - private String convert(String value) { (urlConverter) ? urlConverter.toUrlElement(value) : value } diff --git a/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRedirector.groovy b/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRedirector.groovy index 49913dcdfec..0bcb2030025 100644 --- a/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRedirector.groovy +++ b/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRedirector.groovy @@ -30,6 +30,7 @@ import grails.web.mapping.mvc.exceptions.CannotRedirectException import grails.web.mvc.FlashScope import groovy.transform.CompileStatic import groovy.transform.Generated +import jakarta.servlet.http.HttpServletRequest import org.grails.core.artefact.ControllerArtefactHandler import org.grails.core.artefact.DomainClassArtefactHandler import org.grails.datastore.mapping.model.config.GormProperties @@ -37,8 +38,6 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.HttpMethod import org.springframework.web.servlet.support.RequestDataValueProcessor -import jakarta.servlet.http.HttpServletRequest - /** * A trait for objects that redirect the response * @@ -48,7 +47,6 @@ import jakarta.servlet.http.HttpServletRequest @CompileStatic trait ResponseRedirector implements WebAttributes { - private LinkGenerator linkGenerator private boolean useJsessionId = false @@ -57,7 +55,7 @@ trait ResponseRedirector implements WebAttributes { private Collection redirectListeners @Generated - @Autowired(required=false) + @Autowired(required = false) void setRedirectListeners(Collection redirectListeners) { this.redirectListeners = redirectListeners } @@ -76,7 +74,7 @@ trait ResponseRedirector implements WebAttributes { @Generated LinkGenerator getGrailsLinkGenerator() { - if(this.linkGenerator == null) { + if (this.linkGenerator == null) { this.linkGenerator = webRequest.getApplicationContext().getBean(LinkGenerator) } return this.linkGenerator @@ -90,13 +88,13 @@ trait ResponseRedirector implements WebAttributes { */ @Generated void redirect(object) { - if(object) { + if (object) { Class objectClass = object.getClass() boolean isDomain = DomainClassArtefactHandler.isDomainClass(objectClass) && object instanceof GroovyObject - if(isDomain) { - def id = ((GroovyObject)object).getProperty(GormProperties.IDENTITY) - if(id != null) { + if (isDomain) { + def id = ((GroovyObject) object).getProperty(GormProperties.IDENTITY) + if (id != null) { def args = [:] args.put LinkGenerator.ATTRIBUTE_RESOURCE, object args.put LinkGenerator.ATTRIBUTE_METHOD, HttpMethod.GET.toString() @@ -136,10 +134,9 @@ trait ResponseRedirector implements WebAttributes { */ @Generated Map getChainModel() { - (Map)getFlash().get(FlashScope.CHAIN_MODEL) + (Map) getFlash().get(FlashScope.CHAIN_MODEL) } - /** * Chains from one action to another via an HTTP redirect. The model is retained in the following request in the 'chainModel' property within flash scope. * @@ -149,7 +146,7 @@ trait ResponseRedirector implements WebAttributes { */ @Generated void chain(Map args) { - String controller = (args.controller ?: GrailsNameUtils.getLogicalPropertyName( getClass().name, ControllerArtefactHandler.TYPE)).toString() + String controller = (args.controller ?: GrailsNameUtils.getLogicalPropertyName(getClass().name, ControllerArtefactHandler.TYPE)).toString() String action = args.action?.toString() String namespace = args.remove('namespace') String plugin = args.remove('plugin')?.toString() @@ -160,7 +157,6 @@ trait ResponseRedirector implements WebAttributes { def actionParams = params.findAll { Map.Entry it -> it.key?.toString()?.startsWith('_action_') } actionParams.each { Map.Entry it -> params.remove(it.key) } - def currentWebRequest = webRequest def currentFlash = currentWebRequest.flashScope def chainModel = currentFlash.chainModel @@ -170,7 +166,6 @@ trait ResponseRedirector implements WebAttributes { } currentFlash.chainModel = model - def appCtx = currentWebRequest.applicationContext UrlMappings mappings = appCtx.getBean(UrlMappingsHolder.BEAN_ID, UrlMappings) diff --git a/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy b/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy index 016cdc2ab59..bdb06eb1427 100644 --- a/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy +++ b/grails-controllers/src/main/groovy/grails/artefact/controller/support/ResponseRenderer.groovy @@ -32,8 +32,10 @@ import grails.web.pages.GrailsRenderViewMutator import groovy.json.StreamingJsonBuilder import groovy.transform.CompileStatic import groovy.transform.Generated -import groovy.xml.slurpersupport.GPathResult import groovy.xml.StreamingMarkupBuilder +import groovy.xml.slurpersupport.GPathResult +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse import org.grails.gsp.GroovyPageTemplate import org.grails.io.support.SpringIOUtils import org.grails.web.json.JSONElement @@ -52,10 +54,28 @@ import org.springframework.web.context.request.RequestContextHolder import org.springframework.web.servlet.ModelAndView import org.springframework.web.servlet.View -import jakarta.servlet.http.HttpServletRequest -import jakarta.servlet.http.HttpServletResponse - -import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.* +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.APPLICATION_XML +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_BEAN +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_BUILDER +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_COLLECTION +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_CONTENT_TYPE +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_CONTEXTPATH +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_ENCODING +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_FILE +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_FILE_NAME +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_LAYOUT +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_MODEL +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_PLUGIN +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_STATUS +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_TEMPLATE +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_TEXT +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_VAR +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.ARGUMENT_VIEW +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.BUILDER_TYPE_JSON +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.DEFAULT_ARGUMENT +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.DEFAULT_ENCODING +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.DISPOSITION_HEADER_PREFIX +import static org.grails.plugins.web.controllers.metaclass.RenderDynamicMethod.TEXT_HTML /** * @@ -240,7 +260,6 @@ trait ResponseRenderer extends WebAttributes { String layoutArg = argMap[ARGUMENT_LAYOUT]?.toString() ?: null boolean statusSet = handleStatusArgument(argMap, webRequest, response) - def applicationAttributes = webRequest.attributes if (argMap.containsKey(ARGUMENT_TEXT)) { def textArg = argMap[ARGUMENT_TEXT] @@ -438,7 +457,6 @@ trait ResponseRenderer extends WebAttributes { } } - private boolean handleStatusArgument(Map argMap, GrailsWebRequest webRequest, HttpServletResponse response) { boolean statusSet if (argMap.containsKey(ARGUMENT_STATUS)) { diff --git a/grails-controllers/src/main/groovy/grails/compiler/traits/ControllerTraitInjector.groovy b/grails-controllers/src/main/groovy/grails/compiler/traits/ControllerTraitInjector.groovy index b259cf4b1f1..d6b9fb2db09 100644 --- a/grails-controllers/src/main/groovy/grails/compiler/traits/ControllerTraitInjector.groovy +++ b/grails-controllers/src/main/groovy/grails/compiler/traits/ControllerTraitInjector.groovy @@ -33,7 +33,7 @@ import groovy.transform.CompileStatic */ @CompileStatic class ControllerTraitInjector implements TraitInjector { - + @Override Class getTrait() { Controller diff --git a/grails-controllers/src/main/groovy/grails/web/Controller.groovy b/grails-controllers/src/main/groovy/grails/web/Controller.groovy index 03c7a37bae3..e4aa9a7b3de 100644 --- a/grails-controllers/src/main/groovy/grails/web/Controller.groovy +++ b/grails-controllers/src/main/groovy/grails/web/Controller.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package grails.web import org.codehaus.groovy.transform.GroovyASTTransformationClass @@ -30,7 +29,7 @@ import java.lang.annotation.Target * Created by graemerocher on 28/05/14. */ @Retention(RetentionPolicy.RUNTIME) -@Target( [ ElementType.TYPE ] ) +@Target([ElementType.TYPE]) @GroovyASTTransformationClass("org.grails.compiler.web.ControllerArtefactTypeTransformation") public @interface Controller { } \ No newline at end of file diff --git a/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerActionTransformer.java b/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerActionTransformer.java index 3de3f279432..41b81a13d9d 100644 --- a/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerActionTransformer.java +++ b/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerActionTransformer.java @@ -100,7 +100,18 @@ import java.util.Map; import java.util.regex.Pattern; -import static org.codehaus.groovy.ast.tools.GeneralUtils.*; +import static org.codehaus.groovy.ast.tools.GeneralUtils.args; +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX; +import static org.codehaus.groovy.ast.tools.GeneralUtils.boolX; +import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX; +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX; +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX; +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX; +import static org.codehaus.groovy.ast.tools.GeneralUtils.declX; +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS; +import static org.codehaus.groovy.ast.tools.GeneralUtils.localVarX; +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt; +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX; import static org.grails.compiler.injection.GrailsASTUtils.applyDefaultMethodTarget; import static org.grails.compiler.injection.GrailsASTUtils.applyMethodTarget; import static org.grails.compiler.injection.GrailsASTUtils.buildGetMapExpression; @@ -166,39 +177,21 @@ def someAction() { public class ControllerActionTransformer implements GrailsArtefactClassInjector, AnnotatedClassInjector, CompilationUnitAware { public static final AnnotationNode DELEGATING_METHOD_ANNOATION = new AnnotationNode(ClassHelper.make(DelegatingMethod.class)); - public static Pattern CONTROLLER_PATTERN = Pattern.compile(".+/" + - GrailsResourceUtils.GRAILS_APP_DIR + "/controllers/(.+)Controller\\.groovy"); + public static final Pattern CONTROLLER_PATTERN = Pattern.compile(".+/" + GrailsResourceUtils.GRAILS_APP_DIR + "/controllers/(.+)Controller\\.groovy"); + public static final AnnotationNode ACTION_ANNOTATION_NODE = new AnnotationNode(new ClassNode(Action.class)); + public static final String EXCEPTION_HANDLER_META_DATA_FIELD_NAME = "$exceptionHandlerMetaData"; + public static final String VOID_TYPE = "void"; + + public static final String CONVERT_CLOSURES_KEY = "grails.compile.artefacts.closures.convert"; + private static final String ALLOWED_METHODS_HANDLED_ATTRIBUTE_NAME = "ALLOWED_METHODS_HANDLED"; private static final ClassNode OBJECT_CLASS = new ClassNode(Object.class); - public static final AnnotationNode ACTION_ANNOTATION_NODE = new AnnotationNode( - new ClassNode(Action.class)); private static final String ACTION_MEMBER_TARGET = "commandObjects"; - public static final String EXCEPTION_HANDLER_META_DATA_FIELD_NAME = "$exceptionHandlerMetaData"; private static final TupleExpression EMPTY_TUPLE = new TupleExpression(); @SuppressWarnings({"unchecked"}) - private static final Map TYPE_WRAPPER_CLASS_TO_CONVERSION_METHOD_NAME = CollectionUtils.newMap( - ClassHelper.Integer_TYPE, "int", - ClassHelper.Float_TYPE, "float", - ClassHelper.Long_TYPE, "long", - ClassHelper.Double_TYPE, "double", - ClassHelper.Short_TYPE, "short", - ClassHelper.Boolean_TYPE, "boolean", - ClassHelper.Byte_TYPE, "byte", - ClassHelper.Character_TYPE, "char"); - private static List PRIMITIVE_CLASS_NODES = CollectionUtils.newList( - ClassHelper.boolean_TYPE, - ClassHelper.char_TYPE, - ClassHelper.int_TYPE, - ClassHelper.short_TYPE, - ClassHelper.long_TYPE, - ClassHelper.double_TYPE, - ClassHelper.float_TYPE, - ClassHelper.byte_TYPE); - public static final String VOID_TYPE = "void"; - - public static final String CONVERT_CLOSURES_KEY = "grails.compile.artefacts.closures.convert"; - + private static final Map TYPE_WRAPPER_CLASS_TO_CONVERSION_METHOD_NAME = CollectionUtils.newMap(ClassHelper.Integer_TYPE, "int", ClassHelper.Float_TYPE, "float", ClassHelper.Long_TYPE, "long", ClassHelper.Double_TYPE, "double", ClassHelper.Short_TYPE, "short", ClassHelper.Boolean_TYPE, "boolean", ClassHelper.Byte_TYPE, "byte", ClassHelper.Character_TYPE, "char"); + private static final List PRIMITIVE_CLASS_NODES = CollectionUtils.newList(ClassHelper.boolean_TYPE, ClassHelper.char_TYPE, ClassHelper.int_TYPE, ClassHelper.short_TYPE, ClassHelper.long_TYPE, ClassHelper.double_TYPE, ClassHelper.float_TYPE, ClassHelper.byte_TYPE); private Boolean converterEnabled; private CompilationUnit compilationUnit; @@ -212,7 +205,9 @@ public String[] getArtefactTypes() { public void performInjection(SourceUnit source, GeneratorContext context, ClassNode classNode) { // don't inject if already an @Artefact annotation is applied - if(!classNode.getAnnotations(new ClassNode(Artefact.class)).isEmpty()) return; + if (!classNode.getAnnotations(new ClassNode(Artefact.class)).isEmpty()) { + return; + } performInjectionOnAnnotatedClass(source, context, classNode); @@ -229,14 +224,14 @@ public void performInjectionOnAnnotatedClass(SourceUnit source, GeneratorContext @Override public void performInjectionOnAnnotatedClass(SourceUnit source, ClassNode classNode) { - performInjectionOnAnnotatedClass(source,null, classNode); + performInjectionOnAnnotatedClass(source, null, classNode); } private boolean isExceptionHandlingMethod(MethodNode methodNode) { boolean isExceptionHandler = false; - if(!methodNode.isPrivate() && methodNode.getName().indexOf("$") == -1) { + if (!methodNode.isPrivate() && methodNode.getName().indexOf("$") == -1) { Parameter[] parameters = methodNode.getParameters(); - if(parameters.length == 1) { + if (parameters.length == 1) { ClassNode parameterTypeClassNode = parameters[0].getType(); isExceptionHandler = parameterTypeClassNode.isDerivedFrom(new ClassNode(Exception.class)); } @@ -244,28 +239,21 @@ private boolean isExceptionHandlingMethod(MethodNode methodNode) { return isExceptionHandler; } - - - private void processMethods(ClassNode classNode, SourceUnit source, - GeneratorContext context) { + private void processMethods(ClassNode classNode, SourceUnit source, GeneratorContext context) { List deferredNewMethods = new ArrayList(); for (MethodNode method : classNode.getMethods()) { if (methodShouldBeConfiguredAsControllerAction(method)) { final List declaredMethodsWithThisName = classNode.getDeclaredMethods(method.getName()); - if(declaredMethodsWithThisName != null) { - final int numberOfNonExceptionHandlerMethodsWithThisName = DefaultGroovyMethods.count((Iterable)declaredMethodsWithThisName, new Closure(this) { + if (declaredMethodsWithThisName != null) { + final int numberOfNonExceptionHandlerMethodsWithThisName = DefaultGroovyMethods.count((Iterable) declaredMethodsWithThisName, new Closure(this) { @Override public Object call(Object object) { return !isExceptionHandlingMethod((MethodNode) object); } }).intValue(); if (numberOfNonExceptionHandlerMethodsWithThisName > 1) { - String message = "Controller actions may not be overloaded. The [" + - method.getName() + - "] action has been overloaded in [" + - classNode.getName() + - "]."; + String message = "Controller actions may not be overloaded. The [" + method.getName() + "] action has been overloaded in [" + classNode.getName() + "]."; GrailsASTUtils.error(source, method, message); } } @@ -278,9 +266,9 @@ public Object call(Object object) { Collection exceptionHandlerMethods = getExceptionHandlerMethods(classNode, source); final FieldNode exceptionHandlerMetaDataField = classNode.getField(EXCEPTION_HANDLER_META_DATA_FIELD_NAME); - if(exceptionHandlerMetaDataField == null || !exceptionHandlerMetaDataField.getDeclaringClass().equals(classNode)) { + if (exceptionHandlerMetaDataField == null || !exceptionHandlerMetaDataField.getDeclaringClass().equals(classNode)) { final ListExpression listOfExceptionHandlerMetaData = new ListExpression(); - for(final MethodNode exceptionHandlerMethod : exceptionHandlerMethods) { + for (final MethodNode exceptionHandlerMethod : exceptionHandlerMethods) { final Parameter[] parameters = exceptionHandlerMethod.getParameters(); final Parameter firstParameter = parameters[0]; final ClassNode firstParameterTypeClassNode = firstParameter.getType(); @@ -290,19 +278,16 @@ public Object call(Object object) { defaultControllerExceptionHandlerMetaDataCtorArgs.addExpression(new ClassExpression(firstParameterTypeClassNode.getPlainNodeReference())); listOfExceptionHandlerMetaData.addExpression(new ConstructorCallExpression(new ClassNode(DefaultControllerExceptionHandlerMetaData.class), defaultControllerExceptionHandlerMetaDataCtorArgs)); } - classNode.addField(EXCEPTION_HANDLER_META_DATA_FIELD_NAME, - Modifier.STATIC | Modifier.PRIVATE | Modifier.FINAL, new ClassNode(List.class), - listOfExceptionHandlerMetaData); + classNode.addField(EXCEPTION_HANDLER_META_DATA_FIELD_NAME, Modifier.STATIC | Modifier.PRIVATE | Modifier.FINAL, new ClassNode(List.class), listOfExceptionHandlerMetaData); } - for (MethodNode newMethod : deferredNewMethods) { ClassNodeUtils.addGeneratedMethod(classNode, newMethod); } } /** - * + * * @param method a potential controller action method * @return true if the method should be configured as a controller action, false otherwise */ @@ -313,25 +298,17 @@ protected boolean methodShouldBeConfiguredAsControllerAction(final MethodNode me //Trait methods have a line number of -1 --minLineNumber; } - return !method.isStatic() && - method.isPublic() && - !method.isAbstract() && - method.getAnnotations(ACTION_ANNOTATION_NODE.getClassNode()).isEmpty() && - method.getAnnotations(new ClassNode(ControllerMethod.class)).isEmpty() && - method.getLineNumber() >= minLineNumber && - !method.getName().startsWith("$") && - !method.getReturnType().getName().equals(VOID_TYPE) && - !isExceptionHandlingMethod(method); + return !method.isStatic() && method.isPublic() && !method.isAbstract() && method.getAnnotations(ACTION_ANNOTATION_NODE.getClassNode()).isEmpty() && method.getAnnotations(new ClassNode(ControllerMethod.class)).isEmpty() && method.getLineNumber() >= minLineNumber && !method.getName().startsWith("$") && !method.getReturnType().getName().equals(VOID_TYPE) && !isExceptionHandlingMethod(method); } protected Collection getExceptionHandlerMethods(final ClassNode classNode, SourceUnit sourceUnit) { final Map exceptionTypeToHandlerMethodMap = new HashMap(); final List methods = classNode.getMethods(); - for(MethodNode methodNode : methods) { - if(isExceptionHandlingMethod(methodNode)) { + for (MethodNode methodNode : methods) { + if (isExceptionHandlingMethod(methodNode)) { final Parameter exceptionParameter = methodNode.getParameters()[0]; final ClassNode exceptionType = exceptionParameter.getType(); - if(!exceptionTypeToHandlerMethodMap.containsKey(exceptionType)) { + if (!exceptionTypeToHandlerMethodMap.containsKey(exceptionType)) { exceptionTypeToHandlerMethodMap.put(exceptionType, methodNode); } else { final MethodNode otherHandlerMethod = exceptionTypeToHandlerMethodMap.get(exceptionType); @@ -342,14 +319,14 @@ protected Collection getExceptionHandlerMethods(final ClassNode clas } } final ClassNode superClass = classNode.getSuperClass(); - if(!superClass.equals(OBJECT_CLASS)) { + if (!superClass.equals(OBJECT_CLASS)) { final Collection superClassMethods = getExceptionHandlerMethods(superClass, sourceUnit); - for(MethodNode superClassMethod : superClassMethods) { + for (MethodNode superClassMethod : superClassMethods) { final Parameter exceptionParameter = superClassMethod.getParameters()[0]; final ClassNode exceptionType = exceptionParameter.getType(); // only add this super class handler if we don't already have // a handler for this exception type in this class - if(!exceptionTypeToHandlerMethodMap.containsKey(exceptionType)) { + if (!exceptionTypeToHandlerMethodMap.containsKey(exceptionType)) { exceptionTypeToHandlerMethodMap.put(exceptionType, superClassMethod); } } @@ -361,12 +338,11 @@ protected Collection getExceptionHandlerMethods(final ClassNode clas * Converts a method into a controller action. If the method accepts parameters, * a no-arg counterpart is created which delegates to the original. * - * @param classNode The controller class - * @param methodNode The method to be converted + * @param classNode The controller class + * @param methodNode The method to be converted * @return The no-arg wrapper method, or null if none was created. */ - private MethodNode convertToMethodAction(ClassNode classNode, MethodNode methodNode, - SourceUnit source, GeneratorContext context) { + private MethodNode convertToMethodAction(ClassNode classNode, MethodNode methodNode, SourceUnit source, GeneratorContext context) { final ClassNode returnType = methodNode.getReturnType(); Parameter[] parameters = methodNode.getParameters(); @@ -377,10 +353,8 @@ private MethodNode convertToMethodAction(ClassNode classNode, MethodNode methodN String methodName = methodNode.getName(); String initialValue = param.getInitialExpression().getText(); String methodDeclaration = methodNode.getText(); - String message = "Parameter [%s] to method [%s] has default value [%s]. " + - "Default parameter values are not allowed in controller action methods. ([%s])"; - String formattedMessage = String.format(message, paramName, methodName, - initialValue, methodDeclaration); + String message = "Parameter [%s] to method [%s] has default value [%s]. " + "Default parameter values are not allowed in controller action methods. ([%s])"; + String formattedMessage = String.format(message, paramName, methodName, initialValue, methodDeclaration); GrailsASTUtils.error(source, methodNode, formattedMessage); } } @@ -388,22 +362,15 @@ private MethodNode convertToMethodAction(ClassNode classNode, MethodNode methodN MethodNode method = null; if (methodNode.getParameters().length > 0) { final BlockStatement methodCode = new BlockStatement(); - + final BlockStatement codeToHandleAllowedMethods = getCodeToHandleAllowedMethods(classNode, methodNode.getName()); - final Statement codeToCallOriginalMethod = addOriginalMethodCall(methodNode, initializeActionParameters( - classNode, methodNode, methodNode.getName(), parameters, source, context)); - + final Statement codeToCallOriginalMethod = addOriginalMethodCall(methodNode, initializeActionParameters(classNode, methodNode, methodNode.getName(), parameters, source, context)); + methodCode.addStatement(codeToHandleAllowedMethods); methodCode.addStatement(codeToCallOriginalMethod); - - method = new MethodNode( - methodNode.getName(), - Modifier.PUBLIC, returnType, - ZERO_PARAMETERS, - EMPTY_CLASS_ARRAY, - methodCode); - + method = new MethodNode(methodNode.getName(), Modifier.PUBLIC, returnType, ZERO_PARAMETERS, EMPTY_CLASS_ARRAY, methodCode); + GrailsASTUtils.copyAnnotations(methodNode, method); methodNode.addAnnotation(DELEGATING_METHOD_ANNOATION); @@ -412,7 +379,7 @@ private MethodNode convertToMethodAction(ClassNode classNode, MethodNode methodN } else { annotateActionMethod(classNode, parameters, methodNode); } - + wrapMethodBodyWithExceptionHandling(classNode, methodNode); return method; @@ -429,8 +396,7 @@ private Statement addOriginalMethodCall(MethodNode methodNode, BlockStatement bl arguments.addExpression(new VariableExpression(p.getName(), p.getType())); } - MethodCallExpression callExpression = new MethodCallExpression( - new VariableExpression("this"), methodNode.getName(), arguments); + MethodCallExpression callExpression = new MethodCallExpression(new VariableExpression("this"), methodNode.getName(), arguments); callExpression.setMethodTarget(methodNode); callExpression.setImplicitThis(false); @@ -440,9 +406,7 @@ private Statement addOriginalMethodCall(MethodNode methodNode, BlockStatement bl } private boolean isCommandObjectAction(Parameter[] params) { - return params != null && params.length > 0 - && params[0].getType() != new ClassNode(Object[].class) - && params[0].getType() != new ClassNode(Object.class); + return params != null && params.length > 0 && params[0].getType() != new ClassNode(Object[].class) && params[0].getType() != new ClassNode(Object.class); } private void processClosures(ClassNode classNode, SourceUnit source, GeneratorContext context) { @@ -454,8 +418,7 @@ private void processClosures(ClassNode classNode, SourceUnit source, GeneratorCo for (PropertyNode property : propertyNodes) { initialExpression = property.getInitialExpression(); - if (!property.isStatic() && initialExpression != null && - initialExpression.getClass().equals(ClosureExpression.class)) { + if (!property.isStatic() && initialExpression != null && initialExpression.getClass().equals(ClosureExpression.class)) { closureAction = (ClosureExpression) initialExpression; if (converterEnabled) { transformClosureToMethod(classNode, closureAction, property, source, context); @@ -466,16 +429,13 @@ private void processClosures(ClassNode classNode, SourceUnit source, GeneratorCo } } - protected void addMethodToInvokeClosure(ClassNode controllerClassNode, - PropertyNode closureProperty, SourceUnit source, GeneratorContext context) { + protected void addMethodToInvokeClosure(ClassNode controllerClassNode, PropertyNode closureProperty, SourceUnit source, GeneratorContext context) { MethodNode method = controllerClassNode.getMethod(closureProperty.getName(), ZERO_PARAMETERS); if (method == null || !method.getDeclaringClass().equals(controllerClassNode)) { ClosureExpression closureExpression = (ClosureExpression) closureProperty.getInitialExpression(); final Parameter[] parameters = closureExpression.getParameters(); - final BlockStatement newMethodCode = initializeActionParameters( - controllerClassNode, closureProperty, closureProperty.getName(), - parameters, source, context); + final BlockStatement newMethodCode = initializeActionParameters(controllerClassNode, closureProperty, closureProperty.getName(), parameters, source, context); final ArgumentListExpression closureInvocationArguments = new ArgumentListExpression(); if (parameters != null) { @@ -484,12 +444,10 @@ protected void addMethodToInvokeClosure(ClassNode controllerClassNode, } } - final MethodCallExpression methodCallExpression = new MethodCallExpression( - closureExpression, "call", closureInvocationArguments); + final MethodCallExpression methodCallExpression = new MethodCallExpression(closureExpression, "call", closureInvocationArguments); newMethodCode.addStatement(new ExpressionStatement(applyMethodTarget(methodCallExpression, Closure.class, Object.class))); - final MethodNode methodNode = new MethodNode(closureProperty.getName(), Modifier.PUBLIC, - new ClassNode(Object.class), ZERO_PARAMETERS, EMPTY_CLASS_ARRAY, newMethodCode); + final MethodNode methodNode = new MethodNode(closureProperty.getName(), Modifier.PUBLIC, new ClassNode(Object.class), ZERO_PARAMETERS, EMPTY_CLASS_ARRAY, newMethodCode); wrapMethodBodyWithExceptionHandling(controllerClassNode, methodNode); annotateActionMethod(controllerClassNode, parameters, methodNode); ClassNodeUtils.addGeneratedMethod(controllerClassNode, methodNode); @@ -515,31 +473,31 @@ protected void annotateActionMethod(ClassNode controllerClassNode, final Paramet protected BlockStatement getCodeToHandleAllowedMethods(ClassNode controllerClass, String methodName) { GrailsASTUtils.addEnhancedAnnotation(controllerClass, DefaultGrailsControllerClass.ALLOWED_HTTP_METHODS_PROPERTY); final BlockStatement checkAllowedMethodsBlock = new BlockStatement(); - + final PropertyExpression requestPropertyExpression = new PropertyExpression(new VariableExpression("this"), "request"); - + final FieldNode allowedMethodsField = controllerClass.getField(DefaultGrailsControllerClass.ALLOWED_HTTP_METHODS_PROPERTY); - - if(allowedMethodsField != null) { + + if (allowedMethodsField != null) { final Expression initialAllowedMethodsExpression = allowedMethodsField.getInitialExpression(); - if(initialAllowedMethodsExpression instanceof MapExpression) { + if (initialAllowedMethodsExpression instanceof MapExpression) { boolean actionIsRestricted = false; final MapExpression allowedMethodsMapExpression = (MapExpression) initialAllowedMethodsExpression; final List allowedMethodsMapEntryExpressions = allowedMethodsMapExpression.getMapEntryExpressions(); - for(MapEntryExpression allowedMethodsMapEntryExpression : allowedMethodsMapEntryExpressions) { + for (MapEntryExpression allowedMethodsMapEntryExpression : allowedMethodsMapEntryExpressions) { final Expression allowedMethodsMapEntryKeyExpression = allowedMethodsMapEntryExpression.getKeyExpression(); - if(allowedMethodsMapEntryKeyExpression instanceof ConstantExpression) { + if (allowedMethodsMapEntryKeyExpression instanceof ConstantExpression) { final ConstantExpression allowedMethodsMapKeyConstantExpression = (ConstantExpression) allowedMethodsMapEntryKeyExpression; final Object allowedMethodsMapKeyValue = allowedMethodsMapKeyConstantExpression.getValue(); - if(methodName.equals(allowedMethodsMapKeyValue)) { + if (methodName.equals(allowedMethodsMapKeyValue)) { actionIsRestricted = true; break; } } } - if(actionIsRestricted) { + if (actionIsRestricted) { final PropertyExpression responsePropertyExpression = new PropertyExpression(new VariableExpression("this"), "response"); - + final ArgumentListExpression isAllowedArgumentList = new ArgumentListExpression(); isAllowedArgumentList.addExpression(new ConstantExpression(methodName)); isAllowedArgumentList.addExpression(new PropertyExpression(new VariableExpression("this"), "request")); @@ -552,30 +510,31 @@ protected BlockStatement getCodeToHandleAllowedMethods(ClassNode controllerClass blockToSendError.addStatement(new ExpressionStatement(sendErrorMethodCall)); blockToSendError.addStatement(returnStatement); final IfStatement ifIsValidRequestMethodStatement = new IfStatement(isValidRequestMethod, new ExpressionStatement(new EmptyExpression()), blockToSendError); - + checkAllowedMethodsBlock.addStatement(ifIsValidRequestMethodStatement); } } } - + final ArgumentListExpression argumentListExpression = new ArgumentListExpression(); argumentListExpression.addExpression(new ConstantExpression(ALLOWED_METHODS_HANDLED_ATTRIBUTE_NAME)); argumentListExpression.addExpression(new ConstantExpression(methodName)); - + final Expression setAttributeMethodCall = new MethodCallExpression(requestPropertyExpression, "setAttribute", argumentListExpression); - + final BlockStatement codeToExecuteIfAttributeIsNotSet = new BlockStatement(); codeToExecuteIfAttributeIsNotSet.addStatement(new ExpressionStatement(setAttributeMethodCall)); codeToExecuteIfAttributeIsNotSet.addStatement(checkAllowedMethodsBlock); final BooleanExpression attributeIsSetBooleanExpression = new BooleanExpression(new MethodCallExpression(requestPropertyExpression, "getAttribute", new ArgumentListExpression(new ConstantExpression(ALLOWED_METHODS_HANDLED_ATTRIBUTE_NAME)))); final Statement ifAttributeIsAlreadySetStatement = new IfStatement(attributeIsSetBooleanExpression, new EmptyStatement(), codeToExecuteIfAttributeIsNotSet); - + final BlockStatement code = new BlockStatement(); code.addStatement(ifAttributeIsAlreadySetStatement); return code; } + /** * This will wrap the method body in a try catch block which does something * like this: @@ -591,6 +550,7 @@ protected BlockStatement getCodeToHandleAllowedMethods(ClassNode controllerClass * } * } * + * * @param methodNode the method to add the try catch block to */ protected void wrapMethodBodyWithExceptionHandling(final ClassNode controllerClassNode, final MethodNode methodNode) { @@ -605,14 +565,13 @@ protected void wrapMethodBodyWithExceptionHandling(final ClassNode controllerCla final ClassNode reflectMethodClassNode = new ClassNode(Method.class); final String exceptionHandlerMethodVariableName = "$method"; final Expression exceptionHandlerMethodExpression = new VariableExpression(exceptionHandlerMethodVariableName, new ClassNode(Method.class)); - final Expression declareExceptionHandlerMethod = new DeclarationExpression( - new VariableExpression(exceptionHandlerMethodVariableName, reflectMethodClassNode), Token.newSymbol(Types.EQUALS, 0, 0), getExceptionHandlerMethodCall); + final Expression declareExceptionHandlerMethod = new DeclarationExpression(new VariableExpression(exceptionHandlerMethodVariableName, reflectMethodClassNode), Token.newSymbol(Types.EQUALS, 0, 0), getExceptionHandlerMethodCall); final ArgumentListExpression invokeArguments = new ArgumentListExpression(); invokeArguments.addExpression(thisExpression); invokeArguments.addExpression(caughtExceptionVariableExpression); final MethodCallExpression invokeExceptionHandlerMethodExpression = new MethodCallExpression(new VariableExpression(exceptionHandlerMethodVariableName), "invoke", invokeArguments); applyDefaultMethodTarget(invokeExceptionHandlerMethodExpression, reflectMethodClassNode); - + final Statement returnStatement = new ReturnStatement(invokeExceptionHandlerMethodExpression); final Statement throwCaughtExceptionStatement = new ThrowStatement(caughtExceptionVariableExpression); final Statement ifExceptionHandlerMethodExistsStatement = new IfStatement(new BooleanExpression(exceptionHandlerMethodExpression), returnStatement, throwCaughtExceptionStatement); @@ -632,25 +591,20 @@ protected void wrapMethodBodyWithExceptionHandling(final ClassNode controllerCla final ArgumentListExpression argumentListExpression = new ArgumentListExpression(); argumentListExpression.addExpression(new ConstantExpression(ALLOWED_METHODS_HANDLED_ATTRIBUTE_NAME)); - + final PropertyExpression requestPropertyExpression = new PropertyExpression(new VariableExpression("this"), "request"); final Expression removeAttributeMethodCall = new MethodCallExpression(requestPropertyExpression, "removeAttribute", argumentListExpression); - + final Expression getAttributeMethodCall = new MethodCallExpression(requestPropertyExpression, "getAttribute", new ArgumentListExpression(new ConstantExpression(ALLOWED_METHODS_HANDLED_ATTRIBUTE_NAME))); final VariableExpression attributeValueExpression = new VariableExpression("$allowed_methods_attribute_value", ClassHelper.make(Object.class)); - final Expression initializeAttributeValue = new DeclarationExpression( - attributeValueExpression, Token.newSymbol(Types.EQUALS, 0, 0), getAttributeMethodCall); - final Expression attributeValueMatchesMethodNameExpression = new BinaryExpression(new ConstantExpression(methodNode.getName()), - Token.newSymbol(Types.COMPARE_EQUAL, 0, 0), - attributeValueExpression); - final Statement ifAttributeValueMatchesMethodName = - new IfStatement(new BooleanExpression(attributeValueMatchesMethodNameExpression), - new ExpressionStatement(removeAttributeMethodCall), new EmptyStatement()); + final Expression initializeAttributeValue = new DeclarationExpression(attributeValueExpression, Token.newSymbol(Types.EQUALS, 0, 0), getAttributeMethodCall); + final Expression attributeValueMatchesMethodNameExpression = new BinaryExpression(new ConstantExpression(methodNode.getName()), Token.newSymbol(Types.COMPARE_EQUAL, 0, 0), attributeValueExpression); + final Statement ifAttributeValueMatchesMethodName = new IfStatement(new BooleanExpression(attributeValueMatchesMethodNameExpression), new ExpressionStatement(removeAttributeMethodCall), new EmptyStatement()); final BlockStatement blockToRemoveAttribute = new BlockStatement(); blockToRemoveAttribute.addStatement(new ExpressionStatement(initializeAttributeValue)); blockToRemoveAttribute.addStatement(ifAttributeValueMatchesMethodName); - + final TryCatchStatement tryCatchToRemoveAttribute = new TryCatchStatement(blockToRemoveAttribute, new EmptyStatement()); tryCatchToRemoveAttribute.addCatch(new CatchStatement(new Parameter(ClassHelper.make(Exception.class), "$exceptionRemovingAttribute"), new EmptyStatement())); @@ -659,12 +613,9 @@ protected void wrapMethodBodyWithExceptionHandling(final ClassNode controllerCla methodNode.setCode(tryCatchStatement); } - protected void transformClosureToMethod(ClassNode classNode, ClosureExpression closureAction, - PropertyNode property, SourceUnit source, GeneratorContext context) { + protected void transformClosureToMethod(ClassNode classNode, ClosureExpression closureAction, PropertyNode property, SourceUnit source, GeneratorContext context) { - final MethodNode actionMethod = new MethodNode(property.getName(), - Modifier.PUBLIC, property.getType(), closureAction.getParameters(), - EMPTY_CLASS_ARRAY, closureAction.getCode()); + final MethodNode actionMethod = new MethodNode(property.getName(), Modifier.PUBLIC, property.getType(), closureAction.getParameters(), EMPTY_CLASS_ARRAY, closureAction.getCode()); MethodNode convertedMethod = convertToMethodAction(classNode, actionMethod, source, context); if (convertedMethod != null) { @@ -675,18 +626,14 @@ protected void transformClosureToMethod(ClassNode classNode, ClosureExpression c ClassNodeUtils.addGeneratedMethod(classNode, actionMethod); } - protected BlockStatement initializeActionParameters(ClassNode classNode, ASTNode actionNode, - String actionName, Parameter[] actionParameters, SourceUnit source, - GeneratorContext context) { + protected BlockStatement initializeActionParameters(ClassNode classNode, ASTNode actionNode, String actionName, Parameter[] actionParameters, SourceUnit source, GeneratorContext context) { BlockStatement wrapper = new BlockStatement(); ArgumentListExpression mapBindingResultConstructorArgs = new ArgumentListExpression(); - mapBindingResultConstructorArgs.addExpression(new ConstructorCallExpression( - new ClassNode(HashMap.class), EMPTY_TUPLE)); + mapBindingResultConstructorArgs.addExpression(new ConstructorCallExpression(new ClassNode(HashMap.class), EMPTY_TUPLE)); mapBindingResultConstructorArgs.addExpression(new ConstantExpression("controller")); - final Expression mapBindingResultConstructorCallExpression = new ConstructorCallExpression( - new ClassNode(MapBindingResult.class), mapBindingResultConstructorArgs); + final Expression mapBindingResultConstructorCallExpression = new ConstructorCallExpression(new ClassNode(MapBindingResult.class), mapBindingResultConstructorArgs); final Expression errorsAssignmentExpression = buildSetPropertyExpression(new VariableExpression("this", classNode), "errors", classNode, mapBindingResultConstructorCallExpression); @@ -694,22 +641,18 @@ protected BlockStatement initializeActionParameters(ClassNode classNode, ASTNode if (actionParameters != null) { for (Parameter param : actionParameters) { - initializeMethodParameter(classNode, wrapper, actionNode, actionName, - param, source, context); + initializeMethodParameter(classNode, wrapper, actionNode, actionName, param, source, context); } } return wrapper; } - protected void initializeMethodParameter(final ClassNode classNode, final BlockStatement wrapper, - final ASTNode actionNode, final String actionName, final Parameter param, - final SourceUnit source, final GeneratorContext context) { + protected void initializeMethodParameter(final ClassNode classNode, final BlockStatement wrapper, final ASTNode actionNode, final String actionName, final Parameter param, final SourceUnit source, final GeneratorContext context) { final ClassNode paramTypeClassNode = param.getType(); final String paramName = param.getName(); String requestParameterName = paramName; - List requestParameters = param.getAnnotations( - new ClassNode(RequestParameter.class)); + List requestParameters = param.getAnnotations(new ClassNode(RequestParameter.class)); //Check to see if the method was inherited from a trait if (actionNode instanceof MethodNode && paramName.startsWith("arg")) { @@ -741,65 +684,49 @@ protected void initializeMethodParameter(final ClassNode classNode, final BlockS requestParameterName = requestParameters.get(0).getMember("value").getText(); } - if ((PRIMITIVE_CLASS_NODES.contains(paramTypeClassNode) || - TYPE_WRAPPER_CLASS_TO_CONVERSION_METHOD_NAME.containsKey(paramTypeClassNode))) { + if ((PRIMITIVE_CLASS_NODES.contains(paramTypeClassNode) || TYPE_WRAPPER_CLASS_TO_CONVERSION_METHOD_NAME.containsKey(paramTypeClassNode))) { initializePrimitiveOrTypeWrapperParameter(classNode, wrapper, param, requestParameterName); } else if (paramTypeClassNode.equals(new ClassNode(String.class))) { initializeStringParameter(classNode, wrapper, param, requestParameterName); } else if (!paramTypeClassNode.equals(OBJECT_CLASS)) { - initializeAndValidateCommandObjectParameter(wrapper, classNode, paramTypeClassNode, - actionNode, actionName, paramName, source, context); + initializeAndValidateCommandObjectParameter(wrapper, classNode, paramTypeClassNode, actionNode, actionName, paramName, source, context); } } - protected void initializeAndValidateCommandObjectParameter(final BlockStatement wrapper, - final ClassNode controllerNode, final ClassNode commandObjectNode, - final ASTNode actionNode, final String actionName, final String paramName, - final SourceUnit source, final GeneratorContext context) { + protected void initializeAndValidateCommandObjectParameter(final BlockStatement wrapper, final ClassNode controllerNode, final ClassNode commandObjectNode, final ASTNode actionNode, final String actionName, final String paramName, final SourceUnit source, final GeneratorContext context) { final DeclarationExpression declareCoExpression = declX(localVarX(paramName, commandObjectNode), new EmptyExpression()); wrapper.addStatement(stmt(declareCoExpression)); - if(commandObjectNode.isInterface() || Modifier.isAbstract(commandObjectNode.getModifiers())) { - final String warningMessage = "The [" + actionName + "] action in [" + - controllerNode.getName() + "] accepts a parameter of type [" + - commandObjectNode.getName() + - "]. Interface types and abstract class types are not supported as command objects. This parameter will be ignored."; + if (commandObjectNode.isInterface() || Modifier.isAbstract(commandObjectNode.getModifiers())) { + final String warningMessage = "The [" + actionName + "] action in [" + controllerNode.getName() + "] accepts a parameter of type [" + commandObjectNode.getName() + "]. Interface types and abstract class types are not supported as command objects. This parameter will be ignored."; GrailsASTUtils.warning(source, actionNode, warningMessage); } else { initializeCommandObjectParameter(wrapper, commandObjectNode, paramName, source); - @SuppressWarnings("unchecked") - boolean argumentIsValidateable = GrailsASTUtils.hasAnyAnnotations( - commandObjectNode, - grails.persistence.Entity.class, - jakarta.persistence.Entity.class) || - commandObjectNode.implementsInterface(ClassHelper.make(Validateable.class)); + @SuppressWarnings("unchecked") boolean argumentIsValidateable = GrailsASTUtils.hasAnyAnnotations(commandObjectNode, grails.persistence.Entity.class, jakarta.persistence.Entity.class) || commandObjectNode.implementsInterface(ClassHelper.make(Validateable.class)); if (!argumentIsValidateable && commandObjectNode.isPrimaryClassNode()) { final ModuleNode commandObjectModule = commandObjectNode.getModule(); if (commandObjectModule != null && this.compilationUnit != null) { - if (commandObjectModule == controllerNode.getModule() || - doesModulePathIncludeSubstring(commandObjectModule, - "grails-app" + File.separator + "controllers" + File.separator)) { + if (commandObjectModule == controllerNode.getModule() || doesModulePathIncludeSubstring(commandObjectModule, "grails-app" + File.separator + "controllers" + File.separator)) { TraitInjectionUtils.injectTrait(compilationUnit, source, commandObjectNode, Validateable.class); List declaredConstructors = commandObjectNode.getDeclaredConstructors(); List objectInitializerStatements = commandObjectNode.getObjectInitializerStatements(); - if(declaredConstructors.isEmpty() && !objectInitializerStatements.isEmpty()) { + if (declaredConstructors.isEmpty() && !objectInitializerStatements.isEmpty()) { BlockStatement constructorLogic = new BlockStatement(); ConstructorNode constructorNode = new ConstructorNode(Modifier.PUBLIC, constructorLogic); ClassNodeUtils.addGeneratedConstructor(commandObjectNode, constructorNode); constructorLogic.addStatements(objectInitializerStatements); } argumentIsValidateable = true; - } else if (doesModulePathIncludeSubstring(commandObjectModule, - "grails-app" + File.separator + "domain" + File.separator)) { + } else if (doesModulePathIncludeSubstring(commandObjectModule, "grails-app" + File.separator + "domain" + File.separator)) { argumentIsValidateable = true; } } } - + if (argumentIsValidateable) { final MethodCallExpression validateMethodCallExpression = callX(localVarX(paramName, commandObjectNode), "validate"); final MethodNode validateMethod = commandObjectNode.getMethod("validate", new Parameter[0]); @@ -810,39 +737,26 @@ protected void initializeAndValidateCommandObjectParameter(final BlockStatement wrapper.addStatement(ifCommandObjectIsNotNullThenValidate); } else { // try to dynamically invoke the .validate() method if it is available at runtime... - final Expression respondsToValidateMethodCallExpression = new MethodCallExpression( - new VariableExpression(paramName), "respondsTo", new ArgumentListExpression( - new ConstantExpression("validate"))); - final Expression validateMethodCallExpression = new MethodCallExpression( - new VariableExpression(paramName), "validate", new ArgumentListExpression()); - final Statement ifRespondsToValidateThenValidateStatement = new IfStatement( - new BooleanExpression(respondsToValidateMethodCallExpression), - new ExpressionStatement(validateMethodCallExpression), - new ExpressionStatement(new EmptyExpression())); + final Expression respondsToValidateMethodCallExpression = new MethodCallExpression(new VariableExpression(paramName), "respondsTo", new ArgumentListExpression(new ConstantExpression("validate"))); + final Expression validateMethodCallExpression = new MethodCallExpression(new VariableExpression(paramName), "validate", new ArgumentListExpression()); + final Statement ifRespondsToValidateThenValidateStatement = new IfStatement(new BooleanExpression(respondsToValidateMethodCallExpression), new ExpressionStatement(validateMethodCallExpression), new ExpressionStatement(new EmptyExpression())); final Statement ifCommandObjectIsNotNullThenValidate = new IfStatement(new BooleanExpression(new VariableExpression(paramName)), ifRespondsToValidateThenValidateStatement, new ExpressionStatement(new EmptyExpression())); wrapper.addStatement(ifCommandObjectIsNotNullThenValidate); - - final String warningMessage = "The [" + actionName + "] action accepts a parameter of type [" + - commandObjectNode.getName() + - "] which does not implement grails.validation.Validateable. Data binding will still be applied " + - "to this command object but the instance will not be validateable."; + + final String warningMessage = "The [" + actionName + "] action accepts a parameter of type [" + commandObjectNode.getName() + "] which does not implement grails.validation.Validateable. Data binding will still be applied " + "to this command object but the instance will not be validateable."; GrailsASTUtils.warning(source, actionNode, warningMessage); } - if(GrailsASTUtils.isInnerClassNode(commandObjectNode)) { - final String warningMessage = "The [" + actionName + "] action accepts a parameter of type [" + - commandObjectNode.getName() + - "] which is an inner class. Command object classes should not be inner classes."; + if (GrailsASTUtils.isInnerClassNode(commandObjectNode)) { + final String warningMessage = "The [" + actionName + "] action accepts a parameter of type [" + commandObjectNode.getName() + "] which is an inner class. Command object classes should not be inner classes."; GrailsASTUtils.warning(source, actionNode, warningMessage); - - } - else { + + } else { new DefaultASTDatabindingHelper().injectDatabindingCode(source, context, commandObjectNode); } } } - protected void initializeCommandObjectParameter(final BlockStatement wrapper, - final ClassNode commandObjectNode, final String paramName, SourceUnit source) { + protected void initializeCommandObjectParameter(final BlockStatement wrapper, final ClassNode commandObjectNode, final String paramName, SourceUnit source) { final ArgumentListExpression initializeCommandObjectArguments = args(classX(commandObjectNode), constX(paramName)); final MethodCallExpression initializeCommandObjectMethodCall = callThisX("initializeCommandObject", initializeCommandObjectArguments); applyDefaultMethodTarget(initializeCommandObjectMethodCall, commandObjectNode); @@ -854,7 +768,7 @@ protected void initializeCommandObjectParameter(final BlockStatement wrapper, * Checks to see if a Module is defined at a path which includes the specified substring * * @param moduleNode a ModuleNode - * @param substring The substring to search for + * @param substring The substring to search for * @return true if moduleNode is defined at a path which includes the specified substring */ private boolean doesModulePathIncludeSubstring(ModuleNode moduleNode, final String substring) { @@ -871,26 +785,18 @@ private boolean doesModulePathIncludeSubstring(ModuleNode moduleNode, final Stri return substringFoundInDescription; } - protected void initializeStringParameter(final ClassNode classNode, final BlockStatement wrapper, final Parameter param, - final String requestParameterName) { + protected void initializeStringParameter(final ClassNode classNode, final BlockStatement wrapper, final Parameter param, final String requestParameterName) { final ClassNode paramTypeClassNode = param.getType(); final String methodParamName = param.getName(); Expression getParamsExpression = buildGetPropertyExpression(new VariableExpression("this"), "params", classNode); - final Expression paramsContainsKeyMethodArguments = new ArgumentListExpression( - new ConstantExpression(requestParameterName)); - final BooleanExpression containsKeyExpression = new BooleanExpression( - applyDefaultMethodTarget(new MethodCallExpression(getParamsExpression, "containsKey", paramsContainsKeyMethodArguments), Map.class)); - final Statement initializeParameterStatement = new ExpressionStatement( - new DeclarationExpression(new VariableExpression( - methodParamName, paramTypeClassNode), - Token.newSymbol(Types.EQUALS, 0, 0), - new TernaryExpression(containsKeyExpression, buildGetMapExpression(getParamsExpression, requestParameterName) , new ConstantExpression(null)))); + final Expression paramsContainsKeyMethodArguments = new ArgumentListExpression(new ConstantExpression(requestParameterName)); + final BooleanExpression containsKeyExpression = new BooleanExpression(applyDefaultMethodTarget(new MethodCallExpression(getParamsExpression, "containsKey", paramsContainsKeyMethodArguments), Map.class)); + final Statement initializeParameterStatement = new ExpressionStatement(new DeclarationExpression(new VariableExpression(methodParamName, paramTypeClassNode), Token.newSymbol(Types.EQUALS, 0, 0), new TernaryExpression(containsKeyExpression, buildGetMapExpression(getParamsExpression, requestParameterName), new ConstantExpression(null)))); wrapper.addStatement(initializeParameterStatement); } - protected void initializePrimitiveOrTypeWrapperParameter(final ClassNode classNode, final BlockStatement wrapper, - final Parameter param, final String requestParameterName) { + protected void initializePrimitiveOrTypeWrapperParameter(final ClassNode classNode, final BlockStatement wrapper, final Parameter param, final String requestParameterName) { final ClassNode paramTypeClassNode = param.getType(); final String methodParamName = param.getName(); @@ -904,8 +810,7 @@ protected void initializePrimitiveOrTypeWrapperParameter(final ClassNode classNo } final ConstantExpression paramConstantExpression = new ConstantExpression(requestParameterName); - final Expression paramsTypeConversionMethodArguments = new ArgumentListExpression( - paramConstantExpression/*, defaultValueExpression*/, new ConstantExpression(null)); + final Expression paramsTypeConversionMethodArguments = new ArgumentListExpression(paramConstantExpression/*, defaultValueExpression*/, new ConstantExpression(null)); final String conversionMethodName; if (TYPE_WRAPPER_CLASS_TO_CONVERSION_METHOD_NAME.containsKey(paramTypeClassNode)) { conversionMethodName = TYPE_WRAPPER_CLASS_TO_CONVERSION_METHOD_NAME.get(paramTypeClassNode); @@ -913,69 +818,50 @@ protected void initializePrimitiveOrTypeWrapperParameter(final ClassNode classNo conversionMethodName = paramTypeClassNode.getName(); } Expression getParamsExpression = buildGetPropertyExpression(new VariableExpression("this"), "params", classNode); - final MethodCallExpression retrieveConvertedValueExpression = new MethodCallExpression( - getParamsExpression, conversionMethodName, paramsTypeConversionMethodArguments); + final MethodCallExpression retrieveConvertedValueExpression = new MethodCallExpression(getParamsExpression, conversionMethodName, paramsTypeConversionMethodArguments); Class defaultValueClass = null; // choose any - if("char".equals(conversionMethodName)) { + if ("char".equals(conversionMethodName)) { // TypeConvertingMap.'char' method has 2 different signatures, choose the one with "Character 'char'(String name, Integer defaultValue)" signature defaultValueClass = Integer.class; } applyMethodTarget(retrieveConvertedValueExpression, TypeConvertingMap.class, null, defaultValueClass); final Expression paramsContainsKeyMethodArguments = new ArgumentListExpression(paramConstantExpression); - final BooleanExpression containsKeyExpression = new BooleanExpression( - applyDefaultMethodTarget(new MethodCallExpression(getParamsExpression, "containsKey", paramsContainsKeyMethodArguments), Map.class)); + final BooleanExpression containsKeyExpression = new BooleanExpression(applyDefaultMethodTarget(new MethodCallExpression(getParamsExpression, "containsKey", paramsContainsKeyMethodArguments), Map.class)); final Token equalsToken = Token.newSymbol(Types.EQUALS, 0, 0); - final VariableExpression convertedValueExpression = new VariableExpression( - "___converted_" + methodParamName, new ClassNode(Object.class)); - final DeclarationExpression declareConvertedValueExpression = new DeclarationExpression( - convertedValueExpression, equalsToken, new EmptyExpression()); + final VariableExpression convertedValueExpression = new VariableExpression("___converted_" + methodParamName, new ClassNode(Object.class)); + final DeclarationExpression declareConvertedValueExpression = new DeclarationExpression(convertedValueExpression, equalsToken, new EmptyExpression()); Statement declareVariableStatement = new ExpressionStatement(declareConvertedValueExpression); wrapper.addStatement(declareVariableStatement); - final VariableExpression methodParamExpression = new VariableExpression( - methodParamName, paramTypeClassNode); - final DeclarationExpression declareParameterVariableStatement = new DeclarationExpression( - methodParamExpression, equalsToken, new EmptyExpression()); + final VariableExpression methodParamExpression = new VariableExpression(methodParamName, paramTypeClassNode); + final DeclarationExpression declareParameterVariableStatement = new DeclarationExpression(methodParamExpression, equalsToken, new EmptyExpression()); declareVariableStatement = new ExpressionStatement(declareParameterVariableStatement); wrapper.addStatement(declareVariableStatement); - final Expression assignmentExpression = new BinaryExpression( - convertedValueExpression, equalsToken, - new TernaryExpression(containsKeyExpression, retrieveConvertedValueExpression, defaultValueExpression)); + final Expression assignmentExpression = new BinaryExpression(convertedValueExpression, equalsToken, new TernaryExpression(containsKeyExpression, retrieveConvertedValueExpression, defaultValueExpression)); wrapper.addStatement(new ExpressionStatement(assignmentExpression)); Expression rejectValueMethodCallExpression = getRejectValueExpression(classNode, methodParamName); BlockStatement ifConvertedValueIsNullBlockStatement = new BlockStatement(); - ifConvertedValueIsNullBlockStatement.addStatement( - new ExpressionStatement(rejectValueMethodCallExpression)); - ifConvertedValueIsNullBlockStatement.addStatement( - new ExpressionStatement(new BinaryExpression( - methodParamExpression, equalsToken, defaultValueExpression))); + ifConvertedValueIsNullBlockStatement.addStatement(new ExpressionStatement(rejectValueMethodCallExpression)); + ifConvertedValueIsNullBlockStatement.addStatement(new ExpressionStatement(new BinaryExpression(methodParamExpression, equalsToken, defaultValueExpression))); - final BooleanExpression isConvertedValueNullExpression = new BooleanExpression(new BinaryExpression( - convertedValueExpression, Token.newSymbol(Types.COMPARE_EQUAL, 0, 0), - new ConstantExpression(null))); - final ExpressionStatement assignConvertedValueToParamStatement = new ExpressionStatement( - new BinaryExpression(methodParamExpression, equalsToken, convertedValueExpression)); - final Statement ifStatement = new IfStatement(isConvertedValueNullExpression, - ifConvertedValueIsNullBlockStatement, - assignConvertedValueToParamStatement); + final BooleanExpression isConvertedValueNullExpression = new BooleanExpression(new BinaryExpression(convertedValueExpression, Token.newSymbol(Types.COMPARE_EQUAL, 0, 0), new ConstantExpression(null))); + final ExpressionStatement assignConvertedValueToParamStatement = new ExpressionStatement(new BinaryExpression(methodParamExpression, equalsToken, convertedValueExpression)); + final Statement ifStatement = new IfStatement(isConvertedValueNullExpression, ifConvertedValueIsNullBlockStatement, assignConvertedValueToParamStatement); - wrapper.addStatement(new IfStatement(new BooleanExpression(containsKeyExpression), - ifStatement, new ExpressionStatement(new EmptyExpression()))); + wrapper.addStatement(new IfStatement(new BooleanExpression(containsKeyExpression), ifStatement, new ExpressionStatement(new EmptyExpression()))); } protected Expression getRejectValueExpression(final ClassNode classNode, final String methodParamName) { ArgumentListExpression rejectValueArgs = new ArgumentListExpression(); rejectValueArgs.addExpression(new ConstantExpression(methodParamName)); - rejectValueArgs.addExpression(new ConstantExpression( - "params." + methodParamName + ".conversion.error")); + rejectValueArgs.addExpression(new ConstantExpression("params." + methodParamName + ".conversion.error")); Expression getErrorsExpression = buildGetPropertyExpression(new VariableExpression("this", classNode), "errors", classNode); - Expression rejectValueMethodCallExpression = applyDefaultMethodTarget(new MethodCallExpression( - getErrorsExpression, "rejectValue", rejectValueArgs), Errors.class); + Expression rejectValueMethodCallExpression = applyDefaultMethodTarget(new MethodCallExpression(getErrorsExpression, "rejectValue", rejectValueArgs), Errors.class); return rejectValueMethodCallExpression; } @@ -983,7 +869,6 @@ public void performInjection(SourceUnit source, ClassNode classNode) { performInjection(source, null, classNode); } - public boolean shouldInject(URL url) { return url != null && CONTROLLER_PATTERN.matcher(url.getFile()).find(); } diff --git a/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerArtefactTypeTransformation.java b/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerArtefactTypeTransformation.java index a1ed8b5c353..54c21140b21 100644 --- a/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerArtefactTypeTransformation.java +++ b/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerArtefactTypeTransformation.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.compiler.web; import grails.web.Controller; @@ -24,9 +23,9 @@ import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.control.CompilePhase; import org.codehaus.groovy.control.SourceUnit; -import org.grails.core.artefact.ControllerArtefactHandler; -import org.grails.compiler.injection.ArtefactTypeAstTransformation; import org.codehaus.groovy.transform.GroovyASTTransformation; +import org.grails.compiler.injection.ArtefactTypeAstTransformation; +import org.grails.core.artefact.ControllerArtefactHandler; /** * A transformation that makes an Artefact a controller @@ -36,6 +35,7 @@ */ @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) public class ControllerArtefactTypeTransformation extends ArtefactTypeAstTransformation { + @Override protected String resolveArtefactType(SourceUnit sourceUnit, AnnotationNode annotationNode, ClassNode classNode) { return ControllerArtefactHandler.TYPE; diff --git a/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerDomainTransformer.java b/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerDomainTransformer.java index 519b4cbf7de..3ec41229d23 100644 --- a/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerDomainTransformer.java +++ b/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerDomainTransformer.java @@ -71,7 +71,7 @@ public boolean shouldInject(URL url) { @Override public void performInjection(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) { - super.performInjection(source, context, classNode); + super.performInjection(source, context, classNode); new DefaultASTDatabindingHelper().injectDatabindingCode(source, context, classNode); } } diff --git a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllerExceptionHandlerMetaData.java b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllerExceptionHandlerMetaData.java index 857df8f6539..630c844fb05 100644 --- a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllerExceptionHandlerMetaData.java +++ b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllerExceptionHandlerMetaData.java @@ -21,10 +21,13 @@ /** * Represents meta data which describes an exception handling method * in a controller + * * @since 2.3 * */ public interface ControllerExceptionHandlerMetaData { + Class getExceptionType(); + String getMethodName(); } diff --git a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllersAutoConfiguration.java b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllersAutoConfiguration.java index 3cde4bc4aa9..827fd5de47b 100644 --- a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllersAutoConfiguration.java +++ b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllersAutoConfiguration.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.plugins.web.controllers; import grails.config.Settings; @@ -47,10 +46,13 @@ import java.util.EnumSet; -@AutoConfiguration(before = { HttpEncodingAutoConfiguration.class, WebMvcAutoConfiguration.class }) +@AutoConfiguration(before = {HttpEncodingAutoConfiguration.class, WebMvcAutoConfiguration.class}) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) public class ControllersAutoConfiguration { + @Value("${" + Settings.WEB_SERVLET_PATH + ":#{null}}") + String grailsServletPath; + @Value("${" + Settings.FILTER_ENCODING + ":utf-8}") private String filtersEncoding; @@ -78,9 +80,6 @@ public class ControllersAutoConfiguration { @Value("${" + Settings.CONTROLLERS_UPLOAD_FILE_SIZE_THRESHOLD + ":0}") private int fileSizeThreshold; - @Value("${" + Settings.WEB_SERVLET_PATH + ":#{null}}") - String grailsServletPath; - @Bean @ConditionalOnMissingBean(CharacterEncodingFilter.class) public CharacterEncodingFilter characterEncodingFilter() { @@ -152,9 +151,9 @@ public GrailsWebMvcConfigurer webMvcConfig() { static class GrailsWebMvcConfigurer implements WebMvcConfigurer { - private static final String[] SERVLET_RESOURCE_LOCATIONS = new String[] { "/" }; + private static final String[] SERVLET_RESOURCE_LOCATIONS = new String[]{"/"}; - private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[] { + private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{ "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" }; diff --git a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllersGrailsPlugin.groovy b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllersGrailsPlugin.groovy index 61d12d9581c..269627b7904 100644 --- a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllersGrailsPlugin.groovy +++ b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/ControllersGrailsPlugin.groovy @@ -51,63 +51,65 @@ class ControllersGrailsPlugin extends Plugin { def dependsOn = [core: version, i18n: version, urlMappings: version] @Override - Closure doWithSpring(){ { -> - def application = grailsApplication - def config = application.config + Closure doWithSpring() { + { -> + def application = grailsApplication + def config = application.config - boolean useJsessionId = config.getProperty(Settings.GRAILS_VIEWS_ENABLE_JSESSIONID, Boolean, false) + boolean useJsessionId = config.getProperty(Settings.GRAILS_VIEWS_ENABLE_JSESSIONID, Boolean, false) - if (!Boolean.parseBoolean(System.getProperty(Settings.SETTING_SKIP_BOOTSTRAP))) { - bootStrapClassRunner(BootStrapClassRunner) - } + if (!Boolean.parseBoolean(System.getProperty(Settings.SETTING_SKIP_BOOTSTRAP))) { + bootStrapClassRunner(BootStrapClassRunner) + } - tokenResponseActionResultTransformer(TokenResponseActionResultTransformer) + tokenResponseActionResultTransformer(TokenResponseActionResultTransformer) - exceptionHandler(GrailsExceptionResolver) { - exceptionMappings = ['java.lang.Exception': '/error'] - } + exceptionHandler(GrailsExceptionResolver) { + exceptionMappings = ['java.lang.Exception': '/error'] + } - "${CompositeViewResolver.BEAN_NAME}"(CompositeViewResolver) + "${CompositeViewResolver.BEAN_NAME}"(CompositeViewResolver) - def handlerInterceptors = springConfig.containsBean("localeChangeInterceptor") ? [ref("localeChangeInterceptor")] : [] - def interceptorsClosure = { - interceptors = handlerInterceptors - } - // allow @Controller annotated beans - annotationHandlerMapping(RequestMappingHandlerMapping, interceptorsClosure) - annotationHandlerAdapter(RequestMappingHandlerAdapter) + def handlerInterceptors = springConfig.containsBean("localeChangeInterceptor") ? [ref("localeChangeInterceptor")] : [] + def interceptorsClosure = { + interceptors = handlerInterceptors + } + // allow @Controller annotated beans + annotationHandlerMapping(RequestMappingHandlerMapping, interceptorsClosure) + annotationHandlerAdapter(RequestMappingHandlerAdapter) - for (controller in application.getArtefacts(ControllerArtefactHandler.TYPE)) { - log.debug "Configuring controller $controller.fullName" - if (controller.available) { - def lazyInit = controller.hasProperty("lazyInit") ? controller.getPropertyValue("lazyInit") : true - "${controller.fullName}"(controller.clazz) { bean -> - bean.lazyInit = lazyInit - def beanScope = controller.getScope() - bean.scope = beanScope - bean.autowire = "byName" - if (beanScope == 'prototype') { - bean.beanDefinition.dependencyCheck = AbstractBeanDefinition.DEPENDENCY_CHECK_NONE - } - if (useJsessionId) { - useJessionId = useJsessionId + for (controller in application.getArtefacts(ControllerArtefactHandler.TYPE)) { + log.debug "Configuring controller $controller.fullName" + if (controller.available) { + def lazyInit = controller.hasProperty("lazyInit") ? controller.getPropertyValue("lazyInit") : true + "${controller.fullName}"(controller.clazz) { bean -> + bean.lazyInit = lazyInit + def beanScope = controller.getScope() + bean.scope = beanScope + bean.autowire = "byName" + if (beanScope == 'prototype') { + bean.beanDefinition.dependencyCheck = AbstractBeanDefinition.DEPENDENCY_CHECK_NONE + } + if (useJsessionId) { + useJessionId = useJsessionId + } } } } - } - if (config.getProperty(Settings.SETTING_LEGACY_JSON_BUILDER, Boolean.class, false)) { - log.warn("'grails.json.legacy.builder' is set to TRUE but is NOT supported in this version of Grails.") + if (config.getProperty(Settings.SETTING_LEGACY_JSON_BUILDER, Boolean.class, false)) { + log.warn("'grails.json.legacy.builder' is set to TRUE but is NOT supported in this version of Grails.") + } } - } } + } @Override - void onChange( Map event) { + void onChange(Map event) { if (!(event.source instanceof Class)) { return } def application = grailsApplication - if (application.isArtefactOfType(ControllerArtefactHandler.TYPE, (Class)event.source)) { + if (application.isArtefactOfType(ControllerArtefactHandler.TYPE, (Class) event.source)) { ApplicationContext context = applicationContext if (!context) { if (log.isDebugEnabled()) { @@ -116,7 +118,7 @@ class ControllersGrailsPlugin extends Plugin { return } - GrailsControllerClass controllerClass = (GrailsControllerClass)application.addArtefact(ControllerArtefactHandler.TYPE, (Class)event.source) + GrailsControllerClass controllerClass = (GrailsControllerClass) application.addArtefact(ControllerArtefactHandler.TYPE, (Class) event.source) beans { "${controllerClass.fullName}"(controllerClass.clazz) { bean -> def beanScope = controllerClass.getScope() diff --git a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/DefaultControllerExceptionHandlerMetaData.groovy b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/DefaultControllerExceptionHandlerMetaData.groovy index 05a86ae91c8..83890c461a2 100644 --- a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/DefaultControllerExceptionHandlerMetaData.groovy +++ b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/DefaultControllerExceptionHandlerMetaData.groovy @@ -28,6 +28,7 @@ import groovy.transform.Immutable */ @Immutable(knownImmutableClasses = [Class]) class DefaultControllerExceptionHandlerMetaData implements ControllerExceptionHandlerMetaData { + String methodName Class exceptionType } diff --git a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/api/ControllersDomainBindingApi.java b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/api/ControllersDomainBindingApi.java index b60cd2d3d1a..810724054fd 100644 --- a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/api/ControllersDomainBindingApi.java +++ b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/api/ControllersDomainBindingApi.java @@ -40,7 +40,6 @@ public class ControllersDomainBindingApi { public static final String AUTOWIRE_DOMAIN_METHOD = "autowireDomain"; - /** * Autowires the instance * @@ -53,15 +52,14 @@ public static void initialize(Object instance) { /** * A map based constructor that binds the named arguments to the target instance * - * @param instance The target instance + * @param instance The target instance * @param namedArgs The named arguments */ public static void initialize(Object instance, Map namedArgs) { PersistentEntity dc = getDomainClass(instance); if (dc == null) { DataBindingUtils.bindObjectToInstance(instance, namedArgs); - } - else { + } else { DataBindingUtils.bindObjectToDomainInstance(dc, instance, namedArgs); DataBindingUtils.assignBidirectionalAssociations(instance, namedArgs, dc); } @@ -70,7 +68,7 @@ public static void initialize(Object instance, Map namedArgs) { private static PersistentEntity getDomainClass(Object instance) { PersistentEntity domainClass = null; - if(!Environment.isInitializing()) { + if (!Environment.isInitializing()) { final GrailsApplication grailsApplication = Holders.findApplication(); if (grailsApplication != null) { try { @@ -85,14 +83,14 @@ private static PersistentEntity getDomainClass(Object instance) { } private static void autowire(Object instance) { - if(!Environment.isInitializing()) { + if (!Environment.isInitializing()) { GrailsApplication application = Holders.findApplication(); - if(application != null) { + if (application != null) { try { PersistentEntity domainClass = application.getMappingContext().getPersistentEntity(instance.getClass().getName()); - if(domainClass != null) { + if (domainClass != null) { if (domainClass.getMapping().getMappedForm().isAutowire()) { final ApplicationContext applicationContext = Holders.findApplicationContext(); diff --git a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/metaclass/RenderDynamicMethod.java b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/metaclass/RenderDynamicMethod.java index d974706c559..64b9f35ec29 100644 --- a/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/metaclass/RenderDynamicMethod.java +++ b/grails-controllers/src/main/groovy/org/grails/plugins/web/controllers/metaclass/RenderDynamicMethod.java @@ -24,8 +24,9 @@ * @author Graeme Rocher * @since 0.2 */ -@SuppressWarnings({"unchecked","rawtypes"}) +@SuppressWarnings({"unchecked", "rawtypes"}) public class RenderDynamicMethod { + public static final String METHOD_SIGNATURE = "render"; public static final String ARGUMENT_TEXT = "text"; public static final String ARGUMENT_STATUS = "status"; diff --git a/grails-controllers/src/main/groovy/org/grails/plugins/web/servlet/context/BootStrapClassRunner.groovy b/grails-controllers/src/main/groovy/org/grails/plugins/web/servlet/context/BootStrapClassRunner.groovy index 87ba7989838..430d9af5e8c 100644 --- a/grails-controllers/src/main/groovy/org/grails/plugins/web/servlet/context/BootStrapClassRunner.groovy +++ b/grails-controllers/src/main/groovy/org/grails/plugins/web/servlet/context/BootStrapClassRunner.groovy @@ -27,6 +27,7 @@ import grails.plugins.PluginManagerAware import grails.web.servlet.bootstrap.GrailsBootstrapClass import groovy.transform.CompileStatic import groovy.util.logging.Commons +import jakarta.servlet.ServletContext import org.grails.web.servlet.boostrap.BootstrapArtefactHandler import org.grails.web.servlet.context.GrailsConfigUtils import org.springframework.context.ApplicationContext @@ -34,10 +35,6 @@ import org.springframework.context.ApplicationContextAware import org.springframework.web.context.ServletContextAware import org.springframework.web.context.WebApplicationContext -import jakarta.servlet.ServletContext - - - /** * Runs the BootStrap classes on startup * @@ -55,19 +52,19 @@ class BootStrapClassRunner extends GrailsApplicationLifeCycleAdapter implements @Override void onStartup(Map event) { - if(grailsApplication && applicationContext && servletContext) { - GrailsConfigUtils.executeGrailsBootstraps(grailsApplication, (WebApplicationContext)applicationContext, servletContext, pluginManager ) + if (grailsApplication && applicationContext && servletContext) { + GrailsConfigUtils.executeGrailsBootstraps(grailsApplication, (WebApplicationContext) applicationContext, servletContext, pluginManager) } } @Override void onShutdown(Map event) { - if(grailsApplication && applicationContext) { - for(GrailsClass cls in grailsApplication.getArtefacts(BootstrapArtefactHandler.TYPE)) { + if (grailsApplication && applicationContext) { + for (GrailsClass cls in grailsApplication.getArtefacts(BootstrapArtefactHandler.TYPE)) { try { - ((GrailsBootstrapClass)cls).callDestroy() + ((GrailsBootstrapClass) cls).callDestroy() } catch (Throwable e) { - log.error("Error occurred running Bootstrap destroy method: " + e.getMessage(), e) + log.error("Error occurred running Bootstrap destroy method: " + e.getMessage(), e) } } } diff --git a/grails-controllers/src/main/groovy/org/grails/plugins/web/servlet/mvc/InvalidResponseHandler.groovy b/grails-controllers/src/main/groovy/org/grails/plugins/web/servlet/mvc/InvalidResponseHandler.groovy index 7909be12116..b18fff8c996 100644 --- a/grails-controllers/src/main/groovy/org/grails/plugins/web/servlet/mvc/InvalidResponseHandler.groovy +++ b/grails-controllers/src/main/groovy/org/grails/plugins/web/servlet/mvc/InvalidResponseHandler.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.plugins.web.servlet.mvc import groovy.transform.CompileStatic diff --git a/grails-controllers/src/main/groovy/org/grails/plugins/web/servlet/mvc/ValidResponseHandler.groovy b/grails-controllers/src/main/groovy/org/grails/plugins/web/servlet/mvc/ValidResponseHandler.groovy index f211faae7a5..42069ec5bb5 100644 --- a/grails-controllers/src/main/groovy/org/grails/plugins/web/servlet/mvc/ValidResponseHandler.groovy +++ b/grails-controllers/src/main/groovy/org/grails/plugins/web/servlet/mvc/ValidResponseHandler.groovy @@ -21,7 +21,6 @@ package org.grails.plugins.web.servlet.mvc import groovy.transform.CompileStatic import org.grails.web.servlet.mvc.AbstractTokenResponseHandler - /** * Handles a valid token response. See {@link org.grails.web.servlet.mvc.TokenResponseHandler} * diff --git a/grails-controllers/src/test/groovy/grails/artefact/controller/support/AllowedMethodsHelperSpec.groovy b/grails-controllers/src/test/groovy/grails/artefact/controller/support/AllowedMethodsHelperSpec.groovy index 55228075e2b..446485ac267 100644 --- a/grails-controllers/src/test/groovy/grails/artefact/controller/support/AllowedMethodsHelperSpec.groovy +++ b/grails-controllers/src/test/groovy/grails/artefact/controller/support/AllowedMethodsHelperSpec.groovy @@ -20,9 +20,6 @@ package grails.artefact.controller.support import jakarta.servlet.http.HttpServletRequest - -import org.springframework.http.HttpMethod - import spock.lang.Specification class AllowedMethodsHelperSpec extends Specification { diff --git a/grails-controllers/src/test/groovy/grails/artefact/controller/support/RequestForwarderSpec.groovy b/grails-controllers/src/test/groovy/grails/artefact/controller/support/RequestForwarderSpec.groovy index 3eb5f191952..f1239c2c970 100644 --- a/grails-controllers/src/test/groovy/grails/artefact/controller/support/RequestForwarderSpec.groovy +++ b/grails-controllers/src/test/groovy/grails/artefact/controller/support/RequestForwarderSpec.groovy @@ -72,7 +72,6 @@ class RequestForwarderSpec extends Specification { webRequest.request.getAttribute(GrailsApplicationAttributes.MODEL_AND_VIEW) == null - cleanup: RequestContextHolder.setRequestAttributes(null) } diff --git a/grails-controllers/src/test/groovy/org/grails/compiler/web/ControllerActionTransformerSpec.groovy b/grails-controllers/src/test/groovy/org/grails/compiler/web/ControllerActionTransformerSpec.groovy index 6687f90bcf8..caa00b4f64c 100644 --- a/grails-controllers/src/test/groovy/org/grails/compiler/web/ControllerActionTransformerSpec.groovy +++ b/grails-controllers/src/test/groovy/org/grails/compiler/web/ControllerActionTransformerSpec.groovy @@ -197,14 +197,12 @@ class ControllerActionTransformerSpec extends Specification { 42 == model.paramValue } - void "test controller with trait action with command params"() { given: def cls = gcl.parseClass(''' @grails.artefact.Artefact('Controller') class TestTraitActionToController implements ShowMethod { - } class MyCommandWithArg implements grails.validation.Validateable { @@ -227,7 +225,6 @@ class ControllerActionTransformerSpec extends Specification { valid } - void "Test command object gets Validateable injected"() { when: @@ -330,4 +327,3 @@ class ControllerActionTransformerSpec extends Specification { } } - diff --git a/grails-converters/build.gradle b/grails-converters/build.gradle index c9a0d65d310..ccb7e4c3ea8 100644 --- a/grails-converters/build.gradle +++ b/grails-converters/build.gradle @@ -76,4 +76,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-converters/src/main/groovy/grails/converters/JSON.java b/grails-converters/src/main/groovy/grails/converters/JSON.java index 5dee9f7ea30..46c384f0c1a 100644 --- a/grails-converters/src/main/groovy/grails/converters/JSON.java +++ b/grails-converters/src/main/groovy/grails/converters/JSON.java @@ -23,6 +23,8 @@ import grails.web.mime.MimeType; import groovy.lang.Closure; import groovy.util.BuilderSupport; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.grails.web.converters.AbstractConverter; @@ -35,12 +37,25 @@ import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.ClosureObjectMarshaller; import org.grails.web.converters.marshaller.ObjectMarshaller; -import org.grails.web.json.*; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.*; -import java.util.*; +import org.grails.web.json.JSONArray; +import org.grails.web.json.JSONElement; +import org.grails.web.json.JSONException; +import org.grails.web.json.JSONObject; +import org.grails.web.json.JSONTokener; +import org.grails.web.json.JSONWriter; +import org.grails.web.json.PathCapturingJSONWriterWrapper; +import org.grails.web.json.PrettyPrintJSONWriter; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PushbackInputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; /** * A converter that converts domain classes, Maps, Lists, Arrays, POJOs and POGOs to JSON. @@ -50,7 +65,7 @@ */ public class JSON extends AbstractConverter implements IncludeExcludeConverter { - private final static Log log = LogFactory.getLog(JSON.class); + private static final Log LOG = LogFactory.getLog(JSON.class); private static final String CACHED_JSON = "org.codehaus.groovy.grails.CACHED_JSON_REQUEST_CONTENT"; protected Object target; @@ -60,10 +75,6 @@ public class JSON extends AbstractConverter implements IncludeExclud protected JSONWriter writer; protected Stack referenceStack; - protected ConverterConfiguration initConfig() { - return ConvertersConfigurationHolder.getConverterConfiguration(JSON.class); - } - /** * Default Constructor for a JSON Converter */ @@ -85,6 +96,10 @@ public JSON(Object target) { setTarget(target); } + protected ConverterConfiguration initConfig() { + return ConvertersConfigurationHolder.getConverterConfiguration(JSON.class); + } + public void setPrettyPrint(boolean prettyPrint) { this.prettyPrint = prettyPrint; } @@ -92,8 +107,8 @@ public void setPrettyPrint(boolean prettyPrint) { private void prepareRender(Writer out) { writer = prettyPrint ? new PrettyPrintJSONWriter(out) : new JSONWriter(out); if (circularReferenceBehaviour == CircularReferenceBehaviour.PATH) { - if (log.isInfoEnabled()) { - log.info(String.format("Using experimental CircularReferenceBehaviour.PATH for %s", getClass().getName())); + if (LOG.isInfoEnabled()) { + LOG.info(String.format("Using experimental CircularReferenceBehaviour.PATH for %s", getClass().getName())); } writer = new PathCapturingJSONWriterWrapper(writer); } @@ -104,9 +119,8 @@ private void finalizeRender(Writer out) { try { out.flush(); out.close(); - } - catch (Exception e) { - log.warn("Unexpected exception while closing a writer: " + e.getMessage()); + } catch (Exception e) { + LOG.warn("Unexpected exception while closing a writer: " + e.getMessage()); } } @@ -133,8 +147,7 @@ public void render(HttpServletResponse response) throws ConverterException { response.setContentType(GrailsWebUtil.getContentType(contentType, encoding)); try { render(response.getWriter()); - } - catch (IOException e) { + } catch (IOException e) { throw new ConverterException(e); } } @@ -160,25 +173,20 @@ public void value(Object o) throws ConverterException { try { if (o == null) { writer.valueNull(); - } - else if (o instanceof CharSequence) { + } else if (o instanceof CharSequence) { writer.value(o); - } - else if (o instanceof Class) { - writer.value(((Class)o).getName()); - } - else if (o instanceof Number) { - writer.value((Number)o); + } else if (o instanceof Class) { + writer.value(((Class) o).getName()); + } else if (o instanceof Number) { + writer.value((Number) o); } else if (o instanceof Boolean) { - writer.value((Boolean)o); + writer.value((Boolean) o); } else if (o.getClass().isPrimitive() && !o.getClass().equals(byte[].class)) { writer.value(o); - } - else { + } else { if (referenceStack.contains(o)) { handleCircularRelationship(o); - } - else { + } else { referenceStack.push(o); ObjectMarshaller marshaller = config.getMarshaller(o); if (marshaller == null) { @@ -188,11 +196,9 @@ else if (o instanceof Number) { referenceStack.pop(); } } - } - catch (ConverterException ce) { + } catch (ConverterException ce) { throw ce; - } - catch (JSONException e) { + } catch (JSONException e) { throw new ConverterException(e); } } @@ -258,8 +264,7 @@ public static JSONElement parse(String source) throws ConverterException { // return empty object return new JSONObject(); - } - catch (JSONException e) { + } catch (JSONException e) { throw new ConverterException("Error parsing JSON", e); } } @@ -273,7 +278,7 @@ public static JSONElement parse(String source) throws ConverterException { * @throws ConverterException when the JSON content is not valid */ public static JSONElement parse(InputStream is, String encoding) throws ConverterException { - return parse(IOUtils.toString(is, encoding)); + return parse(IOUtils.toString(is, encoding)); } /** @@ -299,20 +304,19 @@ public static Object parse(HttpServletRequest request) throws ConverterException try { pushbackInputStream = new PushbackInputStream(request.getInputStream()); firstByte = pushbackInputStream.read(); - } catch (IOException ioe) {} + } catch (IOException ioe) { + } // code has only been changed from here down if (firstByte == -1) { json = new JSONObject(); - } - else { + } else { pushbackInputStream.unread(firstByte); json = parse(pushbackInputStream, encoding); } request.setAttribute(CACHED_JSON, json); return json; - } - catch (IOException e) { + } catch (IOException e) { throw new ConverterException("Error parsing JSON", e); } } @@ -343,13 +347,13 @@ protected void handleCircularRelationship(Object o) throws ConverterException { } props.put("_ref", ref.substring(0, ref.length() - 1)); value(props); - } - else { - if(isMap) { - writer.object(); writer.endObject(); - } - else { - writer.array(); writer.endArray(); + } else { + if (isMap) { + writer.object(); + writer.endObject(); + } else { + writer.array(); + writer.endArray(); } } break; @@ -368,6 +372,9 @@ protected void handleCircularRelationship(Object o) throws ConverterException { break; case IGNORE: break; + default: + // do nothing + break; } } @@ -385,8 +392,7 @@ public static Object use(String configName, Closure callable) throws Converte ConvertersConfigurationHolder.setThreadLocalConverterConfiguration(JSON.class, cfg); try { return callable.call(); - } - finally { + } finally { ConvertersConfigurationHolder.setThreadLocalConverterConfiguration(JSON.class, old); } } @@ -394,8 +400,7 @@ public static Object use(String configName, Closure callable) throws Converte public static void use(String cfgName) throws ConverterException { if (cfgName == null || "default".equals(cfgName)) { ConvertersConfigurationHolder.setThreadLocalConverterConfiguration(JSON.class, null); - } - else { + } else { ConvertersConfigurationHolder.setThreadLocalConverterConfiguration(JSON.class, getNamedConfig(cfgName)); } } @@ -437,8 +442,7 @@ public static void createNamedConfig(String name, Closure callable) throws Co try { callable.call(cfg); ConvertersConfigurationHolder.setNamedConverterConfiguration(JSON.class, name, cfg); - } - catch (Exception e) { + } catch (Exception e) { throw ConverterUtil.resolveConverterException(e); } } @@ -452,8 +456,7 @@ public static void withDefaultConfiguration(Closure callable) throws Converte callable.call(cfg); ConvertersConfigurationHolder.setDefaultConfiguration(JSON.class, cfg); ConvertersConfigurationHolder.setDefaultConfiguration(JSON.class, cfg); - } - catch (Throwable t) { + } catch (Throwable t) { throw ConverterUtil.resolveConverterException(t); } } @@ -468,9 +471,17 @@ public void setExcludes(List excludes) { setExcludes(target.getClass(), excludes); } + private enum BuilderMode { + ARRAY, + OBJECT + } + public class Builder extends BuilderSupport { private JSON json; + private Stack stack = new Stack(); + private boolean start = true; + private JSONWriter writer; public Builder(JSON json) { this.json = json; @@ -480,13 +491,9 @@ public Builder(JSON json) { public void execute(Closure callable) { callable.setDelegate(this); // callable.setDelegate(Closure.DELEGATE_FIRST); - invokeMethod("json", new Object[] { callable }); + invokeMethod("json", new Object[]{callable}); } - private Stack stack = new Stack(); - private boolean start = true; - private JSONWriter writer; - @Override protected Object createNode(Object name) { int retVal = 1; @@ -494,8 +501,7 @@ protected Object createNode(Object name) { if (start) { start = false; writeObject(); - } - else { + } else { if (getCurrent() == null && stack.peek() == BuilderMode.OBJECT) { throw new IllegalArgumentException("only call to [element { }] is allowed when creating array"); } @@ -506,8 +512,7 @@ protected Object createNode(Object name) { writer.key(String.valueOf(name)).array(); stack.push(BuilderMode.ARRAY); } - } - catch (JSONException e) { + } catch (JSONException e) { throw new IllegalArgumentException("invalid element"); } @@ -524,13 +529,12 @@ protected Object createNode(Object key, Map valueMap) { writer.object(); for (Object o : valueMap.entrySet()) { Map.Entry element = (Map.Entry) o; - writer.key(String.valueOf(element.getKey()));//.value(element.getValue()); + writer.key(String.valueOf(element.getKey())); //.value(element.getValue()); json.convertAnother(element.getValue()); } writer.endObject(); return null; - } - catch (JSONException e) { + } catch (JSONException e) { throw new IllegalArgumentException("invalid element"); } } @@ -544,7 +548,7 @@ protected Object createNode(Object arg0, Map arg1, Object arg2) { @SuppressWarnings("rawtypes") @Override protected Object createNode(Object key, Object value) { - if (getCurrent() == null && stack.peek()== BuilderMode.OBJECT) { + if (getCurrent() == null && stack.peek() == BuilderMode.OBJECT) { throw new IllegalArgumentException("only call to [element { }] is allowed when creating array"); } @@ -555,17 +559,15 @@ protected Object createNode(Object key, Object value) { retVal = 1; } if (value instanceof Collection) { - Collection c = (Collection)value; + Collection c = (Collection) value; writer.key(String.valueOf(key)); handleCollectionRecurse(c); - } - else { + } else { writer.key(String.valueOf(key)); json.convertAnother(value); //.value(value); } return retVal != 0 ? retVal : null; - } - catch (JSONException e) { + } catch (JSONException e) { throw new IllegalArgumentException("invalid element"); } } @@ -576,8 +578,7 @@ private void handleCollectionRecurse(Collection c) throws JSONException { for (Object element : c) { if (element instanceof Collection) { handleCollectionRecurse((Collection) element); - } - else { + } else { json.convertAnother(element); } } @@ -593,7 +594,7 @@ protected void nodeCompleted(Object parent, Object node) { } try { - int i = ((Integer)node); + int i = ((Integer) node); while (i-- > 0) { last = stack.pop(); if (BuilderMode.ARRAY == last) { @@ -603,8 +604,7 @@ protected void nodeCompleted(Object parent, Object node) { writer.endObject(); } } - } - catch (JSONException e) { + } catch (JSONException e) { throw new IllegalArgumentException("invalid element on the stack"); } } @@ -619,9 +619,4 @@ private void writeObject() throws JSONException { stack.push(BuilderMode.OBJECT); } } - - private enum BuilderMode { - ARRAY, - OBJECT - } } diff --git a/grails-converters/src/main/groovy/grails/converters/XML.java b/grails-converters/src/main/groovy/grails/converters/XML.java index 1a024e518e6..4bb91137e85 100644 --- a/grails-converters/src/main/groovy/grails/converters/XML.java +++ b/grails-converters/src/main/groovy/grails/converters/XML.java @@ -18,18 +18,17 @@ */ package grails.converters; +import grails.core.support.proxy.EntityProxyHandler; +import grails.core.support.proxy.ProxyHandler; import grails.util.GrailsNameUtils; import grails.util.GrailsWebUtil; +import grails.web.mime.MimeType; import groovy.lang.Closure; import groovy.util.BuilderSupport; - +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - -import grails.core.support.proxy.EntityProxyHandler; -import grails.core.support.proxy.ProxyHandler; -import grails.web.mime.MimeType; - import org.grails.buffer.FastStringWriter; import org.grails.web.converters.AbstractConverter; import org.grails.web.converters.Converter; @@ -47,9 +46,6 @@ import org.grails.web.xml.XMLStreamWriter; import org.springframework.util.Assert; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -69,7 +65,7 @@ */ public class XML extends AbstractConverter implements IncludeExcludeConverter { - public static final Log log = LogFactory.getLog(XML.class); + public static final Log LOG = LogFactory.getLog(XML.class); private static final String CACHED_XML = "org.codehaus.groovy.grails.CACHED_XML_REQUEST_CONTENT"; @@ -115,15 +111,14 @@ private void finalizeRender(Writer out) { out.flush(); out.close(); } - } - catch (Exception e) { - log.warn("Unexpected exception while closing a writer: " + e.getMessage()); + } catch (Exception e) { + LOG.warn("Unexpected exception while closing a writer: " + e.getMessage()); } } public void render(Writer out) throws ConverterException { stream = new StreamingMarkupWriter(out, encoding); - writer = config.isPrettyPrint() ? new PrettyPrintXMLStreamWriter(stream): new XMLStreamWriter(stream); + writer = config.isPrettyPrint() ? new PrettyPrintXMLStreamWriter(stream) : new XMLStreamWriter(stream); try { isRendering = true; @@ -132,11 +127,9 @@ public void render(Writer out) throws ConverterException { convertAnother(target); writer.end(); finalizeRender(out); - } - catch (Exception e) { + } catch (Exception e) { throw new ConverterException(e); - } - finally { + } finally { isRendering = false; } } @@ -162,24 +155,22 @@ public String getElementName(Object o) { public void convertAnother(Object o) throws ConverterException { o = config.getProxyHandler().unwrapIfProxy(o); - if (o == null) return; + if (o == null) { + return; + } try { if (o instanceof CharSequence) { writer.characters(o.toString()); - } - else if (o instanceof Class) { - writer.characters(((Class)o).getName()); - } - else if ((o.getClass().isPrimitive() && !o.getClass().equals(byte[].class)) || + } else if (o instanceof Class) { + writer.characters(((Class) o).getName()); + } else if ((o.getClass().isPrimitive() && !o.getClass().equals(byte[].class)) || o instanceof Number || o instanceof Boolean) { writer.characters(String.valueOf(o)); - } - else { + } else { if (referenceStack.contains(o)) { handleCircularRelationship(o); - } - else { + } else { referenceStack.push(o); ObjectMarshaller marshaller = config.getMarshaller(o); if (marshaller == null) { @@ -189,8 +180,7 @@ else if ((o.getClass().isPrimitive() && !o.getClass().equals(byte[].class)) || referenceStack.pop(); } } - } - catch (Throwable t) { + } catch (Throwable t) { throw ConverterUtil.resolveConverterException(t); } } @@ -207,8 +197,7 @@ public XML startNode(String tagName) { checkState(); try { writer.startNode(tagName); - } - catch (Exception e) { + } catch (Exception e) { throw ConverterUtil.resolveConverterException(e); } return this; @@ -218,8 +207,7 @@ public XML chars(String chars) { checkState(); try { writer.characters(chars); - } - catch (Exception e) { + } catch (Exception e) { throw ConverterUtil.resolveConverterException(e); } return this; @@ -229,8 +217,7 @@ public XML attribute(String name, String value) { checkState(); try { writer.attribute(name, value); - } - catch (Exception e) { + } catch (Exception e) { throw ConverterUtil.resolveConverterException(e); } return this; @@ -240,8 +227,7 @@ public XML end() { checkState(); try { writer.end(); - } - catch (Exception e) { + } catch (Exception e) { throw ConverterUtil.resolveConverterException(e); } return this; @@ -259,6 +245,9 @@ protected void handleCircularRelationship(Object o) throws ConverterException { throw new ConverterException("Circular Reference detected: class " + o.getClass().getName()); case INSERT_NULL: convertAnother(null); + default: + // do nothing + break; } } @@ -266,8 +255,7 @@ public void render(HttpServletResponse response) throws ConverterException { response.setContentType(GrailsWebUtil.getContentType(contentType, encoding)); try { render(response.getWriter()); - } - catch (IOException e) { + } catch (IOException e) { throw new ConverterException(e); } } @@ -305,8 +293,7 @@ public String toString() { public static Object parse(String source) throws ConverterException { try { return createXmlSlurper().parseText(source); - } - catch (Exception e) { + } catch (Exception e) { throw new ConverterException("Error parsing XML", e); } } @@ -315,7 +302,7 @@ public static Object parse(String source) throws ConverterException { * Parses the given XML * * @param inputStream an InputStream to read from - * @param encoding the Character Encoding to use + * @param encoding the Character Encoding to use * @return a {@link groovy.xml.slurpersupport.GPathResult} * @throws ConverterException if an error occurs parsing the XML */ @@ -323,8 +310,7 @@ public static Object parse(InputStream inputStream, String encoding) throws Conv try { InputStreamReader reader = new InputStreamReader(inputStream, encoding); return createXmlSlurper().parse(reader); - } - catch (Exception e) { + } catch (Exception e) { throw new ConverterException("Error parsing XML", e); } } @@ -347,8 +333,7 @@ public static Object parse(HttpServletRequest request) throws ConverterException ); request.setAttribute(CACHED_XML, xml); } - } - catch (IOException e) { + } catch (IOException e) { throw new ConverterException("Error parsing XML", e); } } @@ -370,8 +355,7 @@ public static Object use(String configName, Closure callable) throws Converte ConvertersConfigurationHolder.setThreadLocalConverterConfiguration(XML.class, cfg); try { return callable.call(); - } - finally { + } finally { ConvertersConfigurationHolder.setThreadLocalConverterConfiguration(XML.class, old); } } @@ -379,8 +363,7 @@ public static Object use(String configName, Closure callable) throws Converte public static void use(String cfgName) throws ConverterException { if (cfgName == null || "default".equals(cfgName)) { ConvertersConfigurationHolder.setThreadLocalConverterConfiguration(XML.class, null); - } - else { + } else { ConvertersConfigurationHolder.setThreadLocalConverterConfiguration(XML.class, getNamedConfig(cfgName)); } } @@ -422,8 +405,7 @@ public static void createNamedConfig(String name, Closure callable) throws Co try { callable.call(cfg); ConvertersConfigurationHolder.setNamedConverterConfiguration(XML.class, name, cfg); - } - catch (Exception e) { + } catch (Exception e) { throw ConverterUtil.resolveConverterException(e); } } @@ -436,8 +418,7 @@ public static void withDefaultConfiguration(Closure callable) throws Converte try { callable.call(cfg); ConvertersConfigurationHolder.setDefaultConfiguration(XML.class, cfg); - } - catch (Throwable t) { + } catch (Throwable t) { throw ConverterUtil.resolveConverterException(t); } } diff --git a/grails-converters/src/main/groovy/grails/encoders/JSONEncoder.java b/grails-converters/src/main/groovy/grails/encoders/JSONEncoder.java index bb3b3f33bdf..0a62770d58e 100644 --- a/grails-converters/src/main/groovy/grails/encoders/JSONEncoder.java +++ b/grails-converters/src/main/groovy/grails/encoders/JSONEncoder.java @@ -16,16 +16,16 @@ * specific language governing permissions and limitations * under the License. */ - package grails.encoders; import grails.converters.JSON; import org.grails.encoder.impl.BasicJSONEncoder; public class JSONEncoder extends BasicJSONEncoder { + @Override protected Object encodeAsJsonObject(Object o) { - if(o instanceof JSON) { + if (o instanceof JSON) { return o; } else { return new JSON(o); diff --git a/grails-converters/src/main/groovy/grails/encoders/XMLEncoder.java b/grails-converters/src/main/groovy/grails/encoders/XMLEncoder.java index b3cb78a750a..5306b01fe5d 100644 --- a/grails-converters/src/main/groovy/grails/encoders/XMLEncoder.java +++ b/grails-converters/src/main/groovy/grails/encoders/XMLEncoder.java @@ -16,19 +16,19 @@ * specific language governing permissions and limitations * under the License. */ - package grails.encoders; import grails.converters.XML; import org.grails.encoder.impl.BasicXMLEncoder; public class XMLEncoder extends BasicXMLEncoder { + @Override protected Object encodeAsXmlObject(Object o) { - if(o instanceof XML) { + if (o instanceof XML) { return o; } else { - return new XML(o); + return new XML(o); } } } diff --git a/grails-converters/src/main/groovy/grails/web/JSONBuilder.groovy b/grails-converters/src/main/groovy/grails/web/JSONBuilder.groovy index 7ff517a8ec0..40cb1bf438b 100644 --- a/grails-converters/src/main/groovy/grails/web/JSONBuilder.groovy +++ b/grails-converters/src/main/groovy/grails/web/JSONBuilder.groovy @@ -89,17 +89,14 @@ class JSONBuilder { def n = [:] if (current instanceof List) { current << n - } - else { + } else { current[methodName] = n } n.putAll(args[0]) - } - else if (args[-1] instanceof Closure) { + } else if (args[-1] instanceof Closure) { final Object callable = args[-1] handleClosureNode(methodName, callable) - } - else if (args.size() == 1) { + } else if (args.size() == 1) { if (methodName != NODE_ELEMENT) { throw new IllegalArgumentException('Array elements must be defined with the "element" method call eg: element(value)') } @@ -116,16 +113,13 @@ class JSONBuilder { } if (current instanceof List) { current << args[0] - } - else { + } else { throw new IllegalArgumentException('Array elements can only be defined under "array" nodes') } - } - else { + } else { throw new IllegalArgumentException("This builder does not support invocation of [$methodName] with arg list ${args.dump()}") } - } - else { + } else { current[methodName] = [] } } @@ -136,8 +130,7 @@ class JSONBuilder { if (current instanceof List) { current << n - } - else { + } else { current[methodName] = n } current = n @@ -148,8 +141,7 @@ class JSONBuilder { void setProperty(String propName, Object value) { if (value instanceof Closure) { handleClosureNode(propName, value) - } - else if (value instanceof List) { + } else if (value instanceof List) { value = value.collect { if (it instanceof Closure) { def callable = it @@ -163,8 +155,7 @@ class JSONBuilder { return it } current[propName] = value - } - else { + } else { current[propName] = value } } diff --git a/grails-converters/src/main/groovy/org/grails/compiler/web/converters/ConvertersDomainTransformer.java b/grails-converters/src/main/groovy/org/grails/compiler/web/converters/ConvertersDomainTransformer.java index c49f938979d..ee208bad293 100644 --- a/grails-converters/src/main/groovy/org/grails/compiler/web/converters/ConvertersDomainTransformer.java +++ b/grails-converters/src/main/groovy/org/grails/compiler/web/converters/ConvertersDomainTransformer.java @@ -33,7 +33,7 @@ * @since 2.0 */ @AstTransformer -public class ConvertersDomainTransformer extends AbstractGrailsArtefactTransformer{ +public class ConvertersDomainTransformer extends AbstractGrailsArtefactTransformer { @Override public String getArtefactType() { diff --git a/grails-converters/src/main/groovy/org/grails/compiler/web/converters/RenderConverterTrait.groovy b/grails-converters/src/main/groovy/org/grails/compiler/web/converters/RenderConverterTrait.groovy index d75a6533361..89edd161199 100644 --- a/grails-converters/src/main/groovy/org/grails/compiler/web/converters/RenderConverterTrait.groovy +++ b/grails-converters/src/main/groovy/org/grails/compiler/web/converters/RenderConverterTrait.groovy @@ -16,17 +16,15 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.compiler.web.converters import grails.artefact.Enhances import groovy.transform.Generated +import jakarta.servlet.http.HttpServletResponse import org.grails.web.converters.Converter import org.grails.web.servlet.mvc.GrailsWebRequest import org.springframework.web.context.request.RequestContextHolder -import jakarta.servlet.http.HttpServletResponse - @Enhances(["Controller", "Interceptor"]) trait RenderConverterTrait { @@ -37,7 +35,7 @@ trait RenderConverterTrait { */ @Generated void render(Converter converter) { - GrailsWebRequest webRequest = (GrailsWebRequest)RequestContextHolder.currentRequestAttributes() + GrailsWebRequest webRequest = (GrailsWebRequest) RequestContextHolder.currentRequestAttributes() HttpServletResponse response = webRequest.currentResponse webRequest.renderView = false converter.render response diff --git a/grails-converters/src/main/groovy/org/grails/plugins/codecs/JSONCodec.java b/grails-converters/src/main/groovy/org/grails/plugins/codecs/JSONCodec.java index e63ecbb4a98..2ed042f5911 100644 --- a/grails-converters/src/main/groovy/org/grails/plugins/codecs/JSONCodec.java +++ b/grails-converters/src/main/groovy/org/grails/plugins/codecs/JSONCodec.java @@ -16,11 +16,10 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.plugins.codecs; -import org.grails.encoder.impl.JSONCodecFactory; import grails.encoders.JSONEncoder; +import org.grails.encoder.impl.JSONCodecFactory; /** * A codec that encodes strings to JSON @@ -29,6 +28,7 @@ * @since 2.3.4 */ public class JSONCodec extends JSONCodecFactory { + public JSONCodec() { super(); setEncoder(new JSONEncoder()); diff --git a/grails-converters/src/main/groovy/org/grails/plugins/codecs/XMLCodec.java b/grails-converters/src/main/groovy/org/grails/plugins/codecs/XMLCodec.java index aef0d81bb23..08746d9fbb8 100644 --- a/grails-converters/src/main/groovy/org/grails/plugins/codecs/XMLCodec.java +++ b/grails-converters/src/main/groovy/org/grails/plugins/codecs/XMLCodec.java @@ -16,11 +16,10 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.plugins.codecs; -import org.grails.encoder.impl.XMLCodecFactory; import grails.encoders.XMLEncoder; +import org.grails.encoder.impl.XMLCodecFactory; /** * Escapes some characters for inclusion in XML documents. The decoder part can @@ -30,6 +29,7 @@ * @since 2.3 */ public class XMLCodec extends XMLCodecFactory { + public XMLCodec() { super(); this.encoder = new XMLEncoder(); diff --git a/grails-converters/src/main/groovy/org/grails/plugins/converters/ConvertersGrailsPlugin.groovy b/grails-converters/src/main/groovy/org/grails/plugins/converters/ConvertersGrailsPlugin.groovy index a84d32348d4..66ba7173b11 100644 --- a/grails-converters/src/main/groovy/org/grails/plugins/converters/ConvertersGrailsPlugin.groovy +++ b/grails-converters/src/main/groovy/org/grails/plugins/converters/ConvertersGrailsPlugin.groovy @@ -20,8 +20,6 @@ package org.grails.plugins.converters import grails.converters.JSON import grails.converters.XML -import grails.core.GrailsApplication -import grails.core.support.GrailsApplicationAware import grails.plugins.Plugin import grails.util.GrailsUtil import org.grails.plugins.codecs.JSONCodec @@ -45,26 +43,28 @@ class ConvertersGrailsPlugin extends Plugin { def observe = ["controllers"] def dependsOn = [controllers: version, domainClass: version] def providedArtefacts = [ - JSONCodec, - XMLCodec + JSONCodec, + XMLCodec ] @Override - Closure doWithSpring() {{-> - jsonErrorsMarshaller(JsonErrorsMarshaller) + Closure doWithSpring() { + { -> + jsonErrorsMarshaller(JsonErrorsMarshaller) - xmlErrorsMarshaller(XmlErrorsMarshaller) + xmlErrorsMarshaller(XmlErrorsMarshaller) - convertersConfigurationInitializer(ConvertersConfigurationInitializer) + convertersConfigurationInitializer(ConvertersConfigurationInitializer) - errorsXmlMarshallerRegisterer(ObjectMarshallerRegisterer) { - marshaller = { XmlErrorsMarshaller om -> } - converterClass = XML - } + errorsXmlMarshallerRegisterer(ObjectMarshallerRegisterer) { + marshaller = { XmlErrorsMarshaller om -> } + converterClass = XML + } - errorsJsonMarshallerRegisterer(ObjectMarshallerRegisterer) { - marshaller = { JsonErrorsMarshaller om -> } - converterClass = JSON + errorsJsonMarshallerRegisterer(ObjectMarshallerRegisterer) { + marshaller = { JsonErrorsMarshaller om -> } + converterClass = JSON + } } - }} + } } diff --git a/grails-converters/src/main/groovy/org/grails/plugins/converters/api/ConvertersApi.java b/grails-converters/src/main/groovy/org/grails/plugins/converters/api/ConvertersApi.java index 0954b7c9dbe..7810c459334 100644 --- a/grails-converters/src/main/groovy/org/grails/plugins/converters/api/ConvertersApi.java +++ b/grails-converters/src/main/groovy/org/grails/plugins/converters/api/ConvertersApi.java @@ -27,8 +27,8 @@ /** * The API for converting objects to target types such as XML. * - * @since 2.0 * @author Graeme Rocher + * @since 2.0 */ public class ConvertersApi implements ApplicationContextAware { @@ -38,7 +38,7 @@ public class ConvertersApi implements ApplicationContextAware { * Converter an instance from one format to another * * @param instance The instance - * @param clazz The type to convert to + * @param clazz The type to convert to * @return the converted object */ public Object asType(Object instance, Class clazz) { @@ -59,6 +59,6 @@ public ApplicationContext getApplicationContext() { } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext =applicationContext; + this.applicationContext = applicationContext; } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/AbstractConverter.java b/grails-converters/src/main/groovy/org/grails/web/converters/AbstractConverter.java index 42f69dea681..36add090fd8 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/AbstractConverter.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/AbstractConverter.java @@ -67,7 +67,7 @@ public void setEncoding(String encoding) { /** * Set to include properties for the given type * - * @param type The type + * @param type The type * @param properties The properties */ @Override @@ -78,7 +78,7 @@ public void setIncludes(Class type, List properties) { /** * Set to exclude properties for the given type * - * @param type The type + * @param type The type * @param properties The properties */ @Override diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/AbstractParsingParameterCreationListener.groovy b/grails-converters/src/main/groovy/org/grails/web/converters/AbstractParsingParameterCreationListener.groovy index 4a5ddc14074..64863b7ffce 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/AbstractParsingParameterCreationListener.groovy +++ b/grails-converters/src/main/groovy/org/grails/web/converters/AbstractParsingParameterCreationListener.groovy @@ -21,36 +21,34 @@ package org.grails.web.converters import org.grails.web.servlet.mvc.ParameterCreationListener /** -* Abstract base class for parameter creation listeners that parse incoming data such as JSON and XML. + * Abstract base class for parameter creation listeners that parse incoming data such as JSON and XML. -* @author Graeme Rocher -* @since 1.0 -*/ + * @author Graeme Rocher + * @since 1.0 + */ abstract class AbstractParsingParameterCreationListener implements ParameterCreationListener { /** * Populates the target map with current map using the root map to form a nested prefix * so that a hierarchy of maps is flattened. */ - protected createFlattenedKeys(Map root, Map current, Map target, prefix ='', Map previousParent = null) { + protected createFlattenedKeys(Map root, Map current, Map target, prefix = '', Map previousParent = null) { for (entry in current) { if (entry.value instanceof Map) { def childEntry = entry.key def targetParent = previousParent != null ? previousParent : target targetParent[childEntry] = [:] - createFlattenedKeys(root,entry.value, target, "$prefix${childEntry}.",targetParent[childEntry]) - } - else if (prefix) { + createFlattenedKeys(root, entry.value, target, "$prefix${childEntry}.", targetParent[childEntry]) + } else if (prefix) { if (entry.value instanceof Collection) { int i = 0 for (e in entry.value) { if (e instanceof Map) { - def childPrefix = "${prefix[0..-2]}[${i++}]." + def childPrefix = "${prefix[0..-2]}[${i++}]." createFlattenedKeys(root, e, target, childPrefix, previousParent) } } - } - else { + } else { def entryKey = entry.key def entryValue = entry.value if (previousParent != null) { diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/ConfigurableConverter.groovy b/grails-converters/src/main/groovy/org/grails/web/converters/ConfigurableConverter.groovy index 70ac8040652..250b5add132 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/ConfigurableConverter.groovy +++ b/grails-converters/src/main/groovy/org/grails/web/converters/ConfigurableConverter.groovy @@ -24,7 +24,7 @@ package org.grails.web.converters * @author Graeme Rocher * @since 2.3 */ -public interface ConfigurableConverter extends Converter{ +public interface ConfigurableConverter extends Converter { /** * Sets the content type of the converter * @param contentType The content type diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/Converter.java b/grails-converters/src/main/groovy/org/grails/web/converters/Converter.java index c58bbc7b2eb..43e7d30cc25 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/Converter.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/Converter.java @@ -19,16 +19,14 @@ package org.grails.web.converters; import groovy.lang.Closure; +import jakarta.servlet.http.HttpServletResponse; +import org.grails.web.converters.exceptions.ConverterException; +import org.grails.web.converters.marshaller.ObjectMarshaller; import java.io.Writer; import java.util.ArrayList; import java.util.List; -import jakarta.servlet.http.HttpServletResponse; - -import org.grails.web.converters.exceptions.ConverterException; -import org.grails.web.converters.marshaller.ObjectMarshaller; - /** * Defines an Object that can convert an instance and render it to the * response or a supplied writer. @@ -45,7 +43,7 @@ public interface Converter { * @param out The Writer to write to * @throws ConverterException */ - public void render(Writer out) throws ConverterException; + void render(Writer out) throws ConverterException; /** * Marshalls the target and writes it a HttpServletResponse @@ -54,7 +52,7 @@ public interface Converter { * @param response The response to write to * @throws ConverterException */ - public void render(HttpServletResponse response) throws ConverterException; + void render(HttpServletResponse response) throws ConverterException; W getWriter() throws ConverterException; diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/ConverterUtil.java b/grails-converters/src/main/groovy/org/grails/web/converters/ConverterUtil.java index 1f9e8a2e23a..e83ec8dedc3 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/ConverterUtil.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/ConverterUtil.java @@ -19,13 +19,6 @@ package org.grails.web.converters; import groovy.lang.Closure; - -import java.io.File; -import java.lang.reflect.Array; -import java.lang.reflect.Constructor; -import java.util.Collection; -import java.util.Map; - import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.codehaus.groovy.runtime.NullObject; import org.codehaus.groovy.runtime.ResourceGroovyMethods; @@ -37,20 +30,26 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import java.io.File; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.util.Collection; +import java.util.Map; + /** * A utility class for creating and dealing with Converter objects. * * @author Siegfried Puchbauer * @since 0.6 */ -public class ConverterUtil { +public final class ConverterUtil { private static final String PERSISTENCE_BEAN_WRAPPER_CLASS = "org.codehaus.groovy.grails.orm.hibernate.support.HibernateBeanWrapper"; private static final Object[] EMPTY_OBJECT_ARRAY = {}; private ConverterUtil() { - // static only + // static only } public static BeanWrapper createBeanWrapper(Object o) { @@ -58,9 +57,8 @@ public static BeanWrapper createBeanWrapper(Object o) { try { Class c = Class.forName(PERSISTENCE_BEAN_WRAPPER_CLASS, true, Thread.currentThread().getContextClassLoader()); Constructor init = c.getConstructor(new Class[]{Object.class}); - beanWrapper = (BeanWrapper)init.newInstance(new Object[]{o}); - } - catch (Exception e) { + beanWrapper = (BeanWrapper) init.newInstance(new Object[]{o}); + } catch (Exception e) { beanWrapper = new BeanWrapperImpl(o); } return beanWrapper; @@ -70,16 +68,15 @@ public static Object createConverter(Class converterClass, Object target) thr return createConverter(converterClass, target, null); } - public static T createConverter(Class converterClass, Object target, ApplicationContext applicationContext) throws ConverterException{ + public static T createConverter(Class converterClass, Object target, ApplicationContext applicationContext) throws ConverterException { try { T converter = converterClass.newInstance(); if (converter instanceof ApplicationContextAware && applicationContext != null) { - ((ApplicationContextAware)converter).setApplicationContext(applicationContext); + ((ApplicationContextAware) converter).setApplicationContext(applicationContext); } - ((AbstractConverter)converter).setTarget(target); + ((AbstractConverter) converter).setTarget(target); return converter; - } - catch (Exception e) { + } catch (Exception e) { throw new ConverterException("Initialization of Converter Object " + converterClass.getName() + " failed for target " + target.getClass().getName(), e); } @@ -107,15 +104,15 @@ public static Object invokeOriginalAsTypeMethod(Object delegate, Class clazz) } if (delegate instanceof NullObject) { - return ((NullObject)delegate).asType(clazz); + return ((NullObject) delegate).asType(clazz); } if (delegate instanceof Collection && clazz.isArray()) { - int size = ((Collection)delegate).size(); + int size = ((Collection) delegate).size(); if (clazz.getComponentType() == Object.class) { if (size == 0) { return EMPTY_OBJECT_ARRAY; } - return ((Collection)delegate).toArray((Object[])Array.newInstance(clazz.getComponentType(), size)); + return ((Collection) delegate).toArray((Object[]) Array.newInstance(clazz.getComponentType(), size)); } if (size == 0) { return Array.newInstance(clazz.getComponentType(), 0); diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/ConvertersExtension.groovy b/grails-converters/src/main/groovy/org/grails/web/converters/ConvertersExtension.groovy index 7ff9b33d5a1..8e4978f609b 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/ConvertersExtension.groovy +++ b/grails-converters/src/main/groovy/org/grails/web/converters/ConvertersExtension.groovy @@ -21,12 +21,8 @@ package org.grails.web.converters import grails.converters.JSON import grails.converters.XML import groovy.transform.CompileStatic - import jakarta.servlet.http.HttpServletRequest - import org.grails.web.servlet.mvc.GrailsWebRequest -import org.springframework.context.ApplicationContext - /** * @@ -40,7 +36,7 @@ import org.springframework.context.ApplicationContext */ @CompileStatic class ConvertersExtension { - + static getJSON(HttpServletRequest request) { JSON.parse(request) } @@ -48,19 +44,18 @@ class ConvertersExtension { static getXML(HttpServletRequest request) { XML.parse(request) } - + static T asType(instance, Class clazz) { if (ConverterUtil.isConverterClass(clazz)) { - return ConverterUtil.createConverter(clazz, - instance, - GrailsWebRequest.lookup()?.applicationContext) - } - else { - return (T)ConverterUtil.invokeOriginalAsTypeMethod(instance, clazz) + return ConverterUtil.createConverter(clazz, + instance, + GrailsWebRequest.lookup()?.applicationContext) + } else { + return (T) ConverterUtil.invokeOriginalAsTypeMethod(instance, clazz) } } - - static T asType(Object[] array, Class clazz) { - asType((Object)array, clazz) + + static T asType(Object[] array, Class clazz) { + asType((Object) array, clazz) } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ChainedConverterConfiguration.java b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ChainedConverterConfiguration.java index 97e50f50a82..385e23b1506 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ChainedConverterConfiguration.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ChainedConverterConfiguration.java @@ -18,7 +18,12 @@ */ package org.grails.web.converters.configuration; +import grails.core.support.proxy.DefaultProxyHandler; +import grails.core.support.proxy.ProxyHandler; import grails.util.Environment; +import org.grails.web.converters.Converter; +import org.grails.web.converters.exceptions.ConverterException; +import org.grails.web.converters.marshaller.ObjectMarshaller; import java.util.ArrayList; import java.util.Collections; @@ -26,20 +31,12 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import grails.core.support.proxy.DefaultProxyHandler; -import grails.core.support.proxy.ProxyHandler; - -import org.grails.web.converters.Converter; -import org.grails.web.converters.exceptions.ConverterException; -import org.grails.web.converters.marshaller.ObjectMarshaller; - /** * An immutable ConverterConfiguration which chains the lookup calls for ObjectMarshallers * for performance reasons. * * @author Siegfried Puchbauer * @author Graeme Rocher - * * @since 1.1 */ @SuppressWarnings("rawtypes") @@ -54,10 +51,11 @@ public class ChainedConverterConfiguration implements Conve private final boolean cacheObjectMarshallerByClass; private Map> objectMarshallerForClassCache; private final boolean developmentMode = Environment.isDevelopmentMode(); - private final ObjectMarshaller NULL_HOLDER=new ObjectMarshaller() { + private final ObjectMarshaller NULL_HOLDER = new ObjectMarshaller() { public boolean supports(Object object) { return false; } + public void marshalObject(Object object, C converter) throws ConverterException { } }; @@ -123,6 +121,14 @@ public List> getOrderedObjectMarshallers() { return marshallerList; } + public ProxyHandler getProxyHandler() { + return proxyHandler; + } + + public boolean isCacheObjectMarshallerByClass() { + return cacheObjectMarshallerByClass; + } + @SuppressWarnings("hiding") public class ChainedObjectMarshaller implements ObjectMarshaller { @@ -150,12 +156,4 @@ public void marshalObject(Object object, C converter) throws ConverterException om.marshalObject(object, converter); } } - - public ProxyHandler getProxyHandler() { - return proxyHandler; - } - - public boolean isCacheObjectMarshallerByClass() { - return cacheObjectMarshallerByClass; - } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ConverterConfiguration.java b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ConverterConfiguration.java index 090c10e7f90..2039ca6013d 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ConverterConfiguration.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ConverterConfiguration.java @@ -18,17 +18,15 @@ */ package org.grails.web.converters.configuration; -import java.util.List; - import grails.core.support.proxy.ProxyHandler; - import org.grails.web.converters.Converter; import org.grails.web.converters.marshaller.ObjectMarshaller; +import java.util.List; + /** * @author Siegfried Puchbauer * @author Graeme Rocher - * * @since 1.1 */ @SuppressWarnings("rawtypes") @@ -36,12 +34,14 @@ public interface ConverterConfiguration { /** * Lookup the ProxyHandler used to deal with proxies instances. + * * @return The proxy handler */ ProxyHandler getProxyHandler(); /** * Lookup the ObjectMarshaller with the highest priority that support to marshall the given object + * * @param o the object which is about to be converted * @return the ObjectMarshaller instance */ @@ -49,31 +49,36 @@ public interface ConverterConfiguration { /** * Lookup the configured default Character encoding for the Converter + * * @return the Charset name */ String getEncoding(); /** * Lookup the configured CircularReferenceBehaviour (how the converter should behave when a circular reference is detected) - * @see org.grails.web.converters.Converter.CircularReferenceBehaviour + * * @return an instance of CircularReferenceBehaviour + * @see org.grails.web.converters.Converter.CircularReferenceBehaviour */ Converter.CircularReferenceBehaviour getCircularReferenceBehaviour(); /** * Lookup method whether the converter should default to pretty printed output + * * @return a boolean */ boolean isPrettyPrint(); /** * Retrieve the ordered list of ObjectMarshallers + * * @return the List of ObjectMarshallers ordered by priority */ List> getOrderedObjectMarshallers(); /** * Enables caching object marshaller selection by class. + * * @return a boolean */ boolean isCacheObjectMarshallerByClass(); diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ConvertersConfigurationHolder.java b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ConvertersConfigurationHolder.java index 9861be904dd..966fb031752 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ConvertersConfigurationHolder.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ConvertersConfigurationHolder.java @@ -18,25 +18,25 @@ */ package org.grails.web.converters.configuration; +import org.grails.core.lifecycle.ShutdownOperations; +import org.grails.web.converters.Converter; +import org.grails.web.converters.exceptions.ConverterException; +import org.grails.web.converters.marshaller.ObjectMarshaller; + import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import org.grails.core.lifecycle.ShutdownOperations; -import org.grails.web.converters.Converter; -import org.grails.web.converters.exceptions.ConverterException; -import org.grails.web.converters.marshaller.ObjectMarshaller; - /** * Singleton which holds all default and named configurations for the Converter classes. * * @author Siegfried Puchbauer * @since 1.1 */ -@SuppressWarnings({"unchecked","rawtypes"}) -public class ConvertersConfigurationHolder { +@SuppressWarnings({"unchecked", "rawtypes"}) +public final class ConvertersConfigurationHolder { public static final String CONVERTERS_DEFAULT_ENCODING = "UTF-8"; @@ -48,26 +48,28 @@ public void run() { }, true); } - private static ConvertersConfigurationHolder INSTANCE = new ConvertersConfigurationHolder(); + private static final ConvertersConfigurationHolder INSTANCE = new ConvertersConfigurationHolder(); private final ConcurrentMap, ConverterConfiguration> defaultConfiguration = - new ConcurrentHashMap, ConverterConfiguration>(); + new ConcurrentHashMap, ConverterConfiguration>(); private final ConcurrentMap, Map> namedConfigurations = - new ConcurrentHashMap, Map>(); + new ConcurrentHashMap, Map>(); private ThreadLocal, ConverterConfiguration>> threadLocalConfiguration = createThreadLocalConfiguration(); - protected static ThreadLocal, ConverterConfiguration>> createThreadLocalConfiguration() { + private ConvertersConfigurationHolder() { + // singleton + } + + private static ThreadLocal, ConverterConfiguration>> createThreadLocalConfiguration() { return new ThreadLocal, ConverterConfiguration>>() { protected Map, ConverterConfiguration> initialValue() { return new HashMap, ConverterConfiguration>(); - }; - }; - } + } - private ConvertersConfigurationHolder() { - // singleton + ; + }; } public static void clear() { @@ -85,7 +87,7 @@ public static void setDefaultConfiguration(Class c, Lis getInstance().defaultConfiguration.put(c, new DefaultConverterConfiguration(om)); } - private static ConvertersConfigurationHolder getInstance() throws ConverterException{ + private static ConvertersConfigurationHolder getInstance() throws ConverterException { return INSTANCE; } @@ -96,7 +98,7 @@ public static ConverterConfiguration getConverterConfig if (cfg == null) { cfg = new DefaultConverterConfiguration(); ConverterConfiguration existing = getInstance().defaultConfiguration.putIfAbsent(converterClass, cfg); - if(existing != null) { + if (existing != null) { cfg = existing; } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ConvertersConfigurationInitializer.java b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ConvertersConfigurationInitializer.java index 43bb47951bd..77bb49c0f4b 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ConvertersConfigurationInitializer.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ConvertersConfigurationInitializer.java @@ -19,20 +19,15 @@ package org.grails.web.converters.configuration; import grails.config.Config; -import org.grails.config.PropertySourcesConfig; import grails.converters.JSON; import grails.converters.XML; import grails.core.GrailsApplication; import grails.core.support.GrailsApplicationAware; import grails.core.support.proxy.DefaultProxyHandler; import grails.core.support.proxy.ProxyHandler; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.grails.config.PropertySourcesConfig; import org.grails.web.converters.Converter; import org.grails.web.converters.marshaller.ObjectMarshaller; import org.grails.web.converters.marshaller.ProxyUnwrappingMarshaller; @@ -40,6 +35,10 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * @author Siegfried Puchbauer * @since 1.1 @@ -55,7 +54,7 @@ public class ConvertersConfigurationInitializer implements ApplicationContextAwa public static final String SETTING_CONVERTERS_JSON_PRETTY_PRINT = "grails.converters.json.pretty.print"; public static final String SETTING_CONVERTERS_JSON_CACHE_OBJECTS = "grails.converters.json.cacheObjectMarshallerSelectionByClass"; public static final String SETTING_CONVERTERS_XML_DEEP = "grails.converters.xml.default.deep"; - + public static final Log LOG = LogFactory.getLog(ConvertersConfigurationInitializer.class); private ApplicationContext applicationContext; private GrailsApplication grailsApplication; @@ -68,14 +67,12 @@ public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } - public final Log LOG = LogFactory.getLog(ConvertersConfigurationInitializer.class); - public void afterPropertiesSet() { initialize(); } - + public void initialize() { - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("Initializing Converters Default Configurations..."); } initJSONConfiguration(); @@ -85,7 +82,7 @@ public void initialize() { } private void initJSONConfiguration() { - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("Initializing default JSON Converters Configuration..."); } @@ -100,28 +97,26 @@ private void initJSONConfiguration() { Config grailsConfig = getGrailsConfig(); - if ("javascript".equals(grailsConfig.getProperty(SETTING_CONVERTERS_JSON_DATE, String.class, "default",Arrays.asList("javascript", "default")))) { - if(LOG.isDebugEnabled()) { + if ("javascript".equals(grailsConfig.getProperty(SETTING_CONVERTERS_JSON_DATE, String.class, "default", Arrays.asList("javascript", "default")))) { + if (LOG.isDebugEnabled()) { LOG.debug("Using Javascript JSON Date Marshaller."); } marshallers.add(new org.grails.web.converters.marshaller.json.JavascriptDateMarshaller()); - } - else { - if(LOG.isDebugEnabled()) { + } else { + if (LOG.isDebugEnabled()) { LOG.debug("Using default JSON Date Marshaller"); } marshallers.add(new org.grails.web.converters.marshaller.json.DateMarshaller()); } marshallers.add(new org.grails.web.converters.marshaller.json.ToStringBeanMarshaller()); - boolean includeDomainVersion = includeDomainVersionProperty(grailsConfig,"json"); - boolean includeDomainClassName = includeDomainClassProperty(grailsConfig,"json"); + boolean includeDomainVersion = includeDomainVersionProperty(grailsConfig, "json"); + boolean includeDomainClassName = includeDomainClassProperty(grailsConfig, "json"); ProxyHandler proxyHandler = getProxyHandler(); if (grailsConfig.getProperty(SETTING_CONVERTERS_JSON_DEFAULT_DEEP, Boolean.class, false)) { LOG.debug("Using DeepDomainClassMarshaller as default."); marshallers.add(new org.grails.web.converters.marshaller.json.DeepDomainClassMarshaller(includeDomainVersion, includeDomainClassName, proxyHandler, grailsApplication)); - } - else { + } else { marshallers.add(new org.grails.web.converters.marshaller.json.DomainClassMarshaller(includeDomainVersion, includeDomainClassName, proxyHandler, grailsApplication)); } marshallers.add(new org.grails.web.converters.marshaller.json.GroovyBeanMarshaller()); @@ -131,8 +126,8 @@ private void initJSONConfiguration() { cfg.setEncoding(grailsConfig.getProperty(SETTING_CONVERTERS_ENCODING, "UTF-8")); String defaultCirRefBehaviour = grailsConfig.getProperty(SETTING_CONVERTERS_CIRCULAR_REFERENCE_BEHAVIOUR, "DEFAULT"); cfg.setCircularReferenceBehaviour(Converter.CircularReferenceBehaviour.valueOf( - grailsConfig.getProperty(SETTING_CONVERTERS_JSON_CIRCULAR_REFERENCE_BEHAVIOUR,String.class, - defaultCirRefBehaviour, Converter.CircularReferenceBehaviour.allowedValues()))); + grailsConfig.getProperty(SETTING_CONVERTERS_JSON_CIRCULAR_REFERENCE_BEHAVIOUR, String.class, + defaultCirRefBehaviour, Converter.CircularReferenceBehaviour.allowedValues()))); Boolean defaultPrettyPrint = grailsConfig.getProperty(SETTING_CONVERTERS_PRETTY_PRINT, Boolean.class, false); Boolean prettyPrint = grailsConfig.getProperty(SETTING_CONVERTERS_JSON_PRETTY_PRINT, Boolean.class, defaultPrettyPrint); @@ -146,10 +141,9 @@ private void initJSONConfiguration() { private Config getGrailsConfig() { Config grailsConfig; - if(grailsApplication != null) { + if (grailsApplication != null) { grailsConfig = grailsApplication.getConfig(); - } - else { + } else { // empty config, will trigger defaults grailsConfig = new PropertySourcesConfig(); } @@ -158,7 +152,7 @@ private Config getGrailsConfig() { private void initDeepJSONConfiguration() { DefaultConverterConfiguration deepConfig = new DefaultConverterConfiguration(ConvertersConfigurationHolder.getConverterConfiguration(JSON.class), getProxyHandler()); - deepConfig.registerObjectMarshaller(new org.grails.web.converters.marshaller.json.DeepDomainClassMarshaller(includeDomainVersionProperty(getGrailsConfig(),"json"), includeDomainClassProperty(getGrailsConfig(), "json"), getProxyHandler(), grailsApplication)); + deepConfig.registerObjectMarshaller(new org.grails.web.converters.marshaller.json.DeepDomainClassMarshaller(includeDomainVersionProperty(getGrailsConfig(), "json"), includeDomainClassProperty(getGrailsConfig(), "json"), getProxyHandler(), grailsApplication)); ConvertersConfigurationHolder.setNamedConverterConfiguration(JSON.class, "deep", deepConfig); } @@ -182,34 +176,32 @@ private void initXMLConfiguration() { boolean includeDomainVersion = includeDomainVersionProperty(grailsConfig, "xml"); if (grailsConfig.getProperty(SETTING_CONVERTERS_XML_DEEP, Boolean.class, false)) { marshallers.add(new org.grails.web.converters.marshaller.xml.DeepDomainClassMarshaller(includeDomainVersion, proxyHandler, grailsApplication)); - } - else { + } else { marshallers.add(new org.grails.web.converters.marshaller.xml.DomainClassMarshaller(includeDomainVersion, proxyHandler, grailsApplication)); } marshallers.add(new org.grails.web.converters.marshaller.xml.GroovyBeanMarshaller()); marshallers.add(new org.grails.web.converters.marshaller.xml.GenericJavaBeanMarshaller()); - DefaultConverterConfiguration cfg = new DefaultConverterConfiguration(marshallers,proxyHandler); + DefaultConverterConfiguration cfg = new DefaultConverterConfiguration(marshallers, proxyHandler); cfg.setEncoding(grailsConfig.getProperty(SETTING_CONVERTERS_ENCODING, "UTF-8")); String defaultCirRefBehaviour = grailsConfig.getProperty(SETTING_CONVERTERS_CIRCULAR_REFERENCE_BEHAVIOUR, "DEFAULT"); cfg.setCircularReferenceBehaviour(Converter.CircularReferenceBehaviour.valueOf( - grailsConfig.getProperty("grails.converters.xml.circular.reference.behaviour",String.class, - defaultCirRefBehaviour, Converter.CircularReferenceBehaviour.allowedValues()))); + grailsConfig.getProperty("grails.converters.xml.circular.reference.behaviour", String.class, + defaultCirRefBehaviour, Converter.CircularReferenceBehaviour.allowedValues()))); Boolean defaultPrettyPrint = grailsConfig.getProperty(SETTING_CONVERTERS_PRETTY_PRINT, Boolean.class, false); Boolean prettyPrint = grailsConfig.getProperty("grails.converters.xml.pretty.print", Boolean.class, defaultPrettyPrint); cfg.setPrettyPrint(prettyPrint); cfg.setCacheObjectMarshallerByClass(grailsConfig.getProperty("grails.converters.xml.cacheObjectMarshallerSelectionByClass", Boolean.class, true)); registerObjectMarshallersFromApplicationContext(cfg, XML.class); - ConvertersConfigurationHolder.setDefaultConfiguration(XML.class, new ChainedConverterConfiguration(cfg,proxyHandler)); + ConvertersConfigurationHolder.setDefaultConfiguration(XML.class, new ChainedConverterConfiguration(cfg, proxyHandler)); } private ProxyHandler getProxyHandler() { ProxyHandler proxyHandler; if (applicationContext != null) { proxyHandler = applicationContext.getBean(ProxyHandler.class); - } - else { + } else { proxyHandler = new DefaultProxyHandler(); } return proxyHandler; @@ -229,7 +221,7 @@ private boolean includeDomainClassProperty(Config grailsConfig, String converter return grailsConfig.getProperty(String.format("grails.converters.%s.domain.include.class", converterType), Boolean.class, grailsConfig.getProperty("grails.converters.domain.include.class", Boolean.class, false)); } - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) private void registerObjectMarshallersFromApplicationContext( DefaultConverterConfiguration cfg, Class converterClass) { diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/DefaultConverterConfiguration.java b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/DefaultConverterConfiguration.java index b23ee230b75..c08d0e01474 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/DefaultConverterConfiguration.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/DefaultConverterConfiguration.java @@ -18,7 +18,12 @@ */ package org.grails.web.converters.configuration; +import grails.core.support.proxy.DefaultProxyHandler; +import grails.core.support.proxy.ProxyHandler; import groovy.lang.Closure; +import org.grails.web.converters.Converter; +import org.grails.web.converters.marshaller.ClosureObjectMarshaller; +import org.grails.web.converters.marshaller.ObjectMarshaller; import java.util.ArrayList; import java.util.List; @@ -26,13 +31,6 @@ import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; -import grails.core.support.proxy.DefaultProxyHandler; -import grails.core.support.proxy.ProxyHandler; - -import org.grails.web.converters.Converter; -import org.grails.web.converters.marshaller.ClosureObjectMarshaller; -import org.grails.web.converters.marshaller.ObjectMarshaller; - /** * Mutable Converter Configuration with an priority sorted set of ObjectMarshallers * @@ -54,43 +52,6 @@ public class DefaultConverterConfiguration implements Conve private ProxyHandler proxyHandler; private boolean cacheObjectMarshallerByClass = true; - public String getEncoding() { - return encoding != null ? encoding : (delegate != null ? delegate.getEncoding() : null); - } - - public void setEncoding(String encoding) { - this.encoding = encoding; - } - - public Converter.CircularReferenceBehaviour getCircularReferenceBehaviour() { - return circularReferenceBehaviour != null ? circularReferenceBehaviour : (delegate != null ? delegate.getCircularReferenceBehaviour(): null); - } - - public boolean isPrettyPrint() { - return prettyPrint; - } - - public void setPrettyPrint(boolean prettyPrint) { - this.prettyPrint = prettyPrint; - } - - public List> getOrderedObjectMarshallers() { - List> list = new ArrayList>(); - for (Entry entry : objectMarshallers) { - list.add(entry.marshaller); - } - if (delegate != null) { - for (ObjectMarshaller om : delegate.getOrderedObjectMarshallers()) { - list.add(om); - } - } - return list; - } - - public void setCircularReferenceBehaviour(Converter.CircularReferenceBehaviour circularReferenceBehaviour) { - this.circularReferenceBehaviour = circularReferenceBehaviour; - } - public DefaultConverterConfiguration() { proxyHandler = new DefaultProxyHandler(); } @@ -128,6 +89,43 @@ public DefaultConverterConfiguration(List> oms, ProxyHandler this.proxyHandler = proxyHandler; } + public String getEncoding() { + return encoding != null ? encoding : (delegate != null ? delegate.getEncoding() : null); + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public Converter.CircularReferenceBehaviour getCircularReferenceBehaviour() { + return circularReferenceBehaviour != null ? circularReferenceBehaviour : (delegate != null ? delegate.getCircularReferenceBehaviour() : null); + } + + public boolean isPrettyPrint() { + return prettyPrint; + } + + public void setPrettyPrint(boolean prettyPrint) { + this.prettyPrint = prettyPrint; + } + + public List> getOrderedObjectMarshallers() { + List> list = new ArrayList>(); + for (Entry entry : objectMarshallers) { + list.add(entry.marshaller); + } + if (delegate != null) { + for (ObjectMarshaller om : delegate.getOrderedObjectMarshallers()) { + list.add(om); + } + } + return list; + } + + public void setCircularReferenceBehaviour(Converter.CircularReferenceBehaviour circularReferenceBehaviour) { + this.circularReferenceBehaviour = circularReferenceBehaviour; + } + public void registerObjectMarshaller(ObjectMarshaller marshaller) { registerObjectMarshaller(marshaller, DEFAULT_PRIORITY); } @@ -153,8 +151,21 @@ public ObjectMarshaller getMarshaller(Object o) { return delegate != null ? delegate.getMarshaller(o) : null; } - public class Entry implements Comparable { - protected final ObjectMarshaller marshaller; + public ProxyHandler getProxyHandler() { + return proxyHandler; + } + + public boolean isCacheObjectMarshallerByClass() { + return cacheObjectMarshallerByClass; + } + + public void setCacheObjectMarshallerByClass(boolean cacheObjectMarshallerByClass) { + this.cacheObjectMarshallerByClass = cacheObjectMarshallerByClass; + } + + public final class Entry implements Comparable { + + private final ObjectMarshaller marshaller; private final int priority; private final int seq; @@ -168,16 +179,4 @@ public int compareTo(Entry entry) { return priority == entry.priority ? entry.seq - seq : entry.priority - priority; } } - - public ProxyHandler getProxyHandler() { - return proxyHandler; - } - - public boolean isCacheObjectMarshallerByClass() { - return cacheObjectMarshallerByClass; - } - - public void setCacheObjectMarshallerByClass(boolean cacheObjectMarshallerByClass) { - this.cacheObjectMarshallerByClass = cacheObjectMarshallerByClass; - } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ImmutableConverterConfiguration.java b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ImmutableConverterConfiguration.java index 0f65ba087b4..cd70d1495e7 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ImmutableConverterConfiguration.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/ImmutableConverterConfiguration.java @@ -18,15 +18,14 @@ */ package org.grails.web.converters.configuration; -import java.util.Collections; -import java.util.List; - import grails.core.support.proxy.DefaultProxyHandler; import grails.core.support.proxy.ProxyHandler; - import org.grails.web.converters.Converter; import org.grails.web.converters.marshaller.ObjectMarshaller; +import java.util.Collections; +import java.util.List; + /** * Immutable Converter Configuration. * diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/configtest.groovy b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/configtest.groovy index d6c705d030d..4377e228b03 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/configuration/configtest.groovy +++ b/grails-converters/src/main/groovy/org/grails/web/converters/configuration/configtest.groovy @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.web.converters.configuration import grails.converters.JSON @@ -45,23 +44,23 @@ catch (e) { e.printStackTrace() } -def map = [ immutable: 0, chained: 0, default: 0 ] +def map = [immutable: 0, chained: 0, default: 0] def test = { label, jsonConfig -> -def start = System.currentTimeMillis() -30000.times { - assert jsonConfig.getMarshaller(new Object()) -} -def time = System.currentTimeMillis()-start -println "$label --> ${time}ms" -map[label] = map[label] + time + def start = System.currentTimeMillis() + 30000.times { + assert jsonConfig.getMarshaller(new Object()) + } + def time = System.currentTimeMillis() - start + println "$label --> ${time}ms" + map[label] = map[label] + time } test("default", defcfg) test("chained", chcfg) test("immutable", imcfg) - map = [ immutable: 0, chained: 0, default: 0 ] +map = [immutable: 0, chained: 0, default: 0] 100.times { test("chained", chcfg) diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/exceptions/ConverterException.java b/grails-converters/src/main/groovy/org/grails/web/converters/exceptions/ConverterException.java index 3544592b4af..a02ddf738c1 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/exceptions/ConverterException.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/exceptions/ConverterException.java @@ -22,7 +22,6 @@ * Thrown when an error occurs originating from a Converter instance. * * @author Siegfried Puchbauer - * * @since 0.6 */ public class ConverterException extends RuntimeException { diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ByDatasourceDomainClassFetcher.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ByDatasourceDomainClassFetcher.java index 486f03e54d0..f641c44c02e 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ByDatasourceDomainClassFetcher.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ByDatasourceDomainClassFetcher.java @@ -16,14 +16,12 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.web.converters.marshaller; import org.grails.datastore.gorm.GormEnhancer; import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.web.converters.marshaller.DomainClassFetcher; public class ByDatasourceDomainClassFetcher implements DomainClassFetcher { @@ -31,9 +29,9 @@ public class ByDatasourceDomainClassFetcher implements DomainClassFetcher { public PersistentEntity findDomainClass(Object instance) { Class clazz = instance.getClass(); Datastore datastore = GormEnhancer.findDatastore(clazz); - if ( datastore != null) { + if (datastore != null) { MappingContext mappingContext = datastore.getMappingContext(); - if ( mappingContext != null ) { + if (mappingContext != null) { return mappingContext.getPersistentEntity(clazz.getName()); } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ByGrailsApplicationDomainClassFetcher.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ByGrailsApplicationDomainClassFetcher.java index 2e8f485ee04..dacb5f4b6dc 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ByGrailsApplicationDomainClassFetcher.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ByGrailsApplicationDomainClassFetcher.java @@ -16,14 +16,13 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.web.converters.marshaller; import grails.core.GrailsApplication; import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.web.converters.marshaller.DomainClassFetcher; public class ByGrailsApplicationDomainClassFetcher implements DomainClassFetcher { + GrailsApplication grailsApplication; public ByGrailsApplicationDomainClassFetcher(GrailsApplication grailsApplication) { diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ClosureObjectMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ClosureObjectMarshaller.java index 915c1563ba6..86ed32bf3b5 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ClosureObjectMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ClosureObjectMarshaller.java @@ -19,7 +19,6 @@ package org.grails.web.converters.marshaller; import groovy.lang.Closure; - import org.grails.web.converters.Converter; import org.grails.web.converters.exceptions.ConverterException; @@ -51,11 +50,9 @@ public void marshalObject(Object object, T converter) throws ConverterException Object result = null; if (argCount <= 1) { result = closure.call(object); - } - else if (argCount == 2) { + } else if (argCount == 2) { result = closure.call(new Object[]{object, converter}); - } - else { + } else { throw new ConverterException( "Invalid Parameter count for registered Object Marshaller for class " + clazz.getName()); } @@ -63,8 +60,7 @@ else if (argCount == 2) { if (result != null && result != object && result != converter) { converter.convertAnother(result); } - } - catch (Exception e) { + } catch (Exception e) { throw e instanceof ConverterException ? (ConverterException) e : new ConverterException(e); } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/DomainClassFetcher.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/DomainClassFetcher.java index 25e4f4ae636..7780c4fda8a 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/DomainClassFetcher.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/DomainClassFetcher.java @@ -16,12 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.web.converters.marshaller; -import grails.core.GrailsApplication; import org.grails.datastore.mapping.model.PersistentEntity; public interface DomainClassFetcher { + PersistentEntity findDomainClass(Object instance); } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/IncludeExcludePropertyMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/IncludeExcludePropertyMarshaller.java index 185a6f49b70..d69eab62942 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/IncludeExcludePropertyMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/IncludeExcludePropertyMarshaller.java @@ -35,7 +35,7 @@ protected boolean shouldInclude(Object object, String propertyName) { /** * Override for custom exclude logic * - * @param object The object + * @param object The object * @param property The property * @return True if it is excluded */ @@ -46,7 +46,7 @@ protected boolean excludesProperty(Object object, String property) { /** * Override for custom include logic * - * @param object The object + * @param object The object * @param property The property * @return True if it is included */ diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/NameAwareMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/NameAwareMarshaller.java index 1a4a57ebbae..83da1c9b242 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/NameAwareMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/NameAwareMarshaller.java @@ -28,6 +28,7 @@ public interface NameAwareMarshaller { /** * Returns the tag name for the object + * * @param o the object * @return the tag name */ diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ObjectMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ObjectMarshaller.java index 545c139e82b..e692c4929e2 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ObjectMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ObjectMarshaller.java @@ -23,7 +23,7 @@ /** * An ObjectMarshaller is responsible for converting a Java/Groovy Object graph to a serialized form (JSON,XML). - * + *

* The ObjectMarshaller implementation must use a a type parameter - either grails.convereters.JSON or * grails.converters.XML and it should to be thread-safe. * @@ -43,7 +43,8 @@ public interface ObjectMarshaller { /** * Performs the conversion - * @param object the object which is about getting converted + * + * @param object the object which is about getting converted * @param converter the Converter to use * @throws ConverterException on failure */ diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ProxyUnwrappingMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ProxyUnwrappingMarshaller.java index c95425a79f5..775c2caed0b 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ProxyUnwrappingMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/ProxyUnwrappingMarshaller.java @@ -22,7 +22,6 @@ import groovy.lang.GroovySystem; import groovy.lang.MetaClass; import groovy.lang.MetaClassRegistry; - import org.grails.web.converters.Converter; import org.grails.web.converters.exceptions.ConverterException; @@ -31,17 +30,18 @@ * * @author Siegfried Puchbauer * @author Graeme Rocher - * * @since 1.1 */ -@SuppressWarnings({ "unchecked", "rawtypes" }) +@SuppressWarnings({"unchecked", "rawtypes"}) public class ProxyUnwrappingMarshaller implements ObjectMarshaller, NameAwareMarshaller { private static final String HIBERNATE_LAZY_INITIALIZER_PROP = "hibernateLazyInitializer"; private static final String IMPLEMENTATION_PROP = "implementation"; public boolean supports(Object object) { - if (object == null) return false; + if (object == null) { + return false; + } MetaClass mc = GroovySystem.getMetaClassRegistry().getMetaClass(object.getClass()); return mc.hasProperty(object, HIBERNATE_LAZY_INITIALIZER_PROP) != null; } @@ -52,7 +52,9 @@ public void marshalObject(Object object, C converter) throws ConverterException } private Object unwrap(Object o) { - if (o == null) return o; + if (o == null) { + return o; + } final MetaClassRegistry registry = GroovySystem.getMetaClassRegistry(); MetaClass mc = registry.getMetaClass(o.getClass()); diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ArrayMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ArrayMarshaller.java index a70d93e807b..02702bbeb8a 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ArrayMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ArrayMarshaller.java @@ -19,12 +19,11 @@ package org.grails.web.converters.marshaller.json; import grails.converters.JSON; - -import java.lang.reflect.Array; - -import org.grails.web.json.JSONWriter; import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.ObjectMarshaller; +import org.grails.web.json.JSONWriter; + +import java.lang.reflect.Array; /** * @author Siegfried Puchbauer diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ByteArrayMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ByteArrayMarshaller.java index 94914191c3f..0958869736c 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ByteArrayMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ByteArrayMarshaller.java @@ -19,7 +19,6 @@ package org.grails.web.converters.marshaller.json; import grails.converters.JSON; - import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.ObjectMarshaller; diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/CollectionMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/CollectionMarshaller.java index b17871130d9..40c81c49f1c 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/CollectionMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/CollectionMarshaller.java @@ -19,12 +19,11 @@ package org.grails.web.converters.marshaller.json; import grails.converters.JSON; - -import java.util.Collection; - -import org.grails.web.json.JSONWriter; import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.ObjectMarshaller; +import org.grails.web.json.JSONWriter; + +import java.util.Collection; /** * @author Siegfried Puchbauer diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/DateMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/DateMarshaller.java index 91e345630f5..fe68a7e8828 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/DateMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/DateMarshaller.java @@ -19,17 +19,16 @@ package org.grails.web.converters.marshaller.json; import grails.converters.JSON; +import org.apache.commons.lang3.time.FastDateFormat; +import org.grails.web.converters.exceptions.ConverterException; +import org.grails.web.converters.marshaller.ObjectMarshaller; +import org.grails.web.json.JSONException; import java.text.Format; import java.util.Date; import java.util.Locale; import java.util.TimeZone; -import org.apache.commons.lang3.time.FastDateFormat; -import org.grails.web.json.JSONException; -import org.grails.web.converters.exceptions.ConverterException; -import org.grails.web.converters.marshaller.ObjectMarshaller; - /** * JSON ObjectMarshaller which converts a Date Object, conforming to the ECMA-Script-Specification * Draft, to a String value. @@ -43,6 +42,7 @@ public class DateMarshaller implements ObjectMarshaller { /** * Constructor with a custom formatter. + * * @param formatter the formatter */ public DateMarshaller(Format formatter) { @@ -63,8 +63,7 @@ public boolean supports(Object object) { public void marshalObject(Object object, JSON converter) throws ConverterException { try { converter.getWriter().value(formatter.format(object)); - } - catch (JSONException e) { + } catch (JSONException e) { throw new ConverterException(e); } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/DomainClassMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/DomainClassMarshaller.java index a04f62ce6d1..7d161534912 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/DomainClassMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/DomainClassMarshaller.java @@ -19,13 +19,12 @@ package org.grails.web.converters.marshaller.json; import grails.converters.JSON; +import grails.core.GrailsApplication; +import grails.core.support.proxy.DefaultProxyHandler; +import grails.core.support.proxy.EntityProxyHandler; +import grails.core.support.proxy.ProxyHandler; import groovy.lang.GroovyObject; - -import java.util.*; - import org.grails.core.artefact.DomainClassArtefactHandler; - -import grails.core.GrailsApplication; import org.grails.core.exceptions.GrailsConfigurationException; import org.grails.core.util.IncludeExcludeSupport; import org.grails.datastore.mapping.model.PersistentEntity; @@ -41,22 +40,28 @@ import org.grails.web.converters.marshaller.ByGrailsApplicationDomainClassFetcher; import org.grails.web.converters.marshaller.DomainClassFetcher; import org.grails.web.converters.marshaller.IncludeExcludePropertyMarshaller; - -import grails.core.support.proxy.DefaultProxyHandler; -import grails.core.support.proxy.EntityProxyHandler; -import grails.core.support.proxy.ProxyHandler; - import org.grails.web.json.JSONWriter; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + /** * * Object marshaller for domain classes to JSON * * @author Siegfried Puchbauer * @author Graeme Rocher - * * @since 1.1 */ public class DomainClassMarshaller extends IncludeExcludePropertyMarshaller { @@ -114,7 +119,7 @@ public boolean supports(Object object) { return application.isArtefactOfType(DomainClassArtefactHandler.TYPE, name); } - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) public void marshalObject(Object value, JSON json) throws ConverterException { JSONWriter writer = json.getWriter(); value = proxyHandler.unwrapIfProxy(value); @@ -124,38 +129,36 @@ public void marshalObject(Object value, JSON json) throws ConverterException { List includes = json.getIncludes(clazz); IncludeExcludeSupport includeExcludeSupport = new IncludeExcludeSupport(); - BeanWrapper beanWrapper = new BeanWrapperImpl(value); writer.object(); - if(includeClass && shouldInclude(includeExcludeSupport, includes, excludes, value, "class")) { + if (includeClass && shouldInclude(includeExcludeSupport, includes, excludes, value, "class")) { writer.key("class").value(clazz.getName()); } PersistentEntity domainClass = findDomainClass(value); - if ( domainClass == null ) { + if (domainClass == null) { throw new GrailsConfigurationException("Could not retrieve the respective entity for domain " + value.getClass().getName() + " in the mapping context API"); } PersistentProperty id = domainClass.getIdentity(); - if(id != null) { + if (id != null) { //Composite keys dont return an identity. They also do not render in the JSON. //If using Composite keys, it may be advisable to use a customer Marshaller. - if(shouldInclude(includeExcludeSupport, includes, excludes, value, id.getName())) { + if (shouldInclude(includeExcludeSupport, includes, excludes, value, id.getName())) { Object idValue = extractValue(value, id); - if(idValue != null) { + if (idValue != null) { json.property(id.getName(), idValue); } - } + } } - if (shouldInclude(includeExcludeSupport, includes, excludes, value, GormProperties.VERSION) && isIncludeVersion()) { PersistentProperty versionProperty = domainClass.getVersion(); Object version = extractValue(value, versionProperty); - if(version != null) { + if (version != null) { json.property(GormProperties.VERSION, version); } } @@ -167,56 +170,47 @@ public void marshalObject(Object value, JSON json) throws ConverterException { continue; } - if(!shouldInclude(includeExcludeSupport, includes, excludes, value, property.getName())) continue; + if (!shouldInclude(includeExcludeSupport, includes, excludes, value, property.getName())) { + continue; + } writer.key(property.getName()); - if ( !(property instanceof Association) ) { + if (!(property instanceof Association)) { // Write non-relation property Object val = beanWrapper.getPropertyValue(property.getName()); json.convertAnother(val); - } - else { + } else { Object referenceObject = beanWrapper.getPropertyValue(property.getName()); if (isRenderDomainClassRelations()) { if (referenceObject == null) { writer.valueNull(); - } - else { + } else { referenceObject = proxyHandler.unwrapIfProxy(referenceObject); if (referenceObject instanceof SortedMap) { referenceObject = new TreeMap((SortedMap) referenceObject); - } - else if (referenceObject instanceof SortedSet) { + } else if (referenceObject instanceof SortedSet) { referenceObject = new TreeSet((SortedSet) referenceObject); - } - else if (referenceObject instanceof Set) { + } else if (referenceObject instanceof Set) { referenceObject = new LinkedHashSet((Set) referenceObject); - } - else if (referenceObject instanceof Map) { + } else if (referenceObject instanceof Map) { referenceObject = new LinkedHashMap((Map) referenceObject); - } - else if (referenceObject instanceof Collection) { + } else if (referenceObject instanceof Collection) { referenceObject = new ArrayList((Collection) referenceObject); } json.convertAnother(referenceObject); } - } - else { + } else { if (referenceObject == null) { json.value(null); - } - else { - + } else { PersistentEntity referencedDomainClass = ((Association) property).getAssociatedEntity(); // Embedded are now always fully rendered - if (referencedDomainClass == null || ((Association)property).isEmbedded() || property.getType().isEnum()) { + if (referencedDomainClass == null || ((Association) property).isEmbedded() || property.getType().isEnum()) { json.convertAnother(referenceObject); - } - else if ( (property instanceof OneToOne) || (property instanceof ManyToOne)|| ((Association)property).isEmbedded()) { + } else if ((property instanceof OneToOne) || (property instanceof ManyToOne) || ((Association) property).isEmbedded()) { asShortObject(referenceObject, json, referencedDomainClass.getIdentity(), referencedDomainClass); - } - else { + } else { PersistentProperty referencedIdProperty = referencedDomainClass.getIdentity(); @SuppressWarnings("unused") String refPropertyName = ((Association) property).getReferencedPropertyName(); @@ -227,8 +221,7 @@ else if ( (property instanceof OneToOne) || (property instanceof ManyToOne)|| (( asShortObject(el, json, referencedIdProperty, referencedDomainClass); } writer.endArray(); - } - else if (referenceObject instanceof Map) { + } else if (referenceObject instanceof Map) { Map map = (Map) referenceObject; for (Map.Entry entry : map.entrySet()) { String key = String.valueOf(entry.getKey()); @@ -248,9 +241,9 @@ else if (referenceObject instanceof Map) { } private PersistentEntity findDomainClass(Object value) { - for ( DomainClassFetcher fetcher : domainClassFetchers) { + for (DomainClassFetcher fetcher : domainClassFetchers) { PersistentEntity domain = fetcher.findDomainClass(value); - if ( domain != null ) { + if (domain != null) { return domain; } } @@ -258,7 +251,7 @@ private PersistentEntity findDomainClass(Object value) { } private boolean shouldInclude(IncludeExcludeSupport includeExcludeSupport, List includes, List excludes, Object object, String propertyName) { - return includeExcludeSupport.shouldInclude(includes,excludes,propertyName) && shouldInclude(object,propertyName); + return includeExcludeSupport.shouldInclude(includes, excludes, propertyName) && shouldInclude(object, propertyName); } protected void asShortObject(Object refObj, JSON json, PersistentProperty idProperty, PersistentEntity referencedDomainClass) throws ConverterException { @@ -270,29 +263,27 @@ protected void asShortObject(Object refObj, JSON json, PersistentProperty idProp if (idValue == null) { idValue = extractValue(refObj, idProperty); } - } - else { + } else { idValue = extractValue(refObj, idProperty); } JSONWriter writer = json.getWriter(); writer.object(); - if(isIncludeClass()) { + if (isIncludeClass()) { writer.key("class").value(referencedDomainClass.getName()); } - if(idValue != null) { + if (idValue != null) { writer.key("id").value(idValue); } writer.endObject(); } protected Object extractValue(Object domainObject, PersistentProperty property) { - if(property == null) { + if (property == null) { return null; } - if(domainObject instanceof GroovyObject) { - return ((GroovyObject)domainObject).getProperty(property.getName()); - } - else { + if (domainObject instanceof GroovyObject) { + return ((GroovyObject) domainObject).getProperty(property.getName()); + } else { ClassPropertyFetcher propertyFetcher = ClassPropertyFetcher.forClass(domainObject.getClass()); return propertyFetcher.getPropertyValue(domainObject, property.getName()); } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/EnumMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/EnumMarshaller.java index 6e37c7a6914..674cc212077 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/EnumMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/EnumMarshaller.java @@ -19,14 +19,13 @@ package org.grails.web.converters.marshaller.json; import grails.converters.JSON; - -import java.lang.reflect.Method; - -import org.grails.web.json.JSONWriter; import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.ObjectMarshaller; +import org.grails.web.json.JSONWriter; import org.springframework.beans.BeanUtils; +import java.lang.reflect.Method; + /** * @author Siegfried Puchbauer * @since 1.1 @@ -43,19 +42,16 @@ public void marshalObject(Object en, JSON json) throws ConverterException { writer.object(); Class enumClass = en.getClass(); json.property("enumType", enumClass.getName()); - Method nameMethod = BeanUtils.findDeclaredMethod(enumClass, "name" ); + Method nameMethod = BeanUtils.findDeclaredMethod(enumClass, "name"); try { - json.property("name",nameMethod.invoke(en)); - } - catch (Exception e) { + json.property("name", nameMethod.invoke(en)); + } catch (Exception e) { json.property("name", ""); } writer.endObject(); - } - catch (ConverterException ce) { + } catch (ConverterException ce) { throw ce; - } - catch (Exception e) { + } catch (Exception e) { throw new ConverterException("Error converting Enum with class " + en.getClass().getName(), e); } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/GenericJavaBeanMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/GenericJavaBeanMarshaller.java index b4b6fd77a27..d24c8a7268c 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/GenericJavaBeanMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/GenericJavaBeanMarshaller.java @@ -19,22 +19,20 @@ package org.grails.web.converters.marshaller.json; import grails.converters.JSON; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.List; - import grails.persistence.PersistenceMethod; import grails.web.controllers.ControllerMethod; import org.grails.core.util.IncludeExcludeSupport; +import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.IncludeExcludePropertyMarshaller; import org.grails.web.json.JSONWriter; -import org.grails.web.converters.exceptions.ConverterException; -import org.grails.web.converters.marshaller.ObjectMarshaller; import org.springframework.beans.BeanUtils; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.List; + /** * @author Siegfried Puchbauer * @since 1.1 @@ -59,11 +57,17 @@ public void marshalObject(Object o, JSON json) throws ConverterException { String name = property.getName(); Method readMethod = property.getReadMethod(); - if(!shouldInclude(includeExcludeSupport, includes, excludes, o, name)) continue; + if (!shouldInclude(includeExcludeSupport, includes, excludes, o, name)) { + continue; + } - if (readMethod != null && !(name.equals("metaClass"))&& !(name.equals("class"))) { - if(readMethod.getAnnotation(PersistenceMethod.class) != null) continue; - if(readMethod.getAnnotation(ControllerMethod.class) != null) continue; + if (readMethod != null && !(name.equals("metaClass")) && !(name.equals("class"))) { + if (readMethod.getAnnotation(PersistenceMethod.class) != null) { + continue; + } + if (readMethod.getAnnotation(ControllerMethod.class) != null) { + continue; + } Object value = readMethod.invoke(o, (Object[]) null); writer.key(name); json.convertAnother(value); @@ -73,22 +77,22 @@ public void marshalObject(Object o, JSON json) throws ConverterException { int modifiers = field.getModifiers(); if (field.isAccessible() && Modifier.isPublic(modifiers) && !(Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers))) { String name = field.getName(); - if(!shouldInclude(includeExcludeSupport,includes,excludes,o,name)) continue; + if (!shouldInclude(includeExcludeSupport, includes, excludes, o, name)) { + continue; + } writer.key(field.getName()); json.convertAnother(field.get(o)); } } writer.endObject(); - } - catch (ConverterException ce) { + } catch (ConverterException ce) { throw ce; - } - catch (Exception e) { + } catch (Exception e) { throw new ConverterException("Error converting Bean with class " + o.getClass().getName(), e); } } private boolean shouldInclude(IncludeExcludeSupport includeExcludeSupport, List includes, List excludes, Object o, String name) { - return includeExcludeSupport.shouldInclude(includes,excludes, name) && shouldInclude(o,name); + return includeExcludeSupport.shouldInclude(includes, excludes, name) && shouldInclude(o, name); } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/GroovyBeanMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/GroovyBeanMarshaller.java index 796b63a2668..617003aa485 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/GroovyBeanMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/GroovyBeanMarshaller.java @@ -22,6 +22,11 @@ import grails.persistence.PersistenceMethod; import grails.web.controllers.ControllerMethod; import groovy.lang.GroovyObject; +import org.grails.core.util.IncludeExcludeSupport; +import org.grails.web.converters.exceptions.ConverterException; +import org.grails.web.converters.marshaller.IncludeExcludePropertyMarshaller; +import org.grails.web.json.JSONWriter; +import org.springframework.beans.BeanUtils; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; @@ -29,12 +34,6 @@ import java.lang.reflect.Modifier; import java.util.List; -import org.grails.core.util.IncludeExcludeSupport; -import org.grails.web.converters.exceptions.ConverterException; -import org.grails.web.converters.marshaller.IncludeExcludePropertyMarshaller; -import org.grails.web.json.JSONWriter; -import org.springframework.beans.BeanUtils; - /** * @author Siegfried Puchbauer * @since 1.1 @@ -48,7 +47,6 @@ public boolean supports(Object object) { public void marshalObject(Object o, JSON json) throws ConverterException { JSONWriter writer = json.getWriter(); - Class clazz = o.getClass(); List excludes = json.getExcludes(clazz); List includes = json.getIncludes(clazz); @@ -60,11 +58,17 @@ public void marshalObject(Object o, JSON json) throws ConverterException { Method readMethod = property.getReadMethod(); String name = property.getName(); - if(!shouldInclude(includeExcludeSupport, includes, excludes, o, name)) continue; + if (!shouldInclude(includeExcludeSupport, includes, excludes, o, name)) { + continue; + } - if (readMethod != null && !(name.equals("metaClass"))&& !(name.equals("class"))) { - if(readMethod.getAnnotation(PersistenceMethod.class) != null) continue; - if(readMethod.getAnnotation(ControllerMethod.class) != null) continue; + if (readMethod != null && !(name.equals("metaClass")) && !(name.equals("class"))) { + if (readMethod.getAnnotation(PersistenceMethod.class) != null) { + continue; + } + if (readMethod.getAnnotation(ControllerMethod.class) != null) { + continue; + } Object value = readMethod.invoke(o, (Object[]) null); writer.key(name); json.convertAnother(value); @@ -74,23 +78,23 @@ public void marshalObject(Object o, JSON json) throws ConverterException { int modifiers = field.getModifiers(); if (Modifier.isPublic(modifiers) && !(Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers))) { String name = field.getName(); - if(!shouldInclude(includeExcludeSupport,includes,excludes,o,name)) continue; + if (!shouldInclude(includeExcludeSupport, includes, excludes, o, name)) { + continue; + } writer.key(name); json.convertAnother(field.get(o)); } } writer.endObject(); - } - catch (ConverterException ce) { + } catch (ConverterException ce) { throw ce; - } - catch (Exception e) { + } catch (Exception e) { throw new ConverterException("Error converting Bean with class " + clazz.getName(), e); } } private boolean shouldInclude(IncludeExcludeSupport includeExcludeSupport, List includes, List excludes, Object o, String name) { - return includeExcludeSupport.shouldInclude(includes,excludes, name) && shouldInclude(o,name); + return includeExcludeSupport.shouldInclude(includes, excludes, name) && shouldInclude(o, name); } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/InstanceMethodBasedMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/InstanceMethodBasedMarshaller.java index 2a284bdc0ff..c13f9e1b291 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/InstanceMethodBasedMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/InstanceMethodBasedMarshaller.java @@ -22,10 +22,9 @@ import groovy.lang.GroovySystem; import groovy.lang.MetaClass; import groovy.lang.MetaMethod; - -import org.grails.web.json.JSONWriter; import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.ObjectMarshaller; +import org.grails.web.json.JSONWriter; /** * @author Siegfried Puchbauer @@ -40,21 +39,20 @@ public boolean supports(Object object) { public void marshalObject(Object object, JSON converter) throws ConverterException { MetaMethod method = getToJSONMethod(object); try { - Object result = method.invoke(object, new Object[]{ converter }); + Object result = method.invoke(object, new Object[]{converter}); if (result != null && !(result instanceof JSON) && !(result instanceof JSONWriter)) { converter.convertAnother(result); } - } - catch(Throwable e) { - throw e instanceof ConverterException ? (ConverterException)e : - new ConverterException("Error invoking toJSON method of object with class " + object.getClass().getName(),e); + } catch (Throwable e) { + throw e instanceof ConverterException ? (ConverterException) e : + new ConverterException("Error invoking toJSON method of object with class " + object.getClass().getName(), e); } } protected MetaMethod getToJSONMethod(Object object) { MetaClass mc = GroovySystem.getMetaClassRegistry().getMetaClass(object.getClass()); if (mc != null) { - return mc.getMetaMethod("toJSON", new Object[] { JSON.class }); + return mc.getMetaMethod("toJSON", new Object[]{JSON.class}); } return null; } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/JavascriptDateMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/JavascriptDateMarshaller.java index 616e10990af..bf91aaf2e12 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/JavascriptDateMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/JavascriptDateMarshaller.java @@ -19,16 +19,14 @@ package org.grails.web.converters.marshaller.json; import grails.converters.JSON; - -import java.util.Date; - -import org.grails.web.json.JSONException; import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.ObjectMarshaller; +import org.grails.web.json.JSONException; + +import java.util.Date; /** * @author Siegfried Puchbauer - * * @since 1.1 */ public class JavascriptDateMarshaller implements ObjectMarshaller { @@ -40,8 +38,7 @@ public boolean supports(Object object) { public void marshalObject(Object object, JSON converter) throws ConverterException { try { converter.getWriter().value(object); - } - catch (JSONException e) { + } catch (JSONException e) { throw new ConverterException(e); } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/MapMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/MapMarshaller.java index d68ade1dd83..b1ae2dde971 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/MapMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/MapMarshaller.java @@ -19,12 +19,11 @@ package org.grails.web.converters.marshaller.json; import grails.converters.JSON; - -import java.util.Map; - -import org.grails.web.json.JSONWriter; import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.ObjectMarshaller; +import org.grails.web.json.JSONWriter; + +import java.util.Map; /** * @author Siegfried Puchbauer @@ -40,8 +39,8 @@ public boolean supports(Object object) { public void marshalObject(Object o, JSON converter) throws ConverterException { JSONWriter writer = converter.getWriter(); writer.object(); - Map map = (Map) o; - for (Map.Entry entry : map.entrySet()) { + Map map = (Map) o; + for (Map.Entry entry : map.entrySet()) { Object key = entry.getKey(); if (key != null) { writer.key(key.toString()); diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ToStringBeanMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ToStringBeanMarshaller.java index e3231df33d2..d2094d8d9a4 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ToStringBeanMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ToStringBeanMarshaller.java @@ -19,6 +19,8 @@ package org.grails.web.converters.marshaller.json; import grails.converters.JSON; +import org.grails.web.converters.exceptions.ConverterException; +import org.grails.web.converters.marshaller.ObjectMarshaller; import java.net.URL; import java.util.Arrays; @@ -29,9 +31,6 @@ import java.util.Set; import java.util.TimeZone; -import org.grails.web.converters.exceptions.ConverterException; -import org.grails.web.converters.marshaller.ObjectMarshaller; - /** * @author Siegfried Puchbauer * @since 1.1 diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ValidationErrorsMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ValidationErrorsMarshaller.java index c182e193fb6..ec2ec8f5135 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ValidationErrorsMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/json/ValidationErrorsMarshaller.java @@ -19,12 +19,9 @@ package org.grails.web.converters.marshaller.json; import grails.converters.JSON; - -import java.util.Locale; - -import org.grails.web.json.JSONWriter; import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.ObjectMarshaller; +import org.grails.web.json.JSONWriter; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.i18n.LocaleContextHolder; @@ -32,6 +29,8 @@ import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; +import java.util.Locale; + /** * @author Siegfried Puchbauer * @since 1.1 @@ -63,8 +62,7 @@ public void marshalObject(Object object, JSON json) throws ConverterException { Locale locale = LocaleContextHolder.getLocale(); if (applicationContext != null) { json.property("message", applicationContext.getMessage(fe, locale)); - } - else { + } else { json.property("message", fe.getDefaultMessage()); } writer.endObject(); @@ -75,8 +73,7 @@ public void marshalObject(Object object, JSON json) throws ConverterException { Locale locale = LocaleContextHolder.getLocale(); if (applicationContext != null) { json.property("message", applicationContext.getMessage(fe, locale)); - } - else { + } else { json.property("message", fe.getDefaultMessage()); } writer.endObject(); @@ -84,11 +81,9 @@ public void marshalObject(Object object, JSON json) throws ConverterException { } writer.endArray(); writer.endObject(); - } - catch (ConverterException ce) { + } catch (ConverterException ce) { throw ce; - } - catch (Exception e) { + } catch (Exception e) { throw new ConverterException("Error converting Bean with class " + object.getClass().getName(), e); } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/ArrayMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/ArrayMarshaller.java index 2088b13b8ab..68dac3810c1 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/ArrayMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/ArrayMarshaller.java @@ -19,7 +19,6 @@ package org.grails.web.converters.marshaller.xml; import grails.converters.XML; - import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.NameAwareMarshaller; import org.grails.web.converters.marshaller.ObjectMarshaller; @@ -44,8 +43,7 @@ public void marshalObject(Object o, XML xml) throws ConverterException { xml.startNode(xml.getElementName(cur)); xml.convertAnother(cur); xml.end(); - } - else { + } else { xml.startNode("null"); xml.end(); } @@ -55,4 +53,4 @@ public void marshalObject(Object o, XML xml) throws ConverterException { public String getElementName(Object o) { return "array"; } -} \ No newline at end of file +} diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/Base64ByteArrayMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/Base64ByteArrayMarshaller.java index 7ef5ff9c586..f08556255c7 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/Base64ByteArrayMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/Base64ByteArrayMarshaller.java @@ -20,13 +20,12 @@ import grails.converters.XML; import groovy.lang.Writable; - -import java.io.IOException; - import org.codehaus.groovy.runtime.EncodingGroovyMethods; import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.ObjectMarshaller; +import java.io.IOException; + /** * @author Siegfried Puchbauer * @since 1.1 @@ -43,16 +42,14 @@ public void marshalObject(Object object, XML xml) throws ConverterException { Writable w; if (object instanceof byte[]) { - w = EncodingGroovyMethods.encodeBase64((byte[])object); - } - else { - w = EncodingGroovyMethods.encodeBase64((Byte[])object); + w = EncodingGroovyMethods.encodeBase64((byte[]) object); + } else { + w = EncodingGroovyMethods.encodeBase64((Byte[]) object); } try { w.writeTo(xml.getStream()); - } - catch (IOException e) { + } catch (IOException e) { throw new ConverterException(e); } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/CollectionMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/CollectionMarshaller.java index 6e57538cf74..7dfc11ef367 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/CollectionMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/CollectionMarshaller.java @@ -19,14 +19,13 @@ package org.grails.web.converters.marshaller.xml; import grails.converters.XML; - -import java.util.Collection; -import java.util.Set; - import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.NameAwareMarshaller; import org.grails.web.converters.marshaller.ObjectMarshaller; +import java.util.Collection; +import java.util.Set; + /** * @author Siegfried Puchbauer * @since 1.1 @@ -45,8 +44,7 @@ public void marshalObject(Object object, XML xml) throws ConverterException { xml.startNode(xml.getElementName(o)); xml.convertAnother(o); xml.end(); - } - else { + } else { xml.startNode("null"); xml.end(); } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/DateMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/DateMarshaller.java index 6c3c946d58a..1ce9ccdeee6 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/DateMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/DateMarshaller.java @@ -19,15 +19,14 @@ package org.grails.web.converters.marshaller.xml; import grails.converters.XML; - -import java.text.Format; -import java.util.Date; - import org.apache.commons.lang3.time.FastDateFormat; import org.grails.web.converters.ConverterUtil; import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.ObjectMarshaller; +import java.text.Format; +import java.util.Date; + /** * @author Siegfried Puchbauer * @since 1.1 @@ -38,7 +37,8 @@ public class DateMarshaller implements ObjectMarshaller { /** * Constructor with a custom formatter. - * @param formatter the formatter + * + * @param formatter the formatter */ public DateMarshaller(Format formatter) { this.formatter = formatter; @@ -58,8 +58,7 @@ public boolean supports(Object object) { public void marshalObject(Object object, XML xml) throws ConverterException { try { xml.chars(formatter.format(object)); - } - catch (Exception e) { + } catch (Exception e) { throw ConverterUtil.resolveConverterException(e); } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/DeepDomainClassMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/DeepDomainClassMarshaller.java index e75108229d5..aced4b195c0 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/DeepDomainClassMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/DeepDomainClassMarshaller.java @@ -24,7 +24,6 @@ /** * @author Siegfried Puchbauer * @author Graeme Rocher - * * @since 1.1 */ public class DeepDomainClassMarshaller extends DomainClassMarshaller { diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/DomainClassMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/DomainClassMarshaller.java index 3a352bb72a5..ce0e1b79e6a 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/DomainClassMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/DomainClassMarshaller.java @@ -19,18 +19,12 @@ package org.grails.web.converters.marshaller.xml; import grails.converters.XML; - -import java.util.*; - import grails.core.GrailsApplication; - -import org.grails.core.exceptions.GrailsConfigurationException; -import org.grails.core.util.IncludeExcludeSupport; - import grails.core.support.proxy.EntityProxyHandler; import grails.core.support.proxy.ProxyHandler; - import org.grails.core.artefact.DomainClassArtefactHandler; +import org.grails.core.exceptions.GrailsConfigurationException; +import org.grails.core.util.IncludeExcludeSupport; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.config.GormProperties; @@ -48,6 +42,19 @@ import org.springframework.beans.BeanWrapperImpl; import org.springframework.util.StringUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + /** * * Object marshaller for domain classes to XML @@ -92,7 +99,7 @@ public boolean supports(Object object) { return application.isArtefactOfType(DomainClassArtefactHandler.TYPE, name); } - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) public void marshalObject(Object value, XML xml) throws ConverterException { Class clazz = value.getClass(); @@ -102,16 +109,18 @@ public void marshalObject(Object value, XML xml) throws ConverterException { PersistentEntity domainClass = findDomainClass(value); - if ( domainClass == null ) { + if (domainClass == null) { throw new GrailsConfigurationException("Could not retrieve the respective entity for domain " + value.getClass().getName() + " in the mapping context API"); } BeanWrapper beanWrapper = new BeanWrapperImpl(value); PersistentProperty id = domainClass.getIdentity(); - if(shouldInclude(includeExcludeSupport, includes, excludes,value, id.getName())) { + if (shouldInclude(includeExcludeSupport, includes, excludes, value, id.getName())) { Object idValue = beanWrapper.getPropertyValue(id.getName()); - if (idValue != null) xml.attribute("id", String.valueOf(idValue)); + if (idValue != null) { + xml.attribute("id", String.valueOf(idValue)); + } } if (shouldInclude(includeExcludeSupport, includes, excludes, value, GormProperties.VERSION) && includeVersion) { @@ -123,8 +132,8 @@ public void marshalObject(Object value, XML xml) throws ConverterException { } } } - if(includeClass && shouldInclude(includeExcludeSupport, includes, excludes, value, "class")) { - xml.attribute("class",domainClass.getJavaClass().getName()); + if (includeClass && shouldInclude(includeExcludeSupport, includes, excludes, value, "class")) { + xml.attribute("class", domainClass.getJavaClass().getName()); } List properties = domainClass.getPersistentProperties(); @@ -135,50 +144,44 @@ public void marshalObject(Object value, XML xml) throws ConverterException { continue; } - if(!shouldInclude(includeExcludeSupport, includes, excludes, value, property.getName())) continue; + if (!shouldInclude(includeExcludeSupport, includes, excludes, value, property.getName())) { + continue; + } xml.startNode(propertyName); if (!(property instanceof Association)) { // Write non-relation property Object val = beanWrapper.getPropertyValue(propertyName); xml.convertAnother(val); - } - else { + } else { if (isRenderDomainClassRelations()) { Object referenceObject = beanWrapper.getPropertyValue(propertyName); if (referenceObject != null && shouldInitializeProxy(referenceObject)) { referenceObject = proxyHandler.unwrapIfProxy(referenceObject); if (referenceObject instanceof SortedMap) { referenceObject = new TreeMap((SortedMap) referenceObject); - } - else if (referenceObject instanceof SortedSet) { + } else if (referenceObject instanceof SortedSet) { referenceObject = new TreeSet((SortedSet) referenceObject); - } - else if (referenceObject instanceof Set) { + } else if (referenceObject instanceof Set) { referenceObject = new LinkedHashSet((Set) referenceObject); - } - else if (referenceObject instanceof Map) { + } else if (referenceObject instanceof Map) { referenceObject = new LinkedHashMap((Map) referenceObject); - } - else if (referenceObject instanceof Collection) { + } else if (referenceObject instanceof Collection) { referenceObject = new ArrayList((Collection) referenceObject); } xml.convertAnother(referenceObject); } - } - else { + } else { Object referenceObject = beanWrapper.getPropertyValue(propertyName); if (referenceObject != null) { PersistentEntity referencedDomainClass = ((Association) property).getAssociatedEntity(); // Embedded are now always fully rendered - if (referencedDomainClass == null || ((Association)property).isEmbedded() || property.getType().isEnum()) { + if (referencedDomainClass == null || ((Association) property).isEmbedded() || property.getType().isEnum()) { xml.convertAnother(referenceObject); - } - else if ((property instanceof OneToOne) || (property instanceof ManyToOne)|| ((Association)property).isEmbedded()) { + } else if ((property instanceof OneToOne) || (property instanceof ManyToOne) || ((Association) property).isEmbedded()) { asShortObject(referenceObject, xml, referencedDomainClass.getIdentity(), referencedDomainClass); - } - else { + } else { PersistentProperty referencedIdProperty = referencedDomainClass.getIdentity(); @SuppressWarnings("unused") String refPropertyName = ((Association) property).getReferencedPropertyName(); @@ -189,8 +192,7 @@ else if ((property instanceof OneToOne) || (property instanceof ManyToOne)|| ((A asShortObject(el, xml, referencedIdProperty, referencedDomainClass); xml.end(); } - } - else if (referenceObject instanceof Map) { + } else if (referenceObject instanceof Map) { Map map = (Map) referenceObject; for (Map.Entry entry : map.entrySet()) { String key = String.valueOf(entry.getKey()); @@ -209,7 +211,7 @@ else if (referenceObject instanceof Map) { } private boolean shouldInclude(IncludeExcludeSupport includeExcludeSupport, List includes, List excludes, Object object, String name) { - return includeExcludeSupport.shouldInclude(includes, excludes, name) && shouldInclude(object,name); + return includeExcludeSupport.shouldInclude(includes, excludes, name) && shouldInclude(object, name); } private boolean shouldInitializeProxy(Object object) { @@ -220,7 +222,6 @@ protected boolean shouldInitializeProxies() { return true; } - protected void asShortObject(Object refObj, XML xml, PersistentProperty idProperty, PersistentEntity referencedDomainClass) throws ConverterException { Object idValue; if (proxyHandler instanceof EntityProxyHandler) { @@ -229,12 +230,11 @@ protected void asShortObject(Object refObj, XML xml, PersistentProperty idProper ClassPropertyFetcher propertyFetcher = ClassPropertyFetcher.forClass(refObj.getClass()); idValue = propertyFetcher.getPropertyValue(refObj, idProperty.getName()); } - } - else { + } else { ClassPropertyFetcher propertyFetcher = ClassPropertyFetcher.forClass(refObj.getClass()); idValue = propertyFetcher.getPropertyValue(refObj, idProperty.getName()); } - xml.attribute(GormProperties.IDENTITY,String.valueOf(idValue)); + xml.attribute(GormProperties.IDENTITY, String.valueOf(idValue)); } protected boolean isRenderDomainClassRelations() { @@ -242,9 +242,9 @@ protected boolean isRenderDomainClassRelations() { } private PersistentEntity findDomainClass(Object value) { - for ( DomainClassFetcher fetcher : domainClassFetchers) { + for (DomainClassFetcher fetcher : domainClassFetchers) { PersistentEntity domain = fetcher.findDomainClass(value); - if ( domain != null ) { + if (domain != null) { return domain; } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/EnumMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/EnumMarshaller.java index 539d93541a7..f4a4ab873b8 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/EnumMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/EnumMarshaller.java @@ -19,13 +19,12 @@ package org.grails.web.converters.marshaller.xml; import grails.converters.XML; - -import java.lang.reflect.Method; - import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.ObjectMarshaller; import org.springframework.beans.BeanUtils; +import java.lang.reflect.Method; + /** * @author Siegfried Puchbauer * @since 1.1 @@ -43,15 +42,12 @@ public void marshalObject(Object en, XML xml) throws ConverterException { Method nameMethod = BeanUtils.findDeclaredMethod(enumClass, "name"); try { xml.chars(nameMethod.invoke(en).toString()); - } - catch (Exception e) { + } catch (Exception e) { // ignored } - } - catch (ConverterException ce) { + } catch (ConverterException ce) { throw ce; - } - catch (Exception e) { + } catch (Exception e) { throw new ConverterException("Error converting Enum with class " + en.getClass().getName(), e); } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/GenericJavaBeanMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/GenericJavaBeanMarshaller.java index da289b2d881..e55e3a7b00f 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/GenericJavaBeanMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/GenericJavaBeanMarshaller.java @@ -19,16 +19,15 @@ package org.grails.web.converters.marshaller.xml; import grails.converters.XML; +import org.grails.web.converters.exceptions.ConverterException; +import org.grails.web.converters.marshaller.ObjectMarshaller; +import org.springframework.beans.BeanUtils; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import org.grails.web.converters.exceptions.ConverterException; -import org.grails.web.converters.marshaller.ObjectMarshaller; -import org.springframework.beans.BeanUtils; - /** * @author Siegfried Puchbauer * @since 1.1 @@ -60,11 +59,9 @@ public void marshalObject(Object o, XML xml) throws ConverterException { xml.end(); } } - } - catch (ConverterException ce) { + } catch (ConverterException ce) { throw ce; - } - catch (Exception e) { + } catch (Exception e) { throw new ConverterException("Error converting Bean with class " + o.getClass().getName(), e); } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/GroovyBeanMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/GroovyBeanMarshaller.java index 12b25b17cdf..6f2e974df9a 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/GroovyBeanMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/GroovyBeanMarshaller.java @@ -23,6 +23,11 @@ import grails.persistence.PersistenceMethod; import grails.web.controllers.ControllerMethod; import groovy.lang.GroovyObject; +import org.grails.core.util.IncludeExcludeSupport; +import org.grails.datastore.mapping.model.config.GormProperties; +import org.grails.web.converters.exceptions.ConverterException; +import org.grails.web.converters.marshaller.IncludeExcludePropertyMarshaller; +import org.springframework.beans.BeanUtils; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; @@ -30,12 +35,6 @@ import java.lang.reflect.Modifier; import java.util.List; -import org.grails.core.util.IncludeExcludeSupport; -import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.web.converters.exceptions.ConverterException; -import org.grails.web.converters.marshaller.IncludeExcludePropertyMarshaller; -import org.springframework.beans.BeanUtils; - /** * @author Siegfried Puchbauer * @since 1.1 @@ -53,17 +52,25 @@ public void marshalObject(Object o, XML xml) throws ConverterException { List includes = xml.getIncludes(clazz); IncludeExcludeSupport includeExcludeSupport = new IncludeExcludeSupport(); - boolean isEntity = o.getClass().getAnnotation(Entity.class)!=null; + boolean isEntity = o.getClass().getAnnotation(Entity.class) != null; for (PropertyDescriptor property : BeanUtils.getPropertyDescriptors(o.getClass())) { String name = property.getName(); - if(!shouldInclude(includeExcludeSupport,includes,excludes,o, name)) continue; + if (!shouldInclude(includeExcludeSupport, includes, excludes, o, name)) { + continue; + } - if(isEntity && (name.equals(GormProperties.ATTACHED) || name.equals(GormProperties.ERRORS))) continue; + if (isEntity && (name.equals(GormProperties.ATTACHED) || name.equals(GormProperties.ERRORS))) { + continue; + } Method readMethod = property.getReadMethod(); - if (readMethod != null && !(name.equals("metaClass"))&& !(name.equals("class"))) { - if(readMethod.getAnnotation(PersistenceMethod.class) != null) continue; - if(readMethod.getAnnotation(ControllerMethod.class) != null) continue; + if (readMethod != null && !(name.equals("metaClass")) && !(name.equals("class"))) { + if (readMethod.getAnnotation(PersistenceMethod.class) != null) { + continue; + } + if (readMethod.getAnnotation(ControllerMethod.class) != null) { + continue; + } Object value = readMethod.invoke(o, (Object[]) null); xml.startNode(name); xml.convertAnother(value); @@ -74,23 +81,25 @@ public void marshalObject(Object o, XML xml) throws ConverterException { int modifiers = field.getModifiers(); if (Modifier.isPublic(modifiers) && !(Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers))) { String name = field.getName(); - if(!shouldInclude(includeExcludeSupport,includes,excludes,o, name)) continue; - if(isEntity && (name.equals(GormProperties.ATTACHED) || name.equals(GormProperties.ERRORS))) continue; + if (!shouldInclude(includeExcludeSupport, includes, excludes, o, name)) { + continue; + } + if (isEntity && (name.equals(GormProperties.ATTACHED) || name.equals(GormProperties.ERRORS))) { + continue; + } xml.startNode(name); xml.convertAnother(field.get(o)); xml.end(); } } - } - catch (ConverterException ce) { + } catch (ConverterException ce) { throw ce; - } - catch (Exception e) { + } catch (Exception e) { throw new ConverterException("Error converting Bean with class " + o.getClass().getName(), e); } } private boolean shouldInclude(IncludeExcludeSupport includeExcludeSupport, List includes, List excludes, Object o, String name) { - return includeExcludeSupport.shouldInclude(includes,excludes, name) && shouldInclude(o,name); + return includeExcludeSupport.shouldInclude(includes, excludes, name) && shouldInclude(o, name); } } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/InstanceMethodBasedMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/InstanceMethodBasedMarshaller.java index ce1ed7c16f4..173f9f74e81 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/InstanceMethodBasedMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/InstanceMethodBasedMarshaller.java @@ -22,7 +22,6 @@ import groovy.lang.GroovySystem; import groovy.lang.MetaClass; import groovy.lang.MetaMethod; - import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.ObjectMarshaller; @@ -39,21 +38,20 @@ public boolean supports(Object object) { public void marshalObject(Object object, XML converter) throws ConverterException { MetaMethod method = getToXMLMethod(object); try { - Object result = method.invoke(object, new Object[]{ converter }); + Object result = method.invoke(object, new Object[]{converter}); if (result != null && !(result instanceof XML)) { converter.convertAnother(result); } - } - catch(Throwable e) { - throw e instanceof ConverterException ? (ConverterException)e : - new ConverterException("Error invoking toXML method of object with class " + object.getClass().getName(),e); + } catch (Throwable e) { + throw e instanceof ConverterException ? (ConverterException) e : + new ConverterException("Error invoking toXML method of object with class " + object.getClass().getName(), e); } } protected MetaMethod getToXMLMethod(Object object) { MetaClass mc = GroovySystem.getMetaClassRegistry().getMetaClass(object.getClass()); if (mc != null) { - return mc.getMetaMethod("toXML", new Object[] { XML.class }); + return mc.getMetaMethod("toXML", new Object[]{XML.class}); } return null; } diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/MapMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/MapMarshaller.java index 399eca2708b..5dc94db0942 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/MapMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/MapMarshaller.java @@ -19,13 +19,12 @@ package org.grails.web.converters.marshaller.xml; import grails.converters.XML; - -import java.util.Map; - import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.NameAwareMarshaller; import org.grails.web.converters.marshaller.ObjectMarshaller; +import java.util.Map; + /** * @author Siegfried Puchbauer * @since 1.1 @@ -39,8 +38,8 @@ public boolean supports(Object object) { @SuppressWarnings("unchecked") public void marshalObject(Object o, XML xml) throws ConverterException { - Map map = (Map) o; - for (Map.Entry entry : map.entrySet()) { + Map map = (Map) o; + for (Map.Entry entry : map.entrySet()) { xml.startNode("entry").attribute("key", entry.getKey().toString()); xml.convertAnother(entry.getValue()); xml.end(); diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/ToStringBeanMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/ToStringBeanMarshaller.java index 399edf83318..da447f66ee8 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/ToStringBeanMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/ToStringBeanMarshaller.java @@ -19,6 +19,8 @@ package org.grails.web.converters.marshaller.xml; import grails.converters.XML; +import org.grails.web.converters.exceptions.ConverterException; +import org.grails.web.converters.marshaller.ObjectMarshaller; import java.net.URL; import java.util.Arrays; @@ -29,9 +31,6 @@ import java.util.Set; import java.util.TimeZone; -import org.grails.web.converters.exceptions.ConverterException; -import org.grails.web.converters.marshaller.ObjectMarshaller; - /** * @author Siegfried Puchbauer * @since 1.1 diff --git a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/ValidationErrorsMarshaller.java b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/ValidationErrorsMarshaller.java index 6d3955e9c3c..e3a86b762a9 100644 --- a/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/ValidationErrorsMarshaller.java +++ b/grails-converters/src/main/groovy/org/grails/web/converters/marshaller/xml/ValidationErrorsMarshaller.java @@ -19,9 +19,6 @@ package org.grails.web.converters.marshaller.xml; import grails.converters.XML; - -import java.util.Locale; - import org.grails.web.converters.exceptions.ConverterException; import org.grails.web.converters.marshaller.NameAwareMarshaller; import org.grails.web.converters.marshaller.ObjectMarshaller; @@ -32,6 +29,8 @@ import org.springframework.validation.Errors; import org.springframework.validation.FieldError; +import java.util.Locale; + /** * @author Siegfried Puchbauer * @since 1.1 @@ -59,20 +58,18 @@ public void marshalObject(Object object, XML xml) throws ConverterException { Locale locale = LocaleContextHolder.getLocale(); if (applicationContext != null) { xml.startNode("message").chars(applicationContext.getMessage(fe, locale)).end(); - } - else { + } else { String defaultMessage = fe.getDefaultMessage(); - if(defaultMessage != null) + if (defaultMessage != null) { xml.startNode("message").chars(defaultMessage).end(); + } } xml.end(); } } - } - catch (ConverterException ce) { + } catch (ConverterException ce) { throw ce; - } - catch (Exception e) { + } catch (Exception e) { throw new ConverterException("Error converting Bean with class " + object.getClass().getName(), e); } } diff --git a/grails-converters/src/test/groovy/org/grails/web/converters/marshaller/json/DomainClassMarshallerSpec.groovy b/grails-converters/src/test/groovy/org/grails/web/converters/marshaller/json/DomainClassMarshallerSpec.groovy index 53648417e3c..ab50d8640c6 100644 --- a/grails-converters/src/test/groovy/org/grails/web/converters/marshaller/json/DomainClassMarshallerSpec.groovy +++ b/grails-converters/src/test/groovy/org/grails/web/converters/marshaller/json/DomainClassMarshallerSpec.groovy @@ -31,7 +31,6 @@ import spock.lang.Unroll class DomainClassMarshallerSpec extends Specification { - void setup() { } diff --git a/grails-core/build.gradle b/grails-core/build.gradle index e1d525c1790..3e571851969 100644 --- a/grails-core/build.gradle +++ b/grails-core/build.gradle @@ -95,4 +95,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-core/src/main/groovy/grails/artefact/Enhanced.java b/grails-core/src/main/groovy/grails/artefact/Enhanced.java index ae19d8280b7..79e83ebf5d8 100644 --- a/grails-core/src/main/groovy/grails/artefact/Enhanced.java +++ b/grails-core/src/main/groovy/grails/artefact/Enhanced.java @@ -33,7 +33,10 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface Enhanced { + String version(); + String[] enhancedFor() default {}; + Class[] mixins() default {}; } diff --git a/grails-core/src/main/groovy/grails/beans/util/LazyMetaPropertyMap.java b/grails-core/src/main/groovy/grails/beans/util/LazyMetaPropertyMap.java index 9d3aaaea0d8..959cc49b4d3 100644 --- a/grails-core/src/main/groovy/grails/beans/util/LazyMetaPropertyMap.java +++ b/grails-core/src/main/groovy/grails/beans/util/LazyMetaPropertyMap.java @@ -29,23 +29,31 @@ import org.springframework.util.Assert; import java.lang.reflect.Modifier; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * A map implementation that reads an objects properties lazily using Groovy's MetaClass. * * @author Graeme Rocher */ -@SuppressWarnings({"unchecked","rawtypes"}) +@SuppressWarnings({"unchecked", "rawtypes"}) @CompileStatic public class LazyMetaPropertyMap implements Map { + private static final List EXCLUDES = Arrays.asList("class", "constraints", "hasMany", "mapping", "properties", GormProperties.IDENTITY, GormProperties.VERSION, "domainClass", "dirty", GormProperties.ERRORS, "dirtyPropertyNames"); private MetaClass metaClass; private Object instance; - private static List EXCLUDES = Arrays.asList("class", "constraints", "hasMany", "mapping", "properties", GormProperties.IDENTITY, GormProperties.VERSION, "domainClass", "dirty", GormProperties.ERRORS, "dirtyPropertyNames"); /** * Constructs the map + * * @param o The object to inspect */ public LazyMetaPropertyMap(Object o) { @@ -57,6 +65,7 @@ public LazyMetaPropertyMap(Object o) { /** * {@inheritDoc} + * * @see java.util.Map#size() */ public int size() { @@ -65,6 +74,7 @@ public int size() { /** * {@inheritDoc} + * * @see java.util.Map#isEmpty() */ public boolean isEmpty() { @@ -73,10 +83,13 @@ public boolean isEmpty() { /** * {@inheritDoc} + * * @see java.util.Map#containsKey(java.lang.Object) */ public boolean containsKey(Object propertyName) { - if (propertyName instanceof CharSequence) propertyName = propertyName.toString(); + if (propertyName instanceof CharSequence) { + propertyName = propertyName.toString(); + } Assert.isInstanceOf(String.class, propertyName, "This map implementation only supports String based keys!"); String pn = propertyName.toString(); @@ -107,7 +120,7 @@ public Object get(Object propertyName) { if (propertyName instanceof List) { Map submap = new HashMap(); - List propertyNames = (List)propertyName; + List propertyNames = (List) propertyName; for (Object currentName : propertyNames) { if (currentName != null) { currentName = currentName.toString(); @@ -137,11 +150,11 @@ public Object put(Object propertyName, Object propertyValue) { } Object old = null; - MetaProperty mp = metaClass.getMetaProperty((String)propertyName); + MetaProperty mp = metaClass.getMetaProperty((String) propertyName); if (mp != null && !isExcluded(mp)) { old = mp.getProperty(instance); if (propertyValue instanceof Map) { - propertyValue = ((Map)propertyValue).get(propertyName); + propertyValue = ((Map) propertyValue).get(propertyName); } mp.setProperty(instance, propertyValue); } @@ -171,7 +184,9 @@ public void clear() { public Set keySet() { Set names = new HashSet<>(); for (MetaProperty mp : metaClass.getProperties()) { - if (isExcluded(mp)) continue; + if (isExcluded(mp)) { + continue; + } names.add(mp.getName()); } return names; @@ -180,7 +195,9 @@ public Set keySet() { public Collection values() { Collection values = new ArrayList<>(); for (MetaProperty mp : metaClass.getProperties()) { - if (isExcluded(mp)) continue; + if (isExcluded(mp)) { + continue; + } values.add(mp.getProperty(instance)); } return values; @@ -194,7 +211,7 @@ public int hashCode() { @Override public boolean equals(Object o) { if (o instanceof LazyMetaPropertyMap) { - LazyMetaPropertyMap other = (LazyMetaPropertyMap)o; + LazyMetaPropertyMap other = (LazyMetaPropertyMap) o; return instance.equals(other.getInstance()); } return false; @@ -212,7 +229,9 @@ public Object getInstance() { public Set entrySet() { Set entries = new HashSet<>(); for (MetaProperty mp : metaClass.getProperties()) { - if (isExcluded(mp)) continue; + if (isExcluded(mp)) { + continue; + } entries.add(new MapEntry(mp.getName(), mp.getProperty(instance))); } diff --git a/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy b/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy index e219f3b27f6..2ee9a6d383c 100644 --- a/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy +++ b/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy @@ -73,10 +73,10 @@ class GrailsApp extends SpringApplication { * Create a new {@link GrailsApp} instance. The application context will load * beans from the specified sources (see {@link SpringApplication class-level} * documentation for details. The instance can be customized before calling - * {@link #run(String...)}. + * {@link #run(String ...)}. * @param sources the bean sources - * @see #run(Object, String[]) - * @see #GrailsApp(org.springframework.core.io.ResourceLoader, Class...) + * @see #run(Object, String [ ]) + * @see #GrailsApp(org.springframework.core.io.ResourceLoader, Class ...) */ GrailsApp(Class... sources) { super(sources) @@ -86,11 +86,11 @@ class GrailsApp extends SpringApplication { * Create a new {@link GrailsApp} instance. The application context will load * beans from the specified sources (see {@link SpringApplication class-level} * documentation for details. The instance can be customized before calling - * {@link #run(String...)}. + * {@link #run(String ...)}. * @param resourceLoader the resource loader to use * @param sources the bean sources - * @see #run(Object, String[]) - * @see #GrailsApp(org.springframework.core.io.ResourceLoader, Class...) + * @see #run(Object, String [ ]) + * @see #GrailsApp(org.springframework.core.io.ResourceLoader, Class ...) */ GrailsApp(ResourceLoader resourceLoader, Class... sources) { super(resourceLoader, sources) @@ -143,7 +143,8 @@ class GrailsApp extends SpringApplication { configuredEnvironment = environment } - @CompileDynamic // TODO: Report Groovy VerifierError + @CompileDynamic + // TODO: Report Groovy VerifierError protected void enableDevelopmentModeWatch(Environment environment, ConfigurableApplicationContext applicationContext, String... args) { def location = environment.getReloadLocation() @@ -154,6 +155,7 @@ class GrailsApp extends SpringApplication { Queue newFiles = new ConcurrentLinkedQueue<>() directoryWatcher.addListener(new FileExtensionFileChangeListener(['groovy', 'java']) { + @Override void onChange(File file, List extensions) { changedFiles << file.canonicalFile @@ -227,7 +229,6 @@ class GrailsApp extends SpringApplication { } } - developmentModeActive = true Thread.start { CompilerConfiguration compilerConfig = new CompilerConfiguration() @@ -237,7 +238,6 @@ class GrailsApp extends SpringApplication { // Workaround for some IDE / OS combos - 2 events (new + update) for the same file def uniqueChangedFiles = changedFiles as Set - def i = uniqueChangedFiles.size() try { if (i > 1) { @@ -338,6 +338,7 @@ class GrailsApp extends SpringApplication { protected static DirectoryWatcher.FileChangeListener createPluginManagerListener(ConfigurableApplicationContext applicationContext) { def pluginManager = applicationContext.getBean(GrailsPluginManager) return new DirectoryWatcher.FileChangeListener() { + @Override void onChange(File file) { if (!file.name.endsWith('.groovy') && !file.name.endsWith('.java')) { diff --git a/grails-core/src/main/groovy/grails/boot/GrailsAppBuilder.groovy b/grails-core/src/main/groovy/grails/boot/GrailsAppBuilder.groovy index c053cfd731e..aa4748ea9b5 100644 --- a/grails-core/src/main/groovy/grails/boot/GrailsAppBuilder.groovy +++ b/grails-core/src/main/groovy/grails/boot/GrailsAppBuilder.groovy @@ -36,7 +36,7 @@ import org.springframework.core.io.ResourceLoader class GrailsAppBuilder extends SpringApplicationBuilder { @Override - protected SpringApplication createSpringApplication(ResourceLoader resourceLoader, Class < ? > ... sources) { + protected SpringApplication createSpringApplication(ResourceLoader resourceLoader, Class... sources) { return new GrailsApp(resourceLoader, sources) } } diff --git a/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy b/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy index 91bdd5d0d75..660a0b04b5e 100644 --- a/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy +++ b/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy @@ -70,6 +70,7 @@ import org.springframework.core.io.Resource @CompileStatic @Slf4j class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware, ApplicationListener { + static final boolean RELOADING_ENABLED = Environment.isReloadingAgentEnabled() final GrailsApplication grailsApplication @@ -81,24 +82,23 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces boolean loadExternalBeans = true boolean reloadingEnabled = RELOADING_ENABLED - GrailsApplicationPostProcessor(GrailsApplicationLifeCycle lifeCycle, ApplicationContext applicationContext, Class...classes) { + GrailsApplicationPostProcessor(GrailsApplicationLifeCycle lifeCycle, ApplicationContext applicationContext, Class... classes) { this.lifeCycle = lifeCycle - if(lifeCycle instanceof GrailsApplicationClass) { - this.applicationClass = (GrailsApplicationClass)lifeCycle - } - else { + if (lifeCycle instanceof GrailsApplicationClass) { + this.applicationClass = (GrailsApplicationClass) lifeCycle + } else { this.applicationClass = null } this.classes = classes != null ? classes : [] as Class[] grailsApplication = applicationClass != null ? new DefaultGrailsApplication(applicationClass) : new DefaultGrailsApplication() pluginManager = applicationContext?.getBeanNamesForType(GrailsPluginManager) ? applicationContext.getBean(GrailsPluginManager) : new DefaultGrailsPluginManager(grailsApplication) - if(applicationContext != null) { + if (applicationContext != null) { setApplicationContext(applicationContext) } } protected final void initializeGrailsApplication(ApplicationContext applicationContext) { - if(applicationContext == null) { + if (applicationContext == null) { throw new IllegalStateException("ApplicationContext should not be null") } Environment.setInitializing(true) @@ -126,7 +126,7 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces // register plugin provided classes first, this gives the oppurtunity // for application classes to override those provided by a plugin pluginManager.registerProvidedArtefacts(grailsApplication) - for(cls in classes) { + for (cls in classes) { grailsApplication.addArtefact(cls) } } @@ -134,22 +134,25 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces protected void loadApplicationConfig() { org.springframework.core.env.Environment environment = applicationContext.getEnvironment() ConfigurableConversionService conversionService = null - if(environment instanceof ConfigurableEnvironment) { - if(environment instanceof AbstractEnvironment) { + if (environment instanceof ConfigurableEnvironment) { + if (environment instanceof AbstractEnvironment) { conversionService = environment.getConversionService() conversionService.addConverter(new Converter() { + @Override public Resource convert(String source) { return applicationContext.getResource(source); } }); conversionService.addConverter(new Converter() { + @Override public String convert(NavigableMap.NullSafeNavigator source) { return null; } }); conversionService.addConverter(new Converter() { + @Override public Object convert(NavigableMap.NullSafeNavigator source) { return null; @@ -158,22 +161,22 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces } def propertySources = environment.getPropertySources() def plugins = pluginManager.allPlugins - if(plugins) { - for(GrailsPlugin plugin in plugins.reverse()) { + if (plugins) { + for (GrailsPlugin plugin in plugins.reverse()) { def pluginPropertySource = plugin.propertySource - if(pluginPropertySource) { - if(pluginPropertySource instanceof EnumerablePropertySource) { - propertySources.addLast( new PrefixedMapPropertySource( "grails.plugins.$plugin.name", (EnumerablePropertySource)pluginPropertySource ) ) + if (pluginPropertySource) { + if (pluginPropertySource instanceof EnumerablePropertySource) { + propertySources.addLast(new PrefixedMapPropertySource("grails.plugins.$plugin.name", (EnumerablePropertySource) pluginPropertySource)) } propertySources.addLast pluginPropertySource } } } def config = new PropertySourcesConfig(propertySources) - if(conversionService != null) { - config.setConversionService( conversionService ) + if (conversionService != null) { + config.setConversionService(conversionService) } - ((DefaultGrailsApplication)grailsApplication).config = config + ((DefaultGrailsApplication) grailsApplication).config = config } } @@ -186,7 +189,7 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces // first register plugin beans pluginManager.doRuntimeConfiguration(springConfig) - if(loadExternalBeans) { + if (loadExternalBeans) { // now allow overriding via application def context = application.mainContext @@ -213,9 +216,9 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces } } - if(lifeCycle) { + if (lifeCycle) { def withSpring = lifeCycle.doWithSpring() - if(withSpring) { + if (withSpring) { def bb = new BeanBuilder(null, springConfig, application.classLoader) bb.beans withSpring } @@ -239,13 +242,13 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces @Override void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - if(this.applicationContext != applicationContext && applicationContext != null) { + if (this.applicationContext != applicationContext && applicationContext != null) { this.applicationContext = applicationContext initializeGrailsApplication(applicationContext) - if(applicationContext instanceof ConfigurableApplicationContext) { + if (applicationContext instanceof ConfigurableApplicationContext) { def configurable = (ConfigurableApplicationContext) applicationContext configurable.addApplicationListener(this) - configurable.environment.addActiveProfile( grailsApplication.getConfig().getProperty(Settings.PROFILE, String, "web")) + configurable.environment.addActiveProfile(grailsApplication.getConfig().getProperty(Settings.PROFILE, String, "web")) } } } @@ -260,7 +263,7 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces if (event instanceof ContextRefreshedEvent) { if (context.containsBean("grailsDomainClassMappingContext")) { grailsApplication.setMappingContext( - context.getBean("grailsDomainClassMappingContext", MappingContext) + context.getBean("grailsDomainClassMappingContext", MappingContext) ) } Environment.setInitializing(false) @@ -281,8 +284,7 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces for (GrailsApplicationLifeCycle lifeCycle in lifeCycleBeans) { lifeCycle.onStartup(eventMap) } - } - else if(event instanceof ContextClosedEvent) { + } else if (event instanceof ContextClosedEvent) { Map eventMap = [:] eventMap.put('source', pluginManager) for (GrailsApplicationLifeCycle lifeCycle in lifeCycleBeans.asList().reverse()) { diff --git a/grails-core/src/main/groovy/grails/boot/config/GrailsAutoConfiguration.groovy b/grails-core/src/main/groovy/grails/boot/config/GrailsAutoConfiguration.groovy index 23bcd7ec482..653a2246f82 100644 --- a/grails-core/src/main/groovy/grails/boot/config/GrailsAutoConfiguration.groovy +++ b/grails-core/src/main/groovy/grails/boot/config/GrailsAutoConfiguration.groovy @@ -18,9 +18,9 @@ */ package grails.boot.config +import grails.boot.config.tools.ClassPathScanner import grails.config.Config import grails.core.GrailsApplication -import grails.boot.config.tools.ClassPathScanner import grails.core.GrailsApplicationClass import groovy.transform.CompileStatic import org.grails.compiler.injection.AbstractGrailsArtefactTransformer @@ -51,7 +51,7 @@ class GrailsAutoConfiguration implements GrailsApplicationClass, ApplicationCont try { // patch AopConfigUtils if possible Field field = AopConfigUtils.class.getDeclaredField(APC_PRIORITY_LIST_FIELD) - if(field != null) { + if (field != null) { field.setAccessible(true) Object obj = field.get(null) List> list = (List>) obj @@ -70,7 +70,7 @@ class GrailsAutoConfiguration implements GrailsApplicationClass, ApplicationCont */ @Bean GrailsApplicationPostProcessor grailsApplicationPostProcessor() { - return new GrailsApplicationPostProcessor( this, applicationContext, classes() as Class[]) + return new GrailsApplicationPostProcessor(this, applicationContext, classes() as Class[]) } /** @@ -80,15 +80,14 @@ class GrailsAutoConfiguration implements GrailsApplicationClass, ApplicationCont Collection classes = new HashSet() ClassPathScanner scanner = new ClassPathScanner() - if(limitScanningToApplication()) { + if (limitScanningToApplication()) { classes.addAll scanner.scan(getClass(), packageNames()) - } - else { + } else { classes.addAll scanner.scan(new PathMatchingResourcePatternResolver(applicationContext), packageNames()) } ClassLoader classLoader = getClass().getClassLoader() - for(cls in AbstractGrailsArtefactTransformer.transformedClassNames) { + for (cls in AbstractGrailsArtefactTransformer.transformedClassNames) { try { classes << classLoader.loadClass(cls) } catch (ClassNotFoundException cnfe) { @@ -99,7 +98,6 @@ class GrailsAutoConfiguration implements GrailsApplicationClass, ApplicationCont return classes } - /** * Whether classpath scanning should be limited to the application and not dependent JAR files. Users can override this method to enable more broad scanning * at the cost of startup time. @@ -115,7 +113,7 @@ class GrailsAutoConfiguration implements GrailsApplicationClass, ApplicationCont */ Collection packages() { def thisPackage = getClass().package - thisPackage ? [ thisPackage ] : new ArrayList() + thisPackage ? [thisPackage] : new ArrayList() } /** @@ -125,7 +123,6 @@ class GrailsAutoConfiguration implements GrailsApplicationClass, ApplicationCont packages().collect { Package p -> p.name } } - @Override Closure doWithSpring() { null } diff --git a/grails-core/src/main/groovy/grails/boot/config/tools/ClassPathScanner.groovy b/grails-core/src/main/groovy/grails/boot/config/tools/ClassPathScanner.groovy index 88fc29a66bd..fc2ab09e762 100644 --- a/grails-core/src/main/groovy/grails/boot/config/tools/ClassPathScanner.groovy +++ b/grails-core/src/main/groovy/grails/boot/config/tools/ClassPathScanner.groovy @@ -42,8 +42,8 @@ import java.lang.annotation.Annotation @Slf4j @CompileStatic class ClassPathScanner { - private static final List DEFAULT_IGNORED_ROOT_PACKAGES = ['com', 'org', 'net', 'co', 'java', 'javax', 'jakarta', 'groovy'] + private static final List DEFAULT_IGNORED_ROOT_PACKAGES = ['com', 'org', 'net', 'co', 'java', 'javax', 'jakarta', 'groovy'] /** * Scans for classes relative to the given class @@ -53,7 +53,7 @@ class ClassPathScanner { * @return A set of classes */ Set scan(Class applicationClass) { - return scan(applicationClass,[applicationClass.package.name]) + return scan(applicationClass, [applicationClass.package.name]) } /** @@ -65,7 +65,7 @@ class ClassPathScanner { * @return A set of classes */ Set scan(Class applicationClass, Class annotationFilter) { - return scan(applicationClass,[applicationClass.package.name], annotationFilter) + return scan(applicationClass, [applicationClass.package.name], annotationFilter) } /** @@ -76,8 +76,8 @@ class ClassPathScanner { * * @return A set of classes */ - Set scan(Class applicationClass, Closure annotationFilter ) { - return scan(applicationClass,[applicationClass.package.name], annotationFilter) + Set scan(Class applicationClass, Closure annotationFilter) { + return scan(applicationClass, [applicationClass.package.name], annotationFilter) } /** * Scans for classes relative to the given class @@ -105,7 +105,7 @@ class ClassPathScanner { */ Set scan(Class applicationClass, Collection packageNames, Closure annotationFilter = { String annotation -> annotation.startsWith('grails.') }) { ResourcePatternResolver resourcePatternResolver = new GrailsClasspathIgnoringResourceResolver(applicationClass) - return scan(applicationClass.getClassLoader(), resourcePatternResolver,packageNames, annotationFilter) + return scan(applicationClass.getClassLoader(), resourcePatternResolver, packageNames, annotationFilter) } /** @@ -137,13 +137,12 @@ class ClassPathScanner { continue } - if(pkg == "") { + if (pkg == "") { // try the default package in case of a script without recursing into subpackages log.warn("The application defines a Groovy source using the default package. Please move all Groovy sources into a package.") - String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "*.class" + String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "*.class" scanUsingPattern(resourcePatternResolver, pattern, classLoader, annotationFilter, classes) - } - else { + } else { String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(pkg) + Settings.CLASS_RESOURCE_PATTERN; @@ -185,7 +184,6 @@ class ClassPathScanner { } } - @CompileStatic @InheritConstructors @Slf4j @@ -204,7 +202,7 @@ class ClassPathScanner { URL url = resourceUrls.nextElement() // if the path is from a JAR file ignore, plugins inside JAR files will have their own mechanism for loading - if(!url.path.contains('jar!/grails/')) { + if (!url.path.contains('jar!/grails/')) { result.add(convertClassLoaderURL(url)) } @@ -248,10 +246,9 @@ class ClassPathScanner { @Override Enumeration getResources(String name) throws IOException { - if(jarDeployed && name == '') { + if (jarDeployed && name == '') { return applicationClass.getClassLoader().getResources(name) - } - else { + } else { return super.findResources(name) } } diff --git a/grails-core/src/main/groovy/grails/boot/config/tools/ProfilingGrailsApplicationPostProcessor.groovy b/grails-core/src/main/groovy/grails/boot/config/tools/ProfilingGrailsApplicationPostProcessor.groovy index e93d1eea854..23d4bdbe4f5 100644 --- a/grails-core/src/main/groovy/grails/boot/config/tools/ProfilingGrailsApplicationPostProcessor.groovy +++ b/grails-core/src/main/groovy/grails/boot/config/tools/ProfilingGrailsApplicationPostProcessor.groovy @@ -25,7 +25,6 @@ import org.springframework.beans.factory.config.BeanPostProcessor import org.springframework.context.ApplicationContext import org.springframework.context.ConfigurableApplicationContext - /** * Profiles bean creation outputting data to the console * @@ -34,12 +33,11 @@ import org.springframework.context.ConfigurableApplicationContext */ class ProfilingGrailsApplicationPostProcessor extends GrailsApplicationPostProcessor implements BeanPostProcessor { - long startTime ProfilingGrailsApplicationPostProcessor(GrailsApplicationLifeCycle lifeCycle, ApplicationContext applicationContext, Class... classes) { super(lifeCycle, applicationContext, classes) - ((ConfigurableApplicationContext)applicationContext).beanFactory.addBeanPostProcessor(this) + ((ConfigurableApplicationContext) applicationContext).beanFactory.addBeanPostProcessor(this) } @Override @@ -51,7 +49,7 @@ class ProfilingGrailsApplicationPostProcessor extends GrailsApplicationPostProce @Override Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { def totalTime = System.currentTimeMillis() - startTime - if(totalTime > 10) { + if (totalTime > 10) { println "Creating bean $beanName of type ${bean.getClass()} took ${totalTime}ms" } return bean diff --git a/grails-core/src/main/groovy/grails/boot/config/tools/SettingsFile.groovy b/grails-core/src/main/groovy/grails/boot/config/tools/SettingsFile.groovy index 31fa665df3c..a8512cf7d35 100644 --- a/grails-core/src/main/groovy/grails/boot/config/tools/SettingsFile.groovy +++ b/grails-core/src/main/groovy/grails/boot/config/tools/SettingsFile.groovy @@ -21,7 +21,6 @@ package grails.boot.config.tools import groovy.transform.CompileStatic - /** * Used to interpret the Gradle settings.gradle file * @@ -31,7 +30,6 @@ import groovy.transform.CompileStatic @CompileStatic abstract class SettingsFile extends Script { - void include(String[] projectPaths) { binding.setVariable("projectPaths", projectPaths) } diff --git a/grails-core/src/main/groovy/grails/compiler/DelegatingMethod.groovy b/grails-core/src/main/groovy/grails/compiler/DelegatingMethod.groovy index 8e3308a5991..cbfc9ff8cda 100644 --- a/grails-core/src/main/groovy/grails/compiler/DelegatingMethod.groovy +++ b/grails-core/src/main/groovy/grails/compiler/DelegatingMethod.groovy @@ -23,7 +23,6 @@ import java.lang.annotation.Retention import java.lang.annotation.RetentionPolicy import java.lang.annotation.Target - /** * Used to indicate to the compiler that a particular method simply delegates to another one. This information is useful in cases where only the final method * should be transformed and not the methods that delegate to the said method. diff --git a/grails-core/src/main/groovy/grails/compiler/GrailsCompileStatic.groovy b/grails-core/src/main/groovy/grails/compiler/GrailsCompileStatic.groovy index aae251ba80a..9d3a8205781 100644 --- a/grails-core/src/main/groovy/grails/compiler/GrailsCompileStatic.groovy +++ b/grails-core/src/main/groovy/grails/compiler/GrailsCompileStatic.groovy @@ -27,12 +27,12 @@ import groovy.transform.CompileStatic * */ @AnnotationCollector -@CompileStatic(extensions=['org.grails.compiler.ValidateableTypeCheckingExtension', - 'org.grails.compiler.NamedQueryTypeCheckingExtension', - 'org.grails.compiler.HttpServletRequestTypeCheckingExtension', - 'org.grails.compiler.WhereQueryTypeCheckingExtension', - 'org.grails.compiler.DynamicFinderTypeCheckingExtension', - 'org.grails.compiler.DomainMappingTypeCheckingExtension', - 'org.grails.compiler.RelationshipManagementMethodTypeCheckingExtension']) +@CompileStatic(extensions = ['org.grails.compiler.ValidateableTypeCheckingExtension', + 'org.grails.compiler.NamedQueryTypeCheckingExtension', + 'org.grails.compiler.HttpServletRequestTypeCheckingExtension', + 'org.grails.compiler.WhereQueryTypeCheckingExtension', + 'org.grails.compiler.DynamicFinderTypeCheckingExtension', + 'org.grails.compiler.DomainMappingTypeCheckingExtension', + 'org.grails.compiler.RelationshipManagementMethodTypeCheckingExtension']) @interface GrailsCompileStatic { } diff --git a/grails-core/src/main/groovy/grails/compiler/GrailsTypeChecked.groovy b/grails-core/src/main/groovy/grails/compiler/GrailsTypeChecked.groovy index cdc90ad6d41..701b7a120e4 100644 --- a/grails-core/src/main/groovy/grails/compiler/GrailsTypeChecked.groovy +++ b/grails-core/src/main/groovy/grails/compiler/GrailsTypeChecked.groovy @@ -27,13 +27,13 @@ import groovy.transform.TypeChecked * */ @AnnotationCollector -@TypeChecked(extensions=['org.grails.compiler.ValidateableTypeCheckingExtension', - 'org.grails.compiler.NamedQueryTypeCheckingExtension', - 'org.grails.compiler.WhereQueryTypeCheckingExtension', - 'org.grails.compiler.HttpServletRequestTypeCheckingExtension', - 'org.grails.compiler.DynamicFinderTypeCheckingExtension', - 'org.grails.compiler.DomainMappingTypeCheckingExtension', - 'org.grails.compiler.RelationshipManagementMethodTypeCheckingExtension']) +@TypeChecked(extensions = ['org.grails.compiler.ValidateableTypeCheckingExtension', + 'org.grails.compiler.NamedQueryTypeCheckingExtension', + 'org.grails.compiler.WhereQueryTypeCheckingExtension', + 'org.grails.compiler.HttpServletRequestTypeCheckingExtension', + 'org.grails.compiler.DynamicFinderTypeCheckingExtension', + 'org.grails.compiler.DomainMappingTypeCheckingExtension', + 'org.grails.compiler.RelationshipManagementMethodTypeCheckingExtension']) @interface GrailsTypeChecked { } diff --git a/grails-core/src/main/groovy/grails/compiler/ast/AnnotatedClassInjector.java b/grails-core/src/main/groovy/grails/compiler/ast/AnnotatedClassInjector.java index 3b2dbdab1ab..340f9e87fef 100644 --- a/grails-core/src/main/groovy/grails/compiler/ast/AnnotatedClassInjector.java +++ b/grails-core/src/main/groovy/grails/compiler/ast/AnnotatedClassInjector.java @@ -32,7 +32,8 @@ public interface AnnotatedClassInjector { /** * Performs injection on an annotated entity - * @param source The source unit + * + * @param source The source unit * @param classNode The class node */ void performInjectionOnAnnotatedClass(SourceUnit source, GeneratorContext context, ClassNode classNode); diff --git a/grails-core/src/main/groovy/grails/compiler/ast/AstTransformer.java b/grails-core/src/main/groovy/grails/compiler/ast/AstTransformer.java index b0c25757967..05f8c7c872f 100644 --- a/grails-core/src/main/groovy/grails/compiler/ast/AstTransformer.java +++ b/grails-core/src/main/groovy/grails/compiler/ast/AstTransformer.java @@ -26,10 +26,11 @@ /** * Marker annotation that for classes that transform Grails classes at the AST level. * - * @since 2.0 * @author Graeme Rocher + * @since 2.0 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface AstTransformer { + } diff --git a/grails-core/src/main/groovy/grails/compiler/ast/ClassInjector.java b/grails-core/src/main/groovy/grails/compiler/ast/ClassInjector.java index a56a3310ad5..442970875d5 100644 --- a/grails-core/src/main/groovy/grails/compiler/ast/ClassInjector.java +++ b/grails-core/src/main/groovy/grails/compiler/ast/ClassInjector.java @@ -18,19 +18,18 @@ */ package grails.compiler.ast; -import java.lang.reflect.Modifier; -import java.net.URL; - import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.classgen.GeneratorContext; import org.codehaus.groovy.control.SourceUnit; +import java.lang.reflect.Modifier; +import java.net.URL; + /** * When implemented allows additional properties to be injected into Grails * classes at compile time (ie when they are loaded by the GroovyClassLoader). * * @author Graeme Rocher - * * @since 0.2 */ public interface ClassInjector { @@ -40,8 +39,8 @@ public interface ClassInjector { /** * Handles injection of properties, methods etc. into a class. * - * @param source The source unit - * @param context The generator context + * @param source The source unit + * @param context The generator context * @param classNode The ClassNode instance */ void performInjection(SourceUnit source, GeneratorContext context, ClassNode classNode); @@ -49,16 +48,15 @@ public interface ClassInjector { /** * Handles injection of properties, methods etc. into a class. * - * @param source The source unit + * @param source The source unit * @param classNode The ClassNode instance */ void performInjection(SourceUnit source, ClassNode classNode); - /** * Handles injection of properties, methods etc. into a class. * - * @param source The source unit + * @param source The source unit * @param classNode The ClassNode instance */ void performInjectionOnAnnotatedClass(SourceUnit source, ClassNode classNode); diff --git a/grails-core/src/main/groovy/grails/compiler/ast/GlobalClassInjector.groovy b/grails-core/src/main/groovy/grails/compiler/ast/GlobalClassInjector.groovy index f44f65a7deb..1d5a96544ea 100644 --- a/grails-core/src/main/groovy/grails/compiler/ast/GlobalClassInjector.groovy +++ b/grails-core/src/main/groovy/grails/compiler/ast/GlobalClassInjector.groovy @@ -25,6 +25,6 @@ package grails.compiler.ast * @author Graeme Rocher * @since 3.0 */ -public interface GlobalClassInjector extends ClassInjector{ +interface GlobalClassInjector extends ClassInjector { } \ No newline at end of file diff --git a/grails-core/src/main/groovy/grails/compiler/ast/GlobalClassInjectorAdapter.groovy b/grails-core/src/main/groovy/grails/compiler/ast/GlobalClassInjectorAdapter.groovy index 6a8b66d7652..1b46fffafd8 100644 --- a/grails-core/src/main/groovy/grails/compiler/ast/GlobalClassInjectorAdapter.groovy +++ b/grails-core/src/main/groovy/grails/compiler/ast/GlobalClassInjectorAdapter.groovy @@ -48,7 +48,7 @@ abstract class GlobalClassInjectorAdapter implements GlobalClassInjector { @Override void performInjectionOnAnnotatedClass(SourceUnit source, ClassNode classNode) { def className = classNode.name - if(!processesClassNames.contains(className)) { + if (!processesClassNames.contains(className)) { performInjectionInternal source, classNode processesClassNames.add className } diff --git a/grails-core/src/main/groovy/grails/compiler/ast/GrailsDomainClassInjector.java b/grails-core/src/main/groovy/grails/compiler/ast/GrailsDomainClassInjector.java index e0c907ebe7c..58564b299f1 100644 --- a/grails-core/src/main/groovy/grails/compiler/ast/GrailsDomainClassInjector.java +++ b/grails-core/src/main/groovy/grails/compiler/ast/GrailsDomainClassInjector.java @@ -24,7 +24,6 @@ * Mainly just a marker interface for implementations that perform injection on domain classes. * * @author Graeme Rocher - * * @since 0.2 */ public interface GrailsDomainClassInjector extends ClassInjector { diff --git a/grails-core/src/main/groovy/grails/compiler/ast/SupportsClassNode.java b/grails-core/src/main/groovy/grails/compiler/ast/SupportsClassNode.java index afffb0733cb..7be92c0df52 100644 --- a/grails-core/src/main/groovy/grails/compiler/ast/SupportsClassNode.java +++ b/grails-core/src/main/groovy/grails/compiler/ast/SupportsClassNode.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package grails.compiler.ast; import org.codehaus.groovy.ast.ClassNode; @@ -28,6 +27,6 @@ */ public interface SupportsClassNode { - boolean supports(ClassNode classNode); + boolean supports(ClassNode classNode); } diff --git a/grails-core/src/main/groovy/grails/compiler/traits/TraitInjector.java b/grails-core/src/main/groovy/grails/compiler/traits/TraitInjector.java index 59c88849a38..db9de004553 100644 --- a/grails-core/src/main/groovy/grails/compiler/traits/TraitInjector.java +++ b/grails-core/src/main/groovy/grails/compiler/traits/TraitInjector.java @@ -20,12 +20,13 @@ package grails.compiler.traits; /** - * + * * @author Jeff Brown * @since 3.0 * */ public interface TraitInjector { + Class getTrait(); String[] getArtefactTypes(); diff --git a/grails-core/src/main/groovy/grails/config/Config.groovy b/grails-core/src/main/groovy/grails/config/Config.groovy index f5f74e92294..84bc649780d 100644 --- a/grails-core/src/main/groovy/grails/config/Config.groovy +++ b/grails-core/src/main/groovy/grails/config/Config.groovy @@ -46,7 +46,7 @@ interface Config extends PropertyResolver, ConfigMap { * @param toMerge The map to merge * @return This config */ - Config merge(Map toMerge) + Config merge(Map toMerge) /** * Return the property value associated with the given key, or diff --git a/grails-core/src/main/groovy/grails/config/ConfigProperties.groovy b/grails-core/src/main/groovy/grails/config/ConfigProperties.groovy index c33f894fbe0..4a6c718c73b 100644 --- a/grails-core/src/main/groovy/grails/config/ConfigProperties.groovy +++ b/grails-core/src/main/groovy/grails/config/ConfigProperties.groovy @@ -20,7 +20,6 @@ package grails.config import groovy.transform.CompileStatic - /** * Cached access to Config.toProperties to avoid repeated calls * @@ -45,8 +44,8 @@ class ConfigProperties extends Properties { Enumeration propertyNames() { def i = config.keySet().iterator() return ([ - hasMoreElements: {-> i.hasNext() }, - nextElement: {-> i.next() } + hasMoreElements: { -> i.hasNext() }, + nextElement : { -> i.next() } ]) as Enumeration } @@ -67,12 +66,12 @@ class ConfigProperties extends Properties { @Override Enumeration keys() { - return (Enumeration)propertyNames() + return (Enumeration) propertyNames() } @Override Set keySet() { - return (Set)stringPropertyNames() + return (Set) stringPropertyNames() } @Override diff --git a/grails-core/src/main/groovy/grails/config/Settings.groovy b/grails-core/src/main/groovy/grails/config/Settings.groovy index b2114cfafd4..6736a56e00a 100644 --- a/grails-core/src/main/groovy/grails/config/Settings.groovy +++ b/grails-core/src/main/groovy/grails/config/Settings.groovy @@ -215,7 +215,7 @@ interface Settings { /** * The default encoding */ - String DEFAULT_ENCODING = System.getProperty('file.encoding',"UTF-8") + String DEFAULT_ENCODING = System.getProperty('file.encoding', "UTF-8") /** * Whether to log request parameters in the console diff --git a/grails-core/src/main/groovy/grails/config/external/WriterFilteringMap.groovy b/grails-core/src/main/groovy/grails/config/external/WriteFilteringMap.groovy similarity index 100% rename from grails-core/src/main/groovy/grails/config/external/WriterFilteringMap.groovy rename to grails-core/src/main/groovy/grails/config/external/WriteFilteringMap.groovy diff --git a/grails-core/src/main/groovy/grails/core/ApplicationAttributes.java b/grails-core/src/main/groovy/grails/core/ApplicationAttributes.java index 64d5cf424f2..214a0a4c9fb 100644 --- a/grails-core/src/main/groovy/grails/core/ApplicationAttributes.java +++ b/grails-core/src/main/groovy/grails/core/ApplicationAttributes.java @@ -25,6 +25,7 @@ * @since 0.4 */ public interface ApplicationAttributes { + String APPLICATION = "org.codehaus.groovy.grails.APPLICATION"; String APPLICATION_CONTEXT = "org.codehaus.groovy.grails.APPLICATION_CONTEXT"; String PARENT_APPLICATION_CONTEXT = "org.codehaus.groovy.grails.PARENT_APPLICATION_CONTEXT"; diff --git a/grails-core/src/main/groovy/grails/core/ArtefactHandler.java b/grails-core/src/main/groovy/grails/core/ArtefactHandler.java index b5e7e8e8a90..bc3d15e8d85 100644 --- a/grails-core/src/main/groovy/grails/core/ArtefactHandler.java +++ b/grails-core/src/main/groovy/grails/core/ArtefactHandler.java @@ -29,35 +29,39 @@ *

Artefacts need to provide info about themselves, and some callbacks are required * to verify whether or not a class is that kind of artefact/p> * - * @see GrailsApplication#registerArtefactHandler(ArtefactHandler) - * * @author Graeme Rocher * @author Marc Palmer (marc@anyware.co.uk) + * @see GrailsApplication#registerArtefactHandler(ArtefactHandler) * @since 1.0 */ public interface ArtefactHandler extends Ordered { /** * Obtains the plugin name that deals with this artefact. + * * @return The plugin name or null if there isn't one */ String getPluginName(); /** * Implementations must return a name such as "Domain" to indicate the type of artefact they represent. + * * @return The aretfact type, as a String */ String getType(); + /** * @param classNode The ClassNode instance * @return True if the given ClassNode instance is an instance of the Artefact type */ boolean isArtefact(ClassNode classNode); + /** *

Called by the GrailsApplication whenever it needs to know if a given class * is considered to be the kind of artefact represented by this handler.

*

Typically you will check the name of the class and some other properties to see * if it is of the correct artefact type

+ * * @param aClass A class to test * @return true if the class looks like one of your artefacts */ @@ -65,6 +69,7 @@ public interface ArtefactHandler extends Ordered { /** *

Called by GrailsApplication when a new class is found and a GrailsClass wrapping it is required

+ * * @param artefactClass The new class that has been loaded * @return A new custom GrailsClass wrapper containing any extra information your artefact type requires */ @@ -73,6 +78,7 @@ public interface ArtefactHandler extends Ordered { /** *

Called whenever the list of artefacts has changed or been reloaded.

*

It must be safe to call this method multiple times and have any internal data structures reset.

+ * * @param artefacts The collection of artefact classes for this handler */ void initialize(ArtefactInfo artefacts); @@ -81,6 +87,7 @@ public interface ArtefactHandler extends Ordered { *

Called to retrieve an artefact relating to some other key for example a URI or tag name

*

Handlers are responsible for caching the appropriate information using the data passed to them in calls * to initialize()

+ * * @param feature Any object that acts as a key * @return A matching artefact GrailsClass or null if there is no match for this feature ID */ @@ -88,6 +95,7 @@ public interface ArtefactHandler extends Ordered { /** *

Called to check if the specified GrailsClass is one managed by this artefact handler

+ * * @param artefactGrailsClass A GrailsClass instance * @return true if this handler manages the specified GrailsClass */ diff --git a/grails-core/src/main/groovy/grails/core/ArtefactHandlerAdapter.java b/grails-core/src/main/groovy/grails/core/ArtefactHandlerAdapter.java index e3f5ffe80e1..09511f9aa42 100644 --- a/grails-core/src/main/groovy/grails/core/ArtefactHandlerAdapter.java +++ b/grails-core/src/main/groovy/grails/core/ArtefactHandlerAdapter.java @@ -42,7 +42,7 @@ * @author Graeme Rocher * @since 1.0 */ -@SuppressWarnings( "deprecation" ) +@SuppressWarnings("deprecation") public abstract class ArtefactHandlerAdapter implements ArtefactHandler { protected String type; @@ -60,7 +60,7 @@ public ArtefactHandlerAdapter(String type, Class grailsCl } public ArtefactHandlerAdapter(String type, Class grailsClassType, Class grailsClassImpl, - String artefactSuffix, boolean allowAbstract) { + String artefactSuffix, boolean allowAbstract) { this.artefactSuffix = artefactSuffix; this.type = type; this.grailsClassType = grailsClassType; @@ -76,7 +76,6 @@ public String getType() { return type; } - /** * Default implementation of {@link grails.core.ArtefactHandler#isArtefact(org.codehaus.groovy.ast.ClassNode)} which returns true if the ClassNode passes the * {@link #isArtefactResource(org.grails.io.support.Resource)} method and the name of the ClassNode ends with the {@link #artefactSuffix} @@ -89,17 +88,21 @@ public boolean isArtefact(ClassNode classNode) { int modifiers = classNode.getModifiers(); URL url = GrailsASTUtils.getSourceUrl(classNode); - if(url == null) return false; + if (url == null) { + return false; + } try { UrlResource resource = new UrlResource(url); - if(!isArtefactResource(resource)) return false; + if (!isArtefactResource(resource)) { + return false; + } } catch (IOException e) { return false; } - if(isValidArtefactClassNode(classNode, modifiers)) { + if (isValidArtefactClassNode(classNode, modifiers)) { String name = classNode.getName(); - if(name != null && this.artefactSuffix != null && name.endsWith(artefactSuffix)) { + if (name != null && this.artefactSuffix != null && name.endsWith(artefactSuffix)) { return true; } } @@ -130,7 +133,7 @@ public final boolean isArtefact(@SuppressWarnings("rawtypes") Class aClass) { return true; } } catch (Throwable t) { - throw new GrailsRuntimeException("Failed to introspect class: "+ aClass, t); + throw new GrailsRuntimeException("Failed to introspect class: " + aClass, t); } return false; @@ -139,11 +142,14 @@ public final boolean isArtefact(@SuppressWarnings("rawtypes") Class aClass) { /** *

Checks that class's name ends in the suffix specified for this handler.

*

Override for more complex criteria

+ * * @param clazz The class to check * @return true if it is an artefact of this type */ public boolean isArtefactClass(@SuppressWarnings("rawtypes") Class clazz) { - if (clazz == null) return false; + if (clazz == null) { + return false; + } boolean ok = clazz.getName().endsWith(artefactSuffix) && !Closure.class.isAssignableFrom(clazz); if (ok && !allowAbstract) { @@ -155,26 +161,23 @@ public boolean isArtefactClass(@SuppressWarnings("rawtypes") Class clazz) { /** *

Creates new GrailsClass derived object using the type supplied in constructor. May not perform * optimally but is a convenience.

+ * * @param artefactClass Creates a new artefact for the given class * @return An instance of the GrailsClass interface representing the artefact */ public GrailsClass newArtefactClass(@SuppressWarnings("rawtypes") Class artefactClass) { try { - Constructor c = grailsClassImpl.getDeclaredConstructor(new Class[] { Class.class }); + Constructor c = grailsClassImpl.getDeclaredConstructor(new Class[]{Class.class}); // TODO GRAILS-720 plugin class instance created here first - return (GrailsClass) c.newInstance(new Object[] { artefactClass}); - } - catch (NoSuchMethodException e) { - throw new GrailsRuntimeException("Unable to locate constructor with Class parameter for "+artefactClass, e); - } - catch (IllegalAccessException e) { - throw new GrailsRuntimeException("Unable to locate constructor with Class parameter for "+artefactClass, e); - } - catch (InvocationTargetException e) { - throw new GrailsRuntimeException("Error instantiated artefact class [" + artefactClass + "] of type ["+grailsClassImpl+"]: " + (e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName()), e); - } - catch (InstantiationException e) { - throw new GrailsRuntimeException("Error instantiated artefact class [" + artefactClass + "] of type ["+grailsClassImpl+"]: " + (e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName()), e); + return (GrailsClass) c.newInstance(new Object[]{artefactClass}); + } catch (NoSuchMethodException e) { + throw new GrailsRuntimeException("Unable to locate constructor with Class parameter for " + artefactClass, e); + } catch (IllegalAccessException e) { + throw new GrailsRuntimeException("Unable to locate constructor with Class parameter for " + artefactClass, e); + } catch (InvocationTargetException e) { + throw new GrailsRuntimeException("Error instantiated artefact class [" + artefactClass + "] of type [" + grailsClassImpl + "]: " + (e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName()), e); + } catch (InstantiationException e) { + throw new GrailsRuntimeException("Error instantiated artefact class [" + artefactClass + "] of type [" + grailsClassImpl + "]: " + (e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName()), e); } } diff --git a/grails-core/src/main/groovy/grails/core/ArtefactInfo.java b/grails-core/src/main/groovy/grails/core/ArtefactInfo.java index b92da9ec749..a7e5ccea343 100644 --- a/grails-core/src/main/groovy/grails/core/ArtefactInfo.java +++ b/grails-core/src/main/groovy/grails/core/ArtefactInfo.java @@ -25,7 +25,6 @@ * * @author Marc Palmer (marc@anyware.co.uk) * @author Graeme Rocher - * * @since 1.0 */ public interface ArtefactInfo { @@ -33,6 +32,7 @@ public interface ArtefactInfo { /** * Gets you the array of all artefact Class(es), the original classes loaded * that represent the artefacts. + * * @return The array, which may be empty but never null. */ @SuppressWarnings("rawtypes") @@ -41,6 +41,7 @@ public interface ArtefactInfo { /** * Gets you the array of all artefact GrailsClass(es), the classes used to track * information about the artefact. + * * @return The array, which may be empty but never null. */ GrailsClass[] getGrailsClasses(); @@ -48,6 +49,7 @@ public interface ArtefactInfo { /** * Gets you the unmodifiable Map of all artefact Class(es), the actual classes implementing the artefact. *

The Map is keyed by class name, i.e. "BookController"

+ * * @return The Map, which may be empty but never null. */ @SuppressWarnings("rawtypes") @@ -57,6 +59,7 @@ public interface ArtefactInfo { *

Gets you the unmodifiable Map of all artefact GrailsClass(es), the classes that store extra * state relating to the artefact.

*

The Map is keyed by class name, i.e. "BookController"

+ * * @return The Map, which may be empty but never null. */ @SuppressWarnings("rawtypes") @@ -65,6 +68,7 @@ public interface ArtefactInfo { /** *

Retrieves the GrailsClass representing a named artefact.

*

From the GrailsClass you can get to the original artefact Class using getClazz().

+ * * @param name The name of the artefact, i.e. "BookController" * @return The Map, which may be empty but never null. */ @@ -72,6 +76,7 @@ public interface ArtefactInfo { /** * Retrieves a Grails class by its logical property name. For example "BookController" would be "book". + * * @param logicalName The logical name * @return A GrailsClass or null */ diff --git a/grails-core/src/main/groovy/grails/core/DefaultArtefactInfo.java b/grails-core/src/main/groovy/grails/core/DefaultArtefactInfo.java index 181c3c95bce..4a0a48cd17c 100644 --- a/grails-core/src/main/groovy/grails/core/DefaultArtefactInfo.java +++ b/grails-core/src/main/groovy/grails/core/DefaultArtefactInfo.java @@ -18,10 +18,6 @@ */ package grails.core; -import grails.core.ArtefactInfo; -import grails.core.GrailsClass; -import grails.core.InjectableGrailsClass; - import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; @@ -36,18 +32,21 @@ */ public class DefaultArtefactInfo implements ArtefactInfo { + //CHECKSTYLE:OFF + @SuppressWarnings("rawtypes") + public Map handlerData = new HashMap(); + //CHECKSTYLE:ON private LinkedList grailsClasses = new LinkedList(); private Class[] classes; private Map grailsClassesByName = new LinkedHashMap(); private Map> classesByName = new LinkedHashMap>(); private Map logicalPropertyNameToClassMap = new HashMap(); - @SuppressWarnings("rawtypes") - public Map handlerData = new HashMap(); private GrailsClass[] grailsClassesArray; /** *

Call to add a new class to this info object.

*

You must call refresh() later to update the arrays

+ * * @param artefactClass */ public synchronized void addGrailsClass(GrailsClass artefactClass) { @@ -61,7 +60,7 @@ private void addGrailsClassInternal(GrailsClass artefactClass, boolean atStart) Class actualClass = artefactClass.getClazz(); boolean addToGrailsClasses = true; if (artefactClass instanceof InjectableGrailsClass) { - addToGrailsClasses = ((InjectableGrailsClass)artefactClass).getAvailable(); + addToGrailsClasses = ((InjectableGrailsClass) artefactClass).getAvailable(); } if (addToGrailsClasses) { GrailsClass oldVersion = grailsClassesByName.put(actualClass.getName(), artefactClass); @@ -73,8 +72,7 @@ private void addGrailsClassInternal(GrailsClass artefactClass, boolean atStart) if (!grailsClasses.contains(artefactClass)) { if (atStart) { grailsClasses.addFirst(artefactClass); - } - else { + } else { grailsClasses.addLast(artefactClass); } } diff --git a/grails-core/src/main/groovy/grails/core/DefaultGrailsApplication.java b/grails-core/src/main/groovy/grails/core/DefaultGrailsApplication.java index ad31acba6d8..f43d8186589 100644 --- a/grails-core/src/main/groovy/grails/core/DefaultGrailsApplication.java +++ b/grails-core/src/main/groovy/grails/core/DefaultGrailsApplication.java @@ -27,17 +27,6 @@ import groovy.lang.GroovySystem; import groovy.lang.MetaClassRegistry; import groovy.lang.MetaMethod; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.net.URL; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.groovy.reflection.CachedClass; @@ -51,9 +40,7 @@ import org.grails.datastore.mapping.model.MappingContext; import org.grails.io.support.GrailsResourceUtils; import org.grails.spring.beans.GrailsApplicationAwareBeanPostProcessor; -import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanClassLoaderAware; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.ConfigurableEnvironment; @@ -63,6 +50,24 @@ import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * Default implementation of the GrailsApplication interface that manages application loading, * state, and artefact instances. @@ -76,7 +81,6 @@ * @author Marc Palmer * @author Steven Devijver * @author Graeme Rocher - * * @see grails.plugins.GrailsPluginManager * @see grails.plugins.DefaultGrailsPluginManager * @see grails.core.ArtefactHandler @@ -89,9 +93,11 @@ public class DefaultGrailsApplication extends AbstractGrailsApplication implemen protected static final Pattern GETCLASSESMETH_PATTERN = Pattern.compile("(get)(\\w+)(Classes)"); protected static final Pattern ISCLASS_PATTERN = Pattern.compile("(is)(\\w+)(Class)"); protected static final Pattern GETCLASS_PATTERN = Pattern.compile("(get)(\\w+)Class"); + protected static final Log LOG = LogFactory.getLog(DefaultGrailsApplication.class); + + private static boolean extensionMethodsInitialized = false; protected Class[] allClasses = new Class[0]; - protected static Log log = LogFactory.getLog(DefaultGrailsApplication.class); protected Set> loadedClasses = new LinkedHashSet>(); protected ArtefactHandler[] artefactHandlers; @@ -106,20 +112,6 @@ public class DefaultGrailsApplication extends AbstractGrailsApplication implemen protected MappingContext proxyMappingContext = buildMappingContextProxy(this); protected MappingContext mappingContext; - private static MappingContext buildMappingContextProxy(final DefaultGrailsApplication application) { - InvocationHandler proxyHandler = new InvocationHandler() { - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - MappingContext realContext = application.mappingContext; - if(realContext == null) { - throw new GrailsConfigurationException("The method ["+method+"] cannot be accessed before GORM has initialized"); - } - return ReflectionUtils.invokeMethod(method, realContext, args); - } - }; - return (MappingContext) Proxy.newProxyInstance(application.getClass().getClassLoader(), new Class[]{MappingContext.class}, proxyHandler); - } - /** * Creates a new empty Grails application. */ @@ -134,7 +126,7 @@ public DefaultGrailsApplication(GrailsApplicationClass applicationClass) { this(new GroovyClassLoader()); this.applicationClass = applicationClass; } - + public DefaultGrailsApplication(ClassLoader classLoader) { super(); this.classLoader = classLoader; @@ -145,7 +137,7 @@ public DefaultGrailsApplication(ClassLoader classLoader) { * * @param classes The classes */ - public DefaultGrailsApplication(final Class...classes) { + public DefaultGrailsApplication(final Class... classes) { this(classes, new GroovyClassLoader(Thread.currentThread().getContextClassLoader())); } @@ -204,6 +196,20 @@ public DefaultGrailsApplication(org.grails.io.support.Resource[] resources) { } } + private static MappingContext buildMappingContextProxy(final DefaultGrailsApplication application) { + InvocationHandler proxyHandler = new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + MappingContext realContext = application.mappingContext; + if (realContext == null) { + throw new GrailsConfigurationException("The method [" + method + "] cannot be accessed before GORM has initialized"); + } + return ReflectionUtils.invokeMethod(method, realContext, args); + } + }; + return (MappingContext) Proxy.newProxyInstance(application.getClass().getClassLoader(), new Class[]{MappingContext.class}, proxyHandler); + } + /** * @return The application class */ @@ -216,7 +222,7 @@ public GrailsApplicationClass getApplicationClass() { * * @see grails.core.ArtefactHandler */ - @SuppressWarnings( "deprecation" ) + @SuppressWarnings("deprecation") protected void initArtefactHandlers() { List additionalArtefactHandlers = GrailsFactoriesLoader.loadFactories(ArtefactHandler.class, getClassLoader()); @@ -231,7 +237,7 @@ protected void initArtefactHandlers() { private void updateArtefactHandlers() { // Cache the list as an array artefactHandlers = artefactHandlersByName.values().toArray( - new ArtefactHandler[artefactHandlersByName.size()]); + new ArtefactHandler[artefactHandlersByName.size()]); } /** @@ -264,11 +270,11 @@ protected void configureLoadedClasses(Class[] classes) { allClasses = classes; // first load the domain classes - log.debug("Going to inspect artefact classes."); + LOG.debug("Going to inspect artefact classes."); MetaClassRegistry metaClassRegistry = GroovySystem.getMetaClassRegistry(); for (final Class theClass : classes) { - log.debug("Inspecting [" + theClass.getName() + "]"); + LOG.debug("Inspecting [" + theClass.getName() + "]"); // start fresh metaClassRegistry.removeMetaClass(theClass); if (allArtefactClasses.contains(theClass)) { @@ -278,7 +284,7 @@ protected void configureLoadedClasses(Class[] classes) { // check what kind of artefact it is and add to corrent data structure for (ArtefactHandler artefactHandler : artefactHandlers) { if (artefactHandler.isArtefact(theClass)) { - log.debug("Adding artefact " + theClass + " of kind " + artefactHandler.getType()); + LOG.debug("Adding artefact " + theClass + " of kind " + artefactHandler.getType()); GrailsClass gclass = addArtefact(artefactHandler.getType(), theClass); // Also maintain set of all artefacts (!= all classes loaded) allArtefactClasses.add(theClass); @@ -306,7 +312,7 @@ protected void configureLoadedClasses(Class[] classes) { */ protected void refreshArtefactGrailsClassCaches() { for (Object o : artefactInfo.values()) { - ((DefaultArtefactInfo)o).updateComplete(); + ((DefaultArtefactInfo) o).updateComplete(); } } @@ -317,17 +323,15 @@ protected void addToLoaded(Class clazz) { public Config getConfig() { if (config == null) { - if(parentContext != null) { + if (parentContext != null) { org.springframework.core.env.Environment environment = parentContext.getEnvironment(); - if(environment instanceof ConfigurableEnvironment) { + if (environment instanceof ConfigurableEnvironment) { MutablePropertySources propertySources = ((ConfigurableEnvironment) environment).getPropertySources(); this.config = new PropertySourcesConfig(propertySources); - } - else { + } else { this.config = new PropertySourcesConfig(); } - } - else { + } else { this.config = new PropertySourcesConfig(); } @@ -381,7 +385,7 @@ public Class getClassForName(String className) { */ public void refresh() { if (classLoader instanceof GroovyClassLoader) { - configureLoadedClasses(((GroovyClassLoader)classLoader).getLoadedClasses()); + configureLoadedClasses(((GroovyClassLoader) classLoader).getLoadedClasses()); } } @@ -392,8 +396,7 @@ public void rebuild() { if (GrailsUtil.isDevelopmentEnv()) { initialise(); - } - else { + } else { throw new IllegalStateException("Cannot rebuild GrailsApplication when not in development mode!"); } } @@ -545,8 +548,6 @@ public void registerArtefactHandler(ArtefactHandler handler) { updateArtefactHandlers(); } - - public boolean hasArtefactHandler(String type) { return artefactHandlersByName.containsKey(type); } @@ -642,7 +643,9 @@ public Object invokeMethod(String methodName, Object args) { match.find(); if (match.matches()) { if (argsv.length > 0) { - if (argsv[0] instanceof CharSequence) argsv[0] = argsv[0].toString(); + if (argsv[0] instanceof CharSequence) { + argsv[0] = argsv[0].toString(); + } if ((argsv.length != 1) || !(argsv[0] instanceof String)) { throw new IllegalArgumentException( "Dynamic method getClass(artefactName) requires a single String parameter"); @@ -707,8 +710,8 @@ public Object getProperty(String propertyName) { public void initialise() { // get all the classes that were loaded - if (log.isDebugEnabled()) { - log.debug("loaded classes: [" + loadedClasses + "]"); + if (LOG.isDebugEnabled()) { + LOG.debug("loaded classes: [" + loadedClasses + "]"); } Class[] classes = populateAllClasses(); configureLoadedClasses(classes); @@ -716,9 +719,10 @@ public void initialise() { initialised = true; } - private static boolean extensionMethodsInitialized = false; protected static void initialiseGroovyExtensionModules() { - if(extensionMethodsInitialized) return; + if (extensionMethodsInitialized) { + return; + } extensionMethodsInitialized = true; Map> map = new HashMap>(); @@ -738,23 +742,21 @@ protected static void initialiseGroovyExtensionModules() { try { inStream = url.openStream(); properties.load(inStream); - ((MetaClassRegistryImpl)GroovySystem.getMetaClassRegistry()).registerExtensionModuleFromProperties(properties, classLoader, map); - } - catch (IOException e) { + ((MetaClassRegistryImpl) GroovySystem.getMetaClassRegistry()).registerExtensionModuleFromProperties(properties, classLoader, map); + } catch (IOException e) { throw new GroovyRuntimeException("Unable to load module META-INF descriptor", e); - } - finally { - if(inStream != null) { + } finally { + if (inStream != null) { inStream.close(); } } } + } catch (IOException ignored) { } - catch (IOException ignored) {} for (Map.Entry> moduleMethods : map.entrySet()) { CachedClass cls = moduleMethods.getKey(); - cls.addNewMopMethods( moduleMethods.getValue() ); + cls.addNewMopMethods(moduleMethods.getValue()); } } @@ -810,7 +812,7 @@ protected GrailsClass addArtefact(String artefactType, Class artefactClass, b if (handler != null && handler.isArtefact(artefactClass)) { GrailsClass artefactGrailsClass; if (handler instanceof DomainClassArtefactHandler) { - artefactGrailsClass = ((DomainClassArtefactHandler)handler).newArtefactClass(artefactClass, proxyMappingContext); + artefactGrailsClass = ((DomainClassArtefactHandler) handler).newArtefactClass(artefactClass, proxyMappingContext); } else { artefactGrailsClass = handler.newArtefactClass(artefactClass); } @@ -820,8 +822,7 @@ protected GrailsClass addArtefact(String artefactType, Class artefactClass, b DefaultArtefactInfo info = getArtefactInfo(artefactType, true); if (overrideable) { info.addOverridableGrailsClass(artefactGrailsClass); - } - else { + } else { info.addGrailsClass(artefactGrailsClass); } info.updateComplete(); @@ -831,7 +832,7 @@ protected GrailsClass addArtefact(String artefactType, Class artefactClass, b if (isInitialised()) { initializeArtefacts(artefactType); ApplicationContext context = getMainContext(); - if(context instanceof ConfigurableApplicationContext && contextInitialized && ((ConfigurableApplicationContext) context).isActive()) { + if (context instanceof ConfigurableApplicationContext && contextInitialized && ((ConfigurableApplicationContext) context).isActive()) { context.publishEvent(new ArtefactAdditionEvent(artefactGrailsClass)); } @@ -840,15 +841,13 @@ protected GrailsClass addArtefact(String artefactType, Class artefactClass, b return artefactGrailsClass; } - - throw new GrailsConfigurationException("Cannot add " + artefactType + " class [" + artefactClass + "]. It is not a " + artefactType + "!"); } @Override public MappingContext getMappingContext() { - if(mappingContext != null) { + if (mappingContext != null) { return mappingContext; } return proxyMappingContext; diff --git a/grails-core/src/main/groovy/grails/core/GrailsApplication.java b/grails-core/src/main/groovy/grails/core/GrailsApplication.java index fbfb72d3233..79a4a665556 100644 --- a/grails-core/src/main/groovy/grails/core/GrailsApplication.java +++ b/grails-core/src/main/groovy/grails/core/GrailsApplication.java @@ -20,9 +20,6 @@ import grails.config.Config; import grails.util.Metadata; - -import java.util.Map; - import org.grails.datastore.mapping.model.MappingContext; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -40,12 +37,10 @@ *

Implementors of this interface should be aware that a GrailsApplication is only initialised when the initialise() method * is called. In other words GrailsApplication instances are lazily initialised by the Grails runtime. * - * @see #initialise() - * @see ArtefactHandler - * * @author Graeme Rocher * @author Steven Devijver - * + * @see #initialise() + * @see ArtefactHandler * @since 0.1 */ public interface GrailsApplication extends ApplicationContextAware { @@ -99,6 +94,7 @@ public interface GrailsApplication extends ApplicationContextAware { /** * Retrieves all java.lang.Class instances loaded by the Grails class loader + * * @return An array of classes */ @SuppressWarnings("rawtypes") @@ -106,6 +102,7 @@ public interface GrailsApplication extends ApplicationContextAware { /** * Retrieves all java.lang.Class instances considered Artefacts loaded by the Grails class loader + * * @return An array of classes */ @SuppressWarnings("rawtypes") @@ -175,6 +172,7 @@ public interface GrailsApplication extends ApplicationContextAware { /** *

Call this to find out if the class you have is an artefact loaded by grails.

+ * * @param theClazz A class to test * @return true if and only if the class was loaded from grails-app/ * @since 0.5 @@ -185,8 +183,9 @@ public interface GrailsApplication extends ApplicationContextAware { /** *

Check if the specified artefact Class has been loaded by Grails already AND is * of the type expected

+ * * @param artefactType A string identifying the artefact type to check for - * @param theClazz The class to check + * @param theClazz The class to check * @return true if Grails considers the class to be managed as an artefact of the type specified. * @since 0.5 */ @@ -195,8 +194,9 @@ public interface GrailsApplication extends ApplicationContextAware { /** *

Check if the artefact Class with the name specified is of the type expected

+ * * @param artefactType A string identifying the artefact type to check for - * @param className The name of a class to check + * @param className The name of a class to check * @return true if Grails considers the class to be managed as an artefact of the type specified. * @since 0.5 */ @@ -205,8 +205,9 @@ public interface GrailsApplication extends ApplicationContextAware { /** *

Gets the GrailsClass associated with the named artefact class

*

i.e. to get the GrailsClass for controller called "BookController" you pass the name "BookController"

+ * * @param artefactType The type of artefact to retrieve, i.e. "Controller" - * @param name The name of an artefact such as "BookController" + * @param name The name of an artefact such as "BookController" * @return The associated GrailsClass or null * @since 0.5 */ @@ -214,6 +215,7 @@ public interface GrailsApplication extends ApplicationContextAware { /** * Returns the ArtefactHandler for the given class or null + * * @param theClass The class * @return The ArtefactHandler */ @@ -222,6 +224,7 @@ public interface GrailsApplication extends ApplicationContextAware { /** *

Obtain all the class information about the artefactType specified

+ * * @param artefactType An artefact type identifier i.e. "Domain" * @return The artefact info or null if the artefactType is not recognized * @since 0.5 @@ -230,6 +233,7 @@ public interface GrailsApplication extends ApplicationContextAware { /** *

Get an array of all the GrailsClass instances relating to artefacts of the specified type.

+ * * @param artefactType The type of artefact to retrieve, i.e. "Controller" * @return An array of GrailsClasses which may empty by not null * @since 0.5 @@ -239,8 +243,9 @@ public interface GrailsApplication extends ApplicationContextAware { /** *

Get an artefact GrailsClass by a "feature" which depending on the artefact may be a URI or tag name * for example

+ * * @param artefactType The type ID of the artefact, i.e. "TagLib" - * @param featureID The "feature" ID, say a URL or tag name + * @param featureID The "feature" ID, say a URL or tag name * @return The grails class or null if none is found * @since 0.5 */ @@ -248,9 +253,10 @@ public interface GrailsApplication extends ApplicationContextAware { /** *

Registers a new artefact

- * @param artefactType The type ID of the artefact, i.e. "TagLib" + * + * @param artefactType The type ID of the artefact, i.e. "TagLib" * @param artefactClass The class of the artefact. A new GrailsClass will be created automatically and added - * to internal structures, using the appropriate ArtefactHandler + * to internal structures, using the appropriate ArtefactHandler * @return The new grails class for the artefact class * @since 0.5 */ @@ -259,7 +265,8 @@ public interface GrailsApplication extends ApplicationContextAware { /** *

Registers a new artefact

- * @param artefactType The type ID of the artefact, i.e. "TagLib" + * + * @param artefactType The type ID of the artefact, i.e. "TagLib" * @param artefactGrailsClass The GrailsClass of the artefact. * @return The supplied grails class for the artefact class * @since 0.5 @@ -268,12 +275,14 @@ public interface GrailsApplication extends ApplicationContextAware { /** *

Register a new artefact handler

+ * * @param handler The new handler to add */ void registerArtefactHandler(ArtefactHandler handler); /** *

Test whether an artefact handler exists for a given type

+ * * @param type The type of the handler * @return true if it does */ @@ -281,6 +290,7 @@ public interface GrailsApplication extends ApplicationContextAware { /** *

Obtain a list of all the artefact handlers

+ * * @return The list, possible empty but not null, of all currently registered handlers */ ArtefactHandler[] getArtefactHandlers(); @@ -292,6 +302,7 @@ public interface GrailsApplication extends ApplicationContextAware { /** * Returns whether this GrailsApplication has been initialised or not. + * * @return true if it has been initialised */ boolean isInitialised(); @@ -300,6 +311,7 @@ public interface GrailsApplication extends ApplicationContextAware { *

Get access to the project's metadata, specified in application.yml and grails.build.info if it is present

*

This provides access to information like required grails version, application name, version etc * but NOT general application settings.

+ * * @return A read-only Map of data about the application, not environment specific */ Metadata getMetadata(); @@ -307,7 +319,8 @@ public interface GrailsApplication extends ApplicationContextAware { /** * Retrieves an artefact by its logical property name. For example the logical property name of * BookController would be book. - * @param type The artefact type + * + * @param type The artefact type * @param logicalName The logical name * @return The GrailsClass or null if it doesn't exist */ @@ -315,6 +328,7 @@ public interface GrailsApplication extends ApplicationContextAware { /** * Adds the given artefact, attempting to determine type from + * * @param artefact The artefact to add */ @SuppressWarnings("rawtypes") @@ -329,6 +343,7 @@ public interface GrailsApplication extends ApplicationContextAware { /** * Adds an artefact that can be overriden by user defined classes + * * @param artefact An overridable artefact */ @SuppressWarnings("rawtypes") @@ -341,6 +356,7 @@ public interface GrailsApplication extends ApplicationContextAware { /** * Returns the ArtefactHandler for the given type + * * @param type The artefact handler type * @return The artefact handler */ diff --git a/grails-core/src/main/groovy/grails/core/GrailsApplicationClass.groovy b/grails-core/src/main/groovy/grails/core/GrailsApplicationClass.groovy index f8e50d80f3b..7437b674a34 100644 --- a/grails-core/src/main/groovy/grails/core/GrailsApplicationClass.groovy +++ b/grails-core/src/main/groovy/grails/core/GrailsApplicationClass.groovy @@ -26,5 +26,4 @@ package grails.core */ trait GrailsApplicationClass implements GrailsApplicationLifeCycle { - } \ No newline at end of file diff --git a/grails-core/src/main/groovy/grails/core/GrailsApplicationLifeCycleAdapter.groovy b/grails-core/src/main/groovy/grails/core/GrailsApplicationLifeCycleAdapter.groovy index 4abd8b00828..35477b641d9 100644 --- a/grails-core/src/main/groovy/grails/core/GrailsApplicationLifeCycleAdapter.groovy +++ b/grails-core/src/main/groovy/grails/core/GrailsApplicationLifeCycleAdapter.groovy @@ -21,7 +21,6 @@ package grails.core import groovy.transform.CompileStatic - /** * Adapter for the {@link GrailsApplicationLifeCycle} interface * @@ -30,9 +29,10 @@ import groovy.transform.CompileStatic */ @CompileStatic class GrailsApplicationLifeCycleAdapter implements GrailsApplicationLifeCycle { + @Override Closure doWithSpring() { - return {->} + return { -> } } @Override diff --git a/grails-core/src/main/groovy/grails/core/GrailsClass.java b/grails-core/src/main/groovy/grails/core/GrailsClass.java index d79479e3ff1..e7c41656b91 100644 --- a/grails-core/src/main/groovy/grails/core/GrailsClass.java +++ b/grails-core/src/main/groovy/grails/core/GrailsClass.java @@ -18,9 +18,8 @@ */ package grails.core; -import groovy.lang.MetaClass; - import grails.core.support.GrailsApplicationAware; +import groovy.lang.MetaClass; /** * Represents any class in a Grails application. @@ -29,7 +28,7 @@ * @author Graeme Rocher * @since 0.1 */ -public interface GrailsClass extends GrailsApplicationAware{ +public interface GrailsClass extends GrailsApplicationAware { /** * Whether the class is abstract or not @@ -47,6 +46,7 @@ public interface GrailsClass extends GrailsApplicationAware{ /** * Gets the initial value of the given property on the class. + * * @param name The name of the property * @return The initial value */ @@ -54,6 +54,7 @@ public interface GrailsClass extends GrailsApplicationAware{ /** * Returns true if the class has the specified property. + * * @param name The name of the property * @return true if it does */ @@ -61,8 +62,9 @@ public interface GrailsClass extends GrailsApplicationAware{ /** * Creates a new instance of this class. - * + *

* This method can be used as factory method in the Spring application context. + * * @return A new instance of this class */ Object newInstance(); @@ -106,6 +108,7 @@ public interface GrailsClass extends GrailsApplicationAware{ /** * Returns the name of the property in natural terms (eg. 'lastName' becomes 'Last Name') + * * @return The natural property name. */ String getNaturalName(); @@ -137,9 +140,9 @@ public interface GrailsClass extends GrailsApplicationAware{ /** * Obtains a property value for the given name and type + * * @param name The name * @param type The type - * * @return The property value */ T getPropertyValue(String name, Class type); diff --git a/grails-core/src/main/groovy/grails/core/GrailsControllerClass.java b/grails-core/src/main/groovy/grails/core/GrailsControllerClass.java index 3495af179db..dab75c1cbce 100644 --- a/grails-core/src/main/groovy/grails/core/GrailsControllerClass.java +++ b/grails-core/src/main/groovy/grails/core/GrailsControllerClass.java @@ -27,7 +27,6 @@ * * @author Steven Devijver * @author Graeme Rocher - * * @since 1.0 */ public interface GrailsControllerClass extends InjectableGrailsClass { @@ -67,7 +66,6 @@ public interface GrailsControllerClass extends InjectableGrailsClass { */ String NAMESPACE_PROPERTY = "namespace"; - /** * @return The action names */ @@ -88,7 +86,6 @@ public interface GrailsControllerClass extends InjectableGrailsClass { */ boolean isSingleton(); - /** * Returns the default action for this Controller. * @@ -100,23 +97,24 @@ public interface GrailsControllerClass extends InjectableGrailsClass { * Initialize the controller class */ void initialize(); + /** * Tests if a controller maps to a given URI. * * @return true if controller maps to URI */ boolean mapsToURI(String uri); + /** * Invokes a controller action on the given controller instance * * @param controller The controller instance - * @param action The action + * @param action The action * @return The result of the action * @throws Throwable Thrown when an error occurs invoking the action */ Object invoke(Object controller, String action) throws Throwable; - /** * Register a new {@link grails.web.UrlConverter} with the controller * diff --git a/grails-core/src/main/groovy/grails/core/GrailsDataSource.java b/grails-core/src/main/groovy/grails/core/GrailsDataSource.java index 25ed40b30d6..acff3c29dab 100644 --- a/grails-core/src/main/groovy/grails/core/GrailsDataSource.java +++ b/grails-core/src/main/groovy/grails/core/GrailsDataSource.java @@ -71,6 +71,7 @@ public interface GrailsDataSource extends InjectableGrailsClass { /** * Whether to generate the database with HBM 2 DDL, values can be "create", "create-drop" or "update". + * * @return The dbCreate method to use */ String getDbCreate(); @@ -83,6 +84,7 @@ public interface GrailsDataSource extends InjectableGrailsClass { /** * The dialect implementation to use. + * * @return The dialect class or null if none configured */ @SuppressWarnings("rawtypes") diff --git a/grails-core/src/main/groovy/grails/core/GrailsDomainClass.java b/grails-core/src/main/groovy/grails/core/GrailsDomainClass.java index 6415a49a32c..76cc0c789f7 100644 --- a/grails-core/src/main/groovy/grails/core/GrailsDomainClass.java +++ b/grails-core/src/main/groovy/grails/core/GrailsDomainClass.java @@ -18,17 +18,15 @@ */ package grails.core; -import java.util.Map; -import java.util.Set; - import org.springframework.validation.Validator; +import java.util.Map; + /** * Represents a persistable Grails domain class. * * @author Graeme Rocher * @since Jul 5, 2005 - * * @deprecated Use {@link org.grails.datastore.mapping.model.PersistentEntity} instead */ @Deprecated @@ -45,6 +43,7 @@ public interface GrailsDomainClass extends GrailsClass { * @return Whether to autowire */ boolean isAutowire(); + /** * @param domainClass * @return true if the specifying domain class is on the owning side of a relationship diff --git a/grails-core/src/main/groovy/grails/core/GrailsServiceClass.java b/grails-core/src/main/groovy/grails/core/GrailsServiceClass.java index e5888174773..5726c55f9e0 100644 --- a/grails-core/src/main/groovy/grails/core/GrailsServiceClass.java +++ b/grails-core/src/main/groovy/grails/core/GrailsServiceClass.java @@ -36,12 +36,14 @@ public interface GrailsServiceClass extends InjectableGrailsClass { /** * Get the datasource name that this service class works with. + * * @return the name */ String getDatasource(); /** * Check if the service class can use the named DataSource. + * * @param name the name */ boolean usesDatasource(String name); diff --git a/grails-core/src/main/groovy/grails/core/GrailsUrlMappingsClass.java b/grails-core/src/main/groovy/grails/core/GrailsUrlMappingsClass.java index 1e0f21f3293..c386459d03a 100644 --- a/grails-core/src/main/groovy/grails/core/GrailsUrlMappingsClass.java +++ b/grails-core/src/main/groovy/grails/core/GrailsUrlMappingsClass.java @@ -37,7 +37,8 @@ public interface GrailsUrlMappingsClass extends GrailsClass { /** * Returns a List of URI patterns to exclude. - * @return the patterns (Strings) + * + * @return the patterns (Strings) */ @SuppressWarnings("rawtypes") List getExcludePatterns(); diff --git a/grails-core/src/main/groovy/grails/core/events/ArtefactAdditionEvent.groovy b/grails-core/src/main/groovy/grails/core/events/ArtefactAdditionEvent.groovy index 20cf92e1357..2668d02e67c 100644 --- a/grails-core/src/main/groovy/grails/core/events/ArtefactAdditionEvent.groovy +++ b/grails-core/src/main/groovy/grails/core/events/ArtefactAdditionEvent.groovy @@ -19,15 +19,15 @@ package grails.core.events -import groovy.transform.CompileStatic import grails.core.GrailsClass +import groovy.transform.CompileStatic import org.springframework.context.ApplicationEvent /** * An event triggered for the addition of a new artefact */ @CompileStatic -class ArtefactAdditionEvent extends ApplicationEvent{ +class ArtefactAdditionEvent extends ApplicationEvent { /** * Create a new ApplicationEvent. * @param source the component that published the event (never {@code null}) @@ -37,6 +37,6 @@ class ArtefactAdditionEvent extends ApplicationEvent{ } GrailsClass getArtefact() { - (GrailsClass)source + (GrailsClass) source } } diff --git a/grails-core/src/main/groovy/grails/core/support/GrailsApplicationAware.java b/grails-core/src/main/groovy/grails/core/support/GrailsApplicationAware.java index b90b688d2a6..94078af300c 100644 --- a/grails-core/src/main/groovy/grails/core/support/GrailsApplicationAware.java +++ b/grails-core/src/main/groovy/grails/core/support/GrailsApplicationAware.java @@ -26,10 +26,11 @@ * registered by plugins.

* * @author Steven Devijver - * @since 0.2 * @see GrailsApplication + * @since 0.2 */ public interface GrailsApplicationAware extends Aware { + /** *

This method is called by the {@link org.springframework.context.ApplicationContext} that * loads the Grails application. The {@link GrailsApplication} instance that represents diff --git a/grails-core/src/main/groovy/grails/core/support/GrailsConfigurationAware.java b/grails-core/src/main/groovy/grails/core/support/GrailsConfigurationAware.java index 87409703684..f9746ae3b69 100644 --- a/grails-core/src/main/groovy/grails/core/support/GrailsConfigurationAware.java +++ b/grails-core/src/main/groovy/grails/core/support/GrailsConfigurationAware.java @@ -21,7 +21,6 @@ import grails.config.Config; import org.springframework.beans.factory.Aware; - /** * Obtains the Grails ConfigObject via Spring. * diff --git a/grails-core/src/main/groovy/grails/core/support/ParentApplicationContextAware.java b/grails-core/src/main/groovy/grails/core/support/ParentApplicationContextAware.java index ed622109196..e4b89ee4571 100644 --- a/grails-core/src/main/groovy/grails/core/support/ParentApplicationContextAware.java +++ b/grails-core/src/main/groovy/grails/core/support/ParentApplicationContextAware.java @@ -27,6 +27,7 @@ * @author Graeme Rocher * @since 0.4 */ -public interface ParentApplicationContextAware extends Aware { +public interface ParentApplicationContextAware extends Aware { + void setParentApplicationContext(ApplicationContext parent); } diff --git a/grails-core/src/main/groovy/grails/core/support/proxy/EntityProxyHandler.java b/grails-core/src/main/groovy/grails/core/support/proxy/EntityProxyHandler.java index cf90b61e652..26f12615f86 100644 --- a/grails-core/src/main/groovy/grails/core/support/proxy/EntityProxyHandler.java +++ b/grails-core/src/main/groovy/grails/core/support/proxy/EntityProxyHandler.java @@ -24,7 +24,7 @@ * @author Graeme Rocher * @since 1.3.6 */ -public interface EntityProxyHandler extends ProxyHandler{ +public interface EntityProxyHandler extends ProxyHandler { /** * This method returns the identifier of the proxy or null if the diff --git a/grails-core/src/main/groovy/grails/core/support/proxy/ProxyHandler.java b/grails-core/src/main/groovy/grails/core/support/proxy/ProxyHandler.java index 1f8978be36f..1c07bd3db52 100644 --- a/grails-core/src/main/groovy/grails/core/support/proxy/ProxyHandler.java +++ b/grails-core/src/main/groovy/grails/core/support/proxy/ProxyHandler.java @@ -28,6 +28,7 @@ public interface ProxyHandler { /** * Returns true if the specified object is a proxy. + * * @param o The object in question * @return true if it is a proxy */ @@ -51,13 +52,15 @@ public interface ProxyHandler { /** * Initializes an existing uninitialized proxy instance. + * * @param o The proxy instance */ void initialize(Object o); /** * Tests whether an association of the given object has been initialized. - * @param obj The object to check + * + * @param obj The object to check * @param associationName The association * @return true if has been init */ diff --git a/grails-core/src/main/groovy/grails/dev/commands/ApplicationCommand.groovy b/grails-core/src/main/groovy/grails/dev/commands/ApplicationCommand.groovy index d56d756305a..40930b1f857 100644 --- a/grails-core/src/main/groovy/grails/dev/commands/ApplicationCommand.groovy +++ b/grails-core/src/main/groovy/grails/dev/commands/ApplicationCommand.groovy @@ -48,7 +48,7 @@ trait ApplicationCommand implements Named, Described { @Override String getName() { - return GrailsNameUtils.getScriptName( GrailsNameUtils.getLogicalName(getClass().getName(),"Command") ) + return GrailsNameUtils.getScriptName(GrailsNameUtils.getLogicalName(getClass().getName(), "Command")) } @Override diff --git a/grails-core/src/main/groovy/grails/dev/commands/ApplicationContextCommandRegistry.groovy b/grails-core/src/main/groovy/grails/dev/commands/ApplicationContextCommandRegistry.groovy index c6c5a30e714..51a207df2d1 100644 --- a/grails-core/src/main/groovy/grails/dev/commands/ApplicationContextCommandRegistry.groovy +++ b/grails-core/src/main/groovy/grails/dev/commands/ApplicationContextCommandRegistry.groovy @@ -35,7 +35,7 @@ class ApplicationContextCommandRegistry { def registeredCommands = GrailsFactoriesLoader.loadFactories(ApplicationCommand) def iterator = registeredCommands.iterator() - while(iterator.hasNext()) { + while (iterator.hasNext()) { def cmd = iterator.next() commands[cmd.name] = cmd } diff --git a/grails-core/src/main/groovy/grails/dev/commands/GrailsApplicationCommand.groovy b/grails-core/src/main/groovy/grails/dev/commands/GrailsApplicationCommand.groovy index c5bd918fc78..37de9463904 100644 --- a/grails-core/src/main/groovy/grails/dev/commands/GrailsApplicationCommand.groovy +++ b/grails-core/src/main/groovy/grails/dev/commands/GrailsApplicationCommand.groovy @@ -27,8 +27,10 @@ import grails.dev.commands.template.TemplateRendererImpl trait GrailsApplicationCommand implements ApplicationCommand, ModelBuilder { - @Delegate TemplateRenderer templateRenderer - @Delegate FileSystemInteraction fileSystemInteraction + @Delegate + TemplateRenderer templateRenderer + @Delegate + FileSystemInteraction fileSystemInteraction ExecutionContext executionContext boolean handle(ExecutionContext executionContext) { diff --git a/grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteraction.groovy b/grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteraction.groovy index 3a9f461240e..ba1c315d64f 100644 --- a/grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteraction.groovy +++ b/grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteraction.groovy @@ -20,7 +20,6 @@ package grails.dev.commands.io import org.grails.io.support.Resource - /** * Utility methods exposed to scripts for interacting with resources (found on the file system or jars) and the file system * @@ -123,7 +122,7 @@ interface FileSystemInteraction { * @return The class name */ String className(Resource resource) - + /** * Get files matching the given pattern * @@ -133,11 +132,14 @@ interface FileSystemInteraction { Collection files(String pattern) static class CopySpec { + def from def into + void from(path) { this.from = path } + void into(path) { this.into = path } diff --git a/grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteractionImpl.groovy b/grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteractionImpl.groovy index de5af7b4473..1cbbfa199c6 100644 --- a/grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteractionImpl.groovy +++ b/grails-core/src/main/groovy/grails/dev/commands/io/FileSystemInteractionImpl.groovy @@ -20,7 +20,14 @@ package grails.dev.commands.io import grails.util.BuildSettings import groovy.transform.CompileStatic -import org.grails.io.support.* +import org.grails.io.support.DefaultResourceLoader +import org.grails.io.support.FileSystemResource +import org.grails.io.support.GrailsResourceUtils +import org.grails.io.support.PathMatchingResourcePatternResolver +import org.grails.io.support.Resource +import org.grails.io.support.ResourceLoader +import org.grails.io.support.ResourceLocator +import org.grails.io.support.SpringIOUtils /** * Utility methods exposed to scripts for interacting with resources (found on the file system or jars) and the file system @@ -44,7 +51,6 @@ class FileSystemInteractionImpl implements FileSystemInteraction { this.resourcePatternResolver = new PathMatchingResourcePatternResolver(resourceLoader) } - /** * Makes a directory * @@ -78,11 +84,10 @@ class FileSystemInteractionImpl implements FileSystemInteraction { FileSystemInteraction.CopySpec spec = new FileSystemInteraction.CopySpec() callable.delegate = spec callable.call() - if(spec.from && spec.into) { - if(spec.from instanceof Iterable) { - copyAll((Iterable)spec.from, spec.into) - } - else { + if (spec.from && spec.into) { + if (spec.from instanceof Iterable) { + copyAll((Iterable) spec.from, spec.into) + } else { copy(spec.from, spec.into) } } @@ -111,7 +116,7 @@ class FileSystemInteractionImpl implements FileSystemInteraction { @Override FileSystemInteractionImpl copyAll(Iterable resources, destination) { mkdir(destination) - for(path in resources) { + for (path in resources) { def from = resource(path) def to = file(destination) copy(from, to) @@ -128,7 +133,7 @@ class FileSystemInteractionImpl implements FileSystemInteraction { */ @Override FileSystemInteractionImpl copy(Resource from, File to) { - if(!to?.exists()) mkdir(to) + if (!to?.exists()) mkdir(to) if (from && to) { if (to.isDirectory()) { mkdir(to) @@ -148,8 +153,8 @@ class FileSystemInteractionImpl implements FileSystemInteraction { */ @Override File file(Object path) { - if(path instanceof File) return (File)path - else if(path instanceof Resource) return ((Resource)path).file + if (path instanceof File) return (File) path + else if (path instanceof Resource) return ((Resource) path).file else { new File(baseDir ?: new File("."), path.toString()) } @@ -206,24 +211,21 @@ class FileSystemInteractionImpl implements FileSystemInteraction { */ @Override Resource resource(Object path) { - if(!path) return null - if(path instanceof Resource) return (Resource)path + if (!path) return null + if (path instanceof Resource) return (Resource) path def f = file(path) - if(f?.exists() && f.isFile()) { + if (f?.exists() && f.isFile()) { return new FileSystemResource(f) - } - else { + } else { def pathStr = path.toString() def resource = resourceLoader.getResource(pathStr) - if(resource.exists()) { + if (resource.exists()) { return resource - } - else { + } else { def allResources = resources(pathStr) - if(allResources) { + if (allResources) { return allResources[0] - } - else { + } else { return resource } } @@ -254,7 +256,7 @@ class FileSystemInteractionImpl implements FileSystemInteraction { @Override String projectPath(Object path) { def file = file(path) - if(file) { + if (file) { def basePath = baseDir.canonicalPath return (file.canonicalPath - basePath).substring(1) } @@ -272,5 +274,4 @@ class FileSystemInteractionImpl implements FileSystemInteraction { resources(pattern).collect() { Resource res -> res.file } } - } diff --git a/grails-core/src/main/groovy/grails/dev/commands/template/TemplateException.groovy b/grails-core/src/main/groovy/grails/dev/commands/template/TemplateException.groovy index b3062dc9bb5..97f4ac1a030 100644 --- a/grails-core/src/main/groovy/grails/dev/commands/template/TemplateException.groovy +++ b/grails-core/src/main/groovy/grails/dev/commands/template/TemplateException.groovy @@ -20,7 +20,6 @@ package grails.dev.commands.template import groovy.transform.InheritConstructors - /** * Exception thrown when an error in template rendering occurs * diff --git a/grails-core/src/main/groovy/grails/dev/commands/template/TemplateRenderer.groovy b/grails-core/src/main/groovy/grails/dev/commands/template/TemplateRenderer.groovy index 7a6d928d584..9d24662c4cd 100644 --- a/grails-core/src/main/groovy/grails/dev/commands/template/TemplateRenderer.groovy +++ b/grails-core/src/main/groovy/grails/dev/commands/template/TemplateRenderer.groovy @@ -53,7 +53,7 @@ interface TemplateRenderer { * @param destination The destination * @param model The model */ - void render(CharSequence template, File destination ) + void render(CharSequence template, File destination) /** * Render the given template to the given destination @@ -62,7 +62,7 @@ interface TemplateRenderer { * @param destination The destination * @param model The model */ - void render(CharSequence template, File destination, Map model ) + void render(CharSequence template, File destination, Map model) /** * Render the given template to the given destination * @@ -97,7 +97,7 @@ interface TemplateRenderer { * @param destination The destination * @param model The model */ - void render(File template, File destination, Map model ) + void render(File template, File destination, Map model) /** * Render the given template to the given destination @@ -117,7 +117,6 @@ interface TemplateRenderer { */ void render(Resource template, File destination, Model model) - /** * Render the given template to the give destination for the given model * diff --git a/grails-core/src/main/groovy/grails/dev/commands/template/TemplateRendererImpl.groovy b/grails-core/src/main/groovy/grails/dev/commands/template/TemplateRendererImpl.groovy index 2400ccd2bf8..c747feafbb9 100644 --- a/grails-core/src/main/groovy/grails/dev/commands/template/TemplateRendererImpl.groovy +++ b/grails-core/src/main/groovy/grails/dev/commands/template/TemplateRendererImpl.groovy @@ -39,7 +39,8 @@ import org.grails.io.support.ResourceLoader @CompileStatic class TemplateRendererImpl implements TemplateRenderer { - @Delegate FileSystemInteraction fileSystemInteraction + @Delegate + FileSystemInteraction fileSystemInteraction protected Map templateCache = [:] TemplateRendererImpl(File baseDir, ResourceLoader resourceLoader = new DefaultResourceLoader()) { @@ -223,7 +224,6 @@ class TemplateRendererImpl implements TemplateRenderer { return resource(f) } - protected static void writeTemplateToDestination(Template template, Map model, File destination) { destination.parentFile.mkdirs() destination.withWriter { BufferedWriter w -> diff --git a/grails-core/src/main/groovy/grails/persistence/Entity.java b/grails-core/src/main/groovy/grails/persistence/Entity.java index a5ed2a87ae8..5db9ca29b72 100644 --- a/grails-core/src/main/groovy/grails/persistence/Entity.java +++ b/grails-core/src/main/groovy/grails/persistence/Entity.java @@ -18,13 +18,13 @@ */ package grails.persistence; +import org.codehaus.groovy.transform.GroovyASTTransformationClass; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.codehaus.groovy.transform.GroovyASTTransformationClass; - /** * A class annotation used to make a class into a GORM domain class. * diff --git a/grails-core/src/main/groovy/grails/persistence/Event.java b/grails-core/src/main/groovy/grails/persistence/Event.java index 92a183a9b4c..cbe77fc26b9 100644 --- a/grails-core/src/main/groovy/grails/persistence/Event.java +++ b/grails-core/src/main/groovy/grails/persistence/Event.java @@ -30,19 +30,21 @@ public enum Event { onLoad, onSave, beforeLoad, beforeInsert, beforeUpdate, beforeDelete, afterLoad, afterInsert, afterUpdate, afterDelete; - private static final String[] allEvents; + private static final String[] ALL_EVENTS; + static { List events = new ArrayList(); for (Event e : values()) { events.add(e.toString()); } - allEvents = events.toArray(new String[events.size()]); + ALL_EVENTS = events.toArray(new String[events.size()]); } + /** * @return The names of all persistence events */ public static String[] getAllEvents() { - return allEvents; + return ALL_EVENTS; } } diff --git a/grails-core/src/main/groovy/grails/persistence/PersistenceMethod.java b/grails-core/src/main/groovy/grails/persistence/PersistenceMethod.java index a1e86f8e28d..395e8733507 100644 --- a/grails-core/src/main/groovy/grails/persistence/PersistenceMethod.java +++ b/grails-core/src/main/groovy/grails/persistence/PersistenceMethod.java @@ -32,4 +32,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface PersistenceMethod { + } diff --git a/grails-core/src/main/groovy/grails/persistence/support/NullPersistentContextInterceptor.java b/grails-core/src/main/groovy/grails/persistence/support/NullPersistentContextInterceptor.java index 68e7948cf37..5002b0feffa 100644 --- a/grails-core/src/main/groovy/grails/persistence/support/NullPersistentContextInterceptor.java +++ b/grails-core/src/main/groovy/grails/persistence/support/NullPersistentContextInterceptor.java @@ -25,6 +25,7 @@ * @since 1.1.1 */ public class NullPersistentContextInterceptor implements PersistenceContextInterceptor { + public void init() { // NOOP } diff --git a/grails-core/src/main/groovy/grails/persistence/support/PersistenceContextInterceptor.java b/grails-core/src/main/groovy/grails/persistence/support/PersistenceContextInterceptor.java index 22b75b09484..c0b00c6b6f7 100644 --- a/grails-core/src/main/groovy/grails/persistence/support/PersistenceContextInterceptor.java +++ b/grails-core/src/main/groovy/grails/persistence/support/PersistenceContextInterceptor.java @@ -47,7 +47,7 @@ public interface PersistenceContextInterceptor { void reconnect(); /** - * Flushes any pending changes to the DB. + * Flushes any pending changes to the DB. */ void flush(); @@ -68,6 +68,7 @@ public interface PersistenceContextInterceptor { /** * Checks whether the persistence context is open. + * * @return Returns whether the persistence context is open */ boolean isOpen(); diff --git a/grails-core/src/main/groovy/grails/persistence/support/PersistenceContextInterceptorExecutor.groovy b/grails-core/src/main/groovy/grails/persistence/support/PersistenceContextInterceptorExecutor.groovy index 34355c84523..0eecde74663 100644 --- a/grails-core/src/main/groovy/grails/persistence/support/PersistenceContextInterceptorExecutor.groovy +++ b/grails-core/src/main/groovy/grails/persistence/support/PersistenceContextInterceptorExecutor.groovy @@ -45,7 +45,6 @@ class PersistenceContextInterceptorExecutor { destroyPersistenceContextInternal(persistenceContextInterceptors) } - static void initPersistenceContext(ApplicationContext appCtx) { if (appCtx) { final interceptors = appCtx.getBeansOfType(PersistenceContextInterceptor).values() @@ -76,5 +75,4 @@ class PersistenceContextInterceptorExecutor { } } - } diff --git a/grails-core/src/main/groovy/grails/plugins/DefaultGrailsPluginManager.java b/grails-core/src/main/groovy/grails/plugins/DefaultGrailsPluginManager.java index edaddd842ce..3e258fe2ca2 100644 --- a/grails-core/src/main/groovy/grails/plugins/DefaultGrailsPluginManager.java +++ b/grails-core/src/main/groovy/grails/plugins/DefaultGrailsPluginManager.java @@ -210,11 +210,15 @@ public void informObservers(String pluginName, Map event) { if (plugin == null) { return; } - if (!plugin.isEnabled(applicationContext.getEnvironment().getActiveProfiles())) return; + if (!plugin.isEnabled(applicationContext.getEnvironment().getActiveProfiles())) { + return; + } for (GrailsPlugin observingPlugin : getPluginObservers(plugin)) { - if (!observingPlugin.isEnabled(applicationContext.getEnvironment().getActiveProfiles())) continue; + if (!observingPlugin.isEnabled(applicationContext.getEnvironment().getActiveProfiles())) { + continue; + } observingPlugin.notifyOfEvent(event); } @@ -245,22 +249,6 @@ public void loadPlugins() throws PluginException { } protected List sortPlugins(List toSort) { - /* http://en.wikipedia.org/wiki/Topological_sorting - * - * L <- Empty list that will contain the sorted nodes - S <- Set of all nodes - - function visit(node n) - if n has not been visited yet then - mark n as visited - for each node m with an edge from n to m do - visit(m) - add n to L - - for each node n in S do - visit(n) - - */ List sortedPlugins = new ArrayList(toSort.size()); Set visitedPlugins = new HashSet(); Map> loadOrderDependencies = resolveLoadDependencies(toSort); @@ -575,7 +563,9 @@ private boolean hasDelayedDependencies(GrailsPlugin other) { String[] dependencyNames = other.getDependencyNames(); for (String dependencyName : dependencyNames) { for (GrailsPlugin grailsPlugin : delayedLoadPlugins) { - if (grailsPlugin.getName().equals(dependencyName)) return true; + if (grailsPlugin.getName().equals(dependencyName)) { + return true; + } } } return false; @@ -593,8 +583,9 @@ private boolean isDependentOn(GrailsPlugin plugin, GrailsPlugin dependency) { String requiredVersion = plugin.getDependentVersion(name); if (name.equals(dependency.getName()) && - GrailsVersionUtils.isValidVersion(dependency.getVersion(), requiredVersion)) + GrailsVersionUtils.isValidVersion(dependency.getVersion(), requiredVersion)) { return true; + } } return false; } @@ -760,8 +751,8 @@ public void doDynamicMethods() { checkInitialised(); // remove common meta classes just to be sure MetaClassRegistry registry = GroovySystem.getMetaClassRegistry(); - for (Class COMMON_CLASS : COMMON_CLASSES) { - registry.removeMetaClass(COMMON_CLASS); + for (Class commonClass : COMMON_CLASSES) { + registry.removeMetaClass(commonClass); } for (GrailsPlugin plugin : pluginList) { if (plugin.supportsCurrentScopeAndEnvironment()) { diff --git a/grails-core/src/main/groovy/grails/plugins/GrailsPlugin.java b/grails-core/src/main/groovy/grails/plugins/GrailsPlugin.java index 2732abc8865..c09a6c69c5f 100644 --- a/grails-core/src/main/groovy/grails/plugins/GrailsPlugin.java +++ b/grails-core/src/main/groovy/grails/plugins/GrailsPlugin.java @@ -45,9 +45,8 @@ * * @author Steven Devijver * @author Graeme Rocher - * - * @since 0.2 * @see org.springframework.beans.factory.support.BeanDefinitionRegistry + * @since 0.2 */ @SuppressWarnings("rawtypes") public interface GrailsPlugin extends ApplicationContextAware, Comparable, GrailsPluginInfo { @@ -194,15 +193,16 @@ public interface GrailsPlugin extends ApplicationContextAware, Comparable, Grail */ void doWithRuntimeConfiguration(RuntimeSpringConfiguration springConfig); - /** * Makes the plugin excluded for a particular Environment + * * @param env The Environment */ void addExclude(Environment env); /** * Returns whether this plugin supports the given environment name + * * @param environment The environment name * @return true if it does */ @@ -262,7 +262,6 @@ public interface GrailsPlugin extends ApplicationContextAware, Comparable, Grail */ String getDependentVersion(String name); - PropertySource getPropertySource(); /** @@ -272,12 +271,14 @@ public interface GrailsPlugin extends ApplicationContextAware, Comparable, Grail /** * Retrieves the plugin manager if known, otherwise returns null + * * @return The PluginManager or null */ GrailsPluginManager getManager(); /** * Retrieves the wrapped plugin instance for this plugin + * * @return The plugin instance */ GroovyObject getInstance(); @@ -293,6 +294,7 @@ public interface GrailsPlugin extends ApplicationContextAware, Comparable, Grail /** * Calls a "doWithDynamicMethods" closure that allows a plugin to register dynamic methods at runtime + * * @param applicationContext The Spring ApplicationContext instance */ void doWithDynamicMethods(ApplicationContext applicationContext); @@ -304,6 +306,7 @@ public interface GrailsPlugin extends ApplicationContextAware, Comparable, Grail /** * Check whether the plugin is enabled for the given profile + * * @param activeProfiles * @return True if it is */ @@ -327,7 +330,7 @@ public interface GrailsPlugin extends ApplicationContextAware, Comparable, Grail * Notifies the plugin of a specific event for the given event id, which is one of ON_CHANGE, ON_CONFIG_CHANGE * * @param eventKind The event kind - * @param source The source of the event + * @param source The source of the event * @return a Map that represents the event */ Map notifyOfEvent(int eventKind, Object source); @@ -351,24 +354,28 @@ public interface GrailsPlugin extends ApplicationContextAware, Comparable, Grail /** * Returns the name of the plugin as represented in the file system including the version. For example TagLibGrailsPlugin would result in "tag-lib-0.1" + * * @return The file system representation of the plugin name */ String getFileSystemName(); /** * Returns the name of the plugin as represented on the file system without the version. For example TagLibGrailsPlugin would result in "tag-lib" + * * @return The file system name */ String getFileSystemShortName(); /** * Returns the underlying class that represents this plugin + * * @return The plugin class */ Class getPluginClass(); /** * A list of resources that the plugin should exclude from the packaged distribution + * * @return a List of resources */ List getPluginExcludes(); @@ -392,6 +399,7 @@ public interface GrailsPlugin extends ApplicationContextAware, Comparable, Grail /** * Plugin can provide a list of Spring TypeFilters so that annotated components can * be scanned into the ApplicationContext + * * @return A collection of TypeFilter instance */ Collection getTypeFilters(); diff --git a/grails-core/src/main/groovy/grails/plugins/GrailsPluginManager.java b/grails-core/src/main/groovy/grails/plugins/GrailsPluginManager.java index 864209e6a49..fee6eb5dc49 100644 --- a/grails-core/src/main/groovy/grails/plugins/GrailsPluginManager.java +++ b/grails-core/src/main/groovy/grails/plugins/GrailsPluginManager.java @@ -18,17 +18,18 @@ */ package grails.plugins; -import java.io.File; -import java.util.Collection; -import java.util.List; -import java.util.Map; import grails.core.GrailsApplication; -import org.grails.spring.RuntimeSpringConfiguration; import grails.plugins.exceptions.PluginException; +import org.grails.spring.RuntimeSpringConfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.type.filter.TypeFilter; +import java.io.File; +import java.util.Collection; +import java.util.List; +import java.util.Map; + /** *

Handles the loading and management of plug-ins in the Grails system. * A plugin a just like a normal Grails application except that it contains a file ending @@ -46,7 +47,7 @@ *

The doWithWebDescriptor uses mark-up building to provide additional functionality to the web.xml * file * - *

Example: + *

Example: *

  * class ClassEditorGrailsPlugin {
  *      def version = 1.1
@@ -68,12 +69,14 @@ public interface GrailsPluginManager extends ApplicationContextAware {
 
     /**
      * Returns an array of all the loaded plug-ins
+     *
      * @return An array of plug-ins
      */
     GrailsPlugin[] getAllPlugins();
 
     /**
      * Gets plugin installed by the user and not provided by the framework
+     *
      * @return A list of user plugins
      */
     GrailsPlugin[] getUserPlugins();
@@ -128,6 +131,7 @@ public interface GrailsPluginManager extends ApplicationContextAware {
 
     /**
      * Obtains a GrailsPlugin for the given classname
+     *
      * @param name The name of the plugin
      * @return The instance
      */
@@ -151,7 +155,7 @@ public interface GrailsPluginManager extends ApplicationContextAware {
     /**
      * Retrieves a plug-in for its name and version
      *
-     * @param name The name of the plugin
+     * @param name    The name of the plugin
      * @param version The version of the plugin
      * @return The GrailsPlugin instance or null if it doesn't exist
      */
@@ -160,13 +164,14 @@ public interface GrailsPluginManager extends ApplicationContextAware {
     /**
      * Executes the runtime configuration for a specific plugin AND all its dependencies
      *
-     * @param pluginName The name of he plugin
+     * @param pluginName   The name of he plugin
      * @param springConfig The runtime spring config instance
      */
     void doRuntimeConfiguration(String pluginName, RuntimeSpringConfiguration springConfig);
 
     /**
      * Sets the GrailsApplication used be this plugin manager
+     *
      * @param application The GrailsApplication instance
      */
     void setApplication(GrailsApplication application);
@@ -197,7 +202,7 @@ public interface GrailsPluginManager extends ApplicationContextAware {
      * inform the specified plugins observers of the event specified by the passed Map instance
      *
      * @param pluginName The name of the plugin
-     * @param event The event
+     * @param event      The event
      */
     @SuppressWarnings("rawtypes")
     void informObservers(String pluginName, Map event);
@@ -224,18 +229,21 @@ public interface GrailsPluginManager extends ApplicationContextAware {
 
     /**
      * Set whether the core plugins should be loaded
+     *
      * @param shouldLoadCorePlugins True if they should
      */
     void setLoadCorePlugins(boolean shouldLoadCorePlugins);
 
     /**
      * Method for handling changes to a class and triggering on change events etc.
+     *
      * @param aClass The class
      */
     void informOfClassChange(Class aClass);
 
     /**
      * Get all of the TypeFilter definitions defined by the plugins
+     *
      * @return A list of TypeFilter definitions
      */
     List getTypeFilters();
@@ -250,10 +258,10 @@ public interface GrailsPluginManager extends ApplicationContextAware {
 
     /**
      * Returns the pluginContextPath for the given plugin and will force name to camel case instead of '-' lower case
-     *
+     * 

* my-plug-web would resolve to myPlugWeb if forceCamelCase is true. * - * @param name The plugin name + * @param name The plugin name * @param forceCamelCase Force camel case for name * @return the context path */ @@ -270,6 +278,7 @@ public interface GrailsPluginManager extends ApplicationContextAware { /** * Returns the pluginContextPath for the given instance + * * @param instance The instance * @return The pluginContextPath */ @@ -277,6 +286,7 @@ public interface GrailsPluginManager extends ApplicationContextAware { /** * Returns the plugin path for the given class + * * @param theClass The class * @return The pluginContextPath */ @@ -284,6 +294,7 @@ public interface GrailsPluginManager extends ApplicationContextAware { /** * Returns the plugin views directory for the given instance + * * @param instance The instance * @return The pluginContextPath */ @@ -291,6 +302,7 @@ public interface GrailsPluginManager extends ApplicationContextAware { /** * Returns the plugin views directory path for the given class + * * @param theClass The class * @return The pluginContextPath */ @@ -321,6 +333,7 @@ public interface GrailsPluginManager extends ApplicationContextAware { /** * Indicates whether the manager has been shutdown or not + * * @return True if it was shutdown */ boolean isShutdown(); @@ -330,5 +343,5 @@ public interface GrailsPluginManager extends ApplicationContextAware { * * @param pluginFilter The plugin filter */ - public void setPluginFilter(PluginFilter pluginFilter); + void setPluginFilter(PluginFilter pluginFilter); } diff --git a/grails-core/src/main/groovy/grails/plugins/Plugin.groovy b/grails-core/src/main/groovy/grails/plugins/Plugin.groovy index 308c292b124..6b5570afed3 100644 --- a/grails-core/src/main/groovy/grails/plugins/Plugin.groovy +++ b/grails-core/src/main/groovy/grails/plugins/Plugin.groovy @@ -33,7 +33,6 @@ import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContextAware import org.springframework.context.ConfigurableApplicationContext - /** * Super class for plugins to implement. Plugin implementations should define the various plugin hooks * (doWithSpring, doWithApplicationContext, doWithDynamicMethods etc.) @@ -69,7 +68,7 @@ abstract class Plugin implements GrailsApplicationLifeCycle, GrailsApplicationAw /** * The {@link GrailsPluginManager} instance */ - GrailsPluginManager getManager() { pluginManager} + GrailsPluginManager getManager() { pluginManager } /** * Whether the plugin is enabled @@ -81,7 +80,6 @@ abstract class Plugin implements GrailsApplicationLifeCycle, GrailsApplicationAw */ final List artefacts = [] - /** * The {@link ApplicationContext} instance */ @@ -91,8 +89,8 @@ abstract class Plugin implements GrailsApplicationLifeCycle, GrailsApplicationAw * @return The ApplicationContext */ ConfigurableApplicationContext getApplicationContext() { - if(applicationContext instanceof ConfigurableApplicationContext) { - return (ConfigurableApplicationContext)applicationContext + if (applicationContext instanceof ConfigurableApplicationContext) { + return (ConfigurableApplicationContext) applicationContext } return null; } @@ -102,10 +100,10 @@ abstract class Plugin implements GrailsApplicationLifeCycle, GrailsApplicationAw this.applicationContext = applicationContext } /** - * Sub classes should override to provide implementations - * - * @return A closure that defines beans to be executed by Spring - */ + * Sub classes should override to provide implementations + * + * @return A closure that defines beans to be executed by Spring + */ @Override Closure doWithSpring() { null } @@ -167,7 +165,7 @@ abstract class Plugin implements GrailsApplicationLifeCycle, GrailsApplicationAw void beans(Closure beanDefinitions) { def bb = new BeanBuilder(null, grailsApplication.classLoader) bb.beans beanDefinitions - bb.registerBeans((BeanDefinitionRegistry)applicationContext) - new MapBasedSmartPropertyOverrideConfigurer(grailsApplication: grailsApplication).postProcessBeanFactory(((ConfigurableApplicationContext)applicationContext).beanFactory) + bb.registerBeans((BeanDefinitionRegistry) applicationContext) + new MapBasedSmartPropertyOverrideConfigurer(grailsApplication: grailsApplication).postProcessBeanFactory(((ConfigurableApplicationContext) applicationContext).beanFactory) } } diff --git a/grails-core/src/main/groovy/grails/plugins/PluginFilter.java b/grails-core/src/main/groovy/grails/plugins/PluginFilter.java index 7688245dbe7..94eb48d650f 100644 --- a/grails-core/src/main/groovy/grails/plugins/PluginFilter.java +++ b/grails-core/src/main/groovy/grails/plugins/PluginFilter.java @@ -30,8 +30,9 @@ public interface PluginFilter { /** * Returns a filtered list of plugins. + * * @param original the original supplied set of GrailsPlugin instances * @return a sublist of these items */ - List filterPluginList(List original); + List filterPluginList(List original); } diff --git a/grails-core/src/main/groovy/grails/plugins/PluginManagerAware.java b/grails-core/src/main/groovy/grails/plugins/PluginManagerAware.java index 5a9620f8297..97774e98b00 100644 --- a/grails-core/src/main/groovy/grails/plugins/PluginManagerAware.java +++ b/grails-core/src/main/groovy/grails/plugins/PluginManagerAware.java @@ -23,9 +23,8 @@ /** * For implementors interested in obtaining a reference to the Grails PluginManager instance. * - * @see GrailsPluginManager - * * @author Graeme Rocher + * @see GrailsPluginManager * @since 0.6 */ public interface PluginManagerAware extends Aware { diff --git a/grails-core/src/main/groovy/grails/util/AbstractTypeConvertingMap.java b/grails-core/src/main/groovy/grails/util/AbstractTypeConvertingMap.java index c63e151ac60..60062fe11fa 100644 --- a/grails-core/src/main/groovy/grails/util/AbstractTypeConvertingMap.java +++ b/grails-core/src/main/groovy/grails/util/AbstractTypeConvertingMap.java @@ -24,11 +24,20 @@ import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * AbstractTypeConvertingMap is a Map with type conversion capabilities. - * + *

* Type converting maps have no inherent ordering. Two maps with identical entries * but arranged in a different order internally are considered equal. * @@ -36,8 +45,9 @@ * @author Lari Hotari * @since 1.2 */ -@SuppressWarnings({ "rawtypes", "unchecked" }) +@SuppressWarnings({"rawtypes", "unchecked"}) public abstract class AbstractTypeConvertingMap extends GroovyObjectSupport implements Map, Cloneable { + private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.S"; protected Map wrappedMap; @@ -46,13 +56,15 @@ public AbstractTypeConvertingMap() { } public AbstractTypeConvertingMap(Map map) { - if (map == null) map = new LinkedHashMap(); + if (map == null) { + map = new LinkedHashMap(); + } wrappedMap = map; } - + public boolean equals(Map that) { - return equals((Object)that); - } + return equals((Object) that); + } @Override public boolean equals(Object that) { @@ -68,7 +80,7 @@ public boolean equals(Object that) { return false; } - AbstractTypeConvertingMap thatMap = (AbstractTypeConvertingMap)that; + AbstractTypeConvertingMap thatMap = (AbstractTypeConvertingMap) that; if (wrappedMap == thatMap.wrappedMap) { return true; @@ -87,9 +99,9 @@ public boolean equals(Object that) { final Object key = it.next(); Object thisValue = wrappedMap.get(key); Object thatValue = thatMap.wrappedMap.get(key); - if (thisValue == null && thatValue != null || - thisValue != null && thatValue == null || - thisValue != thatValue && !thisValue.equals(thatValue)) { + if (thisValue == null && thatValue != null || + thisValue != null && thatValue == null || + thisValue != thatValue && !thisValue.equals(thatValue)) { return false; } } @@ -107,13 +119,14 @@ public int hashCode() { /** * Helper method for obtaining integer value from parameter + * * @param name The name of the parameter * @return The integer value or null if there isn't one */ public Byte getByte(String name) { Object o = get(name); if (o instanceof Number) { - return ((Number)o).byteValue(); + return ((Number) o).byteValue(); } if (o != null) { @@ -122,8 +135,8 @@ public Byte getByte(String name) { if (string != null && string.length() > 0) { return Byte.parseByte(string); } + } catch (NumberFormatException e) { } - catch (NumberFormatException e) {} } return null; } @@ -131,20 +144,21 @@ public Byte getByte(String name) { public Byte getByte(String name, Integer defaultValue) { Byte value = getByte(name); if (value == null && defaultValue != null) { - value = (byte)defaultValue.intValue(); + value = (byte) defaultValue.intValue(); } return value; } /** * Helper method for obtaining Character value from parameter + * * @param name The name of the parameter * @return The Character value or null if there isn't one */ public Character getChar(String name) { Object o = get(name); if (o instanceof Character) { - return (Character)o; + return (Character) o; } if (o != null) { @@ -157,22 +171,23 @@ public Character getChar(String name) { } public Character getChar(String name, Integer defaultValue) { - Character value=getChar(name); + Character value = getChar(name); if (value == null && defaultValue != null) { - value = (char)defaultValue.intValue(); + value = (char) defaultValue.intValue(); } return value; } /** * Helper method for obtaining integer value from parameter + * * @param name The name of the parameter * @return The integer value or null if there isn't one */ public Integer getInt(String name) { Object o = get(name); if (o instanceof Number) { - return ((Number)o).intValue(); + return ((Number) o).intValue(); } if (o != null) { @@ -181,14 +196,14 @@ public Integer getInt(String name) { if (string != null) { return Integer.parseInt(string); } + } catch (NumberFormatException e) { } - catch (NumberFormatException e) {} } return null; } public Integer getInt(String name, Integer defaultValue) { - Integer value=getInt(name); + Integer value = getInt(name); if (value == null) { value = defaultValue; } @@ -197,26 +212,27 @@ public Integer getInt(String name, Integer defaultValue) { /** * Helper method for obtaining long value from parameter + * * @param name The name of the parameter * @return The long value or null if there isn't one */ public Long getLong(String name) { Object o = get(name); if (o instanceof Number) { - return ((Number)o).longValue(); + return ((Number) o).longValue(); } if (o != null) { try { return Long.parseLong(o.toString()); + } catch (NumberFormatException e) { } - catch (NumberFormatException e) {} } return null; } public Long getLong(String name, Long defaultValue) { - Long value=getLong(name); + Long value = getLong(name); if (value == null) { value = defaultValue; } @@ -224,14 +240,15 @@ public Long getLong(String name, Long defaultValue) { } /** - * Helper method for obtaining short value from parameter - * @param name The name of the parameter - * @return The short value or null if there isn't one - */ + * Helper method for obtaining short value from parameter + * + * @param name The name of the parameter + * @return The short value or null if there isn't one + */ public Short getShort(String name) { Object o = get(name); if (o instanceof Number) { - return ((Number)o).shortValue(); + return ((Number) o).shortValue(); } if (o != null) { @@ -240,14 +257,14 @@ public Short getShort(String name) { if (string != null) { return Short.parseShort(string); } + } catch (NumberFormatException e) { } - catch (NumberFormatException e) {} } return null; } public Short getShort(String name, Integer defaultValue) { - Short value=getShort(name); + Short value = getShort(name); if (value == null && defaultValue != null) { value = defaultValue.shortValue(); } @@ -255,14 +272,15 @@ public Short getShort(String name, Integer defaultValue) { } /** - * Helper method for obtaining double value from parameter - * @param name The name of the parameter - * @return The double value or null if there isn't one - */ + * Helper method for obtaining double value from parameter + * + * @param name The name of the parameter + * @return The double value or null if there isn't one + */ public Double getDouble(String name) { Object o = get(name); if (o instanceof Number) { - return ((Number)o).doubleValue(); + return ((Number) o).doubleValue(); } if (o != null) { @@ -271,14 +289,14 @@ public Double getDouble(String name) { if (string != null) { return Double.parseDouble(string); } + } catch (NumberFormatException e) { } - catch (NumberFormatException e) {} } return null; } public Double getDouble(String name, Double defaultValue) { - Double value=getDouble(name); + Double value = getDouble(name); if (value == null) { value = defaultValue; } @@ -287,13 +305,14 @@ public Double getDouble(String name, Double defaultValue) { /** * Helper method for obtaining float value from parameter + * * @param name The name of the parameter * @return The double value or null if there isn't one */ public Float getFloat(String name) { Object o = get(name); if (o instanceof Number) { - return ((Number)o).floatValue(); + return ((Number) o).floatValue(); } if (o != null) { @@ -302,14 +321,14 @@ public Float getFloat(String name) { if (string != null) { return Float.parseFloat(string); } + } catch (NumberFormatException e) { } - catch (NumberFormatException e) {} } return null; } public Float getFloat(String name, Float defaultValue) { - Float value=getFloat(name); + Float value = getFloat(name); if (value == null) { value = defaultValue; } @@ -318,13 +337,14 @@ public Float getFloat(String name, Float defaultValue) { /** * Helper method for obtaining boolean value from parameter + * * @param name The name of the parameter * @return The boolean value or null if there isn't one */ public Boolean getBoolean(String name) { Object o = get(name); if (o instanceof Boolean) { - return (Boolean)o; + return (Boolean) o; } if (o != null) { @@ -333,8 +353,8 @@ public Boolean getBoolean(String name) { if (string != null) { return GrailsStringUtils.toBoolean(string); } + } catch (Exception e) { } - catch (Exception e) {} } return null; } @@ -351,6 +371,7 @@ public Boolean getBoolean(String name, Boolean defaultValue) { /** * Obtains a date for the parameter name using the default format + * * @param name * @return The date (in the {@link DEFAULT_DATE_FORMAT}) or null */ @@ -360,16 +381,17 @@ public Date getDate(String name) { /** * Obtains a date from the parameter using the given format - * @param name The name + * + * @param name The name * @param format The format * @return The date or null */ public Date getDate(String name, String format) { Object value = get(name); if (value instanceof Date) { - return (Date)value; + return (Date) value; } - + if (value != null) { try { return new SimpleDateFormat(format).parse(value.toString()); @@ -393,7 +415,7 @@ public Date date(String name) { /** * Obtains a date for the given parameter name and format * - * @param name The name of the parameter + * @param name The name of the parameter * @param format The format * @return The date object or null if it cannot be parsed */ @@ -404,7 +426,7 @@ public Date date(String name, String format) { /** * Obtains a date for the given parameter name and format * - * @param name The name of the parameter + * @param name The name of the parameter * @param formats The formats * @return The date object or null if it cannot be parsed */ @@ -414,14 +436,17 @@ public Date date(String name, Collection formats) { private Date getDate(String name, Collection formats) { for (String format : formats) { - Date date = getDate(name,format); - if (date != null) return date; + Date date = getDate(name, format); + if (date != null) { + return date; + } } return null; } /** * Helper method for obtaining a list of values from parameter + * * @param name The name of the parameter * @return A list of values */ @@ -431,10 +456,10 @@ public List getList(String name) { return Collections.emptyList(); } if (paramValues.getClass().isArray()) { - return Arrays.asList((Object[])paramValues); + return Arrays.asList((Object[]) paramValues); } if (paramValues instanceof Collection) { - return new ArrayList((Collection)paramValues); + return new ArrayList((Collection) paramValues); } return Collections.singletonList(paramValues); } diff --git a/grails-core/src/main/groovy/grails/util/CacheEntry.java b/grails-core/src/main/groovy/grails/util/CacheEntry.java index 56dcb6192a3..b04798f66af 100644 --- a/grails-core/src/main/groovy/grails/util/CacheEntry.java +++ b/grails-core/src/main/groovy/grails/util/CacheEntry.java @@ -31,47 +31,56 @@ /** * Wrapper for a value inside a cache that adds timestamp information * for expiration and prevents "cache storms" with a Lock. - * + *

* JMM happens-before is ensured with AtomicReference. - * + *

* Objects in cache are assumed to not change after publication. * * @author Lari Hotari * @since 2.3.4 */ public class CacheEntry { + private static final Logger LOG = LoggerFactory.getLogger(CacheEntry.class); - private final AtomicReference valueRef=new AtomicReference(null); + @SuppressWarnings("rawtypes") + private static final Callable DEFAULT_CACHE_ENTRY_FACTORY = new Callable() { + @Override + public CacheEntry call() throws Exception { + return new CacheEntry(); + } + }; + + private final AtomicReference valueRef = new AtomicReference(null); + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private final Lock readLock = lock.readLock(); + private final Lock writeLock = lock.writeLock(); + private volatile boolean initialized = false; private long createdMillis; - private final ReadWriteLock lock=new ReentrantReadWriteLock(); - private final Lock readLock=lock.readLock(); - private final Lock writeLock=lock.writeLock(); - private volatile boolean initialized=false; public CacheEntry() { expire(); } - + public CacheEntry(V value) { setValue(value); } - + /** * Gets a value from cache. If the key doesn't exist, it will create the value using the updater callback * Prevents cache storms with a lock. * The key is always added to the cache. Null return values will also be cached. * You can use this together with ConcurrentLinkedHashMap to create a bounded LRU cache * - * @param map the cache map - * @param key the key to look up - * @param timeoutMillis cache entry timeout - * @param updater callback to create/update value - * @param cacheEntryFactory callback to create cache entry, not used in default implementation + * @param map the cache map + * @param key the key to look up + * @param timeoutMillis cache entry timeout + * @param updater callback to create/update value + * @param cacheEntryFactory callback to create cache entry, not used in default implementation * @param returnExpiredWhileUpdating when true, return expired value while updating new value - * @param cacheRequestObject context object that gets passed to hasExpired, shouldUpdate and updateValue methods, not used in default implementation + * @param cacheRequestObject context object that gets passed to hasExpired, shouldUpdate and updateValue methods, not used in default implementation * @return the value */ - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) public static V getValue(ConcurrentMap> map, K key, long timeoutMillis, @@ -79,36 +88,26 @@ public static V getValue(ConcurrentMap> map, boolean returnExpiredWhileUpdating, Object cacheRequestObject) { CacheEntry cacheEntry = map.get(key); - if(cacheEntry==null) { + if (cacheEntry == null) { try { cacheEntry = cacheEntryFactory.call(); - } - catch (Exception e) { + } catch (Exception e) { throw new UpdateException(e); } CacheEntry previousEntry = map.putIfAbsent(key, cacheEntry); - if(previousEntry != null) { + if (previousEntry != null) { cacheEntry = previousEntry; } } try { return cacheEntry.getValue(timeoutMillis, updater, returnExpiredWhileUpdating, cacheRequestObject); - } - catch (UpdateException e) { + } catch (UpdateException e) { e.rethrowRuntimeException(); // make compiler happy return null; } } - - @SuppressWarnings("rawtypes") - private static final Callable DEFAULT_CACHE_ENTRY_FACTORY = new Callable() { - @Override - public CacheEntry call() throws Exception { - return new CacheEntry(); - } - }; - + public static V getValue(ConcurrentMap> map, K key, long timeoutMillis, Callable updater) { return getValue(map, key, timeoutMillis, updater, DEFAULT_CACHE_ENTRY_FACTORY, true, null); } @@ -116,14 +115,14 @@ public static V getValue(ConcurrentMap> map, K key, long public static V getValue(ConcurrentMap> map, K key, long timeoutMillis, Callable updater, boolean returnExpiredWhileUpdating) { return getValue(map, key, timeoutMillis, updater, DEFAULT_CACHE_ENTRY_FACTORY, returnExpiredWhileUpdating, null); } - + public V getValue(long timeout, Callable updater) { return getValue(timeout, updater, true, null); } - + /** * gets the current value from the entry and updates it if it's older than timeout - * + *

* updater is a callback for creating an updated value. * * @param timeout @@ -137,12 +136,12 @@ public V getValue(long timeout, Callable updater, boolean returnExpiredWhileU boolean lockAcquired = false; try { long beforeLockingCreatedMillis = createdMillis; - if(returnExpiredWhileUpdating) { - if(!writeLock.tryLock()) { - if(isInitialized()) { + if (returnExpiredWhileUpdating) { + if (!writeLock.tryLock()) { + if (isInitialized()) { return getValueWhileUpdating(cacheRequestObject); } else { - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("Locking cache for update"); } writeLock.lock(); @@ -157,12 +156,11 @@ public V getValue(long timeout, Callable updater, boolean returnExpiredWhileU if (!isInitialized() || shouldUpdate(beforeLockingCreatedMillis, cacheRequestObject)) { try { value = updateValue(getValue(), updater, cacheRequestObject); - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("Updating cache for value [{}]", value); } setValue(value); - } - catch (Exception e) { + } catch (Exception e) { throw new UpdateException(e); } } else { @@ -171,8 +169,8 @@ public V getValue(long timeout, Callable updater, boolean returnExpiredWhileU } return value; } finally { - if(lockAcquired) { - if(LOG.isDebugEnabled()) { + if (lockAcquired) { + if (LOG.isDebugEnabled()) { LOG.debug("Unlocking cache for update"); } writeLock.unlock(); @@ -182,7 +180,7 @@ public V getValue(long timeout, Callable updater, boolean returnExpiredWhileU return getValue(); } } - + protected V getValueWhileUpdating(Object cacheRequestObject) { return valueRef.get(); } @@ -199,9 +197,9 @@ public V getValue() { readLock.unlock(); } } - + public void setValue(V val) { - try{ + try { writeLock.lock(); valueRef.set(val); setInitialized(true); @@ -220,7 +218,7 @@ protected boolean shouldUpdate(long beforeLockingCreatedMillis, Object cacheRequ } protected void resetTimestamp(boolean updated) { - if(updated) { + if (updated) { createdMillis = System.currentTimeMillis(); } } @@ -232,7 +230,7 @@ public long getCreatedMillis() { public void expire() { createdMillis = 0L; } - + public boolean isInitialized() { return initialized; } @@ -242,6 +240,7 @@ public void setInitialized(boolean initialized) { } public static final class UpdateException extends RuntimeException { + private static final long serialVersionUID = 1L; public UpdateException(String message, Throwable cause) { @@ -254,18 +253,18 @@ public UpdateException(Throwable cause) { public void rethrowCause() throws Exception { if (getCause() instanceof Exception) { - throw (Exception)getCause(); + throw (Exception) getCause(); } throw this; } - + public void rethrowRuntimeException() { if (getCause() instanceof RuntimeException) { - throw (RuntimeException)getCause(); + throw (RuntimeException) getCause(); } throw this; } - + } } diff --git a/grails-core/src/main/groovy/grails/util/ClosureToMapPopulator.java b/grails-core/src/main/groovy/grails/util/ClosureToMapPopulator.java index 4f9541f0b91..30243f85701 100644 --- a/grails-core/src/main/groovy/grails/util/ClosureToMapPopulator.java +++ b/grails-core/src/main/groovy/grails/util/ClosureToMapPopulator.java @@ -32,7 +32,7 @@ * @author Graeme Rocher * @since 1.2 */ -@SuppressWarnings({"unchecked","rawtypes"}) +@SuppressWarnings({"unchecked", "rawtypes"}) public class ClosureToMapPopulator extends GroovyObjectSupport { private Map map; @@ -63,16 +63,14 @@ public void setProperty(String name, Object o) { public Object invokeMethod(String name, Object o) { if (o != null) { if (o.getClass().isArray()) { - Object[] args = (Object[])o; + Object[] args = (Object[]) o; if (args.length == 1) { map.put(name, args[0]); - } - else { + } else { map.put(name, Arrays.asList(args)); } - } - else { - map.put(name,o); + } else { + map.put(name, o); } } return null; diff --git a/grails-core/src/main/groovy/grails/util/DomainBuilder.java b/grails-core/src/main/groovy/grails/util/DomainBuilder.java index 1c810e36d18..6536ab54169 100644 --- a/grails-core/src/main/groovy/grails/util/DomainBuilder.java +++ b/grails-core/src/main/groovy/grails/util/DomainBuilder.java @@ -19,25 +19,25 @@ package grails.util; import groovy.util.ObjectGraphBuilder; +import org.codehaus.groovy.runtime.InvokerHelper; import java.lang.reflect.Field; import java.util.Collection; -import org.codehaus.groovy.runtime.InvokerHelper; - /** *

Allows the construction of object graphs of domain classes. Example: * *


  *      def builder = new DomainBuilder()
-
-        def company = builder.company(name: 'ACME') {
-            employee(name: 'Duke', employeeId: 1) {
-                address(street: '123 Groovy Rd')
-            }
-            employee(name: 'George', employeeId: 2)
-        }
+ *
+ * def company = builder.company(name: 'ACME') {
+ * employee(name: 'Duke', employeeId: 1) {
+ * address(street: '123 Groovy Rd')
+ * }
+ * employee(name: 'George', employeeId: 2)
+ * }
  * 
+ * * @author Scott Vlaminck */ public class DomainBuilder extends ObjectGraphBuilder { @@ -48,13 +48,13 @@ public DomainBuilder() { } public static class DefaultGrailsChildPropertySetter implements ChildPropertySetter { + public void setChild(Object parent, Object child, String parentName, String propertyName) { if (isCollection(parent, child, parentName, propertyName)) { - String propName = propertyName.substring(0,1).toUpperCase() + propertyName.substring(1); + String propName = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); String methodName = "addTo" + propName; InvokerHelper.invokeMethod(parent, methodName, child); - } - else { + } else { InvokerHelper.setProperty(parent, propertyName, child); } } @@ -63,8 +63,7 @@ private boolean isCollection(Object parent, Object child, String parentName, Str try { Field field = parent.getClass().getDeclaredField(propertyName); return Collection.class.isAssignableFrom(field.getType()); - } - catch (NoSuchFieldException ignored) { /* ignored */} + } catch (NoSuchFieldException ignored) { /* ignored */ } return false; } diff --git a/grails-core/src/main/groovy/grails/util/ExtendedProxy.java b/grails-core/src/main/groovy/grails/util/ExtendedProxy.java index cbb15a0900c..4e4f55da318 100644 --- a/grails-core/src/main/groovy/grails/util/ExtendedProxy.java +++ b/grails-core/src/main/groovy/grails/util/ExtendedProxy.java @@ -20,12 +20,11 @@ import groovy.lang.MetaClass; import groovy.util.Proxy; - -import java.util.Map; - import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.codehaus.groovy.runtime.InvokerHelper; +import java.util.Map; + /** * Extends the Groovy Proxy implementation and adds proxying of property getters/setters. * @@ -45,7 +44,7 @@ public ExtendedProxy() { public Object getProperty(String property) { Object propertyValue = propertyMap.get(property); if (propertyValue == null) { - propertyValue = InvokerHelper.getMetaClass(getAdaptee()).getProperty(getAdaptee(),property); + propertyValue = InvokerHelper.getMetaClass(getAdaptee()).getProperty(getAdaptee(), property); } return propertyValue; } @@ -53,10 +52,9 @@ public Object getProperty(String property) { @Override public void setProperty(String property, Object newValue) { if (propertyMap.containsKey(property)) { - super.setProperty(property,newValue); - } - else { - InvokerHelper.getMetaClass(getAdaptee()).setProperty(getAdaptee(),property,newValue); + super.setProperty(property, newValue); + } else { + InvokerHelper.getMetaClass(getAdaptee()).setProperty(getAdaptee(), property, newValue); } } diff --git a/grails-core/src/main/groovy/grails/util/GrailsArrayUtils.groovy b/grails-core/src/main/groovy/grails/util/GrailsArrayUtils.groovy index 45a61763dbf..272c4413f5b 100644 --- a/grails-core/src/main/groovy/grails/util/GrailsArrayUtils.groovy +++ b/grails-core/src/main/groovy/grails/util/GrailsArrayUtils.groovy @@ -19,12 +19,11 @@ package grails.util import groovy.transform.CompileStatic - -import java.lang.reflect.Array - import org.codehaus.groovy.runtime.DefaultGroovyMethods import org.springframework.util.ObjectUtils +import java.lang.reflect.Array + /** * Utility methods for working with Arrays * @@ -90,18 +89,17 @@ abstract class GrailsArrayUtils { */ static Object add(Object array, int pos, Object newObject) { - if(array == null) { - Object[] newArray = (Object[])Array.newInstance(newObject.getClass(), 1) + if (array == null) { + Object[] newArray = (Object[]) Array.newInstance(newObject.getClass(), 1) newArray[pos] = newObject return newArray - } - else { + } else { def type = array.getClass().componentType int len = Array.getLength(array) def newArray = Array.newInstance(type, len + 1) System.arraycopy array, 0, newArray, 0, pos Array.set newArray, pos, newObject - if( pos < len ) { + if (pos < len) { System.arraycopy array, pos, newArray, pos + 1, len - pos } return newArray @@ -117,13 +115,12 @@ abstract class GrailsArrayUtils { * @return A new array, one element bigger, with the object added at the given position */ static Object addAll(Object array, Object otherArray) { - if(array == null) { + if (array == null) { return otherArray - } - else { + } else { def type = array.getClass().componentType - int len = Array.getLength( array ) - int len2 = Array.getLength( otherArray ) + int len = Array.getLength(array) + int len2 = Array.getLength(otherArray) def newArray = Array.newInstance(type, len + len2) System.arraycopy(array, 0, newArray, 0, len); @@ -147,25 +144,24 @@ abstract class GrailsArrayUtils { static Object subarray(Object args, int start, int end) { def len = Array.getLength(args) - if(start < 0) start = 0 - if(end > len) end = len + if (start < 0) start = 0 + if (end > len) end = len def type = args.getClass().componentType def newLen = end - start - if(newLen <= 0) { + if (newLen <= 0) { return Array.newInstance(type, 0) - } - else { - def newArray = Array.newInstance(type, newLen ) - System.arraycopy args, start, newArray,0, newLen + } else { + def newArray = Array.newInstance(type, newLen) + System.arraycopy args, start, newArray, 0, newLen return newArray } } static boolean contains(Object[] array, Object elementToSearchFor) { boolean found = false - if(array) { + if (array) { found = DefaultGroovyMethods.contains(array, elementToSearchFor) } found diff --git a/grails-core/src/main/groovy/grails/util/GrailsClassUtils.java b/grails-core/src/main/groovy/grails/util/GrailsClassUtils.java index edec1dd5a8b..bf8477b1fac 100644 --- a/grails-core/src/main/groovy/grails/util/GrailsClassUtils.java +++ b/grails-core/src/main/groovy/grails/util/GrailsClassUtils.java @@ -63,15 +63,16 @@ */ public class GrailsClassUtils { - private static final Log LOG = LogFactory.getLog(GrailsClassUtils.class); public static final Map, Class> PRIMITIVE_TYPE_COMPATIBLE_CLASSES = new HashMap, Class>(); + private static final Log LOG = LogFactory.getLog(GrailsClassUtils.class); /** * Just add two entries to the class compatibility map + * * @param left * @param right */ - private static final void registerPrimitiveClassPair(Class left, Class right) { + private static void registerPrimitiveClassPair(Class left, Class right) { PRIMITIVE_TYPE_COMPATIBLE_CLASSES.put(left, right); PRIMITIVE_TYPE_COMPATIBLE_CLASSES.put(right, left); } @@ -90,6 +91,7 @@ private static final void registerPrimitiveClassPair(Class left, Class rig /** * Return all interfaces that the given instance implements as array, * including ones implemented by superclasses. + * * @param instance the instance to analyze for interfaces * @return all interfaces that the given instance implements as array */ @@ -102,6 +104,7 @@ public static Class[] getAllInterfaces(Object instance) { * Return all interfaces that the given class implements as array, * including ones implemented by superclasses. *

If the class itself is an interface, it gets returned as sole interface. + * * @param clazz the class to analyze for interfaces * @return all interfaces that the given object implements as array */ @@ -113,9 +116,10 @@ public static Class[] getAllInterfacesForClass(Class clazz) { * Return all interfaces that the given class implements as array, * including ones implemented by superclasses. *

If the class itself is an interface, it gets returned as sole interface. - * @param clazz the class to analyze for interfaces + * + * @param clazz the class to analyze for interfaces * @param classLoader the ClassLoader that the interfaces need to be visible in - * (may be {@code null} when accepting all declared interfaces) + * (may be {@code null} when accepting all declared interfaces) * @return all interfaces that the given object implements as array */ public static Class[] getAllInterfacesForClass(Class clazz, ClassLoader classLoader) { @@ -126,6 +130,7 @@ public static Class[] getAllInterfacesForClass(Class clazz, ClassLoader cl /** * Return all interfaces that the given instance implements as Set, * including ones implemented by superclasses. + * * @param instance the instance to analyze for interfaces * @return all interfaces that the given instance implements as Set */ @@ -138,6 +143,7 @@ public static Set getAllInterfacesAsSet(Object instance) { * Return all interfaces that the given class implements as Set, * including ones implemented by superclasses. *

If the class itself is an interface, it gets returned as sole interface. + * * @param clazz the class to analyze for interfaces * @return all interfaces that the given object implements as Set */ @@ -149,9 +155,10 @@ public static Set getAllInterfacesForClassAsSet(Class clazz) { * Return all interfaces that the given class implements as Set, * including ones implemented by superclasses. *

If the class itself is an interface, it gets returned as sole interface. - * @param clazz the class to analyze for interfaces + * + * @param clazz the class to analyze for interfaces * @param classLoader the ClassLoader that the interfaces need to be visible in - * (may be {@code null} when accepting all declared interfaces) + * (may be {@code null} when accepting all declared interfaces) * @return all interfaces that the given object implements as Set */ public static Set getAllInterfacesForClassAsSet(Class clazz, ClassLoader classLoader) { @@ -168,12 +175,12 @@ public static Set getAllInterfacesForClassAsSet(Class clazz, ClassLoader return interfaces; } - /** * Check whether the given class is visible in the given ClassLoader. - * @param clazz the class to check (typically an interface) + * + * @param clazz the class to check (typically an interface) * @param classLoader the ClassLoader to check against (may be {@code null}, - * in which case this method will always return {@code true}) + * in which case this method will always return {@code true}) */ public static boolean isVisible(Class clazz, ClassLoader classLoader) { if (classLoader == null) { @@ -183,8 +190,7 @@ public static boolean isVisible(Class clazz, ClassLoader classLoader) { Class actualClass = classLoader.loadClass(clazz.getName()); return (clazz == actualClass); // Else: different interface class found... - } - catch (ClassNotFoundException ex) { + } catch (ClassNotFoundException ex) { // No interface class found... return false; } @@ -193,18 +199,16 @@ public static boolean isVisible(Class clazz, ClassLoader classLoader) { /** * Returns true if the specified property in the specified class is of the specified type * - * @param clazz The class which contains the property + * @param clazz The class which contains the property * @param propertyName The property name - * @param type The type to check - * + * @param type The type to check * @return A boolean value */ public static boolean isPropertyOfType(Class clazz, String propertyName, Class type) { try { Class propType = getPropertyType(clazz, propertyName); return propType != null && propType.equals(type); - } - catch (Exception e) { + } catch (Exception e) { return false; } } @@ -212,13 +216,12 @@ public static boolean isPropertyOfType(Class clazz, String propertyName, Clas /** * Returns the value of the specified property and type from an instance of the specified Grails class * - * @param clazz The name of the class which contains the property + * @param clazz The name of the class which contains the property * @param propertyName The property name * @param propertyType The property type - * * @return The value of the property or null if none exists */ - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) public static Object getPropertyValueOfNewInstance(Class clazz, String propertyName, Class propertyType) { // validate if (clazz == null || !StringUtils.hasText(propertyName)) { @@ -227,8 +230,7 @@ public static Object getPropertyValueOfNewInstance(Class clazz, String propertyN try { return getPropertyOrStaticPropertyOrFieldValue(BeanUtils.instantiateClass(clazz), propertyName); - } - catch (BeanInstantiationException e) { + } catch (BeanInstantiationException e) { return null; } } @@ -236,9 +238,8 @@ public static Object getPropertyValueOfNewInstance(Class clazz, String propertyN /** * Returns the value of the specified property and type from an instance of the specified Grails class * - * @param clazz The name of the class which contains the property + * @param clazz The name of the class which contains the property * @param propertyName The property name - * * @return The value of the property or null if none exists */ public static Object getPropertyValueOfNewInstance(Class clazz, String propertyName) { @@ -249,8 +250,7 @@ public static Object getPropertyValueOfNewInstance(Class clazz, String proper try { return getPropertyOrStaticPropertyOrFieldValue(BeanUtils.instantiateClass(clazz), propertyName); - } - catch (BeanInstantiationException e) { + } catch (BeanInstantiationException e) { return null; } } @@ -258,7 +258,7 @@ public static Object getPropertyValueOfNewInstance(Class clazz, String proper /** * Retrieves a PropertyDescriptor for the specified instance and property value * - * @param instance The instance + * @param instance The instance * @param propertyValue The value of the property * @return The PropertyDescriptor */ @@ -274,8 +274,7 @@ public static PropertyDescriptor getPropertyDescriptorForValue(Object instance, try { ReflectionUtils.makeAccessible(pd.getReadMethod()); value = pd.getReadMethod().invoke(instance); - } - catch (Exception e) { + } catch (Exception e) { throw new FatalBeanException("Problem calling readMethod of " + pd, e); } if (propertyValue.equals(value)) { @@ -289,9 +288,8 @@ public static PropertyDescriptor getPropertyDescriptorForValue(Object instance, /** * Returns the type of the given property contained within the specified class * - * @param clazz The class which contains the property + * @param clazz The class which contains the property * @param propertyName The name of the property - * * @return The property type or null if none exists */ public static Class getPropertyType(Class clazz, String propertyName) { @@ -300,13 +298,12 @@ public static Class getPropertyType(Class clazz, String propertyName) { } try { - PropertyDescriptor desc=BeanUtils.getPropertyDescriptor(clazz, propertyName); + PropertyDescriptor desc = BeanUtils.getPropertyDescriptor(clazz, propertyName); if (desc != null) { return desc.getPropertyType(); } return null; - } - catch (Exception e) { + } catch (Exception e) { // if there are any errors in instantiating just return null for the moment return null; } @@ -315,9 +312,8 @@ public static Class getPropertyType(Class clazz, String propertyName) { /** * Retrieves all the properties of the given class for the given type * - * @param clazz The class to retrieve the properties from + * @param clazz The class to retrieve the properties from * @param propertyType The type of the properties you wish to retrieve - * * @return An array of PropertyDescriptor instances */ public static PropertyDescriptor[] getPropertiesOfType(Class clazz, Class propertyType) { @@ -336,9 +332,8 @@ public static PropertyDescriptor[] getPropertiesOfType(Class clazz, Class properties.add(descriptor); } } - } - catch (Exception e) { - if(descriptor == null) { + } catch (Exception e) { + if (descriptor == null) { LOG.error(String.format("Got exception while checking property descriptors for class %s", clazz.getName()), e); } else { LOG.error(String.format("Got exception while checking PropertyDescriptor.propertyType for field %s.%s", clazz.getName(), descriptor.getName()), e); @@ -361,7 +356,9 @@ private static boolean isTypeInstanceOfPropertyType(Class type, Class prop * @return An array of PropertyDescriptor instances */ public static PropertyDescriptor[] getPropertiesAssignableToType(Class clazz, Class propertySuperType) { - if (clazz == null || propertySuperType == null) return new PropertyDescriptor[0]; + if (clazz == null || propertySuperType == null) { + return new PropertyDescriptor[0]; + } Set properties = new HashSet(); PropertyDescriptor descriptor = null; @@ -374,9 +371,8 @@ public static PropertyDescriptor[] getPropertiesAssignableToType(Class clazz, properties.add(descriptor); } } - } - catch (Exception e) { - if(descriptor == null) { + } catch (Exception e) { + if (descriptor == null) { LOG.error(String.format("Got exception while checking property descriptors for class %s", clazz.getName()), e); } else { LOG.error(String.format("Got exception while checking PropertyDescriptor.propertyType for field %s.%s", clazz.getName(), descriptor.getName()), e); @@ -388,10 +384,10 @@ public static PropertyDescriptor[] getPropertiesAssignableToType(Class clazz, /** * Retrieves a property of the given class of the specified name and type - * @param clazz The class to retrieve the property from + * + * @param clazz The class to retrieve the property from * @param propertyName The name of the property * @param propertyType The type of the property - * * @return A PropertyDescriptor instance or null if none exists */ public static PropertyDescriptor getProperty(Class clazz, String propertyName, Class propertyType) { @@ -405,8 +401,7 @@ public static PropertyDescriptor getProperty(Class clazz, String propertyName return pd; } return null; - } - catch (Exception e) { + } catch (Exception e) { // if there are any errors in instantiating just return null for the moment return null; } @@ -414,9 +409,9 @@ public static PropertyDescriptor getProperty(Class clazz, String propertyName /** * Retrieves a property of the given class of the specified name and type - * @param clazz The class to retrieve the property from - * @param propertyName The name of the property * + * @param clazz The class to retrieve the property from + * @param propertyName The name of the property * @return A PropertyDescriptor instance or null if none exists */ public static PropertyDescriptor getProperty(Class clazz, String propertyName) { @@ -426,8 +421,7 @@ public static PropertyDescriptor getProperty(Class clazz, String propertyName try { return BeanUtils.getPropertyDescriptor(clazz, propertyName); - } - catch (Exception e) { + } catch (Exception e) { // if there are any errors in instantiating just return null for the moment return null; } @@ -435,12 +429,15 @@ public static PropertyDescriptor getProperty(Class clazz, String propertyName /** * Convenience method for converting a collection to an Object[] + * * @param c The collection - * @return An object array + * @return An object array */ - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) public static Object[] collectionToObjectArray(Collection c) { - if (c == null) return new Object[0]; + if (c == null) { + return new Object[0]; + } return c.toArray(new Object[c.size()]); } @@ -474,7 +471,7 @@ public static boolean isMatchBetweenPrimitiveAndWrapperTypes(Class leftType, Cla * with a bit of magic for native types and polymorphism i.e. Number assigned an int. * If either parameter is null an exception is thrown

* - * @param leftType The type of the left hand part of a notional assignment + * @param leftType The type of the left hand part of a notional assignment * @param rightType The type of the right hand part of a notional assignment * @return true if values of the right hand type can be assigned in Groovy to variables of the left hand type. */ @@ -504,8 +501,7 @@ public static boolean isGroovyAssignableFrom(Class leftType, Class rightTy if (r != null) { result = leftType.isAssignableFrom(r); } - } - else { + } else { // Otherwise it may just be assignable using normal Java polymorphism result = leftType.isAssignableFrom(rightType); } @@ -518,13 +514,13 @@ public static boolean isGroovyAssignableFrom(Class leftType, Class rightTy * recognize this concept of static properties but Groovy does. We also consider public static fields * as static properties with no getters/setters

* - * @param clazz The class to check for static property + * @param clazz The class to check for static property * @param propertyName The property name * @return true if the property with name propertyName has a static getter method */ @SuppressWarnings("rawtypes") public static boolean isStaticProperty(Class clazz, String propertyName) { - Method getter = BeanUtils.findDeclaredMethod(clazz, getGetterName(propertyName), (Class[])null); + Method getter = BeanUtils.findDeclaredMethod(clazz, getGetterName(propertyName), (Class[]) null); if (getter != null) { return isPublicStatic(getter); } @@ -534,8 +530,7 @@ public static boolean isStaticProperty(Class clazz, String propertyName) { if (f != null) { return isPublicStatic(f); } - } - catch (NoSuchFieldException ignored) { + } catch (NoSuchFieldException ignored) { // ignored } @@ -544,6 +539,7 @@ public static boolean isStaticProperty(Class clazz, String propertyName) { /** * Determine whether the method is declared public static + * * @param m * @return true if the method is declared public static */ @@ -554,6 +550,7 @@ public static boolean isPublicStatic(Method m) { /** * Determine whether the field is declared public static + * * @param f * @return true if the field is declared public static */ @@ -564,6 +561,7 @@ public static boolean isPublicStatic(Field f) { /** * Calculate the name for a getter method to retrieve the specified property + * * @param propertyName * @return The name for the getter method for this property, if it were to exist, i.e. getConstraints */ @@ -575,7 +573,7 @@ public static String getGetterName(String propertyName) { *

Get a static field value.

* * @param clazz The class to check for static property - * @param name The field name + * @param name The field name * @return The value if there is one, or null if unset OR there is no such field */ public static Object getStaticFieldValue(Class clazz, String name) { @@ -584,7 +582,8 @@ public static Object getStaticFieldValue(Class clazz, String name) { ReflectionUtils.makeAccessible(field); try { return field.get(clazz); - } catch (IllegalAccessException ignored) {} + } catch (IllegalAccessException ignored) { + } } return null; } @@ -593,19 +592,18 @@ public static Object getStaticFieldValue(Class clazz, String name) { *

Get a static property value, which has a public static getter or is just a public static field.

* * @param clazz The class to check for static property - * @param name The property name + * @param name The property name * @return The value if there is one, or null if unset OR there is no such property */ public static Object getStaticPropertyValue(Class clazz, String name) { - Method getter = BeanUtils.findDeclaredMethod(clazz, getGetterName(name), (Class[])null); + Method getter = BeanUtils.findDeclaredMethod(clazz, getGetterName(name), (Class[]) null); try { if (getter != null) { ReflectionUtils.makeAccessible(getter); return getter.invoke(clazz); } return getStaticFieldValue(clazz, name); - } - catch (Exception ignored) { + } catch (Exception ignored) { // ignored } return null; @@ -658,8 +656,7 @@ public static Object getFieldValue(Object obj, String name) { try { Field f = clazz.getDeclaredField(name); return f.get(obj); - } - catch (Exception e) { + } catch (Exception e) { return null; } } @@ -676,8 +673,7 @@ public static boolean isPublicField(Object obj, String name) { try { Field f = clazz.getDeclaredField(name); return Modifier.isPublic(f.getModifiers()); - } - catch (NoSuchFieldException e) { + } catch (NoSuchFieldException e) { return false; } } @@ -685,13 +681,15 @@ public static boolean isPublicField(Object obj, String name) { /** * Checks whether the specified property is inherited from a super class * - * @param clz The class to check + * @param clz The class to check * @param propertyName The property name * @return true if the property is inherited */ @SuppressWarnings("rawtypes") public static boolean isPropertyInherited(Class clz, String propertyName) { - if (clz == null) return false; + if (clz == null) { + return false; + } Assert.isTrue(StringUtils.hasText(propertyName), "Argument [propertyName] cannot be null or blank"); Class superClass = clz.getSuperclass(); @@ -715,6 +713,7 @@ public static boolean isPropertyGetter(Method method) { /** * Creates a concrete collection for the suppied interface + * * @param interfaceType The interface * @return ArrayList for List, TreeSet for SortedSet, HashSet for Set etc. */ @@ -723,11 +722,9 @@ public static Collection createConcreteCollection(Class interfaceType) { Collection elements; if (interfaceType.equals(List.class) || interfaceType.equals(Collection.class)) { elements = new ArrayList(); - } - else if (interfaceType.equals(SortedSet.class)) { + } else if (interfaceType.equals(SortedSet.class)) { elements = new TreeSet(); - } - else { + } else { elements = new HashSet(); } return elements; @@ -743,10 +740,14 @@ else if (interfaceType.equals(SortedSet.class)) { */ @SuppressWarnings("rawtypes") public static boolean isSetter(String name, Class[] args) { - if (!StringUtils.hasText(name) || args == null)return false; + if (!StringUtils.hasText(name) || args == null) { + return false; + } if (name.startsWith("set")) { - if (args.length != 1) return false; + if (args.length != 1) { + return false; + } return GrailsNameUtils.isPropertyMethodSuffix(name.substring(3)); } @@ -757,13 +758,13 @@ public static boolean isSetter(String name, Class[] args) { public static MetaClass getExpandoMetaClass(Class clazz) { MetaClassRegistry registry = GroovySystem.getMetaClassRegistry(); Assert.isTrue(registry.getMetaClassCreationHandler() instanceof ExpandoMetaClassCreationHandle, - "Grails requires an instance of [ExpandoMetaClassCreationHandle] to be set in Groovy's MetaClassRegistry! (current is : "+registry.getMetaClassCreationHandler()+")"); + "Grails requires an instance of [ExpandoMetaClassCreationHandle] to be set in Groovy's MetaClassRegistry! (current is : " + registry.getMetaClassCreationHandler() + ")"); MetaClass mc = registry.getMetaClass(clazz); AdaptingMetaClass adapter = null; if (mc instanceof AdaptingMetaClass) { adapter = (AdaptingMetaClass) mc; - mc = ((AdaptingMetaClass)mc).getAdaptee(); + mc = ((AdaptingMetaClass) mc).getAdaptee(); } if (!(mc instanceof ExpandoMetaClass)) { @@ -774,7 +775,7 @@ public static MetaClass getExpandoMetaClass(Class clazz) { adapter.setAdaptee(mc); } } - Assert.isTrue(mc instanceof ExpandoMetaClass,"BUG! Method must return an instance of [ExpandoMetaClass]!"); + Assert.isTrue(mc instanceof ExpandoMetaClass, "BUG! Method must return an instance of [ExpandoMetaClass]!"); return mc; } @@ -823,14 +824,16 @@ public static boolean getBooleanFromMap(String key, Map map) { * @return A boolean value which will be false if the map is null, the map doesn't contain the key or the value is false */ public static boolean getBooleanFromMap(String key, Map map, boolean defaultValue) { - if (map == null) return defaultValue; + if (map == null) { + return defaultValue; + } if (map.containsKey(key)) { Object o = map.get(key); if (o == null) { return defaultValue; } if (o instanceof Boolean) { - return (Boolean)o; + return (Boolean) o; } return Boolean.valueOf(o.toString()); } @@ -843,7 +846,7 @@ public static boolean getBooleanFromMap(String key, Map map, boolean defau * that refer to the same reference. Use with caution. * * @param target The target - * @param obj The property value + * @param obj The property value * @return The property name or null */ public static String findPropertyNameForValue(Object target, Object obj) { @@ -862,6 +865,7 @@ public static String findPropertyNameForValue(Object target, Object obj) { /** * Retrieves the name of a setter for the specified property name + * * @param propertyName The property name * @return The setter equivalent */ @@ -873,9 +877,9 @@ public static String getSetterName(String propertyName) { * Returns true if the name of the method specified and the number of arguments make it a javabean property getter. * The name is assumed to be a valid Java method name, that is not verified. * - * @param name The name of the method + * @param name The name of the method * @param returnType The return type of the method - * @param args The arguments + * @param args The arguments * @return true if it is a javabean property getter */ public static boolean isGetter(String name, Class returnType, Class[] args) { @@ -921,7 +925,7 @@ public static String getPropertyForSetter(String setterName) { * Returns whether the specified class is either within one of the specified packages or * within a subpackage of one of the packages * - * @param theClass The class + * @param theClass The class * @param packageList The list of packages * @return true if it is within the list of specified packages */ @@ -958,7 +962,7 @@ public static Object instantiateFromFlatConfig(Map flatConfig, S * attribute of the annotation contains a specific feature name * * @param controllerClass The class to inspect - * @param featureName The name of a feature to check for + * @param featureName The name of a feature to check for * @return true if controllerClass is marked with Enhanced and the enhancedFor attribute includes featureName, otherwise returns false * @see Enhanced * @see Enhanced#enhancedFor() @@ -966,9 +970,9 @@ public static Object instantiateFromFlatConfig(Map flatConfig, S public static Boolean hasBeenEnhancedForFeature(final Class controllerClass, final String featureName) { boolean hasBeenEnhanced = false; final Enhanced enhancedAnnotation = controllerClass.getAnnotation(Enhanced.class); - if(enhancedAnnotation != null) { + if (enhancedAnnotation != null) { final String[] enhancedFor = enhancedAnnotation.enhancedFor(); - if(enhancedFor != null) { + if (enhancedFor != null) { hasBeenEnhanced = GrailsArrayUtils.contains(enhancedFor, featureName); } } @@ -979,7 +983,7 @@ public static FastClass fastClass(Class superClass) { FastClass.Generator gen = new FastClass.Generator(); gen.setType(superClass); gen.setClassLoader(superClass.getClassLoader()); - gen.setUseCache( !Environment.isReloadingAgentEnabled() ); + gen.setUseCache(!Environment.isReloadingAgentEnabled()); return gen.create(); } } diff --git a/grails-core/src/main/groovy/grails/util/GrailsMessageSourceUtils.groovy b/grails-core/src/main/groovy/grails/util/GrailsMessageSourceUtils.groovy index c36fe2918e9..c87237dac42 100644 --- a/grails-core/src/main/groovy/grails/util/GrailsMessageSourceUtils.groovy +++ b/grails-core/src/main/groovy/grails/util/GrailsMessageSourceUtils.groovy @@ -21,11 +21,10 @@ package grails.util import groovy.transform.CompileStatic import org.springframework.context.MessageSource - /** - * A simple class that selects a single {@link org.springframework.context.MessageSource MessageSource} + * A simple class that selects a single {@link org.springframework.context.MessageSource MessageSource} * when two or more are present in the ApplicationContext. - * It defaults to the Grails or Spring {@link org.springframework.context.MessageSource MessageSource}, if present. + * It defaults to the Grails or Spring {@link org.springframework.context.MessageSource MessageSource}, if present. * * @author James Fredley * @since 7.0 @@ -33,23 +32,24 @@ import org.springframework.context.MessageSource @CompileStatic class GrailsMessageSourceUtils { - static MessageSource findPreferredMessageSource(List messageSources){ - if(!messageSources) { + + static MessageSource findPreferredMessageSource(List messageSources) { + if (!messageSources) { return null } - if(messageSources.size() == 1) { + if (messageSources.size() == 1) { return messageSources.get(0) } - MessageSource firstGrailsSpring = messageSources.find {messageSource -> + MessageSource firstGrailsSpring = messageSources.find { messageSource -> String className = messageSource.class.name // use the first Grails or Spring MessageSource className.startsWith("org.grails") || className.startsWith("grails") || className.startsWith("org.springframework") } // return the first Grails or Spring MessageSource - if(firstGrailsSpring) { + if (firstGrailsSpring) { return firstGrailsSpring } diff --git a/grails-core/src/main/groovy/grails/util/GrailsMetaClassUtils.java b/grails-core/src/main/groovy/grails/util/GrailsMetaClassUtils.java index dd72b7b020b..984fb620ceb 100644 --- a/grails-core/src/main/groovy/grails/util/GrailsMetaClassUtils.java +++ b/grails-core/src/main/groovy/grails/util/GrailsMetaClassUtils.java @@ -29,15 +29,14 @@ import groovy.lang.MetaClassRegistry; import groovy.lang.MetaMethod; import groovy.lang.MetaProperty; - -import java.lang.reflect.Constructor; -import java.util.List; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.groovy.runtime.metaclass.ThreadManagedMetaBeanProperty; import org.springframework.beans.BeanUtils; +import java.lang.reflect.Constructor; +import java.util.List; + /** * Provides utility methods for working with the Groovy MetaClass API. * @@ -62,11 +61,11 @@ public static MetaClassRegistry getRegistry() { /** * Copies the ExpandoMetaClass dynamic methods and properties from one Class to another. * - * @param fromClass The source class - * @param toClass The destination class + * @param fromClass The source class + * @param toClass The destination class * @param removeSource Whether to remove the source class after completion. True if yes */ - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) public static void copyExpandoMetaClass(Class fromClass, Class toClass, boolean removeSource) { MetaClassRegistry registry = getRegistry(); @@ -77,20 +76,19 @@ public static void copyExpandoMetaClass(Class fromClass, Class toClass, bo ExpandoMetaClass emc; if (oldMetaClass instanceof AdaptingMetaClass) { - adapter = ((AdaptingMetaClass)oldMetaClass); - emc = (ExpandoMetaClass)adapter.getAdaptee(); + adapter = ((AdaptingMetaClass) oldMetaClass); + emc = (ExpandoMetaClass) adapter.getAdaptee(); if (LOG.isDebugEnabled()) { - LOG.debug("Obtained adapted MetaClass ["+emc+"] from AdapterMetaClass instance ["+adapter+"]"); + LOG.debug("Obtained adapted MetaClass [" + emc + "] from AdapterMetaClass instance [" + adapter + "]"); } if (removeSource) { registry.removeMetaClass(fromClass); } - } - else { - emc = (ExpandoMetaClass)oldMetaClass; + } else { + emc = (ExpandoMetaClass) oldMetaClass; if (LOG.isDebugEnabled()) { - LOG.debug("No adapter MetaClass found, using original ["+emc+"]"); + LOG.debug("No adapter MetaClass found, using original [" + emc + "]"); } } @@ -102,16 +100,15 @@ public static void copyExpandoMetaClass(Class fromClass, Class toClass, bo Closure callable = cim.getClosure(); if (!cim.isStatic()) { replacement.setProperty(cim.getName(), callable); - } - else { - ((GroovyObject)replacement.getProperty(ExpandoMetaClass.STATIC_QUALIFIER)).setProperty(cim.getName(),callable); + } else { + ((GroovyObject) replacement.getProperty(ExpandoMetaClass.STATIC_QUALIFIER)).setProperty(cim.getName(), callable); } } } for (Object o : emc.getExpandoProperties()) { if (o instanceof ThreadManagedMetaBeanProperty) { - ThreadManagedMetaBeanProperty mbp = (ThreadManagedMetaBeanProperty)o; + ThreadManagedMetaBeanProperty mbp = (ThreadManagedMetaBeanProperty) o; replacement.setProperty(mbp.getName(), mbp.getInitialValue()); } } @@ -119,23 +116,21 @@ public static void copyExpandoMetaClass(Class fromClass, Class toClass, bo if (adapter == null) { if (LOG.isDebugEnabled()) { - LOG.debug("Adding MetaClass for class ["+toClass+"] MetaClass ["+replacement+"]"); + LOG.debug("Adding MetaClass for class [" + toClass + "] MetaClass [" + replacement + "]"); } registry.setMetaClass(toClass, replacement); - } - else { + } else { if (LOG.isDebugEnabled()) { LOG.debug("Adding MetaClass for class [" + toClass + "] MetaClass [" + replacement + "] with adapter [" + adapter + "]"); } try { Constructor c = adapter.getClass().getConstructor(new Class[]{MetaClass.class}); - MetaClass newAdapter = (MetaClass) BeanUtils.instantiateClass(c,new Object[]{replacement}); - registry.setMetaClass(toClass,newAdapter); - } - catch (NoSuchMethodException e) { + MetaClass newAdapter = (MetaClass) BeanUtils.instantiateClass(c, new Object[]{replacement}); + registry.setMetaClass(toClass, newAdapter); + } catch (NoSuchMethodException e) { if (LOG.isDebugEnabled()) { - LOG.debug("Exception thrown constructing new MetaClass adapter when reloading: " + e.getMessage(),e); + LOG.debug("Exception thrown constructing new MetaClass adapter when reloading: " + e.getMessage(), e); } } } @@ -154,7 +149,7 @@ public static ExpandoMetaClass getExpandoMetaClass(Class aClass) { registry.removeMetaClass(aClass); mc = registry.getMetaClass(aClass); if (mc instanceof ExpandoMetaClass) { - return (ExpandoMetaClass)mc; + return (ExpandoMetaClass) mc; } ExpandoMetaClass emc = new ExpandoMetaClass(aClass, true, true); @@ -167,9 +162,9 @@ public static MetaClass getMetaClass(Object instance) { if (instance instanceof GroovyObject) { GroovyObject groovyObject = (GroovyObject) instance; MetaClass metaClass = groovyObject.getMetaClass(); - + metaClass = unwrapDelegatingMetaClass(metaClass); - + if (!(metaClass instanceof ExpandoMetaClass)) { metaClass = getExpandoMetaClass(instance.getClass()); groovyObject.setMetaClass(metaClass); @@ -181,9 +176,9 @@ public static MetaClass getMetaClass(Object instance) { } private static MetaClass unwrapDelegatingMetaClass(MetaClass metaClass) { - int counter=0; - while(metaClass instanceof DelegatingMetaClass && counter++ < MAX_DELEGATE_LEVELS) { - metaClass = ((DelegatingMetaClass)metaClass).getAdaptee(); + int counter = 0; + while (metaClass instanceof DelegatingMetaClass && counter++ < MAX_DELEGATE_LEVELS) { + metaClass = ((DelegatingMetaClass) metaClass).getAdaptee(); } return metaClass; } @@ -202,8 +197,8 @@ public static Object getPropertyIfExists(Object instance, String property) { /** * Obtains a property of an instance if it exists * - * @param instance The instance - * @param property The property + * @param instance The instance + * @param property The property * @param requiredType The required type of the property * @return The property value */ @@ -224,7 +219,7 @@ public static T getPropertyIfExists(Object instance, String property, Class< /** * Invokes a method if it exists otherwise returns null * - * @param instance The instance + * @param instance The instance * @param methodName The method name * @return The result of the method call or null */ @@ -235,10 +230,9 @@ public static Object invokeMethodIfExists(Object instance, String methodName) { /** * Invokes a method if it exists otherwise returns null * - * @param instance The instance + * @param instance The instance * @param methodName The method name - * @param args The arguments - * + * @param args The arguments * @return The result of the method call or null */ public static Object invokeMethodIfExists(Object instance, String methodName, Object[] args) { diff --git a/grails-core/src/main/groovy/grails/util/GrailsStringUtils.groovy b/grails-core/src/main/groovy/grails/util/GrailsStringUtils.groovy index 3e1b73351e5..26296771c90 100644 --- a/grails-core/src/main/groovy/grails/util/GrailsStringUtils.groovy +++ b/grails-core/src/main/groovy/grails/util/GrailsStringUtils.groovy @@ -30,7 +30,7 @@ import java.util.regex.Pattern * @since 2.3.6 */ @CompileStatic -abstract class GrailsStringUtils extends StringUtils{ +abstract class GrailsStringUtils extends StringUtils { private static final Pattern BOOLEAN_PATTERN = Pattern.compile(/^on$|^true$|^yes$|^1$/, Pattern.CASE_INSENSITIVE) @@ -62,17 +62,16 @@ abstract class GrailsStringUtils extends StringUtils{ * @param str The string to apply the substring * @param token The token to match */ - static String substringBefore(String str, String token) { - if(token == null) return str + static String substringBefore(String str, String token) { + if (token == null) return str def i = str.indexOf(token) - if(i > -1) { + if (i > -1) { return str.substring(0, i) } return str } - /** * Returns a substring before the last occurance of the given token * @@ -88,11 +87,11 @@ abstract class GrailsStringUtils extends StringUtils{ * @param str The string to apply the substring * @param token The token to match */ - static String substringBeforeLast(String str, String token) { - if(token == null) return str + static String substringBeforeLast(String str, String token) { + if (token == null) return str def i = str.lastIndexOf(token) - if(i > -1) { + if (i > -1) { return str.substring(0, i) } return str @@ -113,11 +112,11 @@ abstract class GrailsStringUtils extends StringUtils{ * @param str The string to apply the substring * @param token The token to match */ - static String substringAfter(String str, String token) { - if(token == null) return str + static String substringAfter(String str, String token) { + if (token == null) return str def i = str.indexOf(token) - if(i > -1) { + if (i > -1) { return str.substring(i + token.length()) } return str @@ -138,11 +137,11 @@ abstract class GrailsStringUtils extends StringUtils{ * @param str The string to apply the substring * @param token The token to match */ - static String substringAfterLast(String str, String token) { - if(token == null) return str + static String substringAfterLast(String str, String token) { + if (token == null) return str def i = str.lastIndexOf(token) - if(i > -1) { + if (i > -1) { return str.substring(i + token.length()) } return str @@ -155,10 +154,9 @@ abstract class GrailsStringUtils extends StringUtils{ * @return The trimmed string */ static String trimStart(String str, String start) { - if(!str || !start || !str.startsWith(start)) { + if (!str || !start || !str.startsWith(start)) { return str - } - else { + } else { return str.substring(start.length()) } } @@ -190,7 +188,7 @@ abstract class GrailsStringUtils extends StringUtils{ * @return The name of the file excluding path and extension */ static String getFileBasename(String path) { - stripFilenameExtension( getFilename(path) ) + stripFilenameExtension(getFilename(path)) } /** @@ -207,12 +205,12 @@ abstract class GrailsStringUtils extends StringUtils{ * GrailsStringUtils.trimToNull("xyz") = "xyz" * GrailsStringUtils.trimToNull(" xyz ") = "xyz" *
- * + * * based on https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/StringUtils.java#L8838 * - * @param str the String to be trimmed, may be null + * @param str the String to be trimmed, may be null * @return the trimmed String, - * {@code null} if only containing space, empty or null String input + * {@code null} if only containing space, empty or null String input * @since 7.0.0 */ static String trimToNull(String str) { diff --git a/grails-core/src/main/groovy/grails/util/GrailsUtil.java b/grails-core/src/main/groovy/grails/util/GrailsUtil.java index 4f344f1f3c4..e34c02c11bd 100644 --- a/grails-core/src/main/groovy/grails/util/GrailsUtil.java +++ b/grails-core/src/main/groovy/grails/util/GrailsUtil.java @@ -31,11 +31,11 @@ * @author Graeme Rocher * @since 0.2 */ -public class GrailsUtil { +public final class GrailsUtil { private static final Log LOG = LogFactory.getLog(GrailsUtil.class); private static final boolean LOG_DEPRECATED = Boolean.valueOf(System.getProperty("grails.log.deprecated", String.valueOf(Environment.isDevelopmentMode()))); - private static final StackTraceFilterer stackFilterer = new DefaultStackTraceFilterer(); + private static final StackTraceFilterer STACK_FILTERER = new DefaultStackTraceFilterer(); private GrailsUtil() { } @@ -60,7 +60,7 @@ private static boolean isBlank(String value) { /** * Logs warning message about deprecation of specified property or method of some class. * - * @param clazz A class + * @param clazz A class * @param methodOrPropName Name of deprecated property or method */ public static void deprecated(Class clazz, String methodOrPropName) { @@ -70,9 +70,9 @@ public static void deprecated(Class clazz, String methodOrPropName) { /** * Logs warning message about deprecation of specified property or method of some class. * - * @param clazz A class + * @param clazz A class * @param methodOrPropName Name of deprecated property or method - * @param version Version of Grails release in which property or method were deprecated + * @param version Version of Grails release in which property or method were deprecated */ public static void deprecated(Class clazz, String methodOrPropName, String version) { if (LOG_DEPRECATED) { @@ -105,7 +105,7 @@ public static void warn(String message) { } public static void printSanitizedStackTrace(Throwable t, PrintWriter p) { - printSanitizedStackTrace(t, p, stackFilterer); + printSanitizedStackTrace(t, p, STACK_FILTERER); } public static void printSanitizedStackTrace(Throwable t, PrintWriter p, StackTraceFilterer stackTraceFilterer) { @@ -114,8 +114,8 @@ public static void printSanitizedStackTrace(Throwable t, PrintWriter p, StackTra StackTraceElement[] trace = t.getStackTrace(); for (StackTraceElement stackTraceElement : trace) { p.println("at " + stackTraceElement.getClassName() + - "(" + stackTraceElement.getMethodName() + - ":" + stackTraceElement.getLineNumber() + ")"); + "(" + stackTraceElement.getMethodName() + + ":" + stackTraceElement.getLineNumber() + ")"); } } @@ -125,6 +125,7 @@ public static void printSanitizedStackTrace(Throwable t) { /** *

Extracts the root cause of the exception, no matter how nested it is

+ * * @param t * @return The deepest cause of the exception that can be found */ @@ -139,22 +140,23 @@ public static Throwable extractRootCause(Throwable t) { /** *

Get the root cause of an exception and sanitize it for display to the user

*

This will MODIFY the stacktrace of the root cause exception object and return it

+ * * @param t * @return The root cause exception instance, with its stace trace modified to filter out grails runtime classes */ public static Throwable sanitizeRootCause(Throwable t) { - return stackFilterer.filter(extractRootCause(t)); + return STACK_FILTERER.filter(extractRootCause(t)); } /** *

Sanitize the exception and ALL nested causes

*

This will MODIFY the stacktrace of the exception instance and all its causes irreversibly

+ * * @param t * @return The root cause exception instances, with stack trace modified to filter out grails runtime classes */ public static Throwable deepSanitize(Throwable t) { - return stackFilterer.filter(t, true); + return STACK_FILTERER.filter(t, true); } - } diff --git a/grails-core/src/main/groovy/grails/util/Holders.java b/grails-core/src/main/groovy/grails/util/Holders.java index 8132c41b6ff..b1bfea711b1 100644 --- a/grails-core/src/main/groovy/grails/util/Holders.java +++ b/grails-core/src/main/groovy/grails/util/Holders.java @@ -36,13 +36,11 @@ /** * Allows looking up key classes in a static context * - * * @author Burt Beckwith * @author Graeme Rocher - * * @since 2.0 */ -public class Holders { +public final class Holders { private static final Log LOG = LogFactory.getLog(Holders.class); private static Holder pluginManagers = new Holder("PluginManager"); @@ -52,6 +50,7 @@ public class Holders { private static List applicationDiscoveryStrategies = GrailsFactoriesLoader.loadFactories(GrailsApplicationDiscoveryStrategy.class, Holders.class.getClassLoader()); private static Holder servletContexts; + static { createServletContextsHolder(); @@ -88,11 +87,11 @@ public static Object getServletContext() { } public static ApplicationContext getApplicationContext() { - for(GrailsApplicationDiscoveryStrategy strategy : applicationDiscoveryStrategies) { + for (GrailsApplicationDiscoveryStrategy strategy : applicationDiscoveryStrategies) { ApplicationContext applicationContext = strategy.findApplicationContext(); - if(applicationContext != null ) { + if (applicationContext != null) { boolean running = ((Lifecycle) applicationContext).isRunning(); - if(running) { + if (running) { return applicationContext; } } @@ -105,22 +104,23 @@ public static ApplicationContext getApplicationContext() { * @return The ApplicationContext or null if it doesn't exist */ public static ApplicationContext findApplicationContext() { - for(GrailsApplicationDiscoveryStrategy strategy : applicationDiscoveryStrategies) { + for (GrailsApplicationDiscoveryStrategy strategy : applicationDiscoveryStrategies) { ApplicationContext applicationContext = strategy.findApplicationContext(); - if(applicationContext != null) { + if (applicationContext != null) { return applicationContext; } } return null; } + /** * * @return The ApplicationContext or null if it doesn't exist */ public static GrailsApplication findApplication() { - for(GrailsApplicationDiscoveryStrategy strategy : applicationDiscoveryStrategies) { + for (GrailsApplicationDiscoveryStrategy strategy : applicationDiscoveryStrategies) { GrailsApplication grailsApplication = strategy.findGrailsApplication(); - if(grailsApplication != null) { + if (grailsApplication != null) { return grailsApplication; } } @@ -180,8 +180,7 @@ public static GrailsPluginManager getPluginManager(boolean mappedOnly) { try { Thread.sleep(100); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { break; } } @@ -216,17 +215,14 @@ private static T get(Holder holder, String type, boolean mappedOnly) { private static void createServletContextsHolder() { try { Class clazz = Holders.class.getClassLoader().loadClass("grails.web.context.WebRequestServletHolder"); - servletContexts = (Holder)clazz.newInstance(); - } - catch (ClassNotFoundException e) { + servletContexts = (Holder) clazz.newInstance(); + } catch (ClassNotFoundException e) { // shouldn't happen LOG.debug("Error initializing servlet context holder, not running in Servlet environment: " + e.getMessage(), e); - } - catch (InstantiationException e) { + } catch (InstantiationException e) { // shouldn't happen LOG.debug("Error initializing servlet context holder, not running in Servlet environment: " + e.getMessage(), e); - } - catch (IllegalAccessException e) { + } catch (IllegalAccessException e) { // shouldn't happen LOG.debug("Error initializing servlet context holder, not running in Servlet environment: " + e.getMessage(), e); } diff --git a/grails-core/src/main/groovy/grails/util/Mixin.java b/grails-core/src/main/groovy/grails/util/Mixin.java index 3de84172871..4e5f0448c14 100644 --- a/grails-core/src/main/groovy/grails/util/Mixin.java +++ b/grails-core/src/main/groovy/grails/util/Mixin.java @@ -18,14 +18,13 @@ */ package grails.util; +import org.codehaus.groovy.transform.GroovyASTTransformationClass; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.codehaus.groovy.transform.GroovyASTTransformationClass; - - /** * * @author Graeme Rocher @@ -38,5 +37,6 @@ @GroovyASTTransformationClass("org.grails.compiler.injection.MixinTransformation") @Deprecated public @interface Mixin { - Class[] value (); + + Class[] value(); } diff --git a/grails-core/src/main/groovy/grails/util/MixinTargetAware.groovy b/grails-core/src/main/groovy/grails/util/MixinTargetAware.groovy index 78e20b97e6b..86399a0de82 100644 --- a/grails-core/src/main/groovy/grails/util/MixinTargetAware.groovy +++ b/grails-core/src/main/groovy/grails/util/MixinTargetAware.groovy @@ -26,7 +26,7 @@ package grails.util * @deprecated Mixins are deprecated in Groovy 4.0 and will be removed in a future version of Grails. */ @Deprecated -public interface MixinTargetAware { +interface MixinTargetAware { void setTarget(T targetObject) } \ No newline at end of file diff --git a/grails-core/src/main/groovy/grails/util/Pair.java b/grails-core/src/main/groovy/grails/util/Pair.java index 12bfe10bdae..30e9e9e0ba9 100644 --- a/grails-core/src/main/groovy/grails/util/Pair.java +++ b/grails-core/src/main/groovy/grails/util/Pair.java @@ -16,10 +16,10 @@ * specific language governing permissions and limitations * under the License. */ - package grails.util; public class Pair { + final A aValue; final B bValue; @@ -47,25 +47,30 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; - Pair other = (Pair)obj; + } + Pair other = (Pair) obj; if (aValue == null) { - if (other.aValue != null) + if (other.aValue != null) { return false; - } - else if (!aValue.equals(other.aValue)) + } + } else if (!aValue.equals(other.aValue)) { return false; + } if (bValue == null) { - if (other.bValue != null) + if (other.bValue != null) { return false; - } - else if (!bValue.equals(other.bValue)) + } + } else if (!bValue.equals(other.bValue)) { return false; + } return true; } diff --git a/grails-core/src/main/groovy/grails/util/Triple.java b/grails-core/src/main/groovy/grails/util/Triple.java index cc166b58f27..9ab3b2e1cf1 100644 --- a/grails-core/src/main/groovy/grails/util/Triple.java +++ b/grails-core/src/main/groovy/grails/util/Triple.java @@ -16,10 +16,10 @@ * specific language governing permissions and limitations * under the License. */ - package grails.util; public class Triple { + final A aValue; final B bValue; final C cValue; @@ -54,31 +54,37 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; - Triple other = (Triple)obj; + } + Triple other = (Triple) obj; if (aValue == null) { - if (other.aValue != null) + if (other.aValue != null) { return false; - } - else if (!aValue.equals(other.aValue)) + } + } else if (!aValue.equals(other.aValue)) { return false; + } if (bValue == null) { - if (other.bValue != null) + if (other.bValue != null) { return false; - } - else if (!bValue.equals(other.bValue)) + } + } else if (!bValue.equals(other.bValue)) { return false; + } if (cValue == null) { - if (other.cValue != null) + if (other.cValue != null) { return false; - } - else if (!cValue.equals(other.cValue)) + } + } else if (!cValue.equals(other.cValue)) { return false; + } return true; } diff --git a/grails-core/src/main/groovy/grails/util/TypeConvertingMap.groovy b/grails-core/src/main/groovy/grails/util/TypeConvertingMap.groovy index 710bc40f16c..7a503e48a9b 100644 --- a/grails-core/src/main/groovy/grails/util/TypeConvertingMap.groovy +++ b/grails-core/src/main/groovy/grails/util/TypeConvertingMap.groovy @@ -31,6 +31,7 @@ import groovy.transform.CompileStatic */ @CompileStatic class TypeConvertingMap extends AbstractTypeConvertingMap { + TypeConvertingMap() { super() } diff --git a/grails-core/src/main/groovy/grails/validation/Constrained.java b/grails-core/src/main/groovy/grails/validation/Constrained.java index b275050790e..7ecc53ec59d 100644 --- a/grails-core/src/main/groovy/grails/validation/Constrained.java +++ b/grails-core/src/main/groovy/grails/validation/Constrained.java @@ -44,13 +44,13 @@ public interface Constrained { /** * @return Returns the maximum possible value. */ - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) Comparable getMax(); /** * @return Returns the minimum possible value. */ - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) Comparable getMin(); /** diff --git a/grails-core/src/main/groovy/grails/validation/ConstraintsEvaluator.java b/grails-core/src/main/groovy/grails/validation/ConstraintsEvaluator.java index ee9a2d115f4..9f0fb1dd3a8 100644 --- a/grails-core/src/main/groovy/grails/validation/ConstraintsEvaluator.java +++ b/grails-core/src/main/groovy/grails/validation/ConstraintsEvaluator.java @@ -38,6 +38,7 @@ public interface ConstraintsEvaluator { /** * The default constraints to use + * * @return A map of default constraints */ Map getDefaultConstraints(); @@ -53,7 +54,7 @@ public interface ConstraintsEvaluator { /** * Evaluate constraints for the given class * - * @param cls The class to evaluate constraints for + * @param cls The class to evaluate constraints for * @param defaultNullable indicates if properties are nullable by default * @return A map of constrained properties */ @@ -62,9 +63,9 @@ public interface ConstraintsEvaluator { /** * Evaluate constraints for the given class * - * @param cls The class to evaluate constraints for - * @param defaultNullable indicates if properties are nullable by default - * @param useOnlyAdHocConstraints indicates if evaluating without pre-declared constraints + * @param cls The class to evaluate constraints for + * @param defaultNullable indicates if properties are nullable by default + * @param useOnlyAdHocConstraints indicates if evaluating without pre-declared constraints * @param adHocConstraintsClosures ad-hoc constraints to evaluate for * @return A map of constrained properties */ diff --git a/grails-core/src/main/groovy/grails/validation/DeferredBindingActions.java b/grails-core/src/main/groovy/grails/validation/DeferredBindingActions.java index 5d9a453b1b4..2a6fb6babf5 100644 --- a/grails-core/src/main/groovy/grails/validation/DeferredBindingActions.java +++ b/grails-core/src/main/groovy/grails/validation/DeferredBindingActions.java @@ -31,10 +31,10 @@ * @author Graeme Rocher * @since 2.0 */ -public class DeferredBindingActions { +public final class DeferredBindingActions { + private static final Log LOG = LogFactory.getLog(DeferredBindingActions.class); private static ThreadLocal> deferredBindingActions = new ThreadLocal>(); - private static Log LOG = LogFactory.getLog(DeferredBindingActions.class); static { ShutdownOperations.addOperation(new Runnable() { diff --git a/grails-core/src/main/groovy/grails/validation/ValidationException.java b/grails-core/src/main/groovy/grails/validation/ValidationException.java index 35f1c2d4fee..6c0a46e89c2 100644 --- a/grails-core/src/main/groovy/grails/validation/ValidationException.java +++ b/grails-core/src/main/groovy/grails/validation/ValidationException.java @@ -29,6 +29,7 @@ * @since 1.2 */ public class ValidationException extends GrailsException { + private static final long serialVersionUID = 1L; private Errors errors; private String fullMessage; @@ -43,17 +44,17 @@ public Errors getErrors() { return errors; } - public String getMessage() { - return fullMessage; + public String getMessage() { + return fullMessage; } - + public static String formatErrors(Errors errors) { return formatErrors(errors, null); } - + public static String formatErrors(Errors errors, String msg) { StringBuilder b = new StringBuilder(); - if(msg != null && msg.length() > 0) { + if (msg != null && msg.length() > 0) { b.append(msg).append(":\n"); } for (ObjectError error : errors.getAllErrors()) { diff --git a/grails-core/src/main/groovy/grails/web/Action.java b/grails-core/src/main/groovy/grails/web/Action.java index 4d3099423c1..7d1778c75e9 100644 --- a/grails-core/src/main/groovy/grails/web/Action.java +++ b/grails-core/src/main/groovy/grails/web/Action.java @@ -32,5 +32,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Action { + Class[] commandObjects() default {}; } diff --git a/grails-core/src/main/groovy/grails/web/CamelCaseUrlConverter.java b/grails-core/src/main/groovy/grails/web/CamelCaseUrlConverter.java index 0793850656a..b0e6d4f865a 100644 --- a/grails-core/src/main/groovy/grails/web/CamelCaseUrlConverter.java +++ b/grails-core/src/main/groovy/grails/web/CamelCaseUrlConverter.java @@ -21,7 +21,6 @@ import grails.util.GrailsNameUtils; import org.springframework.util.StringUtils; - /** * URL converter that allows for camel case URLs * diff --git a/grails-core/src/main/groovy/grails/web/HyphenatedUrlConverter.java b/grails-core/src/main/groovy/grails/web/HyphenatedUrlConverter.java index a9ba2f3668a..fa9033ab571 100644 --- a/grails-core/src/main/groovy/grails/web/HyphenatedUrlConverter.java +++ b/grails-core/src/main/groovy/grails/web/HyphenatedUrlConverter.java @@ -18,7 +18,6 @@ */ package grails.web; - import org.springframework.util.StringUtils; /** diff --git a/grails-core/src/main/groovy/grails/web/UrlConverter.java b/grails-core/src/main/groovy/grails/web/UrlConverter.java index f2a44b7116e..3d544596201 100644 --- a/grails-core/src/main/groovy/grails/web/UrlConverter.java +++ b/grails-core/src/main/groovy/grails/web/UrlConverter.java @@ -25,6 +25,7 @@ * @since 2.0 */ public interface UrlConverter { + String BEAN_NAME = "grailsUrlConverter"; String toUrlElement(String propertyOrClassName); diff --git a/grails-core/src/main/groovy/org/grails/beans/support/PropertiesEditor.java b/grails-core/src/main/groovy/org/grails/beans/support/PropertiesEditor.java index 91ac4018c5a..b316494a91c 100644 --- a/grails-core/src/main/groovy/org/grails/beans/support/PropertiesEditor.java +++ b/grails-core/src/main/groovy/org/grails/beans/support/PropertiesEditor.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.beans.support; import java.util.Map; @@ -25,26 +24,26 @@ /** * Fixed version of Spring's PropertiesEditor that converts all keys and values to String values - * + *

* java.util.Properties should only contain String keys and values - * + * * @author Lari Hotari * @since 2.3.6 * */ public class PropertiesEditor extends org.springframework.beans.propertyeditors.PropertiesEditor { - @SuppressWarnings({ "unchecked", "rawtypes" }) + + @SuppressWarnings({"unchecked", "rawtypes"}) @Override public void setValue(Object value) { if (!(value instanceof Properties) && value instanceof Map) { Properties props = new Properties(); - for(Map.Entry entry : (Set)((Map)value).entrySet()) { + for (Map.Entry entry : (Set) ((Map) value).entrySet()) { props.put(String.valueOf(entry.getKey()), entry.getValue() != null ? String.valueOf(entry.getValue()) : null); } super.setValue(props); - } - else { + } else { super.setValue(value); } } -} \ No newline at end of file +} diff --git a/grails-core/src/main/groovy/org/grails/boot/internal/EnableAutoConfiguration.java b/grails-core/src/main/groovy/org/grails/boot/internal/EnableAutoConfiguration.java index 3a8f951e5cf..39b38c08980 100644 --- a/grails-core/src/main/groovy/org/grails/boot/internal/EnableAutoConfiguration.java +++ b/grails-core/src/main/groovy/org/grails/boot/internal/EnableAutoConfiguration.java @@ -32,4 +32,5 @@ @Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) public @interface EnableAutoConfiguration { + } diff --git a/grails-core/src/main/groovy/org/grails/boot/internal/JavaCompiler.groovy b/grails-core/src/main/groovy/org/grails/boot/internal/JavaCompiler.groovy index 18dc7e6f59e..96345f163cc 100644 --- a/grails-core/src/main/groovy/org/grails/boot/internal/JavaCompiler.groovy +++ b/grails-core/src/main/groovy/org/grails/boot/internal/JavaCompiler.groovy @@ -25,7 +25,6 @@ import org.springframework.util.ClassUtils import javax.tools.ToolProvider import java.nio.charset.Charset - /** * Helper for recompiling Java code at runtime * diff --git a/grails-core/src/main/groovy/org/grails/compiler/CriteriaTypeCheckingExtension.groovy b/grails-core/src/main/groovy/org/grails/compiler/CriteriaTypeCheckingExtension.groovy index 8a00133f8a3..b70cd5f77aa 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/CriteriaTypeCheckingExtension.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/CriteriaTypeCheckingExtension.groovy @@ -23,38 +23,36 @@ import org.codehaus.groovy.ast.expr.ArgumentListExpression import org.codehaus.groovy.ast.expr.ClassExpression import org.codehaus.groovy.ast.expr.MethodCall import org.codehaus.groovy.ast.expr.MethodCallExpression -import org.grails.compiler.injection.GrailsASTUtils import org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport.TypeCheckingDSL - +import org.grails.compiler.injection.GrailsASTUtils /** - * * @since 2.4 */ class CriteriaTypeCheckingExtension extends TypeCheckingDSL { @Override - public Object run() { + Object run() { setup { newScope() } finish { scopeExit() } - + methodNotFound { ClassNode receiver, String name, ArgumentListExpression argList, ClassNode[] argTypes, MethodCall call -> def dynamicCall - if(currentScope.processingCriteriaClosure) { - dynamicCall = makeDynamic (call) + if (currentScope.processingCriteriaClosure) { + dynamicCall = makeDynamic(call) } dynamicCall } - + afterMethodCall { MethodCall call -> - if(isCriteriaCall(call)) { + if (isCriteriaCall(call)) { scopeExit() } } - + beforeMethodCall { MethodCall call -> - if(isCriteriaCall(call)) { + if (isCriteriaCall(call)) { newScope { processingCriteriaClosure = true } @@ -62,11 +60,11 @@ class CriteriaTypeCheckingExtension extends TypeCheckingDSL { } null } - + protected boolean isCriteriaCall(MethodCall call) { - call instanceof MethodCallExpression && - call.objectExpression instanceof ClassExpression && - GrailsASTUtils.isDomainClass(call.objectExpression.type, null) && - (call.method.value == 'withCriteria' || call.method.value == 'createCriteria') + call instanceof MethodCallExpression && + call.objectExpression instanceof ClassExpression && + GrailsASTUtils.isDomainClass(call.objectExpression.type, null) && + (call.method.value == 'withCriteria' || call.method.value == 'createCriteria') } } diff --git a/grails-core/src/main/groovy/org/grails/compiler/DomainMappingTypeCheckingExtension.groovy b/grails-core/src/main/groovy/org/grails/compiler/DomainMappingTypeCheckingExtension.groovy index b95b5dc7b1e..9fb36ed2bb6 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/DomainMappingTypeCheckingExtension.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/DomainMappingTypeCheckingExtension.groovy @@ -23,26 +23,25 @@ import org.codehaus.groovy.ast.expr.ArgumentListExpression import org.codehaus.groovy.ast.expr.ClosureExpression import org.codehaus.groovy.ast.expr.MethodCall import org.codehaus.groovy.ast.stmt.EmptyStatement -import org.grails.compiler.injection.GrailsASTUtils import org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport.TypeCheckingDSL +import org.grails.compiler.injection.GrailsASTUtils /** - * * @since 2.4 */ class DomainMappingTypeCheckingExtension extends TypeCheckingDSL { - + @Override - public Object run() { + Object run() { setup { newScope() } finish { scopeExit() } - + beforeVisitClass { ClassNode classNode -> def mappingProperty = classNode.getField('mapping') - if(mappingProperty && mappingProperty.isStatic() && mappingProperty.initialExpression instanceof ClosureExpression) { + if (mappingProperty && mappingProperty.isStatic() && mappingProperty.initialExpression instanceof ClosureExpression) { def sourceUnit = classNode?.module?.context - if(GrailsASTUtils.isDomainClass(classNode, sourceUnit)) { + if (GrailsASTUtils.isDomainClass(classNode, sourceUnit)) { newScope { mappingClosureCode = mappingProperty.initialExpression.code } @@ -56,7 +55,7 @@ class DomainMappingTypeCheckingExtension extends TypeCheckingDSL { } afterVisitClass { ClassNode classNode -> - if(currentScope.mappingClosureCode) { + if (currentScope.mappingClosureCode) { def mappingProperty = classNode.getField('mapping') mappingProperty.initialExpression.code = currentScope.mappingClosureCode currentScope.checkingMappingClosure = true @@ -67,12 +66,12 @@ class DomainMappingTypeCheckingExtension extends TypeCheckingDSL { methodNotFound { ClassNode receiver, String name, ArgumentListExpression argList, ClassNode[] argTypes, MethodCall call -> def dynamicCall - if(currentScope.mappingClosureCode && currentScope.checkingMappingClosure) { - dynamicCall = makeDynamic (call) + if (currentScope.mappingClosureCode && currentScope.checkingMappingClosure) { + dynamicCall = makeDynamic(call) } dynamicCall } - + null } } diff --git a/grails-core/src/main/groovy/org/grails/compiler/DynamicFinderTypeCheckingExtension.groovy b/grails-core/src/main/groovy/org/grails/compiler/DynamicFinderTypeCheckingExtension.groovy index fa252eaf633..da6431576aa 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/DynamicFinderTypeCheckingExtension.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/DynamicFinderTypeCheckingExtension.groovy @@ -18,18 +18,18 @@ */ package org.grails.compiler +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.expr.ArgumentListExpression +import org.codehaus.groovy.ast.expr.MethodCall +import org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport.TypeCheckingDSL +import org.grails.compiler.injection.GrailsASTUtils + import java.lang.reflect.Modifier import static org.codehaus.groovy.ast.ClassHelper.CLASS_Type import static org.codehaus.groovy.ast.ClassHelper.Integer_TYPE import static org.codehaus.groovy.ast.ClassHelper.LIST_TYPE -import org.codehaus.groovy.ast.ClassNode -import org.codehaus.groovy.ast.expr.ArgumentListExpression -import org.codehaus.groovy.ast.expr.MethodCall -import org.grails.compiler.injection.GrailsASTUtils -import org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport.TypeCheckingDSL - /** * * @since 2.4 @@ -40,14 +40,14 @@ class DynamicFinderTypeCheckingExtension extends TypeCheckingDSL { Object run() { methodNotFound { ClassNode receiver, String name, ArgumentListExpression argList, ClassNode[] argTypes, MethodCall call -> def dynamicCall = null - if(receiver == CLASS_Type) { + if (receiver == CLASS_Type) { def genericsTypes = receiver.genericsTypes - if(genericsTypes) { + if (genericsTypes) { def staticMethodCallTargetType = genericsTypes[0].type - if(staticMethodCallTargetType) { + if (staticMethodCallTargetType) { def sourceUnit = staticMethodCallTargetType?.module?.context - if(GrailsASTUtils.isDomainClass(staticMethodCallTargetType, sourceUnit)) { - switch(name) { + if (GrailsASTUtils.isDomainClass(staticMethodCallTargetType, sourceUnit)) { + switch (name) { case ~/countBy[A-Z].*/: dynamicCall = makeDynamicGormCall(call, Integer_TYPE, staticMethodCallTargetType) break diff --git a/grails-core/src/main/groovy/org/grails/compiler/HttpServletRequestTypeCheckingExtension.groovy b/grails-core/src/main/groovy/org/grails/compiler/HttpServletRequestTypeCheckingExtension.groovy index 4116b5a31d2..2c0f9301f01 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/HttpServletRequestTypeCheckingExtension.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/HttpServletRequestTypeCheckingExtension.groovy @@ -24,7 +24,6 @@ import org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport /** * * @since 3.0.4 - * */ class HttpServletRequestTypeCheckingExtension extends GroovyTypeCheckingExtensionSupport.TypeCheckingDSL { @@ -34,11 +33,11 @@ class HttpServletRequestTypeCheckingExtension extends GroovyTypeCheckingExtensio def run() { unresolvedProperty { PropertyExpression expression -> def property = expression.property - if(isConstantExpression(property)) { + if (isConstantExpression(property)) { def propertyName = property.value - if(propertyName in dynamicPropertyNames) { + if (propertyName in dynamicPropertyNames) { def referenceType = getType(expression.objectExpression) - if(referenceType.name == 'jakarta.servlet.http.HttpServletRequest') { + if (referenceType.name == 'jakarta.servlet.http.HttpServletRequest') { return makeDynamic(expression) } } diff --git a/grails-core/src/main/groovy/org/grails/compiler/NamedQueryTypeCheckingExtension.groovy b/grails-core/src/main/groovy/org/grails/compiler/NamedQueryTypeCheckingExtension.groovy index b90166fb2c1..5b143cad4fc 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/NamedQueryTypeCheckingExtension.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/NamedQueryTypeCheckingExtension.groovy @@ -32,7 +32,7 @@ import org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport.Type class NamedQueryTypeCheckingExtension extends TypeCheckingDSL { @Override - public Object run() { + Object run() { setup { newScope() } finish { scopeExit() } @@ -40,7 +40,7 @@ class NamedQueryTypeCheckingExtension extends TypeCheckingDSL { beforeVisitClass { ClassNode classNode -> def namedQueryProperty = classNode.getField('namedQueries') - if(namedQueryProperty && namedQueryProperty.isStatic() && namedQueryProperty.initialExpression instanceof ClosureExpression) { + if (namedQueryProperty && namedQueryProperty.isStatic() && namedQueryProperty.initialExpression instanceof ClosureExpression) { newScope { namedQueryClosureCode = namedQueryProperty.initialExpression.code } @@ -51,7 +51,7 @@ class NamedQueryTypeCheckingExtension extends TypeCheckingDSL { } afterVisitClass { ClassNode classNode -> - if(currentScope.namedQueryClosureCode) { + if (currentScope.namedQueryClosureCode) { def namedQueryProperty = classNode.getField('namedQueries') namedQueryProperty.initialExpression.code = currentScope.namedQueryClosureCode currentScope.checkingNamedQueryClosure = true @@ -61,8 +61,8 @@ class NamedQueryTypeCheckingExtension extends TypeCheckingDSL { methodNotFound { ClassNode receiver, String name, ArgumentListExpression argList, ClassNode[] argTypes, MethodCall call -> def dynamicCall - if(currentScope.namedQueryClosureCode && currentScope.checkingNamedQueryClosure) { - dynamicCall = makeDynamic (call) + if (currentScope.namedQueryClosureCode && currentScope.checkingNamedQueryClosure) { + dynamicCall = makeDynamic(call) } dynamicCall } diff --git a/grails-core/src/main/groovy/org/grails/compiler/RelationshipManagementMethodTypeCheckingExtension.groovy b/grails-core/src/main/groovy/org/grails/compiler/RelationshipManagementMethodTypeCheckingExtension.groovy index f5b0f23dc66..6435e3cd31e 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/RelationshipManagementMethodTypeCheckingExtension.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/RelationshipManagementMethodTypeCheckingExtension.groovy @@ -19,7 +19,6 @@ package org.grails.compiler import grails.util.GrailsNameUtils - import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.expr.ArgumentListExpression import org.codehaus.groovy.ast.expr.MethodCall @@ -39,11 +38,11 @@ class RelationshipManagementMethodTypeCheckingExtension extends TypeCheckingDSL methodNotFound { ClassNode receiver, String name, ArgumentListExpression argList, ClassNode[] argTypes, MethodCall call -> def dynamicCall def matcher = name =~ /(addTo|removeFrom)([A-Z].*)/ - if(matcher) { + if (matcher) { def sourceUnit = receiver.module?.context - if(GrailsASTUtils.isDomainClass(receiver, sourceUnit)) { + if (GrailsASTUtils.isDomainClass(receiver, sourceUnit)) { def propertyName = GrailsNameUtils.getPropertyName(matcher.group(2)) - if(receiver.getField(propertyName)) { + if (receiver.getField(propertyName)) { dynamicCall = makeDynamic(call, receiver) dynamicCall.declaringClass = receiver } diff --git a/grails-core/src/main/groovy/org/grails/compiler/ValidateableTypeCheckingExtension.groovy b/grails-core/src/main/groovy/org/grails/compiler/ValidateableTypeCheckingExtension.groovy index 4776b4e24e7..2b5aaf459b7 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/ValidateableTypeCheckingExtension.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/ValidateableTypeCheckingExtension.groovy @@ -26,20 +26,19 @@ import org.codehaus.groovy.ast.stmt.EmptyStatement import org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport.TypeCheckingDSL /** - * * @since 2.4 */ class ValidateableTypeCheckingExtension extends TypeCheckingDSL { @Override - public Object run() { + Object run() { setup { newScope() } finish { scopeExit() } - + beforeVisitClass { ClassNode classNode -> def constraintsProperty = classNode.getField('constraints') - if(constraintsProperty && constraintsProperty.isStatic() && constraintsProperty.initialExpression instanceof ClosureExpression) { + if (constraintsProperty && constraintsProperty.isStatic() && constraintsProperty.initialExpression instanceof ClosureExpression) { newScope { constraintsClosureCode = constraintsProperty.initialExpression.code } @@ -50,7 +49,7 @@ class ValidateableTypeCheckingExtension extends TypeCheckingDSL { } afterVisitClass { ClassNode classNode -> - if(currentScope.constraintsClosureCode) { + if (currentScope.constraintsClosureCode) { def constraintsProperty = classNode.getField('constraints') constraintsProperty.initialExpression.code = currentScope.constraintsClosureCode currentScope.checkingConstraintsClosure = true @@ -61,14 +60,14 @@ class ValidateableTypeCheckingExtension extends TypeCheckingDSL { methodNotFound { ClassNode receiver, String name, ArgumentListExpression argList, ClassNode[] argTypes, MethodCall call -> def dynamicCall - if(currentScope.constraintsClosureCode && currentScope.checkingConstraintsClosure) { - if(receiver.getField(name) || 'importFrom' == name) { - dynamicCall = makeDynamic (call) + if (currentScope.constraintsClosureCode && currentScope.checkingConstraintsClosure) { + if (receiver.getField(name) || 'importFrom' == name) { + dynamicCall = makeDynamic(call) } } dynamicCall } - + null } } diff --git a/grails-core/src/main/groovy/org/grails/compiler/WhereQueryTypeCheckingExtension.groovy b/grails-core/src/main/groovy/org/grails/compiler/WhereQueryTypeCheckingExtension.groovy index 3919c0ad68e..6cd49820ce6 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/WhereQueryTypeCheckingExtension.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/WhereQueryTypeCheckingExtension.groovy @@ -23,38 +23,36 @@ import org.codehaus.groovy.ast.expr.ArgumentListExpression import org.codehaus.groovy.ast.expr.ClassExpression import org.codehaus.groovy.ast.expr.MethodCall import org.codehaus.groovy.ast.expr.MethodCallExpression -import org.grails.compiler.injection.GrailsASTUtils import org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport.TypeCheckingDSL - +import org.grails.compiler.injection.GrailsASTUtils /** - * * @since 2.4.1 */ class WhereQueryTypeCheckingExtension extends TypeCheckingDSL { @Override - public Object run() { + Object run() { setup { newScope() } finish { scopeExit() } - + methodNotFound { ClassNode receiver, String name, ArgumentListExpression argList, ClassNode[] argTypes, MethodCall call -> def dynamicCall - if(currentScope.processingWhereQueryClosure) { - dynamicCall = makeDynamic (call) + if (currentScope.processingWhereQueryClosure) { + dynamicCall = makeDynamic(call) } dynamicCall } - + afterMethodCall { MethodCall call -> - if(isWhereQueryCall(call)) { + if (isWhereQueryCall(call)) { scopeExit() } } - + beforeMethodCall { MethodCall call -> - if(isWhereQueryCall(call)) { + if (isWhereQueryCall(call)) { newScope { processingWhereQueryClosure = true } @@ -62,11 +60,11 @@ class WhereQueryTypeCheckingExtension extends TypeCheckingDSL { } null } - + protected boolean isWhereQueryCall(MethodCall call) { - call instanceof MethodCallExpression && - call.objectExpression instanceof ClassExpression && - GrailsASTUtils.isDomainClass(call.objectExpression.type, null) && - call.method.value == 'where' + call instanceof MethodCallExpression && + call.objectExpression instanceof ClassExpression && + GrailsASTUtils.isDomainClass(call.objectExpression.type, null) && + call.method.value == 'where' } } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/ASTErrorsHelper.java b/grails-core/src/main/groovy/org/grails/compiler/injection/ASTErrorsHelper.java index 53e715e4034..3367a478538 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/ASTErrorsHelper.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/ASTErrorsHelper.java @@ -23,14 +23,14 @@ /** * Enhances a class to contain an Errors property of type org.springframework.validation.Errors. Methods added include: * - *

+ * 
  *  public void setErrors(Errors errors)
  *  public Errors getErrors()
  *  public void clearErrors()
  *  public Boolean hasErrors()
  *  
* - * @author Jeff Brown + * @author Jeff Brown */ public interface ASTErrorsHelper { diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/ASTValidationErrorsHelper.java b/grails-core/src/main/groovy/org/grails/compiler/injection/ASTValidationErrorsHelper.java index 6789813c014..24a7c061a1b 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/ASTValidationErrorsHelper.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/ASTValidationErrorsHelper.java @@ -21,9 +21,27 @@ import grails.compiler.ast.GrailsArtefactClassInjector; import grails.validation.ValidationErrors; import org.apache.groovy.ast.tools.AnnotatedNodeUtils; -import org.codehaus.groovy.ast.*; -import org.codehaus.groovy.ast.expr.*; -import org.codehaus.groovy.ast.stmt.*; +import org.codehaus.groovy.ast.ASTNode; +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.FieldNode; +import org.codehaus.groovy.ast.MethodNode; +import org.codehaus.groovy.ast.Parameter; +import org.codehaus.groovy.ast.expr.ArgumentListExpression; +import org.codehaus.groovy.ast.expr.BinaryExpression; +import org.codehaus.groovy.ast.expr.BooleanExpression; +import org.codehaus.groovy.ast.expr.ConstantExpression; +import org.codehaus.groovy.ast.expr.ConstructorCallExpression; +import org.codehaus.groovy.ast.expr.EmptyExpression; +import org.codehaus.groovy.ast.expr.Expression; +import org.codehaus.groovy.ast.expr.MethodCallExpression; +import org.codehaus.groovy.ast.expr.TupleExpression; +import org.codehaus.groovy.ast.expr.VariableExpression; +import org.codehaus.groovy.ast.stmt.BlockStatement; +import org.codehaus.groovy.ast.stmt.ExpressionStatement; +import org.codehaus.groovy.ast.stmt.IfStatement; +import org.codehaus.groovy.ast.stmt.ReturnStatement; +import org.codehaus.groovy.ast.stmt.Statement; import org.codehaus.groovy.syntax.Token; import org.codehaus.groovy.syntax.Types; import org.springframework.validation.Errors; @@ -34,6 +52,7 @@ * @author Jeff Brown */ public class ASTValidationErrorsHelper implements ASTErrorsHelper { + private static final ConstantExpression NULL_EXPRESSION = new ConstantExpression(null); private static final String SET_ERRORS_METHOD_NAME = "setErrors"; private static final String GET_ERRORS_METHOD_NAME = "getErrors"; @@ -145,7 +164,7 @@ protected void addGetErrorsMethod(final ClassNode paramTypeClassNode) { protected void addSetErrorsMethod(final ClassNode paramTypeClassNode) { final String errorsArgumentName = "$errorsArg"; MethodNode setErrorsMethod = paramTypeClassNode.getMethod(SET_ERRORS_METHOD_NAME, - new Parameter[] { new Parameter(ERRORS_CLASS_NODE, errorsArgumentName)}); + new Parameter[]{new Parameter(ERRORS_CLASS_NODE, errorsArgumentName)}); if (setErrorsMethod == null) { final Expression assignErrorsExpression = new BinaryExpression(ERRORS_EXPRESSION, EQUALS_SYMBOL, new VariableExpression(errorsArgumentName)); diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/AbstractArtefactTypeAstTransformation.java b/grails-core/src/main/groovy/org/grails/compiler/injection/AbstractArtefactTypeAstTransformation.java index 6feaa875b11..04cf38c5ae7 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/AbstractArtefactTypeAstTransformation.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/AbstractArtefactTypeAstTransformation.java @@ -38,6 +38,7 @@ */ @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) public abstract class AbstractArtefactTypeAstTransformation implements ASTTransformation, TransformWithPriority { + protected void performInjectionOnArtefactType(SourceUnit sourceUnit, ClassNode cNode, String artefactType) { try { ClassInjector[] classInjectors = GrailsAwareInjectionOperation.getClassInjectors(); @@ -45,16 +46,15 @@ protected void performInjectionOnArtefactType(SourceUnit sourceUnit, ClassNode c if (!injectors.isEmpty()) { AbstractGrailsArtefactTransformer.addToTransformedClasses(cNode.getName()); for (ClassInjector injector : injectors) { - if(injector instanceof AllArtefactClassInjector) { - injector.performInjection(sourceUnit,cNode); - } - else if(injector instanceof AnnotatedClassInjector) { - ((AnnotatedClassInjector)injector).performInjectionOnAnnotatedClass(sourceUnit,null, cNode); + if (injector instanceof AllArtefactClassInjector) { + injector.performInjection(sourceUnit, cNode); + } else if (injector instanceof AnnotatedClassInjector) { + ((AnnotatedClassInjector) injector).performInjectionOnAnnotatedClass(sourceUnit, null, cNode); } } } } catch (RuntimeException e) { - System.err.println("Error occurred calling AST injector ["+getClass()+"]: " + e.getMessage()); + System.err.println("Error occurred calling AST injector [" + getClass() + "]: " + e.getMessage()); throw e; } } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/AbstractGrailsArtefactTransformer.java b/grails-core/src/main/groovy/org/grails/compiler/injection/AbstractGrailsArtefactTransformer.java index d9bacd36883..7e843ef4987 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/AbstractGrailsArtefactTransformer.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/AbstractGrailsArtefactTransformer.java @@ -22,9 +22,29 @@ import grails.compiler.ast.AnnotatedClassInjector; import grails.compiler.ast.GrailsArtefactClassInjector; import org.apache.groovy.ast.tools.AnnotatedNodeUtils; -import org.codehaus.groovy.ast.*; -import org.codehaus.groovy.ast.expr.*; -import org.codehaus.groovy.ast.stmt.*; +import org.codehaus.groovy.ast.AnnotationNode; +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.FieldNode; +import org.codehaus.groovy.ast.InnerClassNode; +import org.codehaus.groovy.ast.MethodNode; +import org.codehaus.groovy.ast.Parameter; +import org.codehaus.groovy.ast.PropertyNode; +import org.codehaus.groovy.ast.expr.ArgumentListExpression; +import org.codehaus.groovy.ast.expr.AttributeExpression; +import org.codehaus.groovy.ast.expr.BinaryExpression; +import org.codehaus.groovy.ast.expr.BooleanExpression; +import org.codehaus.groovy.ast.expr.ClassExpression; +import org.codehaus.groovy.ast.expr.ConstantExpression; +import org.codehaus.groovy.ast.expr.ConstructorCallExpression; +import org.codehaus.groovy.ast.expr.Expression; +import org.codehaus.groovy.ast.expr.MethodCallExpression; +import org.codehaus.groovy.ast.expr.VariableExpression; +import org.codehaus.groovy.ast.stmt.BlockStatement; +import org.codehaus.groovy.ast.stmt.ExpressionStatement; +import org.codehaus.groovy.ast.stmt.IfStatement; +import org.codehaus.groovy.ast.stmt.ReturnStatement; +import org.codehaus.groovy.ast.stmt.ThrowStatement; import org.codehaus.groovy.classgen.GeneratorContext; import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.runtime.MetaClassHelper; @@ -34,43 +54,47 @@ import org.springframework.beans.factory.annotation.Autowired; import java.lang.reflect.Modifier; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * Abstract transformer that takes an implementation class and creates methods * in a target ClassNode that delegate to that implementation class. Subclasses * should override to provide the implementation class details * + * @author Graeme Rocher * @since 2.0 - * @author Graeme Rocher */ @SuppressWarnings("rawtypes") public abstract class AbstractGrailsArtefactTransformer implements GrailsArtefactClassInjector, AnnotatedClassInjector, Comparable { - - private static final Set KNOWN_TRANSFORMED_CLASSES = new LinkedHashSet(); - private static final String INSTANCE_PREFIX = "instance"; - private static final String STATIC_PREFIX = "static"; - private static final AnnotationNode AUTO_WIRED_ANNOTATION = new AnnotationNode(new ClassNode(Autowired.class)); - - protected static final ClassNode OBJECT_CLASS = new ClassNode(Object.class); - public static final int PUBLIC_STATIC_MODIFIER = Modifier.PUBLIC | Modifier.STATIC; public static final String CURRENT_PREFIX = "current"; public static final String METHOD_MISSING_METHOD_NAME = "methodMissing"; public static final String STATIC_METHOD_MISSING_METHOD_NAME = "$static_methodMissing"; + protected static final ClassNode OBJECT_CLASS = new ClassNode(Object.class); + + private static final Set KNOWN_TRANSFORMED_CLASSES = new LinkedHashSet(); + private static final String INSTANCE_PREFIX = "instance"; + private static final String STATIC_PREFIX = "static"; + private static final AnnotationNode AUTO_WIRED_ANNOTATION = new AnnotationNode(new ClassNode(Autowired.class)); private static final String[] DEFAULT_GENERICS_PLACEHOLDERS = new String[]{"D", "T"}; private final Set classesTransformedByThis = new LinkedHashSet(); public String[] getArtefactTypes() { - return new String[]{ getArtefactType() }; + return new String[]{getArtefactType()}; } protected String getArtefactType() { String name = getClass().getSimpleName(); - if(name.endsWith("Transformer")) { + if (name.endsWith("Transformer")) { return name.substring(0, name.length() - 11); } return name; @@ -82,7 +106,7 @@ public void clearCachedState() { /** * Used for ordering not equality. - * + *

* Note: this class has a natural ordering that is inconsistent with equals. * * @see Comparable#compareTo(Object) @@ -92,7 +116,9 @@ public int compareTo(Object o) { } public void performInjection(SourceUnit source, GeneratorContext context, ClassNode classNode) { - if(shouldSkipInjection(classNode) || hasArtefactAnnotation(classNode)) return; + if (shouldSkipInjection(classNode) || hasArtefactAnnotation(classNode)) { + return; + } performInjectionOnAnnotatedClass(source, context, classNode); } @@ -102,7 +128,9 @@ public void performInjectionOnAnnotatedClass(SourceUnit source, ClassNode classN } public void performInjectionOnAnnotatedClass(SourceUnit source, GeneratorContext context, ClassNode classNode) { - if(shouldSkipInjection(classNode)) return; + if (shouldSkipInjection(classNode)) { + return; + } final String className = classNode.getName(); KNOWN_TRANSFORMED_CLASSES.add(className); @@ -124,7 +152,7 @@ public void performInjectionOnAnnotatedClass(SourceUnit source, GeneratorContext } protected void performInstanceImplementationInjection(SourceUnit source, ClassNode classNode, - Map genericsPlaceholders, Class instanceImplementation) { + Map genericsPlaceholders, Class instanceImplementation) { ClassNode implementationNode; final ConstructorCallExpression constructorCallExpression; try { @@ -143,20 +171,18 @@ protected void performInstanceImplementationInjection(SourceUnit source, ClassNo final String lookupMethodName = CURRENT_PREFIX + instanceImplementation.getSimpleName(); MethodNode lookupMethod = createStaticLookupMethod(classNode, implementationNode, apiInstanceProperty, lookupMethodName); apiInstance = new MethodCallExpression(new ClassExpression(classNode), lookupMethodName, ZERO_ARGS); - ((MethodCallExpression)apiInstance).setMethodTarget(lookupMethod); - } - else if (requiresAutowiring()) { + ((MethodCallExpression) apiInstance).setMethodTarget(lookupMethod); + } else if (requiresAutowiring()) { PropertyNode propertyNode = new PropertyNode(apiInstanceProperty, Modifier.PUBLIC, implementationNode, classNode, constructorCallExpression, null, null); propertyNode.addAnnotation(AUTO_WIRED_ANNOTATION); - if(getMarkerAnnotation() != null) { + if (getMarkerAnnotation() != null) { propertyNode.addAnnotation(getMarkerAnnotation()); } classNode.addProperty(propertyNode); - } - else { + } else { FieldNode fieldNode = classNode.getField(apiInstanceProperty); if (fieldNode == null || (Modifier.isPrivate(fieldNode.getModifiers()) && !fieldNode.getDeclaringClass().equals(classNode))) { - fieldNode = new FieldNode(apiInstanceProperty, PRIVATE_STATIC_MODIFIER,implementationNode, classNode,constructorCallExpression); + fieldNode = new FieldNode(apiInstanceProperty, PRIVATE_STATIC_MODIFIER, implementationNode, classNode, constructorCallExpression); classNode.addField(fieldNode); } } @@ -166,8 +192,7 @@ else if (requiresAutowiring()) { for (MethodNode declaredMethod : declaredMethods) { if (GrailsASTUtils.isConstructorMethod(declaredMethod)) { GrailsASTUtils.addDelegateConstructor(classNode, declaredMethod, genericsPlaceholders); - } - else if (isCandidateInstanceMethod(classNode, declaredMethod)) { + } else if (isCandidateInstanceMethod(classNode, declaredMethod)) { addDelegateInstanceMethod(classNode, apiInstance, declaredMethod, getMarkerAnnotation(), genericsPlaceholders); } } @@ -177,7 +202,7 @@ else if (isCandidateInstanceMethod(classNode, declaredMethod)) { } protected void performStaticImplementationInjection(ClassNode classNode, - Map genericsPlaceholders, Class staticImplementation) { + Map genericsPlaceholders, Class staticImplementation) { ClassNode staticImplementationNode = GrailsASTUtils.replaceGenericsPlaceholders(ClassHelper.make(staticImplementation), genericsPlaceholders); final List declaredMethods = staticImplementationNode.getMethods(); @@ -192,10 +217,10 @@ protected void performStaticImplementationInjection(ClassNode classNode, MethodNode lookupMethod = createStaticLookupMethod(classNode, staticImplementationNode, apiInstanceProperty, lookupMethodName); MethodCallExpression apiLookupMethod = new MethodCallExpression(new ClassExpression(classNode), lookupMethodName, ZERO_ARGS); - apiLookupMethod.setMethodTarget(lookupMethod); + apiLookupMethod.setMethodTarget(lookupMethod); for (MethodNode declaredMethod : declaredMethods) { - if (isStaticCandidateMethod(classNode,declaredMethod)) { + if (isStaticCandidateMethod(classNode, declaredMethod)) { addDelegateStaticMethod(classNode, apiLookupMethod, declaredMethod, genericsPlaceholders); } } @@ -215,9 +240,15 @@ protected boolean hasArtefactAnnotation(ClassNode classNode) { } protected boolean isValidTargetClassNode(ClassNode classNode) { - if(classNode.isEnum()) return false; // don't transform enums - if(classNode instanceof InnerClassNode) return false; - if(classNode.getName().contains("$")) return false; + if (classNode.isEnum()) { + return false; // don't transform enums + } + if (classNode instanceof InnerClassNode) { + return false; + } + if (classNode.getName().contains("$")) { + return false; + } return true; } @@ -227,7 +258,7 @@ protected boolean isValidArtefactType() { protected Map resolveGenericsPlaceHolders(ClassNode classNode) { Map genericsPlaceHolders = new LinkedHashMap(); - for(String placeHolder : DEFAULT_GENERICS_PLACEHOLDERS) { + for (String placeHolder : DEFAULT_GENERICS_PLACEHOLDERS) { genericsPlaceHolders.put(placeHolder, classNode); } return genericsPlaceHolders; @@ -238,15 +269,19 @@ protected void addDelegateInstanceMethod(ClassNode classNode, Expression delegat } protected void addDelegateStaticMethod(ClassNode classNode, MethodCallExpression apiLookupMethod, - MethodNode declaredMethod, Map genericsPlaceholders) { + MethodNode declaredMethod, Map genericsPlaceholders) { GrailsASTUtils.addCompileStaticAnnotation(GrailsASTUtils.addDelegateStaticMethod(apiLookupMethod, classNode, declaredMethod, getMarkerAnnotation(), genericsPlaceholders, true)); } private boolean isValidArtefactTypeByConvention(ClassNode classNode) { String[] artefactTypes = getArtefactTypes(); for (String artefactType : artefactTypes) { - if(artefactType.equals("*")) return true; - if(classNode.getName().endsWith(artefactType)) return true; + if (artefactType.equals("*")) { + return true; + } + if (classNode.getName().endsWith(artefactType)) { + return true; + } } return false; } @@ -262,7 +297,7 @@ protected boolean isStaticCandidateMethod(ClassNode classNode, MethodNode declar protected boolean isStaticMethodExcluded(ClassNode classNode, MethodNode declaredMethod) { return GrailsASTUtils.isSetterOrGetterMethod(declaredMethod); } - + protected boolean isStaticMethodIncluded(ClassNode classNode, MethodNode declaredMethod) { return false; } @@ -271,7 +306,7 @@ private MethodNode createStaticLookupMethod(ClassNode classNode, ClassNode imple // if autowiring is required we add a default method that throws an exception // the method should be override via meta-programming in the Grails environment MethodNode lookupMethod = classNode.getMethod(lookupMethodName, ZERO_PARAMETERS); - if (lookupMethod == null || !lookupMethod.getDeclaringClass().equals(classNode)) { + if (lookupMethod == null || !lookupMethod.getDeclaringClass().equals(classNode)) { BlockStatement methodBody = new BlockStatement(); lookupMethod = populateAutowiredApiLookupMethod(classNode, implementationNode, apiProperty, lookupMethodName, methodBody); classNode.addMethod(lookupMethod); @@ -293,30 +328,30 @@ protected boolean requiresStaticLookupMethod() { protected MethodNode populateAutowiredApiLookupMethod(ClassNode classNode, ClassNode implementationNode, String apiProperty, String methodName, BlockStatement methodBody) { - + addApiLookupFieldAndSetter(classNode, implementationNode, apiProperty, null); - + VariableExpression apiVar = new VariableExpression(apiProperty, implementationNode); - + BlockStatement ifBlock = new BlockStatement(); ArgumentListExpression arguments = new ArgumentListExpression(); - arguments.addExpression(new ConstantExpression("Method on class ["+classNode+"] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.")); - ifBlock.addStatement(new ThrowStatement(new ConstructorCallExpression(new ClassNode(IllegalStateException.class), arguments))); + arguments.addExpression(new ConstantExpression("Method on class [" + classNode + "] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.")); + ifBlock.addStatement(new ThrowStatement(new ConstructorCallExpression(new ClassNode(IllegalStateException.class), arguments))); BlockStatement elseBlock = new BlockStatement(); elseBlock.addStatement(new ReturnStatement(apiVar)); - methodBody.addStatement(new IfStatement(new BooleanExpression(new BinaryExpression(apiVar, GrailsASTUtils.EQUALS_OPERATOR, GrailsASTUtils.NULL_EXPRESSION)),ifBlock,elseBlock)); - - MethodNode methodNode = new MethodNode(methodName, PUBLIC_STATIC_MODIFIER, implementationNode,ZERO_PARAMETERS,null,methodBody); + methodBody.addStatement(new IfStatement(new BooleanExpression(new BinaryExpression(apiVar, GrailsASTUtils.EQUALS_OPERATOR, GrailsASTUtils.NULL_EXPRESSION)), ifBlock, elseBlock)); + + MethodNode methodNode = new MethodNode(methodName, PUBLIC_STATIC_MODIFIER, implementationNode, ZERO_PARAMETERS, null, methodBody); return methodNode; } protected void addApiLookupFieldAndSetter(ClassNode classNode, ClassNode implementationNode, - String apiProperty, Expression initialValueExpression) { + String apiProperty, Expression initialValueExpression) { FieldNode fieldNode = classNode.getField(apiProperty); if (fieldNode == null || !fieldNode.getDeclaringClass().equals(classNode)) { fieldNode = new FieldNode(apiProperty, Modifier.PRIVATE | Modifier.STATIC, implementationNode, classNode, initialValueExpression); classNode.addField(fieldNode); - + String setterName = "set" + MetaClassHelper.capitalize(apiProperty); Parameter setterParameter = new Parameter(implementationNode, apiProperty); BlockStatement setterBody = new BlockStatement(); @@ -332,7 +367,7 @@ protected void addApiLookupFieldAndSetter(ClassNode classNode, ClassNode impleme protected MethodNode populateDefaultApiLookupMethod(ClassNode implementationNode, String apiInstanceProperty, String methodName, BlockStatement methodBody) { methodBody.addStatement(new ReturnStatement(new VariableExpression(apiInstanceProperty, implementationNode))); - return new MethodNode(methodName, Modifier.PRIVATE, implementationNode,ZERO_PARAMETERS,null,methodBody); + return new MethodNode(methodName, Modifier.PRIVATE, implementationNode, ZERO_PARAMETERS, null, methodBody); } /** @@ -349,8 +384,8 @@ protected boolean requiresAutowiring() { * Subclasses can override to provide additional transformation * * @param apiInstanceProperty - * @param source The source - * @param classNode The class node + * @param source The source + * @param classNode The class node */ protected void performInjectionInternal(String apiInstanceProperty, SourceUnit source, ClassNode classNode) { // do nothing @@ -384,7 +419,7 @@ protected AnnotationNode getMarkerAnnotation() { } public static Collection getTransformedClassNames() { - return Collections.unmodifiableCollection( KNOWN_TRANSFORMED_CLASSES ); + return Collections.unmodifiableCollection(KNOWN_TRANSFORMED_CLASSES); } public static void addToTransformedClasses(String name) { diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/ApiDelegateTransformation.java b/grails-core/src/main/groovy/org/grails/compiler/injection/ApiDelegateTransformation.java index 31386d714a5..bce8f643321 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/ApiDelegateTransformation.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/ApiDelegateTransformation.java @@ -20,7 +20,11 @@ import org.apache.grails.common.compiler.GroovyTransformOrder; import org.codehaus.groovy.GroovyBugError; -import org.codehaus.groovy.ast.*; +import org.codehaus.groovy.ast.ASTNode; +import org.codehaus.groovy.ast.AnnotatedNode; +import org.codehaus.groovy.ast.AnnotationNode; +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.FieldNode; import org.codehaus.groovy.ast.expr.ClassExpression; import org.codehaus.groovy.ast.expr.Expression; import org.codehaus.groovy.ast.expr.VariableExpression; @@ -41,6 +45,7 @@ */ @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) public class ApiDelegateTransformation implements ASTTransformation, TransformWithPriority { + @Override public int priority() { return GroovyTransformOrder.API_DELEGATE_ORDER; @@ -67,11 +72,11 @@ public void visit(ASTNode[] nodes, SourceUnit source) { GrailsASTUtils.addDelegateInstanceMethods(supportedType, owner, type, new VariableExpression(fieldNode.getName()), resolveGenericsPlaceHolders(supportedType), isNoNullCheck(), isUseCompileStatic()); } } - + protected boolean isNoNullCheck() { return true; } - + protected boolean isUseCompileStatic() { return true; } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/ApplicationClassInjector.groovy b/grails-core/src/main/groovy/org/grails/compiler/injection/ApplicationClassInjector.groovy index 33bbae3495c..ef992f4ce29 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/ApplicationClassInjector.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/ApplicationClassInjector.groovy @@ -87,9 +87,9 @@ class ApplicationClassInjector implements GrailsArtefactClassInjector { @Override @CompileDynamic void performInjectionOnAnnotatedClass(SourceUnit source, ClassNode classNode) { - if(applicationArtefactHandler.isArtefact(classNode)) { - def objectId = Integer.valueOf( System.identityHashCode(classNode) ) - if(!transformedInstances.contains(objectId)) { + if (applicationArtefactHandler.isArtefact(classNode)) { + def objectId = Integer.valueOf(System.identityHashCode(classNode)) + if (!transformedInstances.contains(objectId)) { transformedInstances << objectId List statements = [ @@ -99,16 +99,16 @@ class ApplicationClassInjector implements GrailsArtefactClassInjector { def packageNamesMethod = classNode.getMethod('packageNames', GrailsASTUtils.ZERO_PARAMETERS) - if(packageNamesMethod == null || packageNamesMethod.declaringClass != classNode) { + if (packageNamesMethod == null || packageNamesMethod.declaringClass != classNode) { def collectionClassNode = GrailsASTUtils.replaceGenericsPlaceholders(ClassHelper.make(Collection), [E: ClassHelper.make(String)]) def packageNamesBody = new BlockStatement() def grailsAppDir = GrailsResourceUtils.getAppDir(new UrlResource(GrailsASTUtils.getSourceUrl(source))) - if(grailsAppDir.exists()) { + if (grailsAppDir.exists()) { def packageNames = ResourceUtils.getProjectPackageNames(grailsAppDir.file.parentFile) - .collect() { String str -> new ConstantExpression(str) } - if(packageNames.any() { ConstantExpression packageName -> ['org','com','io','net'].contains(packageName.text) }) { + .collect() { String str -> new ConstantExpression(str) } + if (packageNames.any() { ConstantExpression packageName -> ['org', 'com', 'io', 'net'].contains(packageName.text) }) { GrailsASTUtils.error(source, classNode, "Do not place Groovy sources in common package names such as 'org', 'com', 'io' or 'net' as this can result in performance degradation of classpath scanning") } packageNamesBody.addStatement(new ReturnStatement(new ExpressionStatement(new ListExpression(packageNames.toList())))) @@ -132,7 +132,7 @@ class ApplicationClassInjector implements GrailsArtefactClassInjector { @Override boolean shouldInject(URL url) { - if(url == null) return false + if (url == null) return false def res = new UrlResource(url) return GrailsResourceUtils.isGrailsResource(res) && res.filename == "Application.groovy" } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/ArtefactTypeAstTransformation.java b/grails-core/src/main/groovy/org/grails/compiler/injection/ArtefactTypeAstTransformation.java index 481fb319841..c591dff52df 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/ArtefactTypeAstTransformation.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/ArtefactTypeAstTransformation.java @@ -54,14 +54,15 @@ */ @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) public class ArtefactTypeAstTransformation extends AbstractArtefactTypeAstTransformation implements CompilationUnitAware { + private static final ClassNode MY_TYPE = new ClassNode(Artefact.class); - + protected CompilationUnit compilationUnit; public void visit(ASTNode[] astNodes, SourceUnit sourceUnit) { AnnotatedNode parent = (AnnotatedNode) astNodes[1]; AnnotationNode node = (AnnotationNode) astNodes[0]; - + if (!(node instanceof AnnotationNode) || !(parent instanceof AnnotatedNode)) { throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class"); } @@ -76,25 +77,25 @@ public void visit(ASTNode[] astNodes, SourceUnit sourceUnit) { getAnnotationType().getNameWithoutPackage() + " not allowed for interfaces."); } - if(isApplied(cNode)) { + if (isApplied(cNode)) { return; } - + String artefactType = resolveArtefactType(sourceUnit, node, cNode); - if(artefactType != null) { + if (artefactType != null) { AbstractGrailsArtefactTransformer.addToTransformedClasses(cNode.getName()); } performInjectionOnArtefactType(sourceUnit, cNode, artefactType); - + performTraitInjectionOnArtefactType(sourceUnit, cNode, artefactType); - + postProcess(sourceUnit, node, cNode, artefactType); - - markApplied(cNode); + + markApplied(cNode); } protected void performTraitInjectionOnArtefactType(SourceUnit sourceUnit, - ClassNode cNode, String artefactType) { + ClassNode cNode, String artefactType) { if (compilationUnit != null) { TraitInjectionUtils.processTraitsForNode(sourceUnit, cNode, artefactType, compilationUnit); } @@ -113,10 +114,10 @@ protected Class getAstAppliedMarkerClass() { } protected void postProcess(SourceUnit sourceUnit, AnnotationNode annotationNode, ClassNode classNode, String artefactType) { - if(!getAnnotationType().equals(annotationNode.getClassNode())) { + if (!getAnnotationType().equals(annotationNode.getClassNode())) { // add @Artefact annotation to resulting class so that "short cut" annotations like @TagLib // also produce an @Artefact annotation in the resulting class file - AnnotationNode annotation=new AnnotationNode(getAnnotationType()); + AnnotationNode annotation = new AnnotationNode(getAnnotationType()); annotation.addMember("value", new ConstantExpression(artefactType)); classNode.addAnnotation(annotation); } @@ -138,13 +139,14 @@ protected String resolveArtefactType(SourceUnit sourceUnit, AnnotationNode annot ClassExpression ce = (ClassExpression) objectExpression; try { Field field = ce.getType().getTypeClass().getDeclaredField(pe.getPropertyAsString()); - return (String)field.get(null); - } catch (Exception e) {} + return (String) field.get(null); + } catch (Exception e) { + } } } } - throw new RuntimeException("Class ["+classNode.getName()+"] contains an invalid @Artefact annotation. No artefact found for value specified."); + throw new RuntimeException("Class [" + classNode.getName() + "] contains an invalid @Artefact annotation. No artefact found for value specified."); } protected boolean isArtefactAnnotationNode(AnnotationNode annotationNode) { @@ -162,7 +164,7 @@ protected Class getAnnotationTypeClass() { public void performInjectionOnArtefactType(SourceUnit sourceUnit, ClassNode cNode, String artefactType) { List injectors = findInjectors(artefactType, GrailsAwareInjectionOperation.getClassInjectors()); for (ClassInjector injector : injectors) { - if(injector instanceof CompilationUnitAware) { + if (injector instanceof CompilationUnitAware) { ((CompilationUnitAware) injector).setCompilationUnit(this.compilationUnit); } } @@ -178,7 +180,7 @@ public static void doPerformInjectionOnArtefactType(SourceUnit sourceUnit, Class public static void performInjection(SourceUnit sourceUnit, ClassNode cNode, Collection injectors) { try { for (ClassInjector injector : injectors) { - if(!GrailsASTUtils.isApplied(cNode, injector.getClass())) { + if (!GrailsASTUtils.isApplied(cNode, injector.getClass())) { GrailsASTUtils.markApplied(cNode, injector.getClass()); injector.performInjectionOnAnnotatedClass(sourceUnit, cNode); } @@ -198,14 +200,12 @@ public static List findInjectors(String artefactType, ClassInject for (ClassInjector classInjector : classInjectors) { if (classInjector instanceof AllArtefactClassInjector) { injectors.add(classInjector); - } - else if(classInjector instanceof GlobalClassInjector) { + } else if (classInjector instanceof GlobalClassInjector) { injectors.add(classInjector); - } - else if (classInjector instanceof GrailsArtefactClassInjector) { + } else if (classInjector instanceof GrailsArtefactClassInjector) { GrailsArtefactClassInjector gace = (GrailsArtefactClassInjector) classInjector; - if (hasArtefactType(artefactType,gace)) { + if (hasArtefactType(artefactType, gace)) { injectors.add(gace); } } @@ -214,19 +214,21 @@ else if (classInjector instanceof GrailsArtefactClassInjector) { } public static boolean hasArtefactType(String artefactType, GrailsArtefactClassInjector gace) { - for (String _artefactType : gace.getArtefactTypes()) { - if(_artefactType.equals("*")) return true; - if (_artefactType.equals(artefactType)) { + for (String supportedArtefactType : gace.getArtefactTypes()) { + if (supportedArtefactType.equals("*")) { + return true; + } + if (supportedArtefactType.equals(artefactType)) { return true; } } return false; } - @Override - public void setCompilationUnit(CompilationUnit unit) { - compilationUnit = unit; - } + @Override + public void setCompilationUnit(CompilationUnit unit) { + compilationUnit = unit; + } @Override public int priority() { diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/DefaultGrailsDomainClassInjector.java b/grails-core/src/main/groovy/org/grails/compiler/injection/DefaultGrailsDomainClassInjector.java index 02e64134ec4..45734e880a1 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/DefaultGrailsDomainClassInjector.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/DefaultGrailsDomainClassInjector.java @@ -19,15 +19,6 @@ package org.grails.compiler.injection; import grails.artefact.Artefact; - -import java.lang.reflect.Modifier; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.Set; - import grails.compiler.ast.AstTransformer; import grails.compiler.ast.GrailsArtefactClassInjector; import grails.compiler.ast.GrailsDomainClassInjector; @@ -38,7 +29,16 @@ import org.codehaus.groovy.ast.MethodNode; import org.codehaus.groovy.ast.Parameter; import org.codehaus.groovy.ast.PropertyNode; -import org.codehaus.groovy.ast.expr.*; +import org.codehaus.groovy.ast.expr.BooleanExpression; +import org.codehaus.groovy.ast.expr.ClassExpression; +import org.codehaus.groovy.ast.expr.ConstantExpression; +import org.codehaus.groovy.ast.expr.Expression; +import org.codehaus.groovy.ast.expr.GStringExpression; +import org.codehaus.groovy.ast.expr.ListExpression; +import org.codehaus.groovy.ast.expr.MapEntryExpression; +import org.codehaus.groovy.ast.expr.MapExpression; +import org.codehaus.groovy.ast.expr.TernaryExpression; +import org.codehaus.groovy.ast.expr.VariableExpression; import org.codehaus.groovy.ast.stmt.ReturnStatement; import org.codehaus.groovy.ast.stmt.Statement; import org.codehaus.groovy.classgen.GeneratorContext; @@ -47,6 +47,13 @@ import org.grails.datastore.mapping.model.config.GormProperties; import org.grails.io.support.GrailsResourceUtils; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + /** * Default implementation of domain class injector interface that adds the 'id' * and 'version' properties and other previously boilerplate code. @@ -61,7 +68,9 @@ public class DefaultGrailsDomainClassInjector implements GrailsDomainClassInject public void performInjection(SourceUnit source, GeneratorContext context, ClassNode classNode) { if (GrailsASTUtils.isDomainClass(classNode, source) && shouldInjectClass(classNode)) { - if (!classNode.getAnnotations(new ClassNode(Artefact.class)).isEmpty()) return; + if (!classNode.getAnnotations(new ClassNode(Artefact.class)).isEmpty()) { + return; + } performInjectionOnAnnotatedEntity(classNode); } } @@ -212,7 +221,9 @@ private void injectToStringMethod(ClassNode classNode) { private boolean isEnum(ClassNode classNode) { ClassNode parent = classNode.getSuperClass(); while (parent != null) { - if (parent.getName().equals("java.lang.Enum")) return true; + if (parent.getName().equals("java.lang.Enum")) { + return true; + } parent = parent.getSuperClass(); } return false; @@ -242,7 +253,6 @@ public void performInjection(SourceUnit source, ClassNode classNode) { performInjection(source, null, classNode); } - public void performInjectionOnAnnotatedClass(SourceUnit source, ClassNode classNode) { performInjectionOnAnnotatedEntity(classNode); } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/EnhancesTraitTransformation.groovy b/grails-core/src/main/groovy/org/grails/compiler/injection/EnhancesTraitTransformation.groovy index 98264d97329..bcb01d52073 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/EnhancesTraitTransformation.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/EnhancesTraitTransformation.groovy @@ -18,13 +18,20 @@ */ package org.grails.compiler.injection + import grails.artefact.Enhances import grails.compiler.traits.TraitInjector import groovy.transform.CompilationUnitAware import groovy.transform.CompileStatic import org.apache.grails.common.compiler.GroovyTransformOrder import org.apache.groovy.ast.tools.AnnotatedNodeUtils -import org.codehaus.groovy.ast.* +import org.codehaus.groovy.ast.ASTNode +import org.codehaus.groovy.ast.AnnotatedNode +import org.codehaus.groovy.ast.AnnotationNode +import org.codehaus.groovy.ast.ClassHelper +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.MethodNode +import org.codehaus.groovy.ast.MixinNode import org.codehaus.groovy.ast.expr.CastExpression import org.codehaus.groovy.ast.expr.ClassExpression import org.codehaus.groovy.ast.expr.ListExpression @@ -34,7 +41,7 @@ import org.codehaus.groovy.control.CompilePhase import org.codehaus.groovy.control.SourceUnit import org.codehaus.groovy.transform.GroovyASTTransformation -import static java.lang.reflect.Modifier.* +import static java.lang.reflect.Modifier.PUBLIC /** * Implementation for {@link Enhances) @@ -61,10 +68,9 @@ class EnhancesTraitTransformation extends AbstractArtefactTypeAstTransformation ClassNode cNode = (ClassNode) parent - - if(isTrait(cNode)) { + if (isTrait(cNode)) { def expr = ann.getMember("value") - if(!(expr instanceof ListExpression)) { + if (!(expr instanceof ListExpression)) { def newList = new ListExpression() newList.addExpression(expr) expr = newList @@ -72,27 +78,25 @@ class EnhancesTraitTransformation extends AbstractArtefactTypeAstTransformation def interfaces = [ClassHelper.make(TraitInjector)] as ClassNode[] String traitClassName = cNode.name - if(traitClassName.endsWith('$Trait$Helper')) { + if (traitClassName.endsWith('$Trait$Helper')) { traitClassName = traitClassName[0..-14] } ClassNode transformerNode = new ClassNode("${traitClassName}TraitInjector", PUBLIC, ClassHelper.OBJECT_TYPE, interfaces, MixinNode.EMPTY_ARRAY) - def classNodeRef = ClassHelper.make(traitClassName).getPlainNodeReference() MethodNode getTraitMethodNode = transformerNode.addMethod( - "getTrait", PUBLIC, ClassHelper.CLASS_Type.getPlainNodeReference(), GrailsASTUtils.ZERO_PARAMETERS, null, new ReturnStatement( new ClassExpression(classNodeRef))) + "getTrait", PUBLIC, ClassHelper.CLASS_Type.getPlainNodeReference(), GrailsASTUtils.ZERO_PARAMETERS, null, new ReturnStatement(new ClassExpression(classNodeRef))) AnnotatedNodeUtils.markAsGenerated(transformerNode, getTraitMethodNode) def strArrayType = ClassHelper.STRING_TYPE.makeArray() MethodNode getArtefactTypesMethodNode = transformerNode.addMethod( - "getArtefactTypes", PUBLIC, strArrayType, GrailsASTUtils.ZERO_PARAMETERS, null, new ReturnStatement( CastExpression.asExpression(strArrayType, expr))) + "getArtefactTypes", PUBLIC, strArrayType, GrailsASTUtils.ZERO_PARAMETERS, null, new ReturnStatement(CastExpression.asExpression(strArrayType, expr))) AnnotatedNodeUtils.markAsGenerated(transformerNode, getArtefactTypesMethodNode) def ast = source.AST transformerNode.module = ast - ast.classes.add transformerNode def compilationTargetDirectory = GlobalGrailsClassInjectorTransformation.resolveCompilationTargetDirectory(source) diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/EntityASTTransformation.java b/grails-core/src/main/groovy/org/grails/compiler/injection/EntityASTTransformation.java index 9014a6cc945..ea1c69fdac8 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/EntityASTTransformation.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/EntityASTTransformation.java @@ -22,9 +22,6 @@ import grails.compiler.ast.GrailsDomainClassInjector; import grails.persistence.Entity; import groovy.transform.CompilationUnitAware; - -import java.util.List; - import org.apache.grails.common.compiler.GroovyTransformOrder; import org.codehaus.groovy.ast.ASTNode; import org.codehaus.groovy.ast.AnnotatedNode; @@ -38,6 +35,7 @@ import org.codehaus.groovy.transform.TransformWithPriority; import org.grails.core.artefact.DomainClassArtefactHandler; +import java.util.List; @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) public class EntityASTTransformation implements ASTTransformation, CompilationUnitAware, TransformWithPriority { @@ -70,11 +68,11 @@ public void visit(ASTNode[] astNodes, SourceUnit sourceUnit) { } public void applyTransformation(SourceUnit sourceUnit, ClassNode classNode) { - if(GrailsASTUtils.isApplied(classNode, EntityASTTransformation.class)) { + if (GrailsASTUtils.isApplied(classNode, EntityASTTransformation.class)) { return; } GrailsASTUtils.markApplied(classNode, EntityASTTransformation.class); - + GrailsDomainClassInjector domainInjector = new DefaultGrailsDomainClassInjector(); domainInjector.performInjectionOnAnnotatedEntity(classNode); @@ -87,15 +85,15 @@ public void applyTransformation(SourceUnit sourceUnit, ClassNode classNode) { injector.performInjection(sourceUnit, classNode); } catch (RuntimeException e) { try { - System.err.println("Error occurred calling AST injector ["+injector.getClass().getName()+"]: " + e.getMessage()); + System.err.println("Error occurred calling AST injector [" + injector.getClass().getName() + "]: " + e.getMessage()); } catch (Throwable t) { // ignore } throw e; } } - - if(compilationUnit != null) { + + if (compilationUnit != null) { TraitInjectionUtils.processTraitsForNode(sourceUnit, classNode, DomainClassArtefactHandler.TYPE, compilationUnit); } } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalImportTransformation.groovy b/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalImportTransformation.groovy index 892070f1b9f..8792cd5fa31 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalImportTransformation.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalImportTransformation.groovy @@ -33,9 +33,10 @@ import org.codehaus.groovy.transform.TransformWithPriority * @author Graeme Rocher * @since 3.0 */ -@GroovyASTTransformation( phase= CompilePhase.CONVERSION) +@GroovyASTTransformation(phase = CompilePhase.CONVERSION) @CompileStatic class GlobalImportTransformation implements ASTTransformation, TransformWithPriority { + @Override void visit(ASTNode[] nodes, SourceUnit source) { ModuleNode ast = source.getAST(); diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsASTUtils.java b/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsASTUtils.java index 21d65bd375d..f700d2046e8 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsASTUtils.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsASTUtils.java @@ -27,9 +27,43 @@ import groovy.transform.TypeChecked; import groovy.transform.TypeCheckingMode; import org.apache.groovy.ast.tools.AnnotatedNodeUtils; -import org.codehaus.groovy.ast.*; -import org.codehaus.groovy.ast.expr.*; -import org.codehaus.groovy.ast.stmt.*; +import org.codehaus.groovy.ast.ASTNode; +import org.codehaus.groovy.ast.AnnotatedNode; +import org.codehaus.groovy.ast.AnnotationNode; +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.ConstructorNode; +import org.codehaus.groovy.ast.FieldNode; +import org.codehaus.groovy.ast.GenericsType; +import org.codehaus.groovy.ast.InnerClassNode; +import org.codehaus.groovy.ast.MethodNode; +import org.codehaus.groovy.ast.Parameter; +import org.codehaus.groovy.ast.PropertyNode; +import org.codehaus.groovy.ast.expr.ArgumentListExpression; +import org.codehaus.groovy.ast.expr.BinaryExpression; +import org.codehaus.groovy.ast.expr.BooleanExpression; +import org.codehaus.groovy.ast.expr.ClassExpression; +import org.codehaus.groovy.ast.expr.ClosureExpression; +import org.codehaus.groovy.ast.expr.ConstantExpression; +import org.codehaus.groovy.ast.expr.ConstructorCallExpression; +import org.codehaus.groovy.ast.expr.DeclarationExpression; +import org.codehaus.groovy.ast.expr.Expression; +import org.codehaus.groovy.ast.expr.ListExpression; +import org.codehaus.groovy.ast.expr.MapEntryExpression; +import org.codehaus.groovy.ast.expr.MapExpression; +import org.codehaus.groovy.ast.expr.MethodCallExpression; +import org.codehaus.groovy.ast.expr.NamedArgumentListExpression; +import org.codehaus.groovy.ast.expr.PropertyExpression; +import org.codehaus.groovy.ast.expr.TupleExpression; +import org.codehaus.groovy.ast.expr.VariableExpression; +import org.codehaus.groovy.ast.stmt.BlockStatement; +import org.codehaus.groovy.ast.stmt.CatchStatement; +import org.codehaus.groovy.ast.stmt.ExpressionStatement; +import org.codehaus.groovy.ast.stmt.IfStatement; +import org.codehaus.groovy.ast.stmt.ReturnStatement; +import org.codehaus.groovy.ast.stmt.Statement; +import org.codehaus.groovy.ast.stmt.ThrowStatement; +import org.codehaus.groovy.ast.stmt.TryCatchStatement; import org.codehaus.groovy.classgen.VariableScopeVisitor; import org.codehaus.groovy.control.Janitor; import org.codehaus.groovy.control.SourceUnit; @@ -47,10 +81,22 @@ import java.io.File; import java.io.IOException; -import java.lang.annotation.*; +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.lang.reflect.Modifier; import java.net.URL; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * Helper methods for working with Groovy AST trees. @@ -69,18 +115,19 @@ public class GrailsASTUtils { public static final Token NOT_EQUALS_OPERATOR = Token.newSymbol("!=", 0, 0); public static final String OBJECT_CLASS = "java.lang.Object"; - private static final ClassNode ENHANCED_CLASS_NODE = new ClassNode(Enhanced.class); public static final ClassNode MISSING_METHOD_EXCEPTION = new ClassNode(MissingMethodException.class); public static final ConstantExpression NULL_EXPRESSION = new ConstantExpression(null); public static final Token ASSIGNMENT_OPERATOR = Token.newSymbol(Types.ASSIGNMENT_OPERATOR, 0, 0); public static final ClassNode OBJECT_CLASS_NODE = new ClassNode(Object.class).getPlainNodeReference(); public static final ClassNode VOID_CLASS_NODE = ClassHelper.VOID_TYPE; public static final ClassNode INTEGER_CLASS_NODE = new ClassNode(Integer.class).getPlainNodeReference(); - private static final ClassNode COMPILESTATIC_CLASS_NODE = ClassHelper.make(CompileStatic.class); - private static final ClassNode TYPECHECKINGMODE_CLASS_NODE = ClassHelper.make(TypeCheckingMode.class); public static final Parameter[] ZERO_PARAMETERS = new Parameter[0]; public static final ArgumentListExpression ZERO_ARGUMENTS = new ArgumentListExpression(); + private static final ClassNode ENHANCED_CLASS_NODE = new ClassNode(Enhanced.class); + private static final ClassNode COMPILESTATIC_CLASS_NODE = ClassHelper.make(CompileStatic.class); + private static final ClassNode TYPECHECKINGMODE_CLASS_NODE = ClassHelper.make(TypeCheckingMode.class); + private static final Map EMPTY_GENERICS_PLACE_HOLDERS_MAP = Collections.emptyMap(); public static void warning(final SourceUnit sourceUnit, final ASTNode node, final String warningMessage) { final String sample = sourceUnit.getSample(node.getLineNumber(), node.getColumnNumber(), new Janitor()); @@ -91,8 +138,8 @@ public static void warning(final SourceUnit sourceUnit, final ASTNode node, fina * Generates a fatal compilation error. * * @param sourceUnit the SourceUnit - * @param astNode the ASTNode which caused the error - * @param message The error message + * @param astNode the ASTNode which caused the error + * @param message The error message */ public static void error(final SourceUnit sourceUnit, final ASTNode astNode, final String message) { error(sourceUnit, astNode, message, true); @@ -102,9 +149,9 @@ public static void error(final SourceUnit sourceUnit, final ASTNode astNode, fin * Generates a fatal compilation error. * * @param sourceUnit the SourceUnit - * @param astNode the ASTNode which caused the error - * @param message The error message - * @param fatal indicates if this is a fatal error + * @param astNode the ASTNode which caused the error + * @param message The error message + * @param fatal indicates if this is a fatal error */ public static void error(final SourceUnit sourceUnit, final ASTNode astNode, final String message, final boolean fatal) { final SyntaxException syntaxException = new SyntaxException(message, astNode.getLineNumber(), astNode.getColumnNumber()); @@ -125,10 +172,12 @@ public static boolean hasProperty(ClassNode classNode, String propertyName) { } final MethodNode method = classNode.getMethod(GrailsNameUtils.getGetterName(propertyName), Parameter.EMPTY_ARRAY); - if (method != null) return true; + if (method != null) { + return true; + } // check read-only field with setter - if( classNode.getField(propertyName) != null && !classNode.getMethods(GrailsNameUtils.getSetterName(propertyName)).isEmpty()) { + if (classNode.getField(propertyName) != null && !classNode.getMethods(GrailsNameUtils.getSetterName(propertyName)).isEmpty()) { return true; } @@ -220,36 +269,40 @@ public static ClassNode getFurthestUnresolvedParent(ClassNode classNode) { * foo(Object instance, String bar) would be added with a signature of foo(String) * and 'this' is passed to the delegate instance * - * @param classNode The class node - * @param delegate The expression that looks up the delegate + * @param classNode The class node + * @param delegate The expression that looks up the delegate * @param declaredMethod The declared method * @return The added method node or null if it couldn't be added */ public static MethodNode addDelegateInstanceMethod(ClassNode classNode, Expression delegate, MethodNode declaredMethod) { - return addDelegateInstanceMethod(classNode, delegate, declaredMethod, null, true); + return addDelegateInstanceMethod(classNode, delegate, declaredMethod, null, true); } + public static MethodNode addDelegateInstanceMethod(ClassNode classNode, Expression delegate, MethodNode declaredMethod, AnnotationNode markerAnnotation) { return addDelegateInstanceMethod(classNode, delegate, declaredMethod, markerAnnotation, true); } + public static MethodNode addDelegateInstanceMethod(ClassNode classNode, Expression delegate, MethodNode declaredMethod, boolean thisAsFirstArgument) { - return addDelegateInstanceMethod(classNode,delegate,declaredMethod, null, thisAsFirstArgument); + return addDelegateInstanceMethod(classNode, delegate, declaredMethod, null, thisAsFirstArgument); } + public static MethodNode addDelegateInstanceMethod(ClassNode classNode, Expression delegate, MethodNode declaredMethod, AnnotationNode markerAnnotation, boolean thisAsFirstArgument) { - return addDelegateInstanceMethod(classNode,delegate,declaredMethod, markerAnnotation, thisAsFirstArgument, null, false); + return addDelegateInstanceMethod(classNode, delegate, declaredMethod, markerAnnotation, thisAsFirstArgument, null, false); } + public static MethodNode addDelegateInstanceMethod(ClassNode classNode, Expression delegate, MethodNode declaredMethod, AnnotationNode markerAnnotation, boolean thisAsFirstArgument, Map genericsPlaceholders) { - return addDelegateInstanceMethod(classNode, delegate, declaredMethod, markerAnnotation, thisAsFirstArgument, genericsPlaceholders, false); + return addDelegateInstanceMethod(classNode, delegate, declaredMethod, markerAnnotation, thisAsFirstArgument, genericsPlaceholders, false); } - + /** * Adds a delegate method to the target class node where the first argument * is to the delegate method is 'this'. In other words a method such as * foo(Object instance, String bar) would be added with a signature of foo(String) * and 'this' is passed to the delegate instance * - * @param classNode The class node - * @param delegate The expression that looks up the delegate - * @param declaredMethod The declared method + * @param classNode The class node + * @param delegate The expression that looks up the delegate + * @param declaredMethod The declared method * @param thisAsFirstArgument Whether 'this' should be passed as the first argument to the method * @return The added method node or null if it couldn't be added */ @@ -276,8 +329,8 @@ public static MethodNode addDelegateInstanceMethod(ClassNode classNode, Expressi MethodCallExpression methodCallExpression = new MethodCallExpression(delegate, methodName, arguments); methodCallExpression.setMethodTarget(declaredMethod); - - if(!noNullCheck) { + + if (!noNullCheck) { ThrowStatement missingMethodException = createMissingMethodThrowable(classNode, declaredMethod); VariableExpression apiVar = addApiVariableDeclaration(delegate, declaredMethod, methodBody); IfStatement ifStatement = createIfElseStatementForApiMethodCall(methodCallExpression, apiVar, missingMethodException); @@ -285,12 +338,12 @@ public static MethodNode addDelegateInstanceMethod(ClassNode classNode, Expressi } else { methodBody.addStatement(new ExpressionStatement(methodCallExpression)); } - + MethodNode methodNode = new MethodNode(methodName, Modifier.PUBLIC, returnType, copyParameters(parameterTypes, genericsPlaceholders), GrailsArtefactClassInjector.EMPTY_CLASS_ARRAY, methodBody); copyAnnotations(declaredMethod, methodNode); - if(shouldAddMarkerAnnotation(markerAnnotation, methodNode)) { + if (shouldAddMarkerAnnotation(markerAnnotation, methodNode)) { methodNode.addAnnotation(markerAnnotation); } @@ -310,7 +363,7 @@ private static IfStatement createIfElseStatementForApiMethodCall(MethodCallExpre BlockStatement elseBlock = new BlockStatement(); elseBlock.addStatement(new ExpressionStatement(methodCallExpression)); - return new IfStatement(new BooleanExpression(new BinaryExpression(apiVar, EQUALS_OPERATOR, NULL_EXPRESSION)),ifBlock,elseBlock); + return new IfStatement(new BooleanExpression(new BinaryExpression(apiVar, EQUALS_OPERATOR, NULL_EXPRESSION)), ifBlock, elseBlock); } private static VariableExpression addApiVariableDeclaration(Expression delegate, MethodNode declaredMethod, BlockStatement methodBody) { @@ -330,10 +383,9 @@ private static ThrowStatement createMissingMethodThrowable(ClassNode classNode, /** * Creates an argument list from the given parameter types. * - * @param parameterTypes The parameter types - * @param thisAsFirstArgument Whether to include a reference to 'this' as the first argument + * @param parameterTypes The parameter types + * @param thisAsFirstArgument Whether to include a reference to 'this' as the first argument * @param genericsPlaceholders - * * @return the arguments */ public static ArgumentListExpression createArgumentListFromParameters(Parameter[] parameterTypes, boolean thisAsFirstArgument, Map genericsPlaceholders) { @@ -368,7 +420,7 @@ public static Parameter[] getRemainingParameterTypes(Parameter[] parameters) { /** * Adds a static method call to given class node that delegates to the given method * - * @param classNode The class node + * @param classNode The class node * @param delegateMethod The delegate method * @return The added method node or null if it couldn't be added */ @@ -381,24 +433,25 @@ public static MethodNode addDelegateStaticMethod(ClassNode classNode, MethodNode * Adds a static method to the given class node that delegates to the given method * and resolves the object to invoke the method on from the given expression. * - * @param expression The expression - * @param classNode The class node + * @param expression The expression + * @param classNode The class node * @param delegateMethod The delegate method * @return The added method node or null if it couldn't be added */ public static MethodNode addDelegateStaticMethod(Expression expression, ClassNode classNode, MethodNode delegateMethod) { return addDelegateStaticMethod(expression, classNode, delegateMethod, null, null, true); } - /** - * Adds a static method to the given class node that delegates to the given method - * and resolves the object to invoke the method on from the given expression. - * - * @param delegate The expression - * @param classNode The class node - * @param delegateMethod The delegate method - * @param markerAnnotation A marker annotation to be added to all methods - * @return The added method node or null if it couldn't be added - */ + + /** + * Adds a static method to the given class node that delegates to the given method + * and resolves the object to invoke the method on from the given expression. + * + * @param delegate The expression + * @param classNode The class node + * @param delegateMethod The delegate method + * @param markerAnnotation A marker annotation to be added to all methods + * @return The added method node or null if it couldn't be added + */ public static MethodNode addDelegateStaticMethod(Expression delegate, ClassNode classNode, MethodNode delegateMethod, AnnotationNode markerAnnotation, Map genericsPlaceholders, boolean noNullCheck) { Parameter[] parameterTypes = delegateMethod.getParameters(); String declaredMethodName = delegateMethod.getName(); @@ -411,12 +464,12 @@ public static MethodNode addDelegateStaticMethod(Expression delegate, ClassNode BlockStatement methodBody = new BlockStatement(); ArgumentListExpression arguments = createArgumentListFromParameters(parameterTypes, false, genericsPlaceholders); - + MethodCallExpression methodCallExpression = new MethodCallExpression( delegate, delegateMethod.getName(), arguments); methodCallExpression.setMethodTarget(delegateMethod); - if(!noNullCheck && !(delegate instanceof ClassExpression)) { + if (!noNullCheck && !(delegate instanceof ClassExpression)) { ThrowStatement missingMethodException = createMissingMethodThrowable(classNode, delegateMethod); VariableExpression apiVar = addApiVariableDeclaration(delegate, delegateMethod, methodBody); IfStatement ifStatement = createIfElseStatementForApiMethodCall(methodCallExpression, apiVar, missingMethodException); @@ -424,7 +477,7 @@ public static MethodNode addDelegateStaticMethod(Expression delegate, ClassNode } else { methodBody.addStatement(new ExpressionStatement(methodCallExpression)); } - + ClassNode returnType = replaceGenericsPlaceholders(delegateMethod.getReturnType(), genericsPlaceholders); MethodNode methodNode = new MethodNode(declaredMethodName, Modifier.PUBLIC | Modifier.STATIC, returnType, copyParameters(parameterTypes, genericsPlaceholders), GrailsArtefactClassInjector.EMPTY_CLASS_ARRAY, @@ -442,7 +495,7 @@ public static MethodNode addDelegateStaticMethod(Expression delegate, ClassNode * Adds or modifies an existing constructor to delegate to the * given static constructor method for initialization logic. * - * @param classNode The class node + * @param classNode The class node * @param constructorMethod The constructor static method */ public static ConstructorNode addDelegateConstructor(ClassNode classNode, MethodNode constructorMethod, Map genericsPlaceholders) { @@ -468,8 +521,7 @@ public static ConstructorNode addDelegateConstructor(ClassNode classNode, Method Statement existingBodyCode = constructorNode.getCode(); if (existingBodyCode instanceof BlockStatement) { ((BlockStatement) existingBodyCode).addStatement(constructorInitExpression); - } - else { + } else { constructorNode.setCode(constructorBody); } } @@ -480,16 +532,14 @@ public static ConstructorNode addDelegateConstructor(ClassNode classNode, Method } constructorNode.addAnnotation(new AnnotationNode(new ClassNode(GrailsDelegatingConstructor.class))); return constructorNode; - } - else { + } else { // create new constructor, restoring default constructor if there is none ConstructorNode cn = findConstructor(classNode, constructorParams); if (cn == null) { cn = new ConstructorNode(Modifier.PUBLIC, copyParameters(constructorParams, genericsPlaceholders), null, constructorBody); classNode.addConstructor(cn); AnnotatedNodeUtils.markAsGenerated(classNode, cn); - } - else { + } else { List annotations = cn.getAnnotations(new ClassNode(GrailsDelegatingConstructor.class)); if (annotations.size() == 0) { Statement code = cn.getCode(); @@ -513,11 +563,11 @@ public static ConstructorNode addDelegateConstructor(ClassNode classNode, Method /** * Finds a constructor for the given class node and parameter types * - * @param classNode The class node + * @param classNode The class node * @param constructorParams The parameter types * @return The located constructor or null */ - public static ConstructorNode findConstructor(ClassNode classNode,Parameter[] constructorParams) { + public static ConstructorNode findConstructor(ClassNode classNode, Parameter[] constructorParams) { List declaredConstructors = classNode.getDeclaredConstructors(); for (ConstructorNode declaredConstructor : declaredConstructors) { if (parametersEqual(constructorParams, declaredConstructor.getParameters())) { @@ -574,21 +624,19 @@ public static Parameter[] copyParameters(Parameter[] parameterTypes, Map emptyGenericsPlaceHoldersMap = Collections.emptyMap(); - public static ClassNode nonGeneric(ClassNode type) { - return replaceGenericsPlaceholders(type, emptyGenericsPlaceHoldersMap); + return replaceGenericsPlaceholders(type, EMPTY_GENERICS_PLACE_HOLDERS_MAP); } @SuppressWarnings("unchecked") public static ClassNode nonGeneric(ClassNode type, final ClassNode wildcardReplacement) { - return replaceGenericsPlaceholders(type, emptyGenericsPlaceHoldersMap, wildcardReplacement); + return replaceGenericsPlaceholders(type, EMPTY_GENERICS_PLACE_HOLDERS_MAP, wildcardReplacement); } - + public static ClassNode replaceGenericsPlaceholders(ClassNode type, Map genericsPlaceholders) { return replaceGenericsPlaceholders(type, genericsPlaceholders, null); } - + public static ClassNode replaceGenericsPlaceholders(ClassNode type, Map genericsPlaceholders, ClassNode defaultPlaceholder) { if (type.isArray()) { return replaceGenericsPlaceholders(type.getComponentType(), genericsPlaceholders).makeArray(); @@ -598,14 +646,14 @@ public static ClassNode replaceGenericsPlaceholders(ClassNode type, Map 0) { GenericsType[] copiedGenericsTypes = new GenericsType[parameterized.length]; @@ -628,7 +676,7 @@ public static ClassNode replaceGenericsPlaceholders(ClassNode type, Map 0 && isAssignableFrom(parameterTypes[0].getType(), classNode); + parameterTypes.length > 0 && isAssignableFrom(parameterTypes[0].getType(), classNode); } /** @@ -663,7 +711,7 @@ public static boolean isCandidateInstanceMethod(ClassNode classNode, MethodNode */ public static boolean isAssignableFrom(ClassNode superClass, ClassNode childClass) { ClassNode currentSuper = childClass; - while (currentSuper != null) { + while (currentSuper != null) { if (currentSuper.equals(superClass)) { return true; } @@ -673,7 +721,6 @@ public static boolean isAssignableFrom(ClassNode superClass, ClassNode childClas return false; } - public static boolean isSubclassOfOrImplementsInterface(ClassNode childClass, ClassNode superClass) { String superClassName = superClass.getName(); return isSubclassOfOrImplementsInterface(childClass, superClassName); @@ -687,7 +734,9 @@ private static boolean implementsInterface(ClassNode classNode, String interface ClassNode currentClassNode = classNode; while (currentClassNode != null && !currentClassNode.getName().equals(OBJECT_CLASS)) { ClassNode[] interfaces = currentClassNode.getInterfaces(); - if (implementsInterfaceInternal(interfaces, interfaceName)) return true; + if (implementsInterfaceInternal(interfaces, interfaceName)) { + return true; + } currentClassNode = currentClassNode.getSuperClass(); } return false; @@ -695,12 +744,12 @@ private static boolean implementsInterface(ClassNode classNode, String interface private static boolean implementsInterfaceInternal(ClassNode[] interfaces, String interfaceName) { for (ClassNode anInterface : interfaces) { - if(anInterface.getName().equals(interfaceName)) { + if (anInterface.getName().equals(interfaceName)) { return true; } ClassNode[] childInterfaces = anInterface.getInterfaces(); - if(childInterfaces != null && childInterfaces.length>0) { - return implementsInterfaceInternal(childInterfaces,interfaceName ); + if (childInterfaces != null && childInterfaces.length > 0) { + return implementsInterfaceInternal(childInterfaces, interfaceName); } } @@ -732,10 +781,10 @@ public static boolean isDomainClass(final ClassNode classNode, final SourceUnit final String grailsAppDirToLookFor = File.separator + GRAILS_APP_DIR + File.separator; final int indexOfGrailsAppDir = sourcePath.lastIndexOf(grailsAppDirToLookFor); - if(indexOfGrailsAppDir >= 0) { + if (indexOfGrailsAppDir >= 0) { final String pathToGrailsAppDir = sourcePath.substring(0, indexOfGrailsAppDir + - grailsAppDirToLookFor.length()); + grailsAppDirToLookFor.length()); final String pathToDomainDir = pathToGrailsAppDir + DOMAIN_DIR + File.separator; @@ -744,7 +793,7 @@ public static boolean isDomainClass(final ClassNode classNode, final SourceUnit final String relativePathToDomainSourceFile = className.replace('.', File.separatorChar) + ".groovy"; final String pathToDomainSourceFile = pathToDomainDir + - relativePathToDomainSourceFile; + relativePathToDomainSourceFile; isDomainClass = new File(pathToDomainSourceFile).exists(); } @@ -772,10 +821,9 @@ public static void addDelegateInstanceMethods(ClassNode supportedSuperType, Clas if (isConstructorMethod(declaredMethod)) { addDelegateConstructor(classNode, declaredMethod, genericsPlaceholders); - } - else if (isCandidateInstanceMethod(supportedSuperType, declaredMethod)) { + } else if (isCandidateInstanceMethod(supportedSuperType, declaredMethod)) { MethodNode methodNode = addDelegateInstanceMethod(classNode, delegateInstance, declaredMethod, null, true, genericsPlaceholders, noNullCheck); - if(addCompileStatic) { + if (addCompileStatic) { addCompileStaticAnnotation(methodNode); } } @@ -792,26 +840,23 @@ public static FieldNode addFieldIfNonExistent(ClassNode classNode, ClassNode fie return null; } - /** * Adds the given expression as a member of the given annotation * * @param annotationNode The annotation node - * @param memberName The name of the member - * @param expression The expression + * @param memberName The name of the member + * @param expression The expression */ public static void addExpressionToAnnotationMember(AnnotationNode annotationNode, String memberName, Expression expression) { Expression exclude = annotationNode.getMember(memberName); - if(exclude instanceof ListExpression) { - ((ListExpression)exclude).addExpression(expression); - } - else if(exclude != null) { + if (exclude instanceof ListExpression) { + ((ListExpression) exclude).addExpression(expression); + } else if (exclude != null) { ListExpression list = new ListExpression(); list.addExpression(exclude); list.addExpression(expression); annotationNode.setMember(memberName, list); - } - else { + } else { annotationNode.setMember(memberName, expression); } } @@ -819,7 +864,7 @@ else if(exclude != null) { /** * Adds an annotation to the give nclass node if it doesn't already exist * - * @param classNode The class node + * @param classNode The class node * @param annotationClass The annotation class */ public static void addAnnotationIfNecessary(ClassNode classNode, Class annotationClass) { @@ -829,7 +874,7 @@ public static void addAnnotationIfNecessary(ClassNode classNode, Class annotationClass) { @@ -839,7 +884,7 @@ public static AnnotationNode addAnnotationOrGetExisting(ClassNode classNode, Cla /** * Adds an annotation to the given class node or returns the existing annotation * - * @param classNode The class node + * @param classNode The class node * @param annotationClass The annotation class */ public static AnnotationNode addAnnotationOrGetExisting(ClassNode classNode, Class annotationClass, Map members) { @@ -856,32 +901,30 @@ public static AnnotationNode addAnnotationOrGetExisting(ClassNode classNode, Cla AnnotationNode annotationToAdd = new AnnotationNode(annotationClassNode); if (annotations.isEmpty()) { classNode.addAnnotation(annotationToAdd); - } - else { + } else { AnnotationNode existing = findAnnotation(annotationClassNode, annotations); - if (existing != null){ + if (existing != null) { annotationToAdd = existing; - } - else { + } else { classNode.addAnnotation(annotationToAdd); } } - if(members != null && !members.isEmpty()) { + if (members != null && !members.isEmpty()) { for (Map.Entry memberEntry : members.entrySet()) { Object value = memberEntry.getValue(); - annotationToAdd.setMember( memberEntry.getKey(), value instanceof Expression ? (Expression)value : new ConstantExpression(value)); + annotationToAdd.setMember(memberEntry.getKey(), value instanceof Expression ? (Expression) value : new ConstantExpression(value)); } } return annotationToAdd; } - /** * Add the grails.artefact.Enhanced annotation to classNode if it does not already exist and ensure that * all of the features in the enhancedFor array are represented in the enhancedFor attribute of the * Enhanced annnotation - * @param classNode the class to add the Enhanced annotation to + * + * @param classNode the class to add the Enhanced annotation to * @param enhancedFor an array of feature names to include in the enhancedFor attribute of the annotation * @return the AnnotationNode associated with the Enhanced annotation for classNode * @see Enhanced @@ -892,33 +935,33 @@ public static AnnotationNode addEnhancedAnnotation(final ClassNode classNode, fi if (annotations.isEmpty()) { enhancedAnnotationNode = new AnnotationNode(ENHANCED_CLASS_NODE); String grailsVersion = getGrailsVersion(); - if(grailsVersion == null) { + if (grailsVersion == null) { grailsVersion = System.getProperty("grails.version"); } - if(grailsVersion != null) { + if (grailsVersion != null) { enhancedAnnotationNode.setMember("version", new ConstantExpression(grailsVersion)); } classNode.addAnnotation(enhancedAnnotationNode); } else { enhancedAnnotationNode = annotations.get(0); } - - if(enhancedFor != null && enhancedFor.length > 0) { + + if (enhancedFor != null && enhancedFor.length > 0) { ListExpression enhancedForArray = (ListExpression) enhancedAnnotationNode.getMember("enhancedFor"); - if(enhancedForArray == null) { + if (enhancedForArray == null) { enhancedForArray = new ListExpression(); enhancedAnnotationNode.setMember("enhancedFor", enhancedForArray); } final List featureNameExpressions = enhancedForArray.getExpressions(); - for(final String feature : enhancedFor) { + for (final String feature : enhancedFor) { boolean exists = false; - for(Expression expression : featureNameExpressions) { - if(expression instanceof ConstantExpression && feature.equals(((ConstantExpression)expression).getValue())) { + for (Expression expression : featureNameExpressions) { + if (expression instanceof ConstantExpression && feature.equals(((ConstantExpression) expression).getValue())) { exists = true; break; } } - if(!exists) { + if (!exists) { featureNameExpressions.add(new ConstantExpression(feature)); } } @@ -942,12 +985,13 @@ public static AnnotationNode findAnnotation(ClassNode annotationClassNode, List< public static AnnotationNode findAnnotation(ClassNode classNode, Class type) { List annotations = classNode.getAnnotations(); - return annotations == null ? null : findAnnotation(new ClassNode(type),annotations); + return annotations == null ? null : findAnnotation(new ClassNode(type), annotations); } /** * Returns true if classNode is marked with annotationClass - * @param classNode A ClassNode to inspect + * + * @param classNode A ClassNode to inspect * @param annotationClass an annotation to look for * @return true if classNode is marked with annotationClass, otherwise false */ @@ -957,7 +1001,8 @@ public static boolean hasAnnotation(final ClassNode classNode, final Class... annotationsToLookFor) { for (Class annotationClass : annotationsToLookFor) { - if(hasAnnotation(classNode, annotationClass)) { + if (hasAnnotation(classNode, annotationClass)) { return true; } } @@ -998,11 +1043,11 @@ public static void addMethodIfNotPresent(ClassNode controllerClassNode, MethodNo } public static ExpressionStatement createPrintlnStatement(String message) { - return new ExpressionStatement(new MethodCallExpression(new VariableExpression("this"),"println", new ArgumentListExpression(new ConstantExpression(message)))); + return new ExpressionStatement(new MethodCallExpression(new VariableExpression("this"), "println", new ArgumentListExpression(new ConstantExpression(message)))); } public static ExpressionStatement createPrintlnStatement(String message, String variable) { - return new ExpressionStatement(new MethodCallExpression(new VariableExpression("this"),"println", new ArgumentListExpression(new BinaryExpression(new ConstantExpression(message),Token.newSymbol(Types.PLUS, 0, 0),new VariableExpression(variable))))); + return new ExpressionStatement(new MethodCallExpression(new VariableExpression("this"), "println", new ArgumentListExpression(new BinaryExpression(new ConstantExpression(message), Token.newSymbol(Types.PLUS, 0, 0), new VariableExpression(variable))))); } /** @@ -1018,10 +1063,10 @@ public static void wrapMethodBodyInTryCatchDebugStatements(MethodNode methodNode methodNode.setCode(newCode); BlockStatement catchBlock = new BlockStatement(); ArgumentListExpression logArguments = new ArgumentListExpression(); - logArguments.addExpression(new BinaryExpression(new ConstantExpression("Error initializing class: "),Token.newSymbol(Types.PLUS, 0, 0),new VariableExpression("e"))); + logArguments.addExpression(new BinaryExpression(new ConstantExpression("Error initializing class: "), Token.newSymbol(Types.PLUS, 0, 0), new VariableExpression("e"))); logArguments.addExpression(new VariableExpression("e")); catchBlock.addStatement(new ExpressionStatement(new MethodCallExpression(new VariableExpression("log"), "error", logArguments))); - tryCatchStatement.addCatch(new CatchStatement(new Parameter(new ClassNode(Throwable.class), "e"),catchBlock)); + tryCatchStatement.addCatch(new CatchStatement(new Parameter(new ClassNode(Throwable.class), "e"), catchBlock)); } /** @@ -1057,7 +1102,7 @@ public static Map> getConstraintMetadata(final C for (final MethodCallExpression methodCallExpression : methodExpressions) { final Expression objectExpression = methodCallExpression.getObjectExpression(); - if (objectExpression instanceof VariableExpression && "this".equals(((VariableExpression)objectExpression).getName())) { + if (objectExpression instanceof VariableExpression && "this".equals(((VariableExpression) objectExpression).getName())) { final Expression methodCallArguments = methodCallExpression.getArguments(); if (methodCallArguments instanceof TupleExpression) { final List methodCallArgumentExpressions = ((TupleExpression) methodCallArguments).getExpressions(); @@ -1069,7 +1114,7 @@ public static Map> getConstraintMetadata(final C if (keyExpression instanceof ConstantExpression) { final Object value = ((ConstantExpression) keyExpression).getValue(); if (value instanceof String) { - constraintNameToExpression.put((String)value, mapEntryExpression.getValueExpression()); + constraintNameToExpression.put((String) value, mapEntryExpression.getValueExpression()); } } } @@ -1085,7 +1130,8 @@ public static Map> getConstraintMetadata(final C /** * Returns a map containing the names and types of the given association type. eg. GrailsDomainClassProperty.HAS_MANY - * @param classNode The target class ndoe + * + * @param classNode The target class ndoe * @param associationType The associationType * @return A map */ @@ -1108,21 +1154,23 @@ public static Map getAssocationMap(ClassNode classNode, Strin return associationMap; } - public static Map getAllAssociationMap(ClassNode classNode) { + public static Map getAllAssociationMap(ClassNode classNode) { Map associationMap = new LinkedHashMap(); - associationMap.putAll( getAssocationMap(classNode, GormProperties.HAS_MANY)); - associationMap.putAll( getAssocationMap(classNode, GormProperties.HAS_ONE)); - associationMap.putAll( getAssocationMap(classNode, GormProperties.BELONGS_TO)); + associationMap.putAll(getAssocationMap(classNode, GormProperties.HAS_MANY)); + associationMap.putAll(getAssocationMap(classNode, GormProperties.HAS_ONE)); + associationMap.putAll(getAssocationMap(classNode, GormProperties.BELONGS_TO)); return associationMap; } public static ClassNode findInterface(ClassNode classNode, ClassNode interfaceNode) { - while(!classNode.equals(OBJECT_CLASS_NODE)) { + while (!classNode.equals(OBJECT_CLASS_NODE)) { Set interfaces = classNode.getAllInterfaces(); for (ClassNode anInterface : interfaces) { - if(anInterface.equals(interfaceNode)) return anInterface; + if (anInterface.equals(interfaceNode)) { + return anInterface; + } } classNode = classNode.getSuperClass(); @@ -1132,12 +1180,17 @@ public static ClassNode findInterface(ClassNode classNode, ClassNode interfaceNo public static boolean hasZeroArgsConstructor(ClassNode implementationNode) { List constructors = implementationNode.getDeclaredConstructors(); - if(constructors.isEmpty()) return true; + if (constructors.isEmpty()) { + return true; + } for (ConstructorNode constructor : constructors) { - if(constructor.getParameters().length == 0 ) return true; + if (constructor.getParameters().length == 0) { + return true; + } } return false; } + /** * Whether the given class node is an inner class * @@ -1151,14 +1204,16 @@ public static boolean isInnerClassNode(ClassNode classNode) { /** * Returns true if the given class name is a parent class of the given class * - * @param classNode The class node + * @param classNode The class node * @param parentClassName the parent class name * @return True if it is a subclass */ public static boolean isSubclassOf(ClassNode classNode, String parentClassName) { ClassNode currentSuper = classNode.getSuperClass(); while (currentSuper != null && !currentSuper.getName().equals(OBJECT_CLASS)) { - if (currentSuper.getName().equals(parentClassName)) return true; + if (currentSuper.getName().equals(parentClassName)) { + return true; + } currentSuper = currentSuper.getSuperClass(); } return false; @@ -1166,54 +1221,56 @@ public static boolean isSubclassOf(ClassNode classNode, String parentClassName) @Target(ElementType.CONSTRUCTOR) @Retention(RetentionPolicy.SOURCE) - private static @interface GrailsDelegatingConstructor {} - + private static @interface GrailsDelegatingConstructor { + + } + /** * Marks a method to be staticly compiled - * + * * @param annotatedNode * @return The annotated method */ public static AnnotatedNode addCompileStaticAnnotation(AnnotatedNode annotatedNode) { return addCompileStaticAnnotation(annotatedNode, false); } - + /** * Adds @CompileStatic annotation to method - * + * * @param annotatedNode * @param skip * @return The annotated method */ public static AnnotatedNode addCompileStaticAnnotation(AnnotatedNode annotatedNode, boolean skip) { - if(annotatedNode != null) { + if (annotatedNode != null) { AnnotationNode an = new AnnotationNode(COMPILESTATIC_CLASS_NODE); - if(skip) { - an.addMember("value", new PropertyExpression(new ClassExpression(TYPECHECKINGMODE_CLASS_NODE), "SKIP")); + if (skip) { + an.addMember("value", new PropertyExpression(new ClassExpression(TYPECHECKINGMODE_CLASS_NODE), "SKIP")); } annotatedNode.addAnnotation(an); - if(!skip) { + if (!skip) { annotatedNode.getDeclaringClass().addTransform(StaticCompileTransformation.class, an); } } return annotatedNode; } - + /** * Set the method target of a MethodCallExpression to the first matching method with same number of arguments. * This doesn't check argument types. - * + * * @param methodCallExpression * @param targetClassNode */ public static MethodCallExpression applyDefaultMethodTarget(final MethodCallExpression methodCallExpression, final ClassNode targetClassNode) { - return applyMethodTarget(methodCallExpression, targetClassNode, (ClassNode[])null); + return applyMethodTarget(methodCallExpression, targetClassNode, (ClassNode[]) null); } - + /** * Set the method target of a MethodCallExpression to the first matching method with same number of arguments. * This doesn't check argument types. - * + * * @param methodCallExpression * @param targetClass * @return The method call expression @@ -1221,12 +1278,12 @@ public static MethodCallExpression applyDefaultMethodTarget(final MethodCallExpr public static MethodCallExpression applyDefaultMethodTarget(final MethodCallExpression methodCallExpression, final Class targetClass) { return applyDefaultMethodTarget(methodCallExpression, ClassHelper.make(targetClass).getPlainNodeReference()); } - + /** * Set the method target of a MethodCallExpression to the first matching method with same number and type of arguments. - * + *

* A null parameter type will match any type - * + * * @param methodCallExpression * @param targetClassNode * @param targetParameterTypes @@ -1234,17 +1291,18 @@ public static MethodCallExpression applyDefaultMethodTarget(final MethodCallExpr */ public static MethodCallExpression applyMethodTarget(final MethodCallExpression methodCallExpression, final ClassNode targetClassNode, final ClassNode... targetParameterTypes) { String methodName = methodCallExpression.getMethodAsString(); - if(methodName==null) return methodCallExpression; - int argumentCount = methodCallExpression.getArguments() != null ? ((TupleExpression)methodCallExpression.getArguments()).getExpressions().size() : 0; - + if (methodName == null) { + return methodCallExpression; + } + int argumentCount = methodCallExpression.getArguments() != null ? ((TupleExpression) methodCallExpression.getArguments()).getExpressions().size() : 0; + String methodFoundInClass = null; - - + for (MethodNode method : targetClassNode.getMethods(methodName)) { int methodParameterCount = method.getParameters() != null ? method.getParameters().length : 0; if (methodParameterCount == argumentCount && (targetParameterTypes == null || (parameterTypesMatch(method.getParameters(), targetParameterTypes)))) { String methodFromClass = method.getDeclaringClass().getName(); - if(methodFoundInClass == null) { + if (methodFoundInClass == null) { methodCallExpression.setMethodTarget(method); methodFoundInClass = methodFromClass; } else if (methodFromClass.equals(methodFoundInClass)) { @@ -1254,10 +1312,10 @@ public static MethodCallExpression applyMethodTarget(final MethodCallExpression } return methodCallExpression; } - + /** * Set the method target of a MethodCallExpression to the first matching method with same number and type of arguments. - * + * * @param methodCallExpression * @param targetClass * @param targetParameterClassTypes @@ -1266,10 +1324,10 @@ public static MethodCallExpression applyMethodTarget(final MethodCallExpression public static MethodCallExpression applyMethodTarget(final MethodCallExpression methodCallExpression, final Class targetClass, final Class... targetParameterClassTypes) { return applyMethodTarget(methodCallExpression, ClassHelper.make(targetClass).getPlainNodeReference(), convertTargetParameterTypes(targetParameterClassTypes)); } - + /** * Set the method target of a MethodCallExpression to the first matching method with same number and type of arguments. - * + * * @param methodCallExpression * @param targetClassNode * @param targetParameterClassTypes @@ -1277,13 +1335,13 @@ public static MethodCallExpression applyMethodTarget(final MethodCallExpression */ public static MethodCallExpression applyMethodTarget(final MethodCallExpression methodCallExpression, final ClassNode targetClassNode, final Class... targetParameterClassTypes) { return applyMethodTarget(methodCallExpression, targetClassNode, convertTargetParameterTypes(targetParameterClassTypes)); - } + } private static ClassNode[] convertTargetParameterTypes(final Class[] targetParameterClassTypes) { ClassNode[] targetParameterTypes = null; - if(targetParameterClassTypes != null) { + if (targetParameterClassTypes != null) { targetParameterTypes = new ClassNode[targetParameterClassTypes.length]; - for(int i=0;i < targetParameterClassTypes.length;i++) { + for (int i = 0; i < targetParameterClassTypes.length; i++) { targetParameterTypes[i] = targetParameterClassTypes[i] != null ? ClassHelper.make(targetParameterClassTypes[i]).getPlainNodeReference() : null; } } @@ -1291,18 +1349,20 @@ private static ClassNode[] convertTargetParameterTypes(final Class[] targetPa } private static boolean parameterTypesMatch(Parameter[] parameters, ClassNode[] targetParameterTypes) { - if(targetParameterTypes==null || targetParameterTypes.length==0) return true; - for(int i=0;i < parameters.length;i++) { - if(targetParameterTypes.length > i && targetParameterTypes[i] != null && !parameters[i].getType().getName().equals(targetParameterTypes[i].getName())) { + if (targetParameterTypes == null || targetParameterTypes.length == 0) { + return true; + } + for (int i = 0; i < parameters.length; i++) { + if (targetParameterTypes.length > i && targetParameterTypes[i] != null && !parameters[i].getType().getName().equals(targetParameterTypes[i].getName())) { return false; } } return true; } - + /** * Build static direct call to getter of a property - * + * * @param objectExpression * @param propertyName * @param targetClassNode @@ -1311,10 +1371,10 @@ private static boolean parameterTypesMatch(Parameter[] parameters, ClassNode[] t public static MethodCallExpression buildGetPropertyExpression(final Expression objectExpression, final String propertyName, final ClassNode targetClassNode) { return buildGetPropertyExpression(objectExpression, propertyName, targetClassNode, false); } - + /** * Build static direct call to getter of a property - * + * * @param objectExpression * @param propertyName * @param targetClassNode @@ -1325,15 +1385,15 @@ public static MethodCallExpression buildGetPropertyExpression(final Expression o String methodName = (useBooleanGetter ? "is" : "get") + MetaClassHelper.capitalize(propertyName); MethodCallExpression methodCallExpression = new MethodCallExpression(objectExpression, methodName, MethodCallExpression.NO_ARGUMENTS); MethodNode getterMethod = targetClassNode.getGetterMethod(methodName); - if(getterMethod != null) { + if (getterMethod != null) { methodCallExpression.setMethodTarget(getterMethod); } return methodCallExpression; } - + /** * Build static direct call to setter of a property - * + * * @param objectExpression * @param propertyName * @param targetClassNode @@ -1344,15 +1404,15 @@ public static MethodCallExpression buildSetPropertyExpression(final Expression o String methodName = "set" + MetaClassHelper.capitalize(propertyName); MethodCallExpression methodCallExpression = new MethodCallExpression(objectExpression, methodName, new ArgumentListExpression(valueExpression)); MethodNode setterMethod = targetClassNode.getSetterMethod(methodName); - if(setterMethod != null) { + if (setterMethod != null) { methodCallExpression.setMethodTarget(setterMethod); } return methodCallExpression; } - + /** * Build static direct call to put entry in Map - * + * * @param objectExpression * @param keyName * @param valueExpression @@ -1364,7 +1424,7 @@ public static MethodCallExpression buildPutMapExpression(final Expression object /** * Build static direct call to get entry from Map - * + * * @param objectExpression * @param keyName * @return The method call expression @@ -1372,7 +1432,7 @@ public static MethodCallExpression buildPutMapExpression(final Expression object public static MethodCallExpression buildGetMapExpression(final Expression objectExpression, final String keyName) { return applyDefaultMethodTarget(new MethodCallExpression(objectExpression, "get", new ArgumentListExpression(new ConstantExpression(keyName))), Map.class); } - + public static Expression buildGetThisObjectExpression(boolean inClosureBlock) { if (!inClosureBlock) { return buildThisExpression(); @@ -1384,11 +1444,11 @@ public static Expression buildGetThisObjectExpression(boolean inClosureBlock) { public static Expression buildThisExpression() { return new VariableExpression("this"); } - + public static MethodCallExpression noImplicitThis(MethodCallExpression methodCallExpression) { return applyImplicitThis(methodCallExpression, false); } - + public static MethodCallExpression applyImplicitThis(MethodCallExpression methodCallExpression, boolean useImplicitThis) { methodCallExpression.setImplicitThis(useImplicitThis); return methodCallExpression; @@ -1397,13 +1457,13 @@ public static MethodCallExpression applyImplicitThis(MethodCallExpression method public static void copyAnnotations(final AnnotatedNode from, final AnnotatedNode to) { copyAnnotations(from, to, null, null); } - + public static void copyAnnotations(final AnnotatedNode from, final AnnotatedNode to, final Set included, final Set excluded) { final List annotationsToCopy = from.getAnnotations(); - for(final AnnotationNode node : annotationsToCopy) { + for (final AnnotationNode node : annotationsToCopy) { String annotationClassName = node.getClassNode().getName(); - if((excluded==null || !excluded.contains(annotationClassName)) && - (included==null || included.contains(annotationClassName))) { + if ((excluded == null || !excluded.contains(annotationClassName)) && + (included == null || included.contains(annotationClassName))) { final AnnotationNode copyOfAnnotationNode = cloneAnnotation(node); to.addAnnotation(copyOfAnnotationNode); } @@ -1413,53 +1473,53 @@ public static void copyAnnotations(final AnnotatedNode from, final AnnotatedNode public static AnnotationNode cloneAnnotation(final AnnotationNode node) { final AnnotationNode copyOfAnnotationNode = new AnnotationNode(node.getClassNode()); final Map members = node.getMembers(); - for(final Map.Entry entry : members.entrySet()) { + for (final Map.Entry entry : members.entrySet()) { copyOfAnnotationNode.addMember(entry.getKey(), entry.getValue()); } return copyOfAnnotationNode; } - + public static void filterAnnotations(final AnnotatedNode annotatedNode, final Set classNamesToRetain, final Set classNamesToRemove) { - for(Iterator iterator = annotatedNode.getAnnotations().iterator(); iterator.hasNext(); ) { + for (Iterator iterator = annotatedNode.getAnnotations().iterator(); iterator.hasNext(); ) { final AnnotationNode node = iterator.next(); String annotationClassName = node.getClassNode().getName(); - if((classNamesToRemove==null || classNamesToRemove.contains(annotationClassName)) && - (classNamesToRetain==null || !classNamesToRetain.contains(annotationClassName))) { + if ((classNamesToRemove == null || classNamesToRemove.contains(annotationClassName)) && + (classNamesToRetain == null || !classNamesToRetain.contains(annotationClassName))) { iterator.remove(); } } } - + public static void removeCompileStaticAnnotations(final AnnotatedNode annotatedNode) { filterAnnotations(annotatedNode, null, new LinkedHashSet(Arrays.asList(new String[]{CompileStatic.class.getName(), TypeChecked.class.getName()}))); } - + public static void markApplied(ASTNode astNode, Class transformationClass) { resolveRedirect(astNode).setNodeMetaData(appliedTransformationKey(transformationClass), Boolean.TRUE); } private static ASTNode resolveRedirect(ASTNode astNode) { - if(astNode instanceof ClassNode) { - astNode = ((ClassNode)astNode).redirect(); + if (astNode instanceof ClassNode) { + astNode = ((ClassNode) astNode).redirect(); } return astNode; } - + private static String appliedTransformationKey(Class transformationClass) { return "APPLIED_" + transformationClass.getName(); } - + public static boolean isApplied(ASTNode astNode, Class transformationClass) { return resolveRedirect(astNode).getNodeMetaData(appliedTransformationKey(transformationClass)) == Boolean.TRUE; } - + public static void processVariableScopes(SourceUnit source, ClassNode classNode) { processVariableScopes(source, classNode, null); } - + public static void processVariableScopes(SourceUnit source, ClassNode classNode, MethodNode methodNode) { VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(source); - if(methodNode == null) { + if (methodNode == null) { scopeVisitor.visitClass(classNode); } else { scopeVisitor.prepareVisit(classNode); @@ -1470,7 +1530,7 @@ public static void processVariableScopes(SourceUnit source, ClassNode classNode, public static boolean isGetterMethod(MethodNode md) { String methodName = md.getName(); - return (((methodName.startsWith("get") && methodName.length() > 3) || (methodName.startsWith("is") && methodName.length() > 2)) && (md.getParameters()==null || md.getParameters().length == 0)); + return (((methodName.startsWith("get") && methodName.length() > 3) || (methodName.startsWith("is") && methodName.length() > 2)) && (md.getParameters() == null || md.getParameters().length == 0)); } public static boolean isSetterMethod(MethodNode md) { @@ -1489,7 +1549,7 @@ public static boolean isSetterOrGetterMethod(MethodNode md) { /** * Find URL of SourceUnit - * + *

* source.getSource().getURI() fails in Groovy-Eclipse compiler * * @param source @@ -1498,7 +1558,7 @@ public static boolean isSetterOrGetterMethod(MethodNode md) { public static URL getSourceUrl(SourceUnit source) { URL url = null; final String filename = source.getName(); - if(filename==null) { + if (filename == null) { return null; } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareClassLoader.java b/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareClassLoader.java index 75177984e5c..bb5a9071999 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareClassLoader.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareClassLoader.java @@ -34,6 +34,8 @@ */ public class GrailsAwareClassLoader extends GroovyClassLoader { + private ClassInjector[] classInjectors; + public GrailsAwareClassLoader() { // default } @@ -54,12 +56,10 @@ public GrailsAwareClassLoader(ClassLoader loader, CompilerConfiguration config) super(loader, config); } - private ClassInjector[] classInjectors; - public void setClassInjectors(ClassInjector[] classInjectors) { this.classInjectors = classInjectors; } - + /** * @see groovy.lang.GroovyClassLoader#createCompilationUnit(org.codehaus.groovy.control.CompilerConfiguration, java.security.CodeSource) */ @@ -71,8 +71,7 @@ protected CompilationUnit createCompilationUnit(CompilerConfiguration config, Co if (classInjectors == null) { operation = new GrailsAwareInjectionOperation(); - } - else { + } else { operation = new GrailsAwareInjectionOperation(classInjectors); } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareInjectionOperation.java b/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareInjectionOperation.java index a9d23cfa52c..f763434fbaa 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareInjectionOperation.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareInjectionOperation.java @@ -39,7 +39,12 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; /** * A Groovy compiler injection operation that uses a specified array of @@ -66,7 +71,6 @@ public GrailsAwareInjectionOperation(ClassInjector[] classInjectors) { localClassInjectors = classInjectors; } - public static ClassInjector[] getClassInjectors() { if (classInjectors == null) { initializeState(); @@ -104,7 +108,7 @@ private static void initializeState() { Resource[] resources; try { resources = scanForPatterns(resolver, pattern2, pattern); - if(resources.length == 0) { + if (resources.length == 0) { classLoader = Thread.currentThread().getContextClassLoader(); resolver = new PathMatchingResourcePatternResolver(classLoader); resources = scanForPatterns(resolver, pattern2, pattern); @@ -114,7 +118,9 @@ private static void initializeState() { final Set injectorClasses = new LinkedHashSet(); for (Resource resource : resources) { // ignore not readable classes and closures - if(!resource.isReadable() || resource.getFilename().contains("$_")) continue; + if (!resource.isReadable() || resource.getFilename().contains("$_")) { + continue; + } try (InputStream inputStream = resource.getInputStream()) { final ClassReader classReader = new ClassReader(inputStream); final String astTransformerClassName = AstTransformer.class.getSimpleName(); @@ -125,8 +131,9 @@ public AnnotationVisitor visitAnnotation(String desc, boolean visible) { try { if (visible && desc.contains(astTransformerClassName)) { Class injectorClass = finalClassLoader.loadClass(classReader.getClassName().replace('/', '.')); - if (injectorClasses.contains(injectorClass)) + if (injectorClasses.contains(injectorClass)) { return super.visitAnnotation(desc, true); + } if (ClassInjector.class.isAssignableFrom(injectorClass)) { injectorClasses.add(injectorClass); @@ -164,10 +171,10 @@ public AnnotationVisitor visitAnnotation(String desc, boolean visible) { } } - private static Resource[] scanForPatterns(PathMatchingResourcePatternResolver resolver, String...patterns) throws IOException { + private static Resource[] scanForPatterns(PathMatchingResourcePatternResolver resolver, String... patterns) throws IOException { List results = new ArrayList(); - for(String pattern : patterns) { - results.addAll( Arrays.asList(resolver.getResources(pattern)) ); + for (String pattern : patterns) { + results.addAll(Arrays.asList(resolver.getResources(pattern))); } return results.toArray(new Resource[0]); } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/GroovyEclipseCompilationHelper.groovy b/grails-core/src/main/groovy/org/grails/compiler/injection/GroovyEclipseCompilationHelper.groovy index 5eec1f772ee..5907229ccb0 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/GroovyEclipseCompilationHelper.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/GroovyEclipseCompilationHelper.groovy @@ -40,23 +40,23 @@ class GroovyEclipseCompilationHelper { context.setTypeLocator(new StandardTypeLocator(sourceUnit.getClass().getClassLoader())) context.setRootObject(sourceUnit) try { - // Honour the targetDirectory within the source configuration directory. - File targetDirectory = sourceUnit.configuration.targetDirectory - - if (targetDirectory == null) { - - // Resolve as before. - targetDirectory = ((File) new SpelExpressionParser().parseExpression("eclipseFile.project.getFolder(T(org.eclipse.jdt.core.JavaCore).create(eclipseFile.project).outputLocation).rawLocation.makeAbsolute().toFile().absoluteFile").getValue(context)) - - } else if (!targetDirectory.isAbsolute()) { - // Target directory is set and is not absolute. - // We should assume that this is a path relative to the current eclipse project, - // and needs resolving appropriately. - targetDirectory = ((File) new SpelExpressionParser().parseExpression("eclipseFile.project.getFolder('${targetDirectory.path}').rawLocation.makeAbsolute().toFile().absoluteFile").getValue(context)) - - } - // Else absolute file location. We should return as-is. - return targetDirectory + // Honour the targetDirectory within the source configuration directory. + File targetDirectory = sourceUnit.configuration.targetDirectory + + if (targetDirectory == null) { + + // Resolve as before. + targetDirectory = ((File) new SpelExpressionParser().parseExpression("eclipseFile.project.getFolder(T(org.eclipse.jdt.core.JavaCore).create(eclipseFile.project).outputLocation).rawLocation.makeAbsolute().toFile().absoluteFile").getValue(context)) + + } else if (!targetDirectory.isAbsolute()) { + // Target directory is set and is not absolute. + // We should assume that this is a path relative to the current eclipse project, + // and needs resolving appropriately. + targetDirectory = ((File) new SpelExpressionParser().parseExpression("eclipseFile.project.getFolder('${targetDirectory.path}').rawLocation.makeAbsolute().toFile().absoluteFile").getValue(context)) + + } + // Else absolute file location. We should return as-is. + return targetDirectory } catch (Throwable e) { // Not running Eclipse IDE, probably using the Eclipse compiler with Maven return null diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/MixinTransformation.java b/grails-core/src/main/groovy/org/grails/compiler/injection/MixinTransformation.java index 7a070c74fa3..7fd40925bf6 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/MixinTransformation.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/MixinTransformation.java @@ -22,24 +22,30 @@ import grails.util.Mixin; import grails.util.MixinTargetAware; import groovy.lang.GroovyObjectSupport; - -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.List; - import org.apache.grails.common.compiler.GroovyTransformOrder; import org.codehaus.groovy.ast.ASTNode; import org.codehaus.groovy.ast.AnnotatedNode; import org.codehaus.groovy.ast.AnnotationNode; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.MethodNode; -import org.codehaus.groovy.ast.expr.*; +import org.codehaus.groovy.ast.expr.ClassExpression; +import org.codehaus.groovy.ast.expr.ConstantExpression; +import org.codehaus.groovy.ast.expr.ConstructorCallExpression; +import org.codehaus.groovy.ast.expr.Expression; +import org.codehaus.groovy.ast.expr.ListExpression; +import org.codehaus.groovy.ast.expr.MapEntryExpression; +import org.codehaus.groovy.ast.expr.MapExpression; +import org.codehaus.groovy.ast.expr.VariableExpression; import org.codehaus.groovy.control.CompilePhase; import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.transform.ASTTransformation; import org.codehaus.groovy.transform.GroovyASTTransformation; import org.codehaus.groovy.transform.TransformWithPriority; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.List; + /** * The logic for the {@link grails.util.Mixin} location transform. * @@ -52,9 +58,9 @@ public class MixinTransformation implements ASTTransformation, TransformWithPriority { public static final ClassNode GROOVY_OBJECT_CLASS_NODE = new ClassNode(GroovyObjectSupport.class); + public static final String OBJECT_CLASS = "java.lang.Object"; private static final ClassNode MY_TYPE = new ClassNode(Mixin.class); private static final String MY_TYPE_NAME = "@" + MY_TYPE.getNameWithoutPackage(); - public static final String OBJECT_CLASS = "java.lang.Object"; public void visit(ASTNode[] astNodes, SourceUnit source) { if (!(astNodes[0] instanceof AnnotationNode) || !(astNodes[1] instanceof AnnotatedNode)) { @@ -71,7 +77,7 @@ public void visit(ASTNode[] astNodes, SourceUnit source) { String cName = classNode.getName(); if (classNode.isInterface()) { throw new RuntimeException("Error processing interface '" + cName + "'. " + - MY_TYPE_NAME + " not allowed for interfaces."); + MY_TYPE_NAME + " not allowed for interfaces."); } ListExpression values = getListOfClasses(node); @@ -79,6 +85,7 @@ public void visit(ASTNode[] astNodes, SourceUnit source) { weaveMixinsIntoClass(classNode, values); } + public void weaveMixinsIntoClass(ClassNode classNode, ListExpression values) { if (values != null) { for (Expression current : values.getExpressions()) { @@ -93,14 +100,14 @@ public void weaveMixinsIntoClass(ClassNode classNode, ListExpression values) { boolean isTargetAware = GrailsASTUtils.findInterface(mixinClassNode, new ClassNode(MixinTargetAware.class)) != null; ConstructorCallExpression initialValue; - if(isTargetAware) { + if (isTargetAware) { initialValue = new ConstructorCallExpression(mixinClassNode, new MapExpression( Arrays.asList(new MapEntryExpression(new ConstantExpression("target"), new VariableExpression("this"))) )); - } else { + } else { initialValue = new ConstructorCallExpression(mixinClassNode, GrailsASTUtils.ZERO_ARGUMENTS); } - classNode.addField(fieldName, Modifier.PRIVATE, mixinClassNode,initialValue); + classNode.addField(fieldName, Modifier.PRIVATE, mixinClassNode, initialValue); } VariableExpression fieldReference = new VariableExpression(fieldName, mixinClassNode); @@ -112,8 +119,7 @@ public void weaveMixinsIntoClass(ClassNode classNode, ListExpression values) { if (isCandidateMethod(mixinMethod) && !hasDeclaredMethod(classNode, mixinMethod)) { if (mixinMethod.isStatic()) { GrailsASTUtils.addCompileStaticAnnotation(GrailsASTUtils.addDelegateStaticMethod(classNode, mixinMethod)); - } - else { + } else { GrailsASTUtils.addCompileStaticAnnotation(GrailsASTUtils.addDelegateInstanceMethod(classNode, fieldReference, mixinMethod, false)); } } @@ -129,6 +135,7 @@ public void weaveMixinsIntoClass(ClassNode classNode, ListExpression values) { protected boolean hasDeclaredMethod(ClassNode classNode, MethodNode mixinMethod) { return classNode.hasDeclaredMethod(mixinMethod.getName(), mixinMethod.getParameters()); } + protected ListExpression getListOfClasses(AnnotationNode node) { Expression value = node.getMember("value"); ListExpression values = null; @@ -150,10 +157,10 @@ public static boolean isAddableMethod(MethodNode declaredMethod) { ClassNode groovyMethods = GROOVY_OBJECT_CLASS_NODE; String methodName = declaredMethod.getName(); return !declaredMethod.isSynthetic() && - !methodName.contains("$") && - Modifier.isPublic(declaredMethod.getModifiers()) && - !Modifier.isAbstract(declaredMethod.getModifiers()) && - !groovyMethods.hasMethod(declaredMethod.getName(), declaredMethod.getParameters()); + !methodName.contains("$") && + Modifier.isPublic(declaredMethod.getModifiers()) && + !Modifier.isAbstract(declaredMethod.getModifiers()) && + !groovyMethods.hasMethod(declaredMethod.getName(), declaredMethod.getParameters()); } @Override diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/PluginAstReader.java b/grails-core/src/main/groovy/org/grails/compiler/injection/PluginAstReader.java index 7b0a426b83b..d85e34c8cee 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/PluginAstReader.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/PluginAstReader.java @@ -23,13 +23,20 @@ import org.codehaus.groovy.ast.ClassCodeVisitorSupport; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.PropertyNode; -import org.codehaus.groovy.ast.expr.*; +import org.codehaus.groovy.ast.expr.ConstantExpression; +import org.codehaus.groovy.ast.expr.Expression; +import org.codehaus.groovy.ast.expr.ListExpression; +import org.codehaus.groovy.ast.expr.MapEntryExpression; +import org.codehaus.groovy.ast.expr.MapExpression; import org.codehaus.groovy.control.CompilationFailedException; import org.codehaus.groovy.control.SourceUnit; -import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.grails.io.support.Resource; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** @@ -39,6 +46,7 @@ * @since 3.0 */ class PluginAstReader { + private BasicGrailsPluginInfo pluginInfo; public PluginAstReader() { @@ -52,7 +60,7 @@ GrailsPluginInfo getPluginInfo() { public GrailsPluginInfo readPluginInfo(ClassNode classNode) throws CompilationFailedException { String className = classNode.getNameWithoutPackage(); - if(className.endsWith("GrailsPlugin")) { + if (className.endsWith("GrailsPlugin")) { visitContents(className, classNode); } return pluginInfo; @@ -65,32 +73,28 @@ protected void visitContents(String className, final ClassNode classNode) { public void visitProperty(PropertyNode node) { String name = node.getName(); - - final Expression expr = node.getField().getInitialExpression(); if (expr != null) { Object value = null; if (expr instanceof ListExpression) { final List list = new ArrayList(); - for (Expression i : ((ListExpression)expr).getExpressions()) { + for (Expression i : ((ListExpression) expr).getExpressions()) { list.add(i.getText()); } value = list; - } - else if (expr instanceof MapExpression) { + } else if (expr instanceof MapExpression) { final Map map = new LinkedHashMap(); value = map; - for (MapEntryExpression mee : ((MapExpression)expr).getMapEntryExpressions()) { + for (MapEntryExpression mee : ((MapExpression) expr).getMapEntryExpressions()) { map.put(mee.getKeyExpression().getText(), mee.getValueExpression().getText()); } - } - else { - if(expr instanceof ConstantExpression) { + } else { + if (expr instanceof ConstantExpression) { value = expr.getText(); } } - if(value != null) { + if (value != null) { pluginInfo.setProperty(name, value); super.visitProperty(node); } @@ -109,7 +113,6 @@ protected SourceUnit getSourceUnit() { pluginInfo.setName(GrailsNameUtils.getPluginName(className + ".groovy")); } - /** * Simple Javabean implementation of the GrailsPluginInfo interface. * @@ -120,7 +123,7 @@ public class BasicGrailsPluginInfo implements GrailsPluginInfo { private String name; private String version; - private Map attributes = new ConcurrentHashMap(); + private Map attributes = new ConcurrentHashMap(); public BasicGrailsPluginInfo() { } @@ -146,7 +149,7 @@ public void setProperty(String property, Object newValue) { } public Object getProperty(String property) { - return attributes.get(property); + return attributes.get(property); } public String getFullName() { @@ -161,7 +164,7 @@ public Resource getPluginDir() { return null; } - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) public Map getProperties() { Map props = new HashMap(); props.putAll(attributes); diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/TraitInjectionSupport.groovy b/grails-core/src/main/groovy/org/grails/compiler/injection/TraitInjectionSupport.groovy index 90a8a9cdf70..63920931b5b 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/TraitInjectionSupport.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/TraitInjectionSupport.groovy @@ -22,7 +22,6 @@ package org.grails.compiler.injection import grails.compiler.traits.TraitInjector import groovy.transform.CompileStatic - /** * Utility methods used by {@link TraitInjectionUtils} * @@ -37,13 +36,12 @@ class TraitInjectionSupport { injectors.sort { TraitInjector o1, TraitInjector o2 -> final Class t1 = o1.trait final Class t2 = o2.trait - if(t1 == t2) return 0 + if (t1 == t2) return 0 // lower priority of core traits so that plugins can override - if(o1.getClass().name.startsWith('grails.compiler.traits')) { + if (o1.getClass().name.startsWith('grails.compiler.traits')) { return -1 - } - else { + } else { return 1 } } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/TraitInjectionUtils.java b/grails-core/src/main/groovy/org/grails/compiler/injection/TraitInjectionUtils.java index c7996f4008d..72467ea2a0f 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/TraitInjectionUtils.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/TraitInjectionUtils.java @@ -29,7 +29,12 @@ import org.codehaus.groovy.transform.trait.TraitComposer; import org.grails.core.io.support.GrailsFactoriesLoader; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; /** * @@ -37,7 +42,7 @@ * @since 3.0 * */ -public class TraitInjectionUtils { +public final class TraitInjectionUtils { private static List traitInjectors; @@ -45,7 +50,7 @@ private TraitInjectionUtils() { } private static void extendTraits(CompilationUnit unit, SourceUnit source, ClassNode classNode) { - if(unit.getPhase() != CompilePhase.SEMANTIC_ANALYSIS.getPhaseNumber()) { + if (unit.getPhase() != CompilePhase.SEMANTIC_ANALYSIS.getPhaseNumber()) { TraitComposer.doExtendTraits(classNode, source, unit); } } @@ -64,8 +69,8 @@ private static boolean addTrait(ClassNode classNode, Class trait) { if (!implementsTrait && !traitNotLoaded) { final GenericsType[] genericsTypes = traitClassNode.getGenericsTypes(); final Map parameterNameToParameterValue = new LinkedHashMap(); - if(genericsTypes != null) { - for(GenericsType gt : genericsTypes) { + if (genericsTypes != null) { + for (GenericsType gt : genericsTypes) { parameterNameToParameterValue.put(gt.getName(), classNode); } } @@ -77,13 +82,13 @@ private static boolean addTrait(ClassNode classNode, Class trait) { public static void injectTrait(CompilationUnit unit, SourceUnit source, ClassNode classNode, Class trait) { boolean traitsAdded = addTrait(classNode, trait); - if(traitsAdded) { + if (traitsAdded) { extendTraits(unit, source, classNode); } } private static void doInjectionInternal(CompilationUnit unit, SourceUnit source, ClassNode classNode, - List injectorsToUse) { + List injectorsToUse) { boolean traitsAdded = false; for (TraitInjector injector : injectorsToUse) { @@ -92,28 +97,27 @@ private static void doInjectionInternal(CompilationUnit unit, SourceUnit source, traitsAdded = true; } } - if(traitsAdded) { + if (traitsAdded) { extendTraits(unit, source, classNode); } } private static List getTraitInjectors() { - if(traitInjectors == null) { + if (traitInjectors == null) { traitInjectors = GrailsFactoriesLoader.loadFactories(TraitInjector.class); traitInjectors = TraitInjectionSupport.resolveTraitInjectors(traitInjectors); } - if(traitInjectors != null) { + if (traitInjectors != null) { return Collections.unmodifiableList(traitInjectors); - } - else { + } else { return Collections.emptyList(); } } - - public static void processTraitsForNode(final SourceUnit sourceUnit, + + public static void processTraitsForNode(final SourceUnit sourceUnit, final ClassNode cNode, - final String artefactType, + final String artefactType, final CompilationUnit compilationUnit) { final List traitInjectors = getTraitInjectors(); final List injectorsToUse = new ArrayList(); @@ -123,7 +127,7 @@ public static void processTraitsForNode(final SourceUnit sourceUnit, boolean supportsClassNode = true; if (injector instanceof SupportsClassNode) { - supportsClassNode = ((SupportsClassNode)injector).supports(cNode); + supportsClassNode = ((SupportsClassNode) injector).supports(cNode); } if (artefactTypes.contains(artefactType) && supportsClassNode) { @@ -131,12 +135,12 @@ public static void processTraitsForNode(final SourceUnit sourceUnit, } } try { - if(injectorsToUse.size() > 0) { + if (injectorsToUse.size() > 0) { doInjectionInternal(compilationUnit, sourceUnit, cNode, injectorsToUse); } } catch (RuntimeException e) { try { - System.err.println("Error occurred calling Trait injector ["+TraitInjectionUtils.class.getName()+"]: " + System.err.println("Error occurred calling Trait injector [" + TraitInjectionUtils.class.getName() + "]: " + e.getMessage()); e.printStackTrace(); } catch (Throwable t) { diff --git a/grails-core/src/main/groovy/org/grails/config/CompositeConfig.java b/grails-core/src/main/groovy/org/grails/config/CompositeConfig.java index d179e260652..b921126e6f6 100644 --- a/grails-core/src/main/groovy/org/grails/config/CompositeConfig.java +++ b/grails-core/src/main/groovy/org/grails/config/CompositeConfig.java @@ -22,10 +22,18 @@ import grails.util.GrailsStringUtils; import groovy.transform.CompileStatic; import org.grails.core.exceptions.GrailsConfigurationException; -import org.springframework.util.ClassUtils; - -import java.util.*; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Deque; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; /** * A {@link Config} composed of other Configs @@ -60,7 +68,7 @@ public void addLast(Config config) { @Deprecated public Map flatten() { Map flattened = new LinkedHashMap(); - for(Config c : configs) { + for (Config c : configs) { flattened.putAll(c.flatten()); } return flattened; @@ -69,7 +77,7 @@ public Map flatten() { @Override public Properties toProperties() { Properties properties = new Properties(); - for(Config c : configs) { + for (Config c : configs) { properties.putAll(c.toProperties()); } return properties; @@ -83,7 +91,7 @@ public Config merge(Map toMerge) { @Override public T getProperty(String key, Class targetType, T defaultValue, List allowedValues) { T v = getProperty(key, targetType, defaultValue); - if(!allowedValues.contains(v)) { + if (!allowedValues.contains(v)) { throw new GrailsConfigurationException("Invalid configuration value [$value] for key [${key}]. Possible values $allowedValues"); } return v; @@ -91,9 +99,11 @@ public T getProperty(String key, Class targetType, T defaultValue, List values() { @Override public Set> entrySet() { - Set> entries = new HashSet>(); + Set> entries = new HashSet>(); for (Config config : configs) { entries.addAll(config.entrySet()); } @@ -224,7 +241,9 @@ public String getProperty(String key, String defaultValue) { public T getProperty(String key, Class targetType) { for (Config config : configs) { T v = config.getProperty(key, targetType); - if(v != null) return v; + if (v != null) { + return v; + } } return null; } @@ -238,7 +257,7 @@ public T getProperty(String key, Class targetType, T defaultValue) { @Override public String getRequiredProperty(String key) throws IllegalStateException { String value = getProperty(key); - if(GrailsStringUtils.isBlank(value)) { + if (GrailsStringUtils.isBlank(value)) { throw new IllegalStateException("Value for key [$key] cannot be resolved"); } return value; @@ -247,7 +266,7 @@ public String getRequiredProperty(String key) throws IllegalStateException { @Override public T getRequiredProperty(String key, Class targetType) throws IllegalStateException { T value = getProperty(key, targetType); - if(value == null) { + if (value == null) { throw new IllegalStateException("Value for key [$key] cannot be resolved"); } return value; diff --git a/grails-core/src/main/groovy/org/grails/config/EnvironmentAwarePropertySource.java b/grails-core/src/main/groovy/org/grails/config/EnvironmentAwarePropertySource.java index 923b00f5429..29eb7259a3a 100644 --- a/grails-core/src/main/groovy/org/grails/config/EnvironmentAwarePropertySource.java +++ b/grails-core/src/main/groovy/org/grails/config/EnvironmentAwarePropertySource.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.config; import grails.util.Environment; @@ -35,12 +34,13 @@ */ public class EnvironmentAwarePropertySource extends EnumerablePropertySource { + + protected List propertyNames; + EnvironmentAwarePropertySource(PropertySources source) { super("grails.environment", source); } - protected List propertyNames; - @Override public String[] getPropertyNames() { initialize(); @@ -50,35 +50,37 @@ public String[] getPropertyNames() { @Override public Object getProperty(String name) { initialize(); - if(!propertyNames.contains(name)) { + if (!propertyNames.contains(name)) { return null; } Environment env = Environment.getCurrent(); String key = "environments." + env.getName() + '.' + name; - for(PropertySource propertySource : source) { - if(propertySource != this) { + for (PropertySource propertySource : source) { + if (propertySource != this) { Object value = propertySource.getProperty(key); - if(value != null) return value; + if (value != null) { + return value; + } } } return null; } private void initialize() { - if(propertyNames == null) { + if (propertyNames == null) { propertyNames = new ArrayList<>(); Environment env = Environment.getCurrent(); String key = "environments." + env.getName(); - for(PropertySource propertySource : source) { + for (PropertySource propertySource : source) { - if((propertySource != this) && + if ((propertySource != this) && !propertySource.getName().contains("plugin") && // plugin default configuration is not allowed to be environment aware (GRAILS-12123) propertySource instanceof EnumerablePropertySource) { - EnumerablePropertySource enumerablePropertySource = (EnumerablePropertySource)propertySource; + EnumerablePropertySource enumerablePropertySource = (EnumerablePropertySource) propertySource; - for(String propertyName : enumerablePropertySource.getPropertyNames()) { - if(propertyName.startsWith(key) && propertyName.length() > key.length()) { + for (String propertyName : enumerablePropertySource.getPropertyNames()) { + if (propertyName.startsWith(key) && propertyName.length() > key.length()) { propertyNames.add(propertyName.substring(key.length() + 1)); } } diff --git a/grails-core/src/main/groovy/org/grails/config/NavigableMapConfig.java b/grails-core/src/main/groovy/org/grails/config/NavigableMapConfig.java index 341f5e3811f..d47d0ba0be8 100644 --- a/grails-core/src/main/groovy/org/grails/config/NavigableMapConfig.java +++ b/grails-core/src/main/groovy/org/grails/config/NavigableMapConfig.java @@ -43,19 +43,20 @@ /** * A {@link Config} implementation that operates against a {@link org.grails.config.NavigableMap} * - * @deprecated This class behavior is related to {@link org.grails.config.NavigableMap} which will be removed in future. Use {@link grails.config.Config} instead. * @author Graeme Rocher * @since 3.0 + * @deprecated This class behavior is related to {@link org.grails.config.NavigableMap} which will be removed in future. Use {@link grails.config.Config} instead. */ @Deprecated public abstract class NavigableMapConfig implements Config { + protected static final Logger LOG = LoggerFactory.getLogger(NavigableMapConfig.class); protected ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); protected ConfigurableConversionService conversionService = new DefaultConversionService(); protected NavigableMap configMap = new NavigableMap() { @Override protected Object mergeMapEntry(NavigableMap targetMap, String sourceKey, Object newValue) { - if(newValue instanceof CharSequence) { + if (newValue instanceof CharSequence) { newValue = resolvePlaceholders(newValue.toString()); } return super.mergeMapEntry(targetMap, sourceKey, newValue); @@ -69,8 +70,8 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if(obj instanceof NavigableMapConfig) { - return this.configMap.equals(((NavigableMapConfig)obj).configMap); + if (obj instanceof NavigableMapConfig) { + return this.configMap.equals(((NavigableMapConfig) obj).configMap); } return false; } @@ -153,7 +154,7 @@ public Set> entrySet() { @Override @Deprecated public Map flatten() { - if(LOG.isWarnEnabled()) { + if (LOG.isWarnEnabled()) { LOG.warn("A plugin or your application called the flatten() method which can degrade startup performance"); } return configMap; @@ -176,7 +177,9 @@ public Config merge(Map toMerge) { } public Object asType(Class c) { - if(c==Boolean.class || c==boolean.class) return false; + if (c == Boolean.class || c == boolean.class) { + return false; + } return null; } @@ -208,7 +211,7 @@ public T getProperty(String key, Class targetType) { @Override public T getProperty(String key, Class targetType, T defaultValue, List allowedValues) { T value = getProperty(key, targetType, defaultValue); - if(!allowedValues.contains(value)) { + if (!allowedValues.contains(value)) { throw new GrailsConfigurationException("Invalid configuration value [$value] for key [${key}]. Possible values $allowedValues"); } return value; @@ -280,12 +283,12 @@ private Map convertToMap(NavigableMap from, IdentityHashMap to = new LinkedHashMap<>(); - for (Map.Entry entry: from.entrySet()) { + for (Map.Entry entry : from.entrySet()) { if (entry.getValue() instanceof NavigableMap) { to.put(entry.getKey(), convertToMap((NavigableMap) entry.getValue(), cache)); } else if (entry.getValue() instanceof List) { List newList = new ArrayList<>(); - for (Object o: (List) entry.getValue()) { + for (Object o : (List) entry.getValue()) { if (o instanceof NavigableMap) { newList.add(convertToMap((NavigableMap) o, cache)); } else { @@ -302,13 +305,13 @@ private Map convertToMap(NavigableMap from, IdentityHashMap entry: (Set>) config.entrySet()) { + for (Map.Entry entry : (Set>) config.entrySet()) { final IdentityHashMap> cache = new IdentityHashMap<>(); if (entry.getValue() instanceof NavigableMap) { config.setProperty(entry.getKey(), convertToMap((NavigableMap) entry.getValue(), cache)); } else if (entry.getValue() instanceof List) { final List newList = new ArrayList<>(); - for (Object o: (List) entry.getValue()) { + for (Object o : (List) entry.getValue()) { if (o instanceof NavigableMap) { newList.add(convertToMap((NavigableMap) o, cache)); } else { @@ -362,8 +365,8 @@ private Object toEnumValue(Class targetType, String stringValue) { @Override public String getRequiredProperty(String key) throws IllegalStateException { String value = getProperty(key); - if(GrailsStringUtils.isBlank(value)) { - throw new IllegalStateException("Value for key ["+key+"] cannot be resolved"); + if (GrailsStringUtils.isBlank(value)) { + throw new IllegalStateException("Value for key [" + key + "] cannot be resolved"); } return value; } @@ -371,23 +374,12 @@ public String getRequiredProperty(String key) throws IllegalStateException { @Override public T getRequiredProperty(String key, Class targetType) throws IllegalStateException { T value = getProperty(key, targetType); - if(value == null) { - throw new IllegalStateException("Value for key ["+key+"] cannot be resolved"); + if (value == null) { + throw new IllegalStateException("Value for key [" + key + "] cannot be resolved"); } return value; } - public static class ClassConversionException extends ConversionException { - - public ClassConversionException(Class actual, Class expected) { - super(String.format("Actual type %s is not assignable to expected type %s", actual.getName(), expected.getName())); - } - - public ClassConversionException(String actual, Class expected, Exception ex) { - super(String.format("Could not find/load class %s during attempt to convert to %s", actual, expected.getName()), ex); - } - } - /** * Resolves dot notated getProperty calls on a config object so that injected environmental variables * are properly resolved the same as Groovy's dot notation. @@ -424,4 +416,15 @@ private List convertTokensIntoArrayList(StringTokenizer st) { } return elements; } + + public static class ClassConversionException extends ConversionException { + + public ClassConversionException(Class actual, Class expected) { + super(String.format("Actual type %s is not assignable to expected type %s", actual.getName(), expected.getName())); + } + + public ClassConversionException(String actual, Class expected, Exception ex) { + super(String.format("Could not find/load class %s during attempt to convert to %s", actual, expected.getName()), ex); + } + } } diff --git a/grails-core/src/main/groovy/org/grails/config/NavigableMapPropertySource.groovy b/grails-core/src/main/groovy/org/grails/config/NavigableMapPropertySource.groovy index 5f7bae42155..1f92d369318 100644 --- a/grails-core/src/main/groovy/org/grails/config/NavigableMapPropertySource.groovy +++ b/grails-core/src/main/groovy/org/grails/config/NavigableMapPropertySource.groovy @@ -23,7 +23,6 @@ import org.springframework.boot.origin.OriginTrackedValue import org.springframework.core.env.MapPropertySource import org.springframework.util.StringUtils - /** * A {@link org.springframework.core.env.PropertySource} that doesn't return values for navigable submaps * @@ -43,7 +42,7 @@ class NavigableMapPropertySource extends MapPropertySource { this.propertyNames = source.keySet().findAll() { key -> !(source.get(key) instanceof NavigableMap) } as String[] - navigablePropertyNames = StringUtils.toStringArray(source.keySet()); + navigablePropertyNames = StringUtils.toStringArray(source.keySet()); } @Override @@ -55,8 +54,8 @@ class NavigableMapPropertySource extends MapPropertySource { Object getProperty(String name) { def value = super.getProperty(name) if (value instanceof OriginTrackedValue) { - return ((OriginTrackedValue)value).value - } else if(value instanceof NavigableMap || value instanceof NavigableMap.NullSafeNavigator) { + return ((OriginTrackedValue) value).value + } else if (value instanceof NavigableMap || value instanceof NavigableMap.NullSafeNavigator) { return null } return value diff --git a/grails-core/src/main/groovy/org/grails/config/PrefixedConfig.java b/grails-core/src/main/groovy/org/grails/config/PrefixedConfig.java index 7d3058dfa17..a30a469b954 100644 --- a/grails-core/src/main/groovy/org/grails/config/PrefixedConfig.java +++ b/grails-core/src/main/groovy/org/grails/config/PrefixedConfig.java @@ -20,7 +20,16 @@ import grails.config.Config; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; /** * A config that accepts a prefix @@ -42,13 +51,21 @@ public PrefixedConfig(String prefix, Config delegate) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } PrefixedConfig entries = (PrefixedConfig) o; - if (delegate != null ? !delegate.equals(entries.delegate) : entries.delegate != null) return false; - if (prefix != null ? !prefix.equals(entries.prefix) : entries.prefix != null) return false; + if (delegate != null ? !delegate.equals(entries.delegate) : entries.delegate != null) { + return false; + } + if (prefix != null ? !prefix.equals(entries.prefix) : entries.prefix != null) { + return false; + } return true; } @@ -79,7 +96,6 @@ public Properties toProperties() { return properties; } - @Override public Object getAt(Object key) { return get(key); @@ -233,7 +249,6 @@ public void clear() { throw new UnsupportedOperationException("Config cannot be modified"); } - @Override public Config merge(Map toMerge) { throw new UnsupportedOperationException("Config cannot be modified"); @@ -241,7 +256,7 @@ public Config merge(Map toMerge) { @Override public T getProperty(String key, Class targetType, T defaultValue, List allowedValues) { - return delegate.getProperty(key,targetType,defaultValue,allowedValues); + return delegate.getProperty(key, targetType, defaultValue, allowedValues); } @Override diff --git a/grails-core/src/main/groovy/org/grails/config/PrefixedMapPropertySource.groovy b/grails-core/src/main/groovy/org/grails/config/PrefixedMapPropertySource.groovy index 8e36d4d5af6..80c7481bed6 100644 --- a/grails-core/src/main/groovy/org/grails/config/PrefixedMapPropertySource.groovy +++ b/grails-core/src/main/groovy/org/grails/config/PrefixedMapPropertySource.groovy @@ -30,6 +30,7 @@ import org.springframework.core.env.EnumerablePropertySource @CompileStatic class PrefixedMapPropertySource extends EnumerablePropertySource { + final EnumerablePropertySource source final String prefix final String[] propertyNames diff --git a/grails-core/src/main/groovy/org/grails/config/PropertySourcesConfig.java b/grails-core/src/main/groovy/org/grails/config/PropertySourcesConfig.java index dc58d0f06bc..33aaa0781d5 100644 --- a/grails-core/src/main/groovy/org/grails/config/PropertySourcesConfig.java +++ b/grails-core/src/main/groovy/org/grails/config/PropertySourcesConfig.java @@ -44,7 +44,6 @@ public class PropertySourcesConfig extends NavigableMapConfig { protected PropertySources propertySources; protected PropertySourcesPropertyResolver propertySourcesPropertyResolver; - public PropertySourcesConfig(PropertySources propertySources) { this.propertySources = propertySources; this.propertySourcesPropertyResolver = new PropertySourcesPropertyResolver(propertySources); @@ -66,6 +65,7 @@ public PropertySourcesConfig(Map mapPropertySource) { this.propertySourcesPropertyResolver = new PropertySourcesPropertyResolver(propertySources); initializeFromPropertySources(propertySources); } + public PropertySourcesConfig(PropertySource propertySource) { MutablePropertySources mutablePropertySources = new MutablePropertySources(); mutablePropertySources.addFirst(propertySource); @@ -73,6 +73,7 @@ public PropertySourcesConfig(PropertySource propertySource) { this.propertySourcesPropertyResolver = new PropertySourcesPropertyResolver(propertySources); initializeFromPropertySources(propertySources); } + public PropertySources getPropertySources() { return propertySources; } @@ -84,20 +85,20 @@ public void refresh() { protected void initializeFromPropertySources(PropertySources propertySources) { EnvironmentAwarePropertySource environmentAwarePropertySource = new EnvironmentAwarePropertySource(propertySources); - if(propertySources instanceof MutablePropertySources) { + if (propertySources instanceof MutablePropertySources) { final String applicationConfig = "applicationConfigurationProperties"; if (propertySources.contains(applicationConfig)) { - ((MutablePropertySources)propertySources).addBefore(applicationConfig, environmentAwarePropertySource); + ((MutablePropertySources) propertySources).addBefore(applicationConfig, environmentAwarePropertySource); } else { - ((MutablePropertySources)propertySources).addLast(environmentAwarePropertySource); + ((MutablePropertySources) propertySources).addLast(environmentAwarePropertySource); } } List> propertySourceList = DefaultGroovyMethods.toList(propertySources); Collections.reverse(propertySourceList); - for(PropertySource propertySource : propertySourceList) { - if(propertySource instanceof EnumerablePropertySource) { - EnumerablePropertySource enumerablePropertySource = (EnumerablePropertySource)propertySource; + for (PropertySource propertySource : propertySourceList) { + if (propertySource instanceof EnumerablePropertySource) { + EnumerablePropertySource enumerablePropertySource = (EnumerablePropertySource) propertySource; mergeEnumerablePropertySource(enumerablePropertySource); } } @@ -113,7 +114,9 @@ private void mergeEnumerablePropertySource(EnumerablePropertySource enumerablePr for (String propertyName : propertyNames) { Object value = enumerablePropertySource.getProperty(propertyName); if (value instanceof ConfigObject) { - if (((ConfigObject) value).isEmpty()) continue; + if (((ConfigObject) value).isEmpty()) { + continue; + } } else { value = processAndEvaluate(value); } @@ -129,13 +132,13 @@ private Object processAndEvaluate(Object value) { value = resolvePlaceholders(value.toString()); } else if (value instanceof List) { List result = new ArrayList<>(); - for (Object element : (List)value) { + for (Object element : (List) value) { result.add(processAndEvaluate(element)); } return result; } else if (value instanceof Map) { Map result = new LinkedHashMap<>(); - for (Object key : ((Map)value).keySet()) { + for (Object key : ((Map) value).keySet()) { result.put(key, processAndEvaluate(((Map) value).get(key))); } return result; @@ -154,7 +157,7 @@ public void setConversionService(ConfigurableConversionService conversionService @Override public String resolvePlaceholders(String text) { - if(!GrailsStringUtils.isBlank(text)) { + if (!GrailsStringUtils.isBlank(text)) { return propertySourcesPropertyResolver.resolvePlaceholders(text); } return text; @@ -165,5 +168,4 @@ public String resolveRequiredPlaceholders(String text) throws IllegalArgumentExc return propertySourcesPropertyResolver.resolveRequiredPlaceholders(text); } - } diff --git a/grails-core/src/main/groovy/org/grails/config/yaml/YamlPropertySourceLoader.java b/grails-core/src/main/groovy/org/grails/config/yaml/YamlPropertySourceLoader.java index 2d612dddd77..0bd07d83971 100644 --- a/grails-core/src/main/groovy/org/grails/config/yaml/YamlPropertySourceLoader.java +++ b/grails-core/src/main/groovy/org/grails/config/yaml/YamlPropertySourceLoader.java @@ -18,7 +18,6 @@ */ package org.grails.config.yaml; - import grails.plugins.GrailsPlugin; import grails.util.Environment; import org.grails.config.NavigableMap; @@ -31,7 +30,11 @@ import org.springframework.core.io.Resource; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; /** @@ -42,9 +45,10 @@ */ @Order(Ordered.HIGHEST_PRECEDENCE) public class YamlPropertySourceLoader extends YamlProcessor implements PropertySourceLoader { + @Override public String[] getFileExtensions() { - return new String[] { "yml", "yaml" }; + return new String[]{"yml", "yaml"}; } @Override @@ -85,12 +89,11 @@ public List> load(String name, Resource resource, List propertySource.merge(map, true); }); propertySources.add( - new NavigableMapPropertySource(name ,propertySource)); + new NavigableMapPropertySource(name, propertySource)); return propertySources; } - public List> load() { final List> result = new ArrayList<>(); process((properties, map) -> result.add(getFlattenedMap(map))); diff --git a/grails-core/src/main/groovy/org/grails/core/AbstractGrailsApplication.java b/grails-core/src/main/groovy/org/grails/core/AbstractGrailsApplication.java index efd24eff04d..8b082d6a079 100644 --- a/grails-core/src/main/groovy/org/grails/core/AbstractGrailsApplication.java +++ b/grails-core/src/main/groovy/org/grails/core/AbstractGrailsApplication.java @@ -40,6 +40,7 @@ import org.springframework.util.ClassUtils; public abstract class AbstractGrailsApplication extends GroovyObjectSupport implements GrailsApplication, ApplicationContextAware, BeanClassLoaderAware, SmartApplicationListener { + protected ClassLoader classLoader; protected Config config; @SuppressWarnings("rawtypes") diff --git a/grails-core/src/main/groovy/org/grails/core/AbstractGrailsClass.java b/grails-core/src/main/groovy/org/grails/core/AbstractGrailsClass.java index 71509ee9cff..7c66d68703f 100644 --- a/grails-core/src/main/groovy/org/grails/core/AbstractGrailsClass.java +++ b/grails-core/src/main/groovy/org/grails/core/AbstractGrailsClass.java @@ -47,11 +47,12 @@ * * @author Steven Devijver * @author Graeme Rocher - * * @since 0.1 */ public abstract class AbstractGrailsClass implements GrailsClass { + protected GrailsApplication grailsApplication; + private final Class clazz; private final String fullName; private final String name; @@ -61,13 +62,12 @@ public abstract class AbstractGrailsClass implements GrailsClass { private final String propertyName; private final String logicalPropertyName; private ClassPropertyFetcher classPropertyFetcher; - protected GrailsApplication grailsApplication; private boolean isAbstract; /** * Used by all child classes to create a new instance and get the name right. * - * @param clazz the Grails class + * @param clazz the Grails class * @param trailingName the trailing part of the name for this class type */ public AbstractGrailsClass(Class clazz, String trailingName) { @@ -82,8 +82,7 @@ public AbstractGrailsClass(Class clazz, String trailingName) { propertyName = GrailsNameUtils.getPropertyNameRepresentation(shortName); if (!StringUtils.hasText(name)) { logicalPropertyName = propertyName; - } - else { + } else { logicalPropertyName = GrailsNameUtils.getPropertyNameRepresentation(name); } isAbstract = Modifier.isAbstract(clazz.getModifiers()); @@ -118,13 +117,11 @@ public Object newInstance() { defaultConstructor.setAccessible(true); } return defaultConstructor.newInstance(new Object[]{}); - } - catch (Exception e) { + } catch (Exception e) { Throwable targetException; if (e instanceof InvocationTargetException) { - targetException = ((InvocationTargetException)e).getTargetException(); - } - else { + targetException = ((InvocationTargetException) e).getTargetException(); + } else { targetException = e; } throw new NewInstanceCreationException("Could not create a new instance of class [" + @@ -159,14 +156,13 @@ public String getPackageName() { public Object getReferenceInstance() { Object obj = BeanUtils.instantiateClass(clazz); if (obj instanceof GroovyObject) { - ((GroovyObject)obj).setMetaClass(getMetaClass()); + ((GroovyObject) obj).setMetaClass(getMetaClass()); } return obj; } - private ClassPropertyFetcher resolvePropertyFetcher() { - if(classPropertyFetcher == null) { + if (classPropertyFetcher == null) { classPropertyFetcher = ClassPropertyFetcher.forClass(clazz); } return classPropertyFetcher; @@ -185,7 +181,7 @@ public boolean isReadableProperty(String propName) { } public boolean isActionMethod(String methodName) { - Method m = ReflectionUtils.findMethod(getClazz(), methodName, new Class[0]); + Method m = ReflectionUtils.findMethod(getClazz(), methodName, new Class[0]); if (m != null) { ReflectionUtils.makeAccessible(m); } @@ -204,7 +200,6 @@ public boolean hasMetaProperty(String propName) { return (getMetaClass().getMetaProperty(propName) != null); } - /** *

Looks for a property of the reference instance with a given name and type.

*

If found its value is returned. We follow the Java bean conventions with augmentation for groovy support @@ -236,6 +231,7 @@ public T getStaticPropertyValue(String propName, Class type) { /** * Get the value of the named property, with support for static properties in both Java and Groovy classes * (which as of Groovy JSR 1.0 RC 01 only have getters in the metaClass) + * * @param propName * @param type * @return The property value or null @@ -244,12 +240,10 @@ public T getPropertyValue(String propName, Class type) { return ClassPropertyFetcher.getStaticPropertyValue(getClazz(), propName, type); } - public Object getPropertyValueObject(String propertyNAme) { return getPropertyValue(propertyNAme, Object.class); } - /* (non-Javadoc) * @see grails.core.GrailsClass#getPropertyValue(java.lang.String) */ @@ -263,8 +257,8 @@ public boolean isAbstract() { } /* (non-Javadoc) - * @see grails.core.GrailsClass#hasProperty(java.lang.String) - */ + * @see grails.core.GrailsClass#hasProperty(java.lang.String) + */ public boolean hasProperty(String propName) { return ClassPropertyFetcher.getPropertyType(getClazz(), propName) != null; } diff --git a/grails-core/src/main/groovy/org/grails/core/AbstractInjectableGrailsClass.java b/grails-core/src/main/groovy/org/grails/core/AbstractInjectableGrailsClass.java index 806d417cbba..161e84d5970 100644 --- a/grails-core/src/main/groovy/org/grails/core/AbstractInjectableGrailsClass.java +++ b/grails-core/src/main/groovy/org/grails/core/AbstractInjectableGrailsClass.java @@ -25,7 +25,6 @@ * * @author Graeme Rocher * @author Steven Devijver - * * @since 0.1 */ public abstract class AbstractInjectableGrailsClass extends AbstractGrailsClass implements InjectableGrailsClass { diff --git a/grails-core/src/main/groovy/org/grails/core/DefaultGrailsControllerClass.java b/grails-core/src/main/groovy/org/grails/core/DefaultGrailsControllerClass.java index db80a7c582a..03a01a5b81f 100644 --- a/grails-core/src/main/groovy/org/grails/core/DefaultGrailsControllerClass.java +++ b/grails-core/src/main/groovy/org/grails/core/DefaultGrailsControllerClass.java @@ -32,7 +32,10 @@ import java.lang.invoke.MethodType; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; /** * Evaluates the conventions contained within controllers to perform auto-configuration. @@ -45,18 +48,20 @@ public class DefaultGrailsControllerClass extends AbstractInjectableGrailsClass implements GrailsControllerClass { public static final String CONTROLLER = "Controller"; - - private static final String DEFAULT_CLOSURE_PROPERTY = "defaultAction"; public static final String ALLOWED_HTTP_METHODS_PROPERTY = "allowedMethods"; public static final Object[] EMPTY_ARGS = new Object[0]; public static final String SCOPE = "scope"; public static final String SCOPE_SINGLETON = "singleton"; + + private static final String DEFAULT_CLOSURE_PROPERTY = "defaultAction"; + + protected Map actionUriToViewName = new HashMap(); + private String scope; private Map actions = new HashMap(); private String defaultActionName; private String namespace; - protected Map actionUriToViewName = new HashMap(); - + public DefaultGrailsControllerClass(Class clazz) { super(clazz, CONTROLLER); namespace = getStaticPropertyValue(NAMESPACE_PROPERTY, String.class); @@ -112,10 +117,9 @@ private void methodStrategy(Map methodNames) { for (Method method : superClass.getMethods()) { if (Modifier.isPublic(method.getModifiers()) && method.getAnnotation(Action.class) != null) { String methodName = method.getName(); - if(Environment.isDevelopmentMode()) { + if (Environment.isDevelopmentMode()) { methodNames.put(methodName, new ReflectionInvoker(method)); - } - else { + } else { MethodHandle mh; try { mh = lookup.findVirtual(superClass, methodName, MethodType.methodType(method.getReturnType())); @@ -137,18 +141,17 @@ private void methodStrategy(Map methodNames) { @Override public boolean mapsToURI(String uri) { - if(uri.startsWith("/")) { + if (uri.startsWith("/")) { String[] tokens = uri.substring(1).split("\\/"); - if(tokens.length>0) { + if (tokens.length > 0) { String controllerName = tokens[0]; - if(getLogicalPropertyName().equals(controllerName)) { - if(tokens.length>1) { + if (getLogicalPropertyName().equals(controllerName)) { + if (tokens.length > 1) { String actionName = tokens[1]; - if(actions.containsKey(actionName) || defaultActionName.equals(actionName)) { + if (actions.containsKey(actionName) || defaultActionName.equals(actionName)) { return true; } - } - else { + } else { return true; } } @@ -166,7 +169,7 @@ public boolean mapsToURI(String uri) { public void registerUrlConverter(UrlConverter urlConverter) { for (String actionName : new ArrayList(actions.keySet())) { actionUriToViewName.put(urlConverter.toUrlElement(actionName), actionName); - actions.put( urlConverter.toUrlElement(actionName), actions.remove(actionName)); + actions.put(urlConverter.toUrlElement(actionName), actions.remove(actionName)); } defaultActionName = urlConverter.toUrlElement(defaultActionName); } @@ -175,15 +178,19 @@ public void registerUrlConverter(UrlConverter urlConverter) { * Invokes the controller action for the given name on the given controller instance * * @param controller The controller instance - * @param action The action name + * @param action The action name * @return The result of the action * @throws Throwable */ @Override public Object invoke(Object controller, String action) throws Throwable { - if(action == null) action = this.defaultActionName; + if (action == null) { + action = this.defaultActionName; + } ActionInvoker handle = actions.get(action); - if(handle == null) throw new IllegalArgumentException("Invalid action name: " + action); + if (handle == null) { + throw new IllegalArgumentException("Invalid action name: " + action); + } return handle.invoke(controller); } @@ -194,10 +201,12 @@ public String actionUriToViewName(String actionUri) { } private interface ActionInvoker { + Object invoke(Object controller) throws Throwable; } private class ReflectionInvoker implements ActionInvoker { + private final Method method; public ReflectionInvoker(Method method) { @@ -210,7 +219,9 @@ public Object invoke(Object controller) throws Throwable { return method.invoke(controller); } } + private class MethodHandleInvoker implements ActionInvoker { + private final MethodHandle handle; public MethodHandleInvoker(MethodHandle handle) { @@ -218,7 +229,7 @@ public MethodHandleInvoker(MethodHandle handle) { } @Override - public Object invoke(Object controller) throws Throwable{ + public Object invoke(Object controller) throws Throwable { return handle.invoke(controller); } } diff --git a/grails-core/src/main/groovy/org/grails/core/DefaultGrailsDomainClass.java b/grails-core/src/main/groovy/org/grails/core/DefaultGrailsDomainClass.java index 6bbf1a612fa..f68370bf37c 100644 --- a/grails-core/src/main/groovy/org/grails/core/DefaultGrailsDomainClass.java +++ b/grails-core/src/main/groovy/org/grails/core/DefaultGrailsDomainClass.java @@ -32,7 +32,8 @@ import org.springframework.util.ClassUtils; import org.springframework.validation.Validator; -import java.util.*; +import java.util.Collections; +import java.util.Map; /** * Default implementation of the {@link GrailsDomainClass} interface @@ -44,8 +45,7 @@ @Deprecated public class DefaultGrailsDomainClass extends AbstractGrailsClass implements GrailsDomainClass { - private static final Logger log = LoggerFactory.getLogger(DefaultGrailsDomainClass.class); - + private static final Logger LOG = LoggerFactory.getLogger(DefaultGrailsDomainClass.class); private PersistentEntity persistentEntity; private MappingContext mappingContext; @@ -66,23 +66,21 @@ public DefaultGrailsDomainClass(Class clazz) { super(clazz, ""); } - private void verifyContextIsInitialized() { if (mappingContext == null) { throw new GrailsConfigurationException("That API cannot be accessed before the spring context is initialized"); } else { - if (log.isWarnEnabled()) { - log.warn("The GrailsDomainClass API should no longer be used to retrieve data about domain classes. Use the mapping context API instead"); + if (LOG.isWarnEnabled()) { + LOG.warn("The GrailsDomainClass API should no longer be used to retrieve data about domain classes. Use the mapping context API instead"); } if (persistentEntity == null) { persistentEntity = mappingContext.getPersistentEntity(this.getFullName()); if (persistentEntity == null) { MappingContext concreteMappingContext = getApplication().getMappingContext(); - if(concreteMappingContext.getClass() == KeyValueMappingContext.class) { + if (concreteMappingContext.getClass() == KeyValueMappingContext.class) { // In a unit testing context, allow persistentEntity = concreteMappingContext.addPersistentEntity(getClazz()); - } - else { + } else { throw new GrailsConfigurationException("Could not retrieve the respective entity for domain " + this.getName() + " in the mapping context API"); } } @@ -92,7 +90,7 @@ private void verifyContextIsInitialized() { @Override public boolean isAutowire() { - if(autowire == null) { + if (autowire == null) { verifyContextIsInitialized(); autowire = persistentEntity.getMapping().getMappedForm().isAutowire(); } @@ -128,12 +126,11 @@ public String getPropertyName() { @Override public Map getConstrainedProperties() { verifyContextIsInitialized(); - if(constrainedProperties == null) { + if (constrainedProperties == null) { ConstrainedDiscovery constrainedDiscovery = GrailsFactoriesLoader.loadFactory(ConstrainedDiscovery.class); - if(constrainedDiscovery == null) { + if (constrainedDiscovery == null) { constrainedProperties = Collections.emptyMap(); - } - else { + } else { constrainedProperties = constrainedDiscovery.findConstrainedProperties(persistentEntity); } } diff --git a/grails-core/src/main/groovy/org/grails/core/DefaultGrailsUrlMappingsClass.java b/grails-core/src/main/groovy/org/grails/core/DefaultGrailsUrlMappingsClass.java index ca39838b624..7eed768c249 100644 --- a/grails-core/src/main/groovy/org/grails/core/DefaultGrailsUrlMappingsClass.java +++ b/grails-core/src/main/groovy/org/grails/core/DefaultGrailsUrlMappingsClass.java @@ -38,7 +38,7 @@ public DefaultGrailsUrlMappingsClass(Class clazz) { public Closure getMappingsClosure() { Closure result = getStaticPropertyValue(MAPPINGS_CLOSURE, Closure.class); if (result == null) { - throw new RuntimeException(MAPPINGS_CLOSURE + " closure does not exists for class " + getClazz().getName()); + throw new RuntimeException(MAPPINGS_CLOSURE + " closure does not exists for class " + getClazz().getName()); } return result; } diff --git a/grails-core/src/main/groovy/org/grails/core/artefact/AnnotationDomainClassArtefactHandler.java b/grails-core/src/main/groovy/org/grails/core/artefact/AnnotationDomainClassArtefactHandler.java index 35288876e16..ed923546800 100644 --- a/grails-core/src/main/groovy/org/grails/core/artefact/AnnotationDomainClassArtefactHandler.java +++ b/grails-core/src/main/groovy/org/grails/core/artefact/AnnotationDomainClassArtefactHandler.java @@ -18,11 +18,11 @@ */ package org.grails.core.artefact; +import jakarta.persistence.Entity; + import java.util.HashSet; import java.util.Set; -import jakarta.persistence.Entity; - /** * Detects annotated domain classes for EJB3 style mappings. * diff --git a/grails-core/src/main/groovy/org/grails/core/artefact/ControllerArtefactHandler.java b/grails-core/src/main/groovy/org/grails/core/artefact/ControllerArtefactHandler.java index a1ac7c0c943..58f7f2babaa 100644 --- a/grails-core/src/main/groovy/org/grails/core/artefact/ControllerArtefactHandler.java +++ b/grails-core/src/main/groovy/org/grails/core/artefact/ControllerArtefactHandler.java @@ -18,9 +18,7 @@ */ package org.grails.core.artefact; -import org.grails.core.AbstractGrailsClass; import grails.core.ArtefactHandlerAdapter; -import grails.core.GrailsClass; import grails.core.GrailsControllerClass; import org.grails.core.DefaultGrailsControllerClass; @@ -32,7 +30,7 @@ *

Lookups are cached in non-development mode, and the cache size can be controlled using the grails.urlmapping.cache.maxsize config property.

* * @author Marc Palmer (marc@anyware.co.uk) -*/ + */ public class ControllerArtefactHandler extends ArtefactHandlerAdapter { public static final String TYPE = "Controller"; @@ -48,5 +46,4 @@ public String getPluginName() { return PLUGIN_NAME; } - } diff --git a/grails-core/src/main/groovy/org/grails/core/artefact/DomainClassArtefactHandler.java b/grails-core/src/main/groovy/org/grails/core/artefact/DomainClassArtefactHandler.java index 63babbcb489..4ef30f24e36 100644 --- a/grails-core/src/main/groovy/org/grails/core/artefact/DomainClassArtefactHandler.java +++ b/grails-core/src/main/groovy/org/grails/core/artefact/DomainClassArtefactHandler.java @@ -48,7 +48,7 @@ public class DomainClassArtefactHandler extends ArtefactHandlerAdapter implement public static final String TYPE = "Domain"; public static final String PLUGIN_NAME = "domainClass"; - private static final String ENTITY_ANN_NAME = "Entity"; + private static final String ENTITY_ANN_NAME = "Entity"; private static final String GRAILS_PACKAGE_PREFIX = "grails."; private static final String JAKARTA_PERSISTENCE = "jakarta.persistence"; @@ -86,17 +86,19 @@ protected boolean isValidArtefactClassNode(ClassNode classNode, int modifiers) { return !classNode.isEnum() && !(classNode instanceof InnerClassNode); } - @Override public boolean isArtefact(ClassNode classNode) { - if(classNode == null) return false; - if(!isValidArtefactClassNode(classNode, classNode.getModifiers())) return false; + if (classNode == null) { + return false; + } + if (!isValidArtefactClassNode(classNode, classNode.getModifiers())) { + return false; + } URL url = GrailsASTUtils.getSourceUrl(classNode); - if(url != null) { + if (url != null) { return GrailsResourceUtils.isDomainClass(url); - } - else { + } else { return super.isArtefact(classNode); } } @@ -109,12 +111,12 @@ public boolean isArtefactClass(Class clazz) { public static boolean isDomainClass(Class clazz, boolean allowProxyClass) { boolean retval = isDomainClass(clazz); - if(!retval && allowProxyClass && clazz != null && clazz.getSimpleName().contains("$")) { + if (!retval && allowProxyClass && clazz != null && clazz.getSimpleName().contains("$")) { retval = isDomainClass(clazz.getSuperclass()); } return retval; } - + public static boolean isDomainClass(Class clazz) { return clazz != null && doIsDomainClassCheck(clazz); @@ -126,7 +128,9 @@ private static boolean doIsDomainClassCheck(Class clazz) { return false; } - if (clazz.isEnum()) return false; + if (clazz.isEnum()) { + return false; + } Artefact artefactAnn = null; try { artefactAnn = clazz.getAnnotation(Artefact.class); @@ -134,7 +138,7 @@ private static boolean doIsDomainClassCheck(Class clazz) { // happens if a reference to a class that no longer exists is there } - if( artefactAnn != null && artefactAnn.value().equals(DomainClassArtefactHandler.TYPE) ) { + if (artefactAnn != null && artefactAnn.value().equals(DomainClassArtefactHandler.TYPE)) { return true; } @@ -151,7 +155,7 @@ private static boolean doIsDomainClassCheck(Class clazz) { String annName = annType.getSimpleName(); String pkgName = annType.getPackage().getName(); - if(ENTITY_ANN_NAME.equals(annName) && pkgName.startsWith(GRAILS_PACKAGE_PREFIX) || pkgName.startsWith(JAKARTA_PERSISTENCE)) { + if (ENTITY_ANN_NAME.equals(annName) && pkgName.startsWith(GRAILS_PACKAGE_PREFIX) || pkgName.startsWith(JAKARTA_PERSISTENCE)) { return true; } } diff --git a/grails-core/src/main/groovy/org/grails/core/cfg/CustomSafeConstructor.groovy b/grails-core/src/main/groovy/org/grails/core/cfg/CustomSafeConstructor.groovy index 09ac2b95e3f..6e0dbb07ae6 100644 --- a/grails-core/src/main/groovy/org/grails/core/cfg/CustomSafeConstructor.groovy +++ b/grails-core/src/main/groovy/org/grails/core/cfg/CustomSafeConstructor.groovy @@ -20,12 +20,12 @@ package org.grails.core.cfg import groovy.transform.Internal import org.yaml.snakeyaml.LoaderOptions +import org.yaml.snakeyaml.constructor.Construct import org.yaml.snakeyaml.constructor.SafeConstructor import org.yaml.snakeyaml.nodes.MappingNode +import org.yaml.snakeyaml.nodes.Node import org.yaml.snakeyaml.nodes.SequenceNode import org.yaml.snakeyaml.nodes.Tag -import org.yaml.snakeyaml.constructor.Construct -import org.yaml.snakeyaml.nodes.Node /** * Yaml constructor to create containers with sensible diff --git a/grails-core/src/main/groovy/org/grails/core/cfg/GroovyConfigPropertySourceLoader.groovy b/grails-core/src/main/groovy/org/grails/core/cfg/GroovyConfigPropertySourceLoader.groovy index 6cdace651b0..c3e9a28548c 100644 --- a/grails-core/src/main/groovy/org/grails/core/cfg/GroovyConfigPropertySourceLoader.groovy +++ b/grails-core/src/main/groovy/org/grails/core/cfg/GroovyConfigPropertySourceLoader.groovy @@ -16,7 +16,6 @@ */ package org.grails.core.cfg -import grails.util.BuildSettings import grails.util.Environment import grails.util.Metadata import groovy.transform.CompileStatic @@ -43,37 +42,37 @@ class GroovyConfigPropertySourceLoader implements PropertySourceLoader { @Override List> load(String name, Resource resource) throws IOException { - return load(name, resource, Collections.emptyList()) + return load(name, resource, Collections. emptyList()) } List> load(String name, Resource resource, List filteredKeys) throws IOException { if (!loadedFiles.contains(name)) { def env = Environment.current.name - if(resource.exists()) { + if (resource.exists()) { ConfigSlurper configSlurper = env ? new ConfigSlurper(env) : new ConfigSlurper() configSlurper.setBinding(userHome: System.getProperty('user.home'), appName: Metadata.getCurrent().getApplicationName(), - appVersion: Metadata.getCurrent().getApplicationVersion() ) + appVersion: Metadata.getCurrent().getApplicationVersion()) try { def configObject = configSlurper.parse(resource.URL) - for(key in filteredKeys) { + for (key in filteredKeys) { configObject.remove(key) } def propertySource = new NavigableMap() propertySource.merge(configObject, false) - Resource runtimeResource = resource.createRelative( resource.filename.replace('application', 'runtime') ) - if(runtimeResource.exists()) { - def runtimeConfig = configSlurper.parse( runtimeResource.getURL() ) + Resource runtimeResource = resource.createRelative(resource.filename.replace('application', 'runtime')) + if (runtimeResource.exists()) { + def runtimeConfig = configSlurper.parse(runtimeResource.getURL()) propertySource.merge(runtimeConfig, false) } final NavigableMapPropertySource navigableMapPropertySource = new NavigableMapPropertySource(name, propertySource) loadedFiles.add(name) - return Collections.>singletonList(navigableMapPropertySource) + return Collections.> singletonList(navigableMapPropertySource) } catch (Throwable e) { log.error("Unable to load $resource.filename: $e.message", e) throw new GrailsConfigurationException("Error loading $resource.filename due to [${e.getClass().name}]: $e.message", e) diff --git a/grails-core/src/main/groovy/org/grails/core/exceptions/DefaultErrorsPrinter.groovy b/grails-core/src/main/groovy/org/grails/core/exceptions/DefaultErrorsPrinter.groovy index ff97ad72b8e..5b3d60cb3b2 100644 --- a/grails-core/src/main/groovy/org/grails/core/exceptions/DefaultErrorsPrinter.groovy +++ b/grails-core/src/main/groovy/org/grails/core/exceptions/DefaultErrorsPrinter.groovy @@ -91,7 +91,8 @@ class DefaultErrorsPrinter extends DefaultStackTracePrinter implements CodeSnipp res = res ?: resourceLocator?.findResourceForClassName(className) if (res != null) { - if (lineNumbersShown[res.filename].contains(lineNumber)) continue // don't repeat the same lines twice + if (lineNumbersShown[res.filename].contains(lineNumber)) continue + // don't repeat the same lines twice lineNumbersShown[res.filename] << lineNumber pw.print formatCodeSnippetStart(res, lineNumber, attrs) @@ -110,12 +111,10 @@ class DefaultErrorsPrinter extends DefaultStackTracePrinter implements CodeSnipp boolean isErrorLine = currentLineNumber == lineNumber if (isErrorLine) { pw.print formatCodeSnippetErrorLine(currentLineNumber, currentLine, attrs) - } - else { + } else { pw.print formatCodeSnippetLine(currentLineNumber, currentLine, attrs) } - } - else if (currentLineNumber > last) { + } else if (currentLineNumber > last) { break } @@ -134,8 +133,7 @@ class DefaultErrorsPrinter extends DefaultStackTracePrinter implements CodeSnipp } pw.print formatCodeSnippetEnd(res, lineNumber) } - } - else { + } else { if (!first) { break } @@ -165,12 +163,11 @@ class DefaultErrorsPrinter extends DefaultStackTracePrinter implements CodeSnipp } catch (e) { // ignore } - } - else if (start instanceof MultipleCompilationErrorsException) { + } else if (start instanceof MultipleCompilationErrorsException) { MultipleCompilationErrorsException mcee = start Object message = mcee.getErrorCollector().getErrors().iterator().next() if (message instanceof SyntaxErrorMessage) { - SyntaxErrorMessage sem = (SyntaxErrorMessage)message + SyntaxErrorMessage sem = (SyntaxErrorMessage) message final tmp = new FileSystemResource(sem.getCause().getSourceLocator()) if (tmp.exists()) { res = tmp @@ -190,12 +187,11 @@ class DefaultErrorsPrinter extends DefaultStackTracePrinter implements CodeSnipp if (cause instanceof SourceCodeAware) { SourceCodeAware sca = cause lineNumber = sca.lineNumber - } - else if (cause instanceof MultipleCompilationErrorsException) { + } else if (cause instanceof MultipleCompilationErrorsException) { MultipleCompilationErrorsException mcee = cause Object message = mcee.getErrorCollector().getErrors().iterator().next() if (message instanceof SyntaxErrorMessage) { - SyntaxErrorMessage sem = (SyntaxErrorMessage)message + SyntaxErrorMessage sem = (SyntaxErrorMessage) message lineNumber = sem.getCause().getLine() } } diff --git a/grails-core/src/main/groovy/org/grails/core/io/CachingPathMatchingResourcePatternResolver.groovy b/grails-core/src/main/groovy/org/grails/core/io/CachingPathMatchingResourcePatternResolver.groovy index 030fb3d76a0..9ae92070f2b 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/CachingPathMatchingResourcePatternResolver.groovy +++ b/grails-core/src/main/groovy/org/grails/core/io/CachingPathMatchingResourcePatternResolver.groovy @@ -31,9 +31,10 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver */ @CompileStatic class CachingPathMatchingResourcePatternResolver extends PathMatchingResourcePatternResolver { + public static final CachingPathMatchingResourcePatternResolver INSTANCE = new CachingPathMatchingResourcePatternResolver(); - private CachingPathMatchingResourcePatternResolver(){} + private CachingPathMatchingResourcePatternResolver() {} CachingPathMatchingResourcePatternResolver(ResourceLoader parent) { super(parent) diff --git a/grails-core/src/main/groovy/org/grails/core/io/DefaultResourceLocator.java b/grails-core/src/main/groovy/org/grails/core/io/DefaultResourceLocator.java index 328785d9f07..6b2b99071e9 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/DefaultResourceLocator.java +++ b/grails-core/src/main/groovy/org/grails/core/io/DefaultResourceLocator.java @@ -18,7 +18,18 @@ */ package org.grails.core.io; +import grails.plugins.GrailsPlugin; +import grails.plugins.GrailsPluginManager; +import grails.plugins.PluginManagerAware; import grails.util.Environment; +import org.grails.io.support.GrailsResourceUtils; +import org.grails.plugins.BinaryGrailsPlugin; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.FileSystemResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import java.io.File; import java.io.FileFilter; @@ -29,18 +40,6 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import org.grails.io.support.GrailsResourceUtils; -import org.grails.plugins.BinaryGrailsPlugin; -import grails.plugins.GrailsPlugin; -import grails.plugins.GrailsPluginManager; -import grails.plugins.PluginManagerAware; -import org.springframework.context.ResourceLoaderAware; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.FileSystemResourceLoader; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; - /** * Default ResourceLocator implementation that doesn't take into account servlet loading. * @@ -61,7 +60,7 @@ public class DefaultResourceLocator implements ResourceLocator, ResourceLoaderAw protected List resourceSearchDirectories = new ArrayList(); protected Map classNameToResourceCache = new ConcurrentHashMap(); protected Map uriToResourceCache = new ConcurrentHashMap(); - protected ResourceLoader defaultResourceLoader = new FileSystemResourceLoader(); + protected ResourceLoader defaultResourceLoader = new FileSystemResourceLoader(); protected GrailsPluginManager pluginManager; protected boolean warDeployed = Environment.isWarDeployed(); @@ -114,16 +113,14 @@ public Resource findResourceForURI(String uri) { if (defaultResource != null && defaultResource.exists()) { resource = defaultResource; } - } - else { + } else { String uriWebAppRelative = WEB_APP_DIR + uri; for (String resourceSearchDirectory : resourceSearchDirectories) { Resource res = resolveExceptionSafe(resourceSearchDirectory + uriWebAppRelative); if (res.exists()) { resource = res; - } - else if (!warDeployed) { + } else if (!warDeployed) { Resource dir = resolveExceptionSafe(resourceSearchDirectory); if (dir.exists() && info != null) { try { @@ -155,8 +152,7 @@ else if (!warDeployed) { if (resource != null) { uriToResourceCache.put(uri, resource); - } - else if (warDeployed) { + } else if (warDeployed) { uriToResourceCache.put(uri, NULL_RESOURCE); } } @@ -168,7 +164,7 @@ protected Resource findResourceInBinaryPlugins(PluginResourceInfo info) { String fullPluginName = info.pluginName; for (GrailsPlugin plugin : pluginManager.getAllPlugins()) { if (plugin.getFileSystemName().equals(fullPluginName) && (plugin instanceof BinaryGrailsPlugin)) { - return ((BinaryGrailsPlugin)plugin).getResource(info.uri); + return ((BinaryGrailsPlugin) plugin).getResource(info.uri); } } } @@ -242,6 +238,7 @@ public void setPluginManager(GrailsPluginManager pluginManager) { } class PluginResourceInfo { + String pluginName; String uri; } diff --git a/grails-core/src/main/groovy/org/grails/core/io/GrailsByteArrayResource.java b/grails-core/src/main/groovy/org/grails/core/io/GrailsByteArrayResource.java index 06c2c0ded5b..b61601b6dc9 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/GrailsByteArrayResource.java +++ b/grails-core/src/main/groovy/org/grails/core/io/GrailsByteArrayResource.java @@ -18,11 +18,11 @@ */ package org.grails.core.io; +import org.springframework.core.io.ByteArrayResource; + import java.io.IOException; import java.net.URL; -import org.springframework.core.io.ByteArrayResource; - /** * Hacky version of the ByteArrayResource that implements the {@link * #getURL()} method, required for the resource to work with Spring's diff --git a/grails-core/src/main/groovy/org/grails/core/io/GrailsResource.groovy b/grails-core/src/main/groovy/org/grails/core/io/GrailsResource.groovy index 84bee6a1227..46406bb7c7e 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/GrailsResource.groovy +++ b/grails-core/src/main/groovy/org/grails/core/io/GrailsResource.groovy @@ -29,7 +29,7 @@ import org.springframework.core.io.Resource * @since 3.0 */ @CompileStatic -class GrailsResource implements Resource{ +class GrailsResource implements Resource { org.grails.io.support.Resource resource diff --git a/grails-core/src/main/groovy/org/grails/core/io/MockFileResource.java b/grails-core/src/main/groovy/org/grails/core/io/MockFileResource.java index 406b66609aa..5f8a0dc6c97 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/MockFileResource.java +++ b/grails-core/src/main/groovy/org/grails/core/io/MockFileResource.java @@ -18,11 +18,11 @@ */ package org.grails.core.io; +import org.springframework.core.io.ByteArrayResource; + import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; -import org.springframework.core.io.ByteArrayResource; - /** * Mocks the behavior of a FileResource. * diff --git a/grails-core/src/main/groovy/org/grails/core/io/MockResourceLoader.java b/grails-core/src/main/groovy/org/grails/core/io/MockResourceLoader.java index 8a0d49b1be6..adc8eaf62ff 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/MockResourceLoader.java +++ b/grails-core/src/main/groovy/org/grails/core/io/MockResourceLoader.java @@ -18,12 +18,12 @@ */ package org.grails.core.io; -import java.io.File; - import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; +import java.io.File; + /** * Loads from the file system if its not found on the classpath. Useful for mock testing. * diff --git a/grails-core/src/main/groovy/org/grails/core/io/MockStringResourceLoader.java b/grails-core/src/main/groovy/org/grails/core/io/MockStringResourceLoader.java index 70eddad6a8c..0db3c8adca0 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/MockStringResourceLoader.java +++ b/grails-core/src/main/groovy/org/grails/core/io/MockStringResourceLoader.java @@ -18,13 +18,12 @@ */ package org.grails.core.io; -import java.io.UnsupportedEncodingException; +import org.springframework.core.io.Resource; + import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; -import org.springframework.core.io.Resource; - /** * Loads Resources from Strings that are registered as Mock resources. * @@ -49,11 +48,12 @@ public Resource getResource(String location) { * of the resource. * * @param location The location - * @param res The resource itself + * @param res The resource itself */ public void registerMockResource(String location, Resource res) { mockResources.put(location, res); } + /** * Registers a mock resource with the first argument as the location and the second as the contents * of the resource. diff --git a/grails-core/src/main/groovy/org/grails/core/io/PluginPathAwareFileSystemResourceLoader.java b/grails-core/src/main/groovy/org/grails/core/io/PluginPathAwareFileSystemResourceLoader.java index 704967e80b9..95c484bdcf6 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/PluginPathAwareFileSystemResourceLoader.java +++ b/grails-core/src/main/groovy/org/grails/core/io/PluginPathAwareFileSystemResourceLoader.java @@ -31,7 +31,7 @@ * @author Graeme Rocher * @since 2.0 */ -public class PluginPathAwareFileSystemResourceLoader extends FileSystemResourceLoader{ +public class PluginPathAwareFileSystemResourceLoader extends FileSystemResourceLoader { public static final String WEB_APP_DIRECTORY = "web-app"; ResourceLocator resourceLocator = new DefaultResourceLocator(); @@ -49,7 +49,7 @@ protected Resource getResourceByPath(String path) { String resourcePath = path; if (resourcePath.startsWith(WEB_APP_DIRECTORY)) { - resourcePath = resourcePath.substring("web-app".length(),resourcePath.length()); + resourcePath = resourcePath.substring("web-app".length(), resourcePath.length()); } Resource res = resourceLocator.findResourceForURI(resourcePath); if (res != null) { diff --git a/grails-core/src/main/groovy/org/grails/core/io/ResourceLocator.java b/grails-core/src/main/groovy/org/grails/core/io/ResourceLocator.java index 0b01be4216a..72202622fb7 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/ResourceLocator.java +++ b/grails-core/src/main/groovy/org/grails/core/io/ResourceLocator.java @@ -40,12 +40,14 @@ public interface ResourceLocator { /** * Multiple locations to search. See #setSearchLocation + * * @param searchLocations The locations to search */ void setSearchLocations(Collection searchLocations); /** * Finds a resource for the given URI + * * @param uri The URI * @return The resource or null if it doesn't exist */ @@ -53,7 +55,7 @@ public interface ResourceLocator { /** * Finds the .groovy file or .java file for a given class from a Grails project. - * + *

* Note that this method will return null in production since sources are not packaged unless an * appropriate search location is specified to locate the resource * diff --git a/grails-core/src/main/groovy/org/grails/core/io/SpringResource.java b/grails-core/src/main/groovy/org/grails/core/io/SpringResource.java index 7a330a057b6..46ec8955743 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/SpringResource.java +++ b/grails-core/src/main/groovy/org/grails/core/io/SpringResource.java @@ -32,7 +32,8 @@ * @author Graeme Rocher * @since 2.2 */ -public class SpringResource implements Resource{ +public class SpringResource implements Resource { + org.springframework.core.io.Resource springResource; public SpringResource(org.springframework.core.io.Resource springResource) { diff --git a/grails-core/src/main/groovy/org/grails/core/io/StaticResourceLoader.java b/grails-core/src/main/groovy/org/grails/core/io/StaticResourceLoader.java index 263884873a0..0cae3f3e098 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/StaticResourceLoader.java +++ b/grails-core/src/main/groovy/org/grails/core/io/StaticResourceLoader.java @@ -18,14 +18,14 @@ */ package org.grails.core.io; -import java.io.IOException; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; +import java.io.IOException; + /** * A ResourceLoader that loads resources from a statically defined base resource. * @@ -33,6 +33,7 @@ * @since 0.5 */ public class StaticResourceLoader implements ResourceLoader { + private static final Logger LOG = LoggerFactory.getLogger(StaticResourceLoader.class); private Resource baseResource; @@ -43,18 +44,17 @@ public void setBaseResource(Resource baseResource) { public Resource getResource(String location) { Assert.state(baseResource != null, "Property [baseResource] not set!"); - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("Loading resource for path {} from base resource {}", location, baseResource); } try { Resource resource = baseResource.createRelative(location); - if(LOG.isDebugEnabled() && resource.exists()) { + if (LOG.isDebugEnabled() && resource.exists()) { LOG.debug("Found resource for path {} from base resource {}", location, baseResource); } return resource; - } - catch (IOException e) { - if(LOG.isDebugEnabled()) { + } catch (IOException e) { + if (LOG.isDebugEnabled()) { LOG.debug("Error loading resource for path: " + location, e); } return null; diff --git a/grails-core/src/main/groovy/org/grails/core/io/StaticResourceLocator.java b/grails-core/src/main/groovy/org/grails/core/io/StaticResourceLocator.java index 417b70ce6c0..274b284c076 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/StaticResourceLocator.java +++ b/grails-core/src/main/groovy/org/grails/core/io/StaticResourceLocator.java @@ -31,8 +31,9 @@ * @author Graeme Rocher * @since 2.0 */ -public class StaticResourceLocator implements ResourceLocator{ - private Map classToResourceMap = new HashMap(); +public class StaticResourceLocator implements ResourceLocator { + + private Map classToResourceMap = new HashMap(); public void setSearchLocation(String searchLocation) { // do nothing diff --git a/grails-core/src/main/groovy/org/grails/core/io/support/GrailsFactoriesLoader.groovy b/grails-core/src/main/groovy/org/grails/core/io/support/GrailsFactoriesLoader.groovy index 69b7dcf4d67..5b2182bbcf8 100644 --- a/grails-core/src/main/groovy/org/grails/core/io/support/GrailsFactoriesLoader.groovy +++ b/grails-core/src/main/groovy/org/grails/core/io/support/GrailsFactoriesLoader.groovy @@ -36,10 +36,8 @@ import org.springframework.util.ClassUtils @CompileStatic class GrailsFactoriesLoader extends FactoriesLoaderSupport { - private static final Object[] NO_ARGUMENTS = [] as Object[] - - + /** * Load the factory implementations of the given type from the default location, * using the given class loader. @@ -47,7 +45,7 @@ class GrailsFactoriesLoader extends FactoriesLoaderSupport { * @param factoryClass the interface or abstract class representing the factory */ static List loadFactories(Class factoryClass) { - (List)loadFactoriesWithArguments(factoryClass, GrailsFactoriesLoader.class.classLoader) + (List) loadFactoriesWithArguments(factoryClass, GrailsFactoriesLoader.class.classLoader) } /** @@ -58,13 +56,13 @@ class GrailsFactoriesLoader extends FactoriesLoaderSupport { * @param classLoader the ClassLoader to use for loading (can be {@code null} to use the default) */ static List loadFactories(Class factoryClass, ClassLoader classLoader) { - (List)loadFactoriesWithArguments(factoryClass, classLoader, NO_ARGUMENTS) + (List) loadFactoriesWithArguments(factoryClass, classLoader, NO_ARGUMENTS) } static List loadFactoriesWithArguments(Class factoryClass, ClassLoader classLoader, Object[] arguments) { - boolean hasArguments = !(arguments != null && arguments.length==0) - List results = new ArrayList() - for(Class clazz : loadFactoryClasses(factoryClass, classLoader)) { + boolean hasArguments = !(arguments != null && arguments.length == 0) + List results = new ArrayList() + for (Class clazz : loadFactoryClasses(factoryClass, classLoader)) { results.add(hasArguments ? clazz.newInstance(arguments) : clazz.getDeclaredConstructor().newInstance()) } @@ -76,29 +74,28 @@ class GrailsFactoriesLoader extends FactoriesLoaderSupport { OrderComparator.sort((List) results) results } - + static List> loadFactoryClasses(Class factoryClass, ClassLoader classLoader = GrailsFactoriesLoader.class.classLoader) { Assert.notNull factoryClass, "'factoryClass' must not be null" - + def factoryNames = loadFactoryNames(factoryClass, classLoader) List> result = [] for (String factoryName in factoryNames) { def clazz = loadFactoryClass(factoryName, factoryClass, classLoader) - if(clazz) { + if (clazz) { result.add clazz } } return result } - private static Class loadFactoryClass(String instanceClassName, Class factoryClass, ClassLoader classLoader) { try { def instanceClass = ClassUtils.forName(instanceClassName, classLoader) if (!factoryClass.isAssignableFrom(instanceClass)) { throw new IllegalArgumentException( - "Class [$instanceClassName] is not assignable to [$factoryClass.name]") + "Class [$instanceClassName] is not assignable to [$factoryClass.name]") } return (Class) instanceClass } @@ -110,7 +107,7 @@ class GrailsFactoriesLoader extends FactoriesLoaderSupport { static T loadFactory(Class factoryClass, ClassLoader classLoader = GrailsFactoriesLoader.class.classLoader) { def all = loadFactories(factoryClass, classLoader) - if(all) { + if (all) { return all.get(0) } } @@ -121,8 +118,8 @@ class GrailsFactoriesLoader extends FactoriesLoaderSupport { static T loadFactory(Class factoryClass, ClassLoader classLoader, Object... arguments) { def all = loadFactoriesWithArguments(factoryClass, classLoader, arguments) - if(all) { - return (T)all.get(0) + if (all) { + return (T) all.get(0) } } } diff --git a/grails-core/src/main/groovy/org/grails/core/lifecycle/ShutdownOperations.java b/grails-core/src/main/groovy/org/grails/core/lifecycle/ShutdownOperations.java index a2c3adaa390..021fb6db68e 100644 --- a/grails-core/src/main/groovy/org/grails/core/lifecycle/ShutdownOperations.java +++ b/grails-core/src/main/groovy/org/grails/core/lifecycle/ShutdownOperations.java @@ -32,13 +32,14 @@ * @since 2.0 */ public class ShutdownOperations { - private static final Log LOG = LogFactory.getLog(ShutdownOperations.class); - - private static final Collection shutdownOperations = new LinkedHashSet<>(); - private static final Collection preservedShutdownOperations = new LinkedHashSet<>(); public static final Runnable DEFAULT_SHUTDOWN_OPERATION = Holders::reset; + private static final Log LOG = LogFactory.getLog(ShutdownOperations.class); + + private static final Collection SHUTDOWN_OPERATIONS = new LinkedHashSet<>(); + private static final Collection PRESERVED_SHUTDOWN_OPERATIONS = new LinkedHashSet<>(); + static { resetOperations(); } @@ -48,7 +49,7 @@ public class ShutdownOperations { */ public static synchronized void runOperations() { try { - for (Runnable shutdownOperation : shutdownOperations) { + for (Runnable shutdownOperation : SHUTDOWN_OPERATIONS) { try { shutdownOperation.run(); } catch (Exception e) { @@ -56,13 +57,14 @@ public static synchronized void runOperations() { } } } finally { - shutdownOperations.clear(); - shutdownOperations.addAll(preservedShutdownOperations); + SHUTDOWN_OPERATIONS.clear(); + SHUTDOWN_OPERATIONS.addAll(PRESERVED_SHUTDOWN_OPERATIONS); } } /** * Adds a shutdown operation which will be run once for the next shutdown + * * @param runnable The runnable operation */ public static synchronized void addOperation(Runnable runnable) { @@ -71,13 +73,14 @@ public static synchronized void addOperation(Runnable runnable) { /** * Adds a shutdown operation - * @param runnable The runnable operation + * + * @param runnable The runnable operation * @param preserveForNextShutdown should preserve the operation for subsequent shutdowns, useful in tests */ public static synchronized void addOperation(Runnable runnable, boolean preserveForNextShutdown) { - shutdownOperations.add(runnable); - if(preserveForNextShutdown) { - preservedShutdownOperations.add(runnable); + SHUTDOWN_OPERATIONS.add(runnable); + if (preserveForNextShutdown) { + PRESERVED_SHUTDOWN_OPERATIONS.add(runnable); } } @@ -85,8 +88,8 @@ public static synchronized void addOperation(Runnable runnable, boolean preserve * Clears all shutdown operations without running them. Also clears operations that are kept after running operations. */ public static synchronized void resetOperations() { - shutdownOperations.clear(); - preservedShutdownOperations.clear(); + SHUTDOWN_OPERATIONS.clear(); + PRESERVED_SHUTDOWN_OPERATIONS.clear(); // default operations addOperation(DEFAULT_SHUTDOWN_OPERATION, true); } diff --git a/grails-core/src/main/groovy/org/grails/core/support/ClassEditor.java b/grails-core/src/main/groovy/org/grails/core/support/ClassEditor.java index 4d04356e1fa..5526d87bfea 100644 --- a/grails-core/src/main/groovy/org/grails/core/support/ClassEditor.java +++ b/grails-core/src/main/groovy/org/grails/core/support/ClassEditor.java @@ -18,16 +18,15 @@ */ package org.grails.core.support; -import java.beans.PropertyEditorSupport; - import org.springframework.util.ClassUtils; +import java.beans.PropertyEditorSupport; + /** * Converts Strings to Class references for Spring. * * @author Steven Devijver * @author Graeme Rocher - * * @since Aug 8, 2005 */ public class ClassEditor extends PropertyEditorSupport { @@ -50,7 +49,7 @@ public void setClassLoader(ClassLoader classLoader) { @Override public String getAsText() { - return ((Class)getValue()).getName(); + return ((Class) getValue()).getName(); } @Override @@ -59,13 +58,11 @@ public void setAsText(String className) throws IllegalArgumentException { Class clazz = ClassUtils.resolvePrimitiveClassName(className); if (clazz != null) { setValue(clazz); - } - else { + } else { final ClassLoader cl = classLoader != null ? classLoader : Thread.currentThread().getContextClassLoader(); setValue(cl.loadClass(className)); } - } - catch (ClassNotFoundException e) { + } catch (ClassNotFoundException e) { throw new IllegalArgumentException("Could not load class [" + className + "]!"); } } diff --git a/grails-core/src/main/groovy/org/grails/core/support/GrailsApplicationDiscoveryStrategy.groovy b/grails-core/src/main/groovy/org/grails/core/support/GrailsApplicationDiscoveryStrategy.groovy index 04eaa25b9f4..d7874f7178a 100644 --- a/grails-core/src/main/groovy/org/grails/core/support/GrailsApplicationDiscoveryStrategy.groovy +++ b/grails-core/src/main/groovy/org/grails/core/support/GrailsApplicationDiscoveryStrategy.groovy @@ -26,7 +26,7 @@ import org.springframework.context.ApplicationContext * * @since 2.4 */ -public interface GrailsApplicationDiscoveryStrategy { +interface GrailsApplicationDiscoveryStrategy { /** * @return Find the GrailsApplication instance diff --git a/grails-core/src/main/groovy/org/grails/core/support/internal/tools/ClassRelativeClassLoader.java b/grails-core/src/main/groovy/org/grails/core/support/internal/tools/ClassRelativeClassLoader.java index 10c0b056bea..79068617a08 100644 --- a/grails-core/src/main/groovy/org/grails/core/support/internal/tools/ClassRelativeClassLoader.java +++ b/grails-core/src/main/groovy/org/grails/core/support/internal/tools/ClassRelativeClassLoader.java @@ -16,14 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.core.support.internal.tools; import grails.io.IOUtils; import grails.util.BuildSettings; import org.springframework.core.io.FileSystemResource; -import org.springframework.core.io.Resource; -import org.springframework.core.io.UrlResource; import java.io.IOException; import java.net.URL; @@ -32,27 +29,27 @@ /** * A classloader that only finds resources and classes that are in the same jar as the given class - * + *

* For internal use only * * @author Graeme Rocher * @since 3.1.13 */ class ClassRelativeClassLoader extends URLClassLoader { + public ClassRelativeClassLoader(Class targetClass) { super(createClassLoaderUrls(targetClass), ClassLoader.getSystemClassLoader()); } private static URL[] createClassLoaderUrls(Class targetClass) { URL root = IOUtils.findRootResource(targetClass); - if(BuildSettings.RESOURCES_DIR != null && BuildSettings.RESOURCES_DIR.exists()) { + if (BuildSettings.RESOURCES_DIR != null && BuildSettings.RESOURCES_DIR.exists()) { try { - return new URL[] {root, new FileSystemResource(BuildSettings.RESOURCES_DIR.getCanonicalFile()).getURL() }; + return new URL[]{root, new FileSystemResource(BuildSettings.RESOURCES_DIR.getCanonicalFile()).getURL()}; } catch (IOException e) { return new URL[]{root}; } - } - else { + } else { return new URL[]{root}; } } @@ -64,11 +61,12 @@ public URL getResource(String name) { @Override public Enumeration getResources(String name) throws IOException { - if("".equals(name)) { + if ("".equals(name)) { final URL[] urls = getURLs(); final int l = urls.length; return new Enumeration() { int i = 0; + @Override public boolean hasMoreElements() { return i < l; @@ -79,11 +77,9 @@ public URL nextElement() { return urls[i++]; } }; - } - else { + } else { return findResources(name); } } - } diff --git a/grails-core/src/main/groovy/org/grails/core/support/internal/tools/ClassRelativeResourcePatternResolver.java b/grails-core/src/main/groovy/org/grails/core/support/internal/tools/ClassRelativeResourcePatternResolver.java index a66e938f145..7a0388e95fd 100644 --- a/grails-core/src/main/groovy/org/grails/core/support/internal/tools/ClassRelativeResourcePatternResolver.java +++ b/grails-core/src/main/groovy/org/grails/core/support/internal/tools/ClassRelativeResourcePatternResolver.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.core.support.internal.tools; import org.springframework.core.io.Resource; diff --git a/grails-core/src/main/groovy/org/grails/core/support/internal/tools/MetaClassChangeReporter.java b/grails-core/src/main/groovy/org/grails/core/support/internal/tools/MetaClassChangeReporter.java index 5d4a9e99e18..7c42dd569fb 100644 --- a/grails-core/src/main/groovy/org/grails/core/support/internal/tools/MetaClassChangeReporter.java +++ b/grails-core/src/main/groovy/org/grails/core/support/internal/tools/MetaClassChangeReporter.java @@ -28,7 +28,8 @@ * @author Graeme Rocher * @since 2.0 */ -public class MetaClassChangeReporter implements MetaClassRegistryChangeEventListener{ +public class MetaClassChangeReporter implements MetaClassRegistryChangeEventListener { + /** * Called when the a constant MetaClass is updated. If the new MetaClass is null, then the MetaClass * is removed. Be careful, while this method is executed other updates may happen. If you want this @@ -40,7 +41,7 @@ public void updateConstantMetaClass(MetaClassRegistryChangeEvent cmcu) { Class classToUpdate = cmcu.getClassToUpdate(); MetaClass newMetaClass = cmcu.getNewMetaClass(); - System.out.println("Class ["+classToUpdate+"] updated MetaClass to ["+newMetaClass+"]"); + System.out.println("Class [" + classToUpdate + "] updated MetaClass to [" + newMetaClass + "]"); Thread.dumpStack(); } } diff --git a/grails-core/src/main/groovy/org/grails/core/util/BeanCreationProfilingPostProcessor.java b/grails-core/src/main/groovy/org/grails/core/util/BeanCreationProfilingPostProcessor.java index 3fd7d6feb5e..737e79268ad 100644 --- a/grails-core/src/main/groovy/org/grails/core/util/BeanCreationProfilingPostProcessor.java +++ b/grails-core/src/main/groovy/org/grails/core/util/BeanCreationProfilingPostProcessor.java @@ -35,8 +35,8 @@ */ public class BeanCreationProfilingPostProcessor implements InstantiationAwareBeanPostProcessor, ApplicationListener { - private final StopWatch stopWatch = new StopWatch("Bean Creation StopWatch"); private static final Logger LOG = LoggerFactory.getLogger("org.grails.startup"); + private final StopWatch stopWatch = new StopWatch("Bean Creation StopWatch"); @Override public Object postProcessBeforeInstantiation(@Nullable Class beanClass, @Nullable String beanName) throws BeansException { @@ -53,7 +53,7 @@ public Object postProcessAfterInitialization(@Nullable Object bean, @Nullable St @Override public void onApplicationEvent(@NonNull ContextRefreshedEvent event) { stopWatch.complete(); - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug(stopWatch.prettyPrint()); } } diff --git a/grails-core/src/main/groovy/org/grails/core/util/StopWatch.java b/grails-core/src/main/groovy/org/grails/core/util/StopWatch.java index 7eb48693ad3..76fdb339e51 100644 --- a/grails-core/src/main/groovy/org/grails/core/util/StopWatch.java +++ b/grails-core/src/main/groovy/org/grails/core/util/StopWatch.java @@ -16,11 +16,13 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.core.util; import java.text.NumberFormat; -import java.util.*; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Deque; +import java.util.LinkedList; /** * Based on the Spring StopWatch class, but supporting nested tasks @@ -42,20 +44,25 @@ public class StopWatch { private final Deque runningTasks = new LinkedList(); private final Deque taskList = new LinkedList(); - /** Is the stop watch currently running? */ + /** + * Is the stop watch currently running? + */ private boolean running; - /** Name of the current task */ + /** + * Name of the current task + */ private String currentTaskName; private TaskInfo lastTaskInfo; private int taskCount; - /** Total running time */ + /** + * Total running time + */ private long totalTimeMillis; - /** * Construct a new stop watch. Does not start any task. */ @@ -66,19 +73,19 @@ public StopWatch() { /** * Construct a new stop watch with the given id. * Does not start any task. + * * @param id identifier for this stop watch. - * Handy when we have output from multiple stop watches - * and need to distinguish between them. + * Handy when we have output from multiple stop watches + * and need to distinguish between them. */ public StopWatch(String id) { this.id = id; } - - /** * Start an unnamed task. The results are undefined if {@link #stop()} * or timing methods are called without invoking this method. + * * @see #stop() */ public void start() throws IllegalStateException { @@ -88,6 +95,7 @@ public void start() throws IllegalStateException { /** * Start a named task. The results are undefined if {@link #stop()} * or timing methods are called without invoking this method. + * * @param taskName the name of the task to start * @see #stop() */ @@ -103,6 +111,7 @@ public void start(String taskName) throws IllegalStateException { * Stop the current task. The results are undefined if timing * methods are called without invoking at least one pair * {@link #start()} / {@link #stop()} methods. + * * @see #start() */ public void stop() throws IllegalStateException { @@ -110,7 +119,7 @@ public void stop() throws IllegalStateException { throw new IllegalStateException("Can't stop StopWatch: it's not running"); } - if(!runningTasks.isEmpty()) { + if (!runningTasks.isEmpty()) { TaskInfo lastTask = runningTasks.pop(); lastTask.stop(); @@ -131,7 +140,6 @@ public boolean isRunning() { return this.running; } - /** * Return the time taken by the last task. */ @@ -162,7 +170,6 @@ public TaskInfo getLastTaskInfo() throws IllegalStateException { return this.lastTaskInfo; } - /** * Return the total time in milliseconds for all tasks. */ @@ -191,7 +198,6 @@ public TaskInfo[] getTaskInfo() { return this.taskList.toArray(new TaskInfo[this.taskList.size()]); } - /** * Return a short description of the total running time. */ @@ -245,7 +251,6 @@ public String toString() { return sb.toString(); } - /** * Inner class to hold data about one task executed within the stop watch. */ @@ -256,7 +261,6 @@ public static final class TaskInfo { private final long startTime; private long endTime; - TaskInfo(String taskName, long startTime) { this.taskName = taskName; this.startTime = startTime; diff --git a/grails-core/src/main/groovy/org/grails/dev/support/DevelopmentShutdownHook.groovy b/grails-core/src/main/groovy/org/grails/dev/support/DevelopmentShutdownHook.groovy index 57e712951df..1b3cb243cb3 100644 --- a/grails-core/src/main/groovy/org/grails/dev/support/DevelopmentShutdownHook.groovy +++ b/grails-core/src/main/groovy/org/grails/dev/support/DevelopmentShutdownHook.groovy @@ -19,7 +19,6 @@ package org.grails.dev.support import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j import org.slf4j.LoggerFactory import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContextAware @@ -44,7 +43,7 @@ class DevelopmentShutdownHook implements ApplicationContextAware { Runtime.runtime.addShutdownHook { try { Thread.start { - ((ConfigurableApplicationContext)applicationContext).close() + ((ConfigurableApplicationContext) applicationContext).close() }.join(2000) } catch (Throwable e) { LoggerFactory.getLogger(DevelopmentShutdownHook).warn("Error shutting down application: ${e.message}", e) diff --git a/grails-core/src/main/groovy/org/grails/plugins/AbstractGrailsPlugin.java b/grails-core/src/main/groovy/org/grails/plugins/AbstractGrailsPlugin.java index 8a8b0db4c07..36ea8186515 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/AbstractGrailsPlugin.java +++ b/grails-core/src/main/groovy/org/grails/plugins/AbstractGrailsPlugin.java @@ -52,14 +52,16 @@ * @author Graeme Rocher */ public abstract class AbstractGrailsPlugin extends GroovyObjectSupport implements GrailsPlugin { - private static final Logger LOG = LoggerFactory.getLogger(AbstractGrailsPlugin.class); public static final String PLUGIN_YML = "plugin.yml"; public static final String PLUGIN_YML_PATH = "/" + PLUGIN_YML; public static final String PLUGIN_GROOVY = "plugin.groovy"; public static final String PLUGIN_GROOVY_PATH = "/" + PLUGIN_GROOVY; + + private static final Logger LOG = LoggerFactory.getLogger(AbstractGrailsPlugin.class); private static final List DEFAULT_CONFIG_IGNORE_LIST = Arrays.asList("dataSource", "hibernate"); private static Resource basePluginResource = null; + protected PropertySource propertySource; protected GrailsApplication grailsApplication; protected boolean isBase = false; @@ -72,17 +74,6 @@ public abstract class AbstractGrailsPlugin extends GroovyObjectSupport implement protected String[] evictionList = {}; protected Config config; - /** - * Wrapper Grails class for plugins. - * - * @author Graeme Rocher - */ - class GrailsPluginClass extends AbstractGrailsClass { - public GrailsPluginClass(Class clazz) { - super(clazz, TRAILING_NAME); - } - } - public AbstractGrailsPlugin(Class pluginClass, GrailsApplication application) { Assert.notNull(pluginClass, "Argument [pluginClass] cannot be null"); Assert.isTrue(pluginClass.getName().endsWith(TRAILING_NAME), @@ -92,7 +83,7 @@ public AbstractGrailsPlugin(Class pluginClass, GrailsApplication application) this.pluginClass = pluginClass; Resource resource = readPluginConfiguration(pluginClass); - if(resource != null && resource.exists()) { + if (resource != null && resource.exists()) { final String filename = resource.getFilename(); try { if (filename.equals(PLUGIN_YML)) { @@ -103,7 +94,7 @@ public AbstractGrailsPlugin(Class pluginClass, GrailsApplication application) this.propertySource = propertySourceLoader.load(GrailsNameUtils.getLogicalPropertyName(pluginClass.getSimpleName(), "GrailsPlugin") + "-" + PLUGIN_GROOVY, resource, DEFAULT_CONFIG_IGNORE_LIST).stream().findFirst().orElse(null); } } catch (IOException e) { - LOG.warn("Error loading " + filename + " for plugin: " + pluginClass.getName() +": " + e.getMessage(), e); + LOG.warn("Error loading {} for plugin: {}: {}", filename, pluginClass.getName(), e.getMessage(), e); } } } @@ -114,13 +105,12 @@ public PropertySource getPropertySource() { } /* (non-Javadoc) - * @see grails.plugins.GrailsPlugin#refresh() - */ + * @see grails.plugins.GrailsPlugin#refresh() + */ public void refresh() { // do nothing } - @Override public boolean isEnabled(String[] profiles) { return true; @@ -132,13 +122,13 @@ protected Resource readPluginConfiguration(Class pluginClass) { Boolean groovyResourceExists = groovyResource != null && groovyResource.exists(); - if(ymlResource != null && ymlResource.exists()) { + if (ymlResource != null && ymlResource.exists()) { if (groovyResourceExists) { throw new RuntimeException("A plugin [" + pluginClass.getName() + "] may define a plugin.yml or a plugin.groovy, but not both"); } return ymlResource; } - if(groovyResourceExists) { + if (groovyResourceExists) { return groovyResource; } return null; @@ -177,7 +167,6 @@ public boolean hasInterestInChange(String path) { return false; } - public String[] getDependencyNames() { return dependencyNames; } @@ -240,13 +229,21 @@ public String[] getEvictionNames() { @Override public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof AbstractGrailsPlugin)) return false; + if (this == o) { + return true; + } + if (!(o instanceof AbstractGrailsPlugin)) { + return false; + } AbstractGrailsPlugin that = (AbstractGrailsPlugin) o; - if (!pluginClass.equals(that.pluginClass)) return false; - if (!version.equals(that.version)) return false; + if (!pluginClass.equals(that.pluginClass)) { + return false; + } + if (!version.equals(that.version)) { + return false; + } return true; } @@ -260,22 +257,44 @@ public int hashCode() { public int compareTo(Object o) { AbstractGrailsPlugin that = (AbstractGrailsPlugin) o; - if (equals(that)) return 0; + if (equals(that)) { + return 0; + } String thatName = that.getName(); for (String pluginName : getLoadAfterNames()) { - if (pluginName.equals(thatName)) return -1; + if (pluginName.equals(thatName)) { + return -1; + } } for (String pluginName : getLoadBeforeNames()) { - if (pluginName.equals(thatName)) return 1; + if (pluginName.equals(thatName)) { + return 1; + } } for (String pluginName : that.getLoadAfterNames()) { - if (pluginName.equals(getName())) return 1; + if (pluginName.equals(getName())) { + return 1; + } } for (String pluginName : that.getLoadBeforeNames()) { - if (pluginName.equals(getName())) return -1; + if (pluginName.equals(getName())) { + return -1; + } } return 0; } + + /** + * Wrapper Grails class for plugins. + * + * @author Graeme Rocher + */ + static class GrailsPluginClass extends AbstractGrailsClass { + + public GrailsPluginClass(Class clazz) { + super(clazz, TRAILING_NAME); + } + } } diff --git a/grails-core/src/main/groovy/org/grails/plugins/AbstractGrailsPluginManager.java b/grails-core/src/main/groovy/org/grails/plugins/AbstractGrailsPluginManager.java index 3593d9e2262..ecd4a2f0a5c 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/AbstractGrailsPluginManager.java +++ b/grails-core/src/main/groovy/org/grails/plugins/AbstractGrailsPluginManager.java @@ -17,12 +17,14 @@ package org.grails.plugins; import grails.artefact.Enhanced; -import grails.plugins.Plugin; -import grails.plugins.PluginFilter; -import org.grails.config.NavigableMap; +import grails.core.ArtefactHandler; +import grails.core.GrailsApplication; import grails.plugins.GrailsPlugin; import grails.plugins.GrailsPluginManager; import grails.plugins.GrailsVersionUtils; +import grails.plugins.Plugin; +import grails.plugins.PluginFilter; +import grails.plugins.exceptions.PluginException; import grails.util.Environment; import grails.util.GrailsNameUtils; import groovy.lang.ExpandoMetaClass; @@ -30,26 +32,13 @@ import groovy.lang.MetaClassRegistry; import groovy.util.ConfigObject; import groovy.util.ConfigSlurper; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import grails.core.ArtefactHandler; -import grails.core.GrailsApplication; - +import org.codehaus.groovy.runtime.DefaultGroovyMethods; +import org.grails.config.NavigableMap; +import org.grails.io.support.GrailsResourceUtils; import org.grails.plugins.support.WatchPattern; import org.grails.spring.RuntimeSpringConfiguration; -import org.grails.io.support.GrailsResourceUtils; - -import grails.plugins.exceptions.PluginException; - -import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; @@ -65,6 +54,13 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Abstract implementation of the GrailsPluginManager interface * @@ -73,9 +69,14 @@ */ public abstract class AbstractGrailsPluginManager implements GrailsPluginManager { + public static final String CONFIG_FILE = "application.groovy"; + private static final Log LOG = LogFactory.getLog(AbstractGrailsPluginManager.class); private static final String BLANK = ""; - public static final String CONFIG_FILE = "application.groovy"; + private static final String CONFIG_BINDING_USER_HOME = "userHome"; + private static final String CONFIG_BINDING_APP_NAME = "appName"; + private static final String CONFIG_BINDING_APP_VERSION = "appVersion"; + protected List pluginList = new ArrayList(); protected GrailsApplication application; protected Resource[] pluginResources = new Resource[0]; @@ -88,11 +89,6 @@ public abstract class AbstractGrailsPluginManager implements GrailsPluginManager protected Map failedPlugins = new HashMap(); protected boolean loadCorePlugins = true; - private static final String CONFIG_BINDING_USER_HOME = "userHome"; - private static final String CONFIG_BINDING_APP_NAME = "appName"; - private static final String CONFIG_BINDING_APP_VERSION = "appVersion"; - - public AbstractGrailsPluginManager(GrailsApplication application) { Assert.notNull(application, "Argument [application] cannot be null!"); this.application = application; @@ -134,22 +130,22 @@ public GrailsPlugin getFailedPlugin(String name) { /** * Base implementation that simply goes through the list of plugins and calls doWithRuntimeConfiguration on each + * * @param springConfig The RuntimeSpringConfiguration instance */ public void doRuntimeConfiguration(RuntimeSpringConfiguration springConfig) { ApplicationContext context = springConfig.getUnrefreshedApplicationContext(); AutowireCapableBeanFactory autowireCapableBeanFactory = context.getAutowireCapableBeanFactory(); - if(autowireCapableBeanFactory instanceof ConfigurableListableBeanFactory) { - ConfigurableListableBeanFactory beanFactory = (ConfigurableListableBeanFactory)autowireCapableBeanFactory; + if (autowireCapableBeanFactory instanceof ConfigurableListableBeanFactory) { + ConfigurableListableBeanFactory beanFactory = (ConfigurableListableBeanFactory) autowireCapableBeanFactory; ConversionService existingConversionService = beanFactory.getConversionService(); ConverterRegistry converterRegistry; - if(existingConversionService == null) { + if (existingConversionService == null) { GenericConversionService conversionService = new GenericConversionService(); converterRegistry = conversionService; beanFactory.setConversionService(conversionService); - } - else { - converterRegistry = (ConverterRegistry)existingConversionService; + } else { + converterRegistry = (ConverterRegistry) existingConversionService; } converterRegistry.addConverter(new Converter() { @@ -181,7 +177,9 @@ public void doRuntimeConfiguration(String pluginName, RuntimeSpringConfiguration return; } - if(!plugin.isEnabled(applicationContext.getEnvironment().getActiveProfiles())) return; + if (!plugin.isEnabled(applicationContext.getEnvironment().getActiveProfiles())) { + return; + } String[] dependencyNames = plugin.getDependencyNames(); doRuntimeConfigurationForDependencies(dependencyNames, springConfig); @@ -206,7 +204,9 @@ private void doRuntimeConfigurationForDependencies(String[] dependencyNames, Run if (pluginDependencies.length > 0) { doRuntimeConfigurationForDependencies(pluginDependencies, springConfig); } - if(isPluginDisabledForProfile(current)) continue; + if (isPluginDisabledForProfile(current)) { + continue; + } current.doWithRuntimeConfiguration(springConfig); } } @@ -217,7 +217,9 @@ private void doRuntimeConfigurationForDependencies(String[] dependencyNames, Run public void doPostProcessing(ApplicationContext ctx) { checkInitialised(); for (GrailsPlugin plugin : pluginList) { - if(isPluginDisabledForProfile(plugin)) continue; + if (isPluginDisabledForProfile(plugin)) { + continue; + } if (plugin.supportsCurrentScopeAndEnvironment()) { plugin.doWithApplicationContext(ctx); } @@ -267,7 +269,9 @@ public void doDynamicMethods() { } ApplicationContext ctx = applicationContext; for (GrailsPlugin plugin : pluginList) { - if(!plugin.isEnabled(ctx.getEnvironment().getActiveProfiles())) continue; + if (!plugin.isEnabled(ctx.getEnvironment().getActiveProfiles())) { + continue; + } plugin.doWithDynamicMethods(ctx); } } @@ -301,7 +305,9 @@ public void registerProvidedArtefacts(GrailsApplication app) { Collections.reverse(plugins); for (GrailsPlugin plugin : plugins) { if (plugin.supportsCurrentScopeAndEnvironment()) { - if(isPluginDisabledForProfile(plugin)) continue; + if (isPluginDisabledForProfile(plugin)) { + continue; + } for (Class artefact : plugin.getProvidedArtefacts()) { String shortName = GrailsNameUtils.getShortName(artefact); if (artefact.getName().equals(shortName)) { @@ -327,7 +333,9 @@ private boolean isAlreadyRegistered(GrailsApplication app, Class artefact) { public void doArtefactConfiguration() { checkInitialised(); for (GrailsPlugin plugin : pluginList) { - if(isPluginDisabledForProfile(plugin)) continue; + if (isPluginDisabledForProfile(plugin)) { + continue; + } if (plugin.supportsCurrentScopeAndEnvironment()) { plugin.doArtefactConfiguration(); } @@ -341,7 +349,7 @@ protected boolean isPluginDisabledForProfile(GrailsPlugin plugin) { public void onStartup(Map event) { for (GrailsPlugin plugin : pluginList) { if (plugin.getInstance() instanceof Plugin) { - ((Plugin)plugin.getInstance()).onStartup(event); + ((Plugin) plugin.getInstance()).onStartup(event); } } } @@ -354,7 +362,9 @@ public void shutdown() { Collections.reverse(reversePluginList); for (GrailsPlugin plugin : reversePluginList) { - if(!plugin.isEnabled(applicationContext.getEnvironment().getActiveProfiles())) continue; + if (!plugin.isEnabled(applicationContext.getEnvironment().getActiveProfiles())) { + continue; + } if (plugin.supportsCurrentScopeAndEnvironment()) { plugin.notifyOfEvent(GrailsPlugin.EVENT_ON_SHUTDOWN, plugin); } @@ -395,28 +405,28 @@ public void informOfClassChange(Class aClass) { GrailsPlugin plugin = getGrailsPlugin(pluginName); if (plugin != null) { - if(!plugin.isEnabled(applicationContext.getEnvironment().getActiveProfiles())) return; + if (!plugin.isEnabled(applicationContext.getEnvironment().getActiveProfiles())) { + return; + } plugin.notifyOfEvent(GrailsPlugin.EVENT_ON_CHANGE, aClass); - } - else { + } else { String classNameAsPath = aClass.getName().replace('.', File.separatorChar); String groovyClass = classNameAsPath + ".groovy"; String javaClass = classNameAsPath + ".java"; for (GrailsPlugin grailsPlugin : pluginList) { List watchPatterns = grailsPlugin.getWatchedResourcePatterns(); - if(watchPatterns != null) { + if (watchPatterns != null) { for (WatchPattern watchPattern : watchPatterns) { File parent = watchPattern.getDirectory(); String extension = watchPattern.getExtension(); - if(parent != null && extension != null) { + if (parent != null && extension != null) { File f = new File(parent, groovyClass); - if(f.exists() && f.getName().endsWith(extension)) { + if (f.exists() && f.getName().endsWith(extension)) { grailsPlugin.notifyOfEvent(GrailsPlugin.EVENT_ON_CHANGE, aClass); - } - else { + } else { f = new File(parent, javaClass); - if(f.exists() && f.getName().endsWith(extension)) { + if (f.exists() && f.getName().endsWith(extension)) { grailsPlugin.notifyOfEvent(GrailsPlugin.EVENT_ON_CHANGE, aClass); } } @@ -434,7 +444,7 @@ public String getPluginPath(String name) { public String getPluginPath(String name, boolean forceCamelCase) { GrailsPlugin plugin = getGrailsPlugin(name); if (plugin != null && !plugin.isBasePlugin()) { - if(forceCamelCase){ + if (forceCamelCase) { return plugin.getPluginPathCamelCase(); } else { return plugin.getPluginPath(); @@ -460,7 +470,7 @@ public GrailsPlugin getPluginForInstance(Object instance) { public GrailsPlugin getPluginForClass(Class theClass) { if (theClass != null) { grails.plugins.metadata.GrailsPlugin ann = - theClass.getAnnotation(grails.plugins.metadata.GrailsPlugin.class); + theClass.getAnnotation(grails.plugins.metadata.GrailsPlugin.class); if (ann != null) { return getGrailsPlugin(ann.name()); } @@ -514,9 +524,7 @@ public void informOfClassChange(File file, @SuppressWarnings("rawtypes") Class c // ignore LOG.debug("Error in changing Config", e); } - } - else { - + } else { if (cls != null) { MetaClassRegistry registry = GroovySystem.getMetaClassRegistry(); registry.removeMetaClass(cls); @@ -524,7 +532,7 @@ public void informOfClassChange(File file, @SuppressWarnings("rawtypes") Class c newMc.initialize(); registry.setMetaClass(cls, newMc); - Enhanced en = AnnotationUtils.findAnnotation(cls,Enhanced.class); + Enhanced en = AnnotationUtils.findAnnotation(cls, Enhanced.class); if (en != null) { Class[] mixinClasses = en.mixins(); if (mixinClasses != null) { @@ -538,8 +546,7 @@ public void informOfClassChange(File file, @SuppressWarnings("rawtypes") Class c try { if (cls == null) { grailsPlugin.notifyOfEvent(GrailsPlugin.EVENT_ON_CHANGE, new FileSystemResource(file)); - } - else { + } else { grailsPlugin.notifyOfEvent(GrailsPlugin.EVENT_ON_CHANGE, cls); } Environment.setCurrentReloadError(null); @@ -566,7 +573,7 @@ private Class loadApplicationClass(String className) { public String getPluginPathForClass(Class theClass) { if (theClass != null) { grails.plugins.metadata.GrailsPlugin ann = - theClass.getAnnotation(grails.plugins.metadata.GrailsPlugin.class); + theClass.getAnnotation(grails.plugins.metadata.GrailsPlugin.class); if (ann != null) { return getPluginPath(ann.name()); } diff --git a/grails-core/src/main/groovy/org/grails/plugins/BasePluginFilter.java b/grails-core/src/main/groovy/org/grails/plugins/BasePluginFilter.java index e63082dcd6f..2d60f38f5de 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/BasePluginFilter.java +++ b/grails-core/src/main/groovy/org/grails/plugins/BasePluginFilter.java @@ -38,6 +38,11 @@ */ public abstract class BasePluginFilter implements PluginFilter { + /** + * Holds a name to GrailsPlugin map (String, Plugin). + */ + protected Map nameMap; + /** * The supplied included plugin names (a String). */ @@ -53,11 +58,6 @@ public abstract class BasePluginFilter implements PluginFilter { */ private final List derivedPlugins = new ArrayList(); - /** - * Holds a name to GrailsPlugin map (String, Plugin). - */ - protected Map nameMap; - /** * Temporary field holding list of plugin names added to the filtered List * to return (String). @@ -93,7 +93,7 @@ public BasePluginFilter(String[] included) { /** * Template method shared by subclasses of BasePluginFilter. */ - public List filterPluginList(List original) { + public List filterPluginList(List original) { originalPlugins = Collections.unmodifiableList(original); addedNames = new HashSet(); @@ -128,10 +128,8 @@ private void buildDerivedPluginList() { * Checks whether a plugin is dependent on another plugin with the specified * name * - * @param plugin - * the plugin to compare - * @param pluginName - * the name to compare against + * @param plugin the plugin to compare + * @param pluginName the name to compare against * @return true if plugin depends on pluginName */ protected boolean isDependentOn(GrailsPlugin plugin, String pluginName) { @@ -153,12 +151,8 @@ protected boolean isDependentOn(GrailsPlugin plugin, String pluginName) { } /** - * Returns the sublist of the supplied set who are explicitly named, either + * Sets explicitlyNamedPlugins to a sublist of the supplied set who are explicitly named, either * as included or excluded plugins - * - * @return a sublist containing the elements of the original list - * corresponding with the explicitlyNamed items as passed into the - * constructor */ private void buildExplicitlyNamedList() { @@ -166,7 +160,7 @@ private void buildExplicitlyNamedList() { // included set for (GrailsPlugin plugin : originalPlugins) { - // find explicitly included plugins + // find explicitly included plugins String name = plugin.getName(); if (suppliedNames.contains(name)) { explicitlyNamedPlugins.add(plugin); diff --git a/grails-core/src/main/groovy/org/grails/plugins/BinaryGrailsPlugin.java b/grails-core/src/main/groovy/org/grails/plugins/BinaryGrailsPlugin.java index 8984702f106..866f9b3054e 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/BinaryGrailsPlugin.java +++ b/grails-core/src/main/groovy/org/grails/plugins/BinaryGrailsPlugin.java @@ -36,14 +36,19 @@ import java.io.InputStreamReader; import java.net.URL; import java.nio.charset.Charset; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; /** * Models a pre-compiled binary plugin. * + * @author Graeme Rocher * @see grails.plugins.GrailsPlugin - * - * @author Graeme Rocher * @since 2.0 */ @SuppressWarnings("rawtypes") @@ -68,14 +73,14 @@ public class BinaryGrailsPlugin extends DefaultGrailsPlugin { * Creates a binary plugin instance. * * @param pluginClass The plugin class - * @param descriptor The META-INF/grails-plugin.xml descriptor + * @param descriptor The META-INF/grails-plugin.xml descriptor * @param application The application */ public BinaryGrailsPlugin(Class pluginClass, BinaryGrailsPluginDescriptor descriptor, GrailsApplication application) { super(pluginClass, application); this.descriptor = descriptor; URL rootResource = IOUtils.findRootResource(pluginClass); - if(rootResource == null) { + if (rootResource == null) { throw new PluginException("Cannot evaluate plugin location for plugin " + pluginClass); } this.baseResource = new UrlResource(rootResource); @@ -86,9 +91,9 @@ public BinaryGrailsPlugin(Class pluginClass, BinaryGrailsPluginDescriptor des } this.projectDirectory = isJar ? null : IOUtils.findApplicationDirectoryFile(pluginClass); - if(BuildSettings.BASE_DIR != null && projectDirectory != null) { + if (BuildSettings.BASE_DIR != null && projectDirectory != null) { try { - if(projectDirectory.getCanonicalPath().startsWith(BuildSettings.BASE_DIR.getCanonicalPath())) { + if (projectDirectory.getCanonicalPath().startsWith(BuildSettings.BASE_DIR.getCanonicalPath())) { isBase = true; } } catch (IOException e) { @@ -97,11 +102,11 @@ public BinaryGrailsPlugin(Class pluginClass, BinaryGrailsPluginDescriptor des } URL rootResourcesURL = IOUtils.findRootResourcesURL(pluginClass); - if(rootResourcesURL == null) { + if (rootResourcesURL == null) { throw new PluginException("Cannot evaluate plugin location for plugin " + pluginClass); } - this.baseResourcesResource= new UrlResource(rootResourcesURL); + this.baseResourcesResource = new UrlResource(rootResourcesURL); if (descriptor != null) { initializeProvidedArtefacts(descriptor.getProvidedlassNames()); initializeViewMap(descriptor); @@ -125,7 +130,7 @@ protected void initializeViewMap(BinaryGrailsPluginDescriptor descriptor) { if (viewsPropertiesResource == null || !viewsPropertiesResource.exists()) { try { String urlString = descriptorResource.getURL().toString(); - if(urlString.endsWith(PLUGIN_DESCRIPTOR_PATH)) { + if (urlString.endsWith(PLUGIN_DESCRIPTOR_PATH)) { urlString = urlString.substring(0, urlString.length() - PLUGIN_DESCRIPTOR_PATH.length()); URL newUrl = new URL(urlString + RELATIVE_VIEWS_PROPERTIES); viewsPropertiesResource = new UrlResource(newUrl); @@ -151,14 +156,16 @@ protected void initializeViewMap(BinaryGrailsPluginDescriptor descriptor) { final Class viewClass = grailsApplication.getClassLoader().loadClass(viewClassName); precompiledViewMap.put(viewName, viewClass); } catch (Throwable e) { - throw new PluginException("Failed to initialize view ["+viewName+"] from plugin ["+ getName()+ "] : " + e.getMessage(), e); + throw new PluginException("Failed to initialize view [" + viewName + "] from plugin [" + getName() + "] : " + e.getMessage(), e); } } } catch (IOException e) { - LOG.error("Error loading views for binary plugin ["+this+"]: " + e.getMessage(),e); + LOG.error("Error loading views for binary plugin [" + this + "]: " + e.getMessage(), e); } finally { try { - if (input != null) input.close(); + if (input != null) { + input.close(); + } } catch (IOException e) { // ignore } @@ -174,7 +181,7 @@ protected void initializeProvidedArtefacts(List classNames) { try { artefacts.add(classLoader.loadClass(className)); } catch (Throwable e) { - throw new PluginException("Failed to initialize class ["+className+"] from plugin ["+ getName()+ "] : " + e.getMessage(), e); + throw new PluginException("Failed to initialize class [" + className + "] from plugin [" + getName() + "] : " + e.getMessage(), e); } } @@ -217,7 +224,7 @@ public Resource getResource(String path) { /** * Obtains all properties for this binary plugin for the given locale. - * + *

* Note this method does not cache so clients should in general cache the results of this method. * * @param locale The locale @@ -226,7 +233,7 @@ public Resource getResource(String path) { public Properties getProperties(final Locale locale) { Resource url = this.baseResourcesResource; Properties properties = null; - if(url != null) { + if (url != null) { StaticResourceLoader resourceLoader = new StaticResourceLoader(); resourceLoader.setBaseResource(url); ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(resourceLoader); @@ -234,7 +241,7 @@ public Properties getProperties(final Locale locale) { // first load all properties Resource[] resources = resolver.getResources('*' + PROPERTIES_EXTENSION); resources = resources.length > 0 ? filterResources(resources, locale) : resources; - if(resources.length > 0) { + if (resources.length > 0) { properties = new Properties(); // message bundles are locale specific. The more underscores the locale has the more specific the locale @@ -246,11 +253,10 @@ public Properties getProperties(final Locale locale) { int firstUnderscoreCount = StringUtils.countOccurrencesOf(f1, "_"); int secondUnderscoreCount = StringUtils.countOccurrencesOf(f2, "_"); - if(firstUnderscoreCount == secondUnderscoreCount) { + if (firstUnderscoreCount == secondUnderscoreCount) { return 0; - } - else { - return firstUnderscoreCount > secondUnderscoreCount ? 1 : -1; + } else { + return firstUnderscoreCount > secondUnderscoreCount ? 1 : -1; } }); @@ -263,25 +269,21 @@ public Properties getProperties(final Locale locale) { return properties; } - private Resource[] filterResources(Resource[] resources, Locale locale) { List finalResources = new ArrayList(resources.length); for (Resource resource : resources) { String fn = resource.getFilename(); - if(fn.indexOf(UNDERSCORE) > -1) { - if(fn.endsWith(UNDERSCORE + locale.toString() + PROPERTIES_EXTENSION)) { + if (fn.indexOf(UNDERSCORE) > -1) { + if (fn.endsWith(UNDERSCORE + locale.toString() + PROPERTIES_EXTENSION)) { finalResources.add(resource); - } - else if(fn.endsWith(UNDERSCORE + locale.getLanguage() + UNDERSCORE + locale.getCountry() + PROPERTIES_EXTENSION)) { + } else if (fn.endsWith(UNDERSCORE + locale.getLanguage() + UNDERSCORE + locale.getCountry() + PROPERTIES_EXTENSION)) { finalResources.add(resource); - } - else if(fn.endsWith(UNDERSCORE + locale.getLanguage() + PROPERTIES_EXTENSION)) { + } else if (fn.endsWith(UNDERSCORE + locale.getLanguage() + PROPERTIES_EXTENSION)) { finalResources.add(resource); } - } - else { + } else { finalResources.add(resource); } } @@ -307,10 +309,9 @@ private void loadFromResources(Properties properties, Resource[] resources) thro * Resolves a view for the given view name. * * @param viewName The view name - * * @return The view class which is a subclass of GroovyPage */ - public Class resolveView(String viewName) { + public Class resolveView(String viewName) { // this is a workaround for GRAILS-9234; in that scenario the viewName will be // "/WEB-INF/grails-app/views/plugins/plugin9234-0.1/junk/_book.gsp" with the diff --git a/grails-core/src/main/groovy/org/grails/plugins/BinaryGrailsPluginDescriptor.java b/grails-core/src/main/groovy/org/grails/plugins/BinaryGrailsPluginDescriptor.java index 4d0830a6278..4a41ecf9f76 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/BinaryGrailsPluginDescriptor.java +++ b/grails-core/src/main/groovy/org/grails/plugins/BinaryGrailsPluginDescriptor.java @@ -22,6 +22,7 @@ import org.grails.core.exceptions.GrailsConfigurationException; import org.grails.io.support.SpringIOUtils; import org.springframework.core.io.Resource; + import java.io.IOException; import java.io.InputStream; import java.util.List; @@ -62,7 +63,7 @@ public List getProvidedlassNames() { * @return The parsed descriptor */ public GPathResult getParsedXml() { - if(parsedXml == null) { + if (parsedXml == null) { InputStream inputStream; try { inputStream = resource.getInputStream(); diff --git a/grails-core/src/main/groovy/org/grails/plugins/CoreGrailsPlugin.groovy b/grails-core/src/main/groovy/org/grails/plugins/CoreGrailsPlugin.groovy index c87b8449875..2573d3a2ee1 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/CoreGrailsPlugin.groovy +++ b/grails-core/src/main/groovy/org/grails/plugins/CoreGrailsPlugin.groovy @@ -19,24 +19,24 @@ package org.grails.plugins import grails.config.Settings +import grails.core.support.proxy.DefaultProxyHandler import grails.plugins.Plugin import grails.util.BuildSettings import grails.util.Environment import grails.util.GrailsUtil import groovy.transform.CompileStatic +import org.grails.beans.support.PropertiesEditor +import org.grails.core.io.DefaultResourceLocator +import org.grails.core.support.ClassEditor +import org.grails.dev.support.DevelopmentShutdownHook import org.grails.spring.DefaultRuntimeSpringConfiguration +import org.grails.spring.RuntimeSpringConfigUtilities import org.grails.spring.RuntimeSpringConfiguration import org.grails.spring.aop.autoproxy.GroovyAwareAspectJAwareAdvisorAutoProxyCreator import org.grails.spring.aop.autoproxy.GroovyAwareInfrastructureAdvisorAutoProxyCreator -import org.grails.spring.context.support.MapBasedSmartPropertyOverrideConfigurer -import org.grails.spring.RuntimeSpringConfigUtilities -import org.grails.core.io.DefaultResourceLocator import org.grails.spring.beans.GrailsApplicationAwareBeanPostProcessor import org.grails.spring.beans.PluginManagerAwareBeanPostProcessor -import org.grails.core.support.ClassEditor -import org.grails.dev.support.DevelopmentShutdownHook -import org.grails.beans.support.PropertiesEditor -import grails.core.support.proxy.DefaultProxyHandler +import org.grails.spring.context.support.MapBasedSmartPropertyOverrideConfigurer import org.springframework.beans.factory.config.CustomEditorConfigurer import org.springframework.beans.factory.support.DefaultListableBeanFactory import org.springframework.beans.factory.xml.XmlBeanDefinitionReader @@ -54,96 +54,96 @@ import org.springframework.util.ClassUtils class CoreGrailsPlugin extends Plugin { def version = GrailsUtil.getGrailsVersion() - def watchedResources = [ "file:./grails-app/conf/spring/resources.xml", - "file:./grails-app/conf/spring/resources.groovy", - "file:./grails-app/conf/application.groovy", - "file:./grails-app/conf/application.yml"] + def watchedResources = ["file:./grails-app/conf/spring/resources.xml", + "file:./grails-app/conf/spring/resources.groovy", + "file:./grails-app/conf/application.groovy", + "file:./grails-app/conf/application.yml"] private static final SPRING_PROXY_TARGET_CLASS_CONFIG = "spring.aop.proxy-target-class" @Override - Closure doWithSpring() { {-> + Closure doWithSpring() { + { -> - def application = grailsApplication + def application = grailsApplication - // Grails config as properties - def config = application.config + // Grails config as properties + def config = application.config - // enable post-processing of @Configuration beans defined by plugins - grailsConfigurationClassPostProcessor ConfigurationClassPostProcessor - grailsBeanOverrideConfigurer(MapBasedSmartPropertyOverrideConfigurer) { - delegate.grailsApplication = application - } + // enable post-processing of @Configuration beans defined by plugins + grailsConfigurationClassPostProcessor ConfigurationClassPostProcessor + grailsBeanOverrideConfigurer(MapBasedSmartPropertyOverrideConfigurer) { + delegate.grailsApplication = application + } - Class proxyCreatorClazz = null - // replace AutoProxy advisor with Groovy aware one - if (ClassUtils.isPresent('org.aspectj.lang.annotation.Around', application.classLoader) && !config.getProperty(Settings.SPRING_DISABLE_ASPECTJ, Boolean)) { - proxyCreatorClazz = GroovyAwareAspectJAwareAdvisorAutoProxyCreator - } else { - proxyCreatorClazz = GroovyAwareInfrastructureAdvisorAutoProxyCreator - } + Class proxyCreatorClazz = null + // replace AutoProxy advisor with Groovy aware one + if (ClassUtils.isPresent('org.aspectj.lang.annotation.Around', application.classLoader) && !config.getProperty(Settings.SPRING_DISABLE_ASPECTJ, Boolean)) { + proxyCreatorClazz = GroovyAwareAspectJAwareAdvisorAutoProxyCreator + } else { + proxyCreatorClazz = GroovyAwareInfrastructureAdvisorAutoProxyCreator + } - Boolean isProxyTargetClass = config.getProperty(SPRING_PROXY_TARGET_CLASS_CONFIG, Boolean) - "org.springframework.aop.config.internalAutoProxyCreator"(proxyCreatorClazz) { - if (isProxyTargetClass != null) { - proxyTargetClass = isProxyTargetClass + Boolean isProxyTargetClass = config.getProperty(SPRING_PROXY_TARGET_CLASS_CONFIG, Boolean) + "org.springframework.aop.config.internalAutoProxyCreator"(proxyCreatorClazz) { + if (isProxyTargetClass != null) { + proxyTargetClass = isProxyTargetClass + } } - } - def packagesToScan = [] + def packagesToScan = [] - def beanPackages = config.getProperty(Settings.SPRING_BEAN_PACKAGES, List) - if (beanPackages) { - packagesToScan += beanPackages - } + def beanPackages = config.getProperty(Settings.SPRING_BEAN_PACKAGES, List) + if (beanPackages) { + packagesToScan += beanPackages + } + if (packagesToScan) { + xmlns grailsContext: "https://grails.org/schema/context" + grailsContext.'component-scan'('base-package': packagesToScan.join(',')) + } - if (packagesToScan) { - xmlns grailsContext:"http://grails.org/schema/context" - grailsContext.'component-scan'('base-package':packagesToScan.join(',')) - } + grailsApplicationAwarePostProcessor(GrailsApplicationAwareBeanPostProcessor, ref("grailsApplication")) + pluginManagerPostProcessor(PluginManagerAwareBeanPostProcessor) - grailsApplicationAwarePostProcessor(GrailsApplicationAwareBeanPostProcessor, ref("grailsApplication")) - pluginManagerPostProcessor(PluginManagerAwareBeanPostProcessor) + // add shutdown hook if not running in war deployed mode + final warDeployed = Environment.isWarDeployed() + final devMode = !warDeployed && environment == Environment.DEVELOPMENT + if (devMode && ClassUtils.isPresent('jline.Terminal', application.classLoader)) { + shutdownHook(DevelopmentShutdownHook) + } + abstractGrailsResourceLocator { + searchLocations = [BuildSettings.BASE_DIR.absolutePath] + } + grailsResourceLocator(DefaultResourceLocator) { bean -> + bean.parent = "abstractGrailsResourceLocator" + } - // add shutdown hook if not running in war deployed mode - final warDeployed = Environment.isWarDeployed() - final devMode = !warDeployed && environment == Environment.DEVELOPMENT - if (devMode && ClassUtils.isPresent('jline.Terminal', application.classLoader)) { - shutdownHook(DevelopmentShutdownHook) - } - abstractGrailsResourceLocator { - searchLocations = [BuildSettings.BASE_DIR.absolutePath] - } - grailsResourceLocator(DefaultResourceLocator) { bean -> - bean.parent = "abstractGrailsResourceLocator" - } + customEditors(CustomEditorConfigurer) { + customEditors = [(Class) : ClassEditor, + (Properties): PropertiesEditor] + } - customEditors(CustomEditorConfigurer) { - customEditors = [(Class): ClassEditor, - (Properties): PropertiesEditor] + proxyHandler(DefaultProxyHandler) } - - proxyHandler(DefaultProxyHandler) - }} + } @Override @CompileStatic void onChange(Map event) { - GenericApplicationContext applicationContext = (GenericApplicationContext)this.applicationContext + GenericApplicationContext applicationContext = (GenericApplicationContext) this.applicationContext if (event.source instanceof Resource) { - Resource res = (Resource)event.source - if(res.filename.endsWith('.xml')) { + Resource res = (Resource) event.source + if (res.filename.endsWith('.xml')) { def xmlBeans = new DefaultListableBeanFactory() new XmlBeanDefinitionReader(xmlBeans).loadBeanDefinitions(res) - for(String beanName in xmlBeans.beanDefinitionNames) { + for (String beanName in xmlBeans.beanDefinitionNames) { applicationContext.registerBeanDefinition(beanName, xmlBeans.getBeanDefinition(beanName)) } } - } - else if (event.source instanceof Class) { + } else if (event.source instanceof Class) { def clazz = (Class) event.source - if(Script.isAssignableFrom(clazz)) { + if (Script.isAssignableFrom(clazz)) { RuntimeSpringConfiguration springConfig = new DefaultRuntimeSpringConfiguration(applicationContext) RuntimeSpringConfigUtilities.reloadSpringResourcesConfig(springConfig, grailsApplication, clazz) springConfig.registerBeansWithContext(applicationContext) diff --git a/grails-core/src/main/groovy/org/grails/plugins/CorePluginFinder.java b/grails-core/src/main/groovy/org/grails/plugins/CorePluginFinder.java index f306a09e225..796a0ec9306 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/CorePluginFinder.java +++ b/grails-core/src/main/groovy/org/grails/plugins/CorePluginFinder.java @@ -36,7 +36,13 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; -import java.util.*; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * Loads core plugin classes. Contains functionality moved in from DefaultGrailsPluginManager. @@ -46,9 +52,10 @@ */ public class CorePluginFinder implements ParentApplicationContextAware { - private static final Logger LOG = LoggerFactory.getLogger(CorePluginFinder.class); public static final String CORE_PLUGIN_PATTERN = "META-INF/grails-plugin.xml"; + private static final Logger LOG = LoggerFactory.getLogger(CorePluginFinder.class); + private final Set> foundPluginClasses = new HashSet>(); @SuppressWarnings("unused") private final GrailsApplication application; @@ -91,8 +98,6 @@ private Resource[] resolvePluginResources() throws IOException { return resourceList.toArray(new Resource[resourceList.size()]); } - - @SuppressWarnings("rawtypes") private void loadCorePluginsFromResources(Resource[] resources) throws IOException { @@ -109,7 +114,7 @@ private void loadCorePluginsFromResources(Resource[] resources) throws IOExcepti for (String pluginType : ph.pluginTypes) { Class pluginClass = attemptCorePluginClassLoad(pluginType); - if(pluginClass != null) { + if (pluginClass != null) { addPlugin(pluginClass); binaryDescriptors.put(pluginClass, new BinaryGrailsPluginDescriptor(resource, ph.pluginClasses)); } @@ -128,7 +133,6 @@ private void loadCorePluginsFromResources(Resource[] resources) throws IOExcepti } } - private Class attemptCorePluginClassLoad(String pluginClassName) { try { final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); @@ -143,7 +147,6 @@ private Class attemptCorePluginClassLoad(String pluginClassName) { return null; } - private void addPlugin(Class plugin) { foundPluginClasses.add(plugin); } @@ -156,6 +159,7 @@ private enum PluginParseState { } class PluginHandler extends DefaultHandler { + PluginParseState state = PluginParseState.PARSING; List pluginTypes = new ArrayList<>(); @@ -164,11 +168,10 @@ class PluginHandler extends DefaultHandler { @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - if(localName.equals("type")) { + if (localName.equals("type")) { state = PluginParseState.TYPE; buff = new StringBuilder(); - } - else if(localName.equals("resource")) { + } else if (localName.equals("resource")) { state = PluginParseState.RESOURCE; buff = new StringBuilder(); } @@ -183,6 +186,9 @@ public void characters(char[] ch, int start, int length) throws SAXException { case RESOURCE: buff.append(String.valueOf(ch, start, length)); break; + default: + // do nothing + break; } } @@ -195,6 +201,9 @@ public void endElement(String uri, String localName, String qName) throws SAXExc case RESOURCE: pluginClasses.add(buff.toString()); break; + default: + // do nothing + break; } state = PluginParseState.PARSING; } diff --git a/grails-core/src/main/groovy/org/grails/plugins/DefaultGrailsPlugin.java b/grails-core/src/main/groovy/org/grails/plugins/DefaultGrailsPlugin.java index 6ab8520d9b0..b3ccc138fc0 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/DefaultGrailsPlugin.java +++ b/grails-core/src/main/groovy/org/grails/plugins/DefaultGrailsPlugin.java @@ -81,19 +81,21 @@ @SuppressWarnings("rawtypes") public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentApplicationContextAware { + protected static final Log LOG = LogFactory.getLog(DefaultGrailsPlugin.class); + private static final String PLUGIN_CHANGE_EVENT_CTX = "ctx"; private static final String PLUGIN_CHANGE_EVENT_APPLICATION = "application"; private static final String PLUGIN_CHANGE_EVENT_PLUGIN = "plugin"; private static final String PLUGIN_CHANGE_EVENT_SOURCE = "source"; private static final String PLUGIN_CHANGE_EVENT_MANAGER = "manager"; - protected static final Log LOG = LogFactory.getLog(DefaultGrailsPlugin.class); private static final String INCLUDES = "includes"; private static final String EXCLUDES = "excludes"; + protected BeanWrapper pluginBean; + private GrailsPluginClass pluginGrailsClass; private GroovyObject plugin; - protected BeanWrapper pluginBean; private Closure onChangeListener; private Resource[] watchedResources = {}; @@ -113,6 +115,10 @@ public class DefaultGrailsPlugin extends AbstractGrailsPlugin implements ParentA private Resource pluginDescriptor; private List watchedResourcePatterns; + public DefaultGrailsPlugin(Class pluginClass, GrailsApplication application) { + this(pluginClass, null, application); + } + public DefaultGrailsPlugin(Class pluginClass, Resource resource, GrailsApplication application) { super(pluginClass, application); // create properties @@ -123,16 +129,19 @@ public DefaultGrailsPlugin(Class pluginClass, Resource resource, GrailsApplic try { initialisePlugin(pluginClass); } catch (Throwable e) { - throw new PluginException("Error initialising plugin for class ["+pluginClass.getName()+"]:" + e.getMessage(), e); + throw new PluginException("Error initialising plugin for class [" + pluginClass.getName() + "]:" + e.getMessage(), e); } } @Override public boolean isEnabled(String[] activeProfiles) { - if(profiles == null) return true; - else { + if (profiles == null) { + return true; + } else { for (String activeProfile : activeProfiles) { - if(profiles.contains(activeProfile)) return true; + if (profiles.contains(activeProfile)) { + return true; + } } } return false; @@ -141,11 +150,11 @@ public boolean isEnabled(String[] activeProfiles) { @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { super.setApplicationContext(applicationContext); - if(this.plugin instanceof ApplicationContextAware) { - ((ApplicationContextAware)plugin).setApplicationContext(applicationContext); + if (this.plugin instanceof ApplicationContextAware) { + ((ApplicationContextAware) plugin).setApplicationContext(applicationContext); } - if(this.plugin instanceof ApplicationListener) { - ((ConfigurableApplicationContext)applicationContext).addApplicationListener((ApplicationListener)plugin); + if (this.plugin instanceof ApplicationListener) { + ((ConfigurableApplicationContext) applicationContext).addApplicationListener((ApplicationListener) plugin); } } @@ -169,23 +178,22 @@ public boolean hasInterestInChange(String path) { @Override public void setManager(GrailsPluginManager manager) { super.setManager(manager); - if(plugin instanceof Plugin) { - ((Plugin)plugin).setPluginManager(manager); + if (plugin instanceof Plugin) { + ((Plugin) plugin).setPluginManager(manager); } } private void initialisePlugin(Class clazz) { pluginGrailsClass = new GrailsPluginClass(clazz); - plugin = (GroovyObject)pluginGrailsClass.newInstance(); - if(plugin instanceof Plugin) { - Plugin p = (Plugin)plugin; + plugin = (GroovyObject) pluginGrailsClass.newInstance(); + if (plugin instanceof Plugin) { + Plugin p = (Plugin) plugin; p.setApplicationContext(applicationContext); p.setPlugin(this); p.setGrailsApplication(grailsApplication); p.setPluginManager(manager); - } - else if(plugin instanceof GrailsApplicationAware) { - ((GrailsApplicationAware)plugin).setGrailsApplication(grailsApplication); + } else if (plugin instanceof GrailsApplicationAware) { + ((GrailsApplicationAware) plugin).setGrailsApplication(grailsApplication); } pluginBean = new BeanWrapperImpl(plugin); @@ -223,11 +231,14 @@ private void evaluatePluginScopes() { // Damn I wish Java had closures pluginEnvs = evaluateIncludeExcludeProperty(ENVIRONMENTS, new Closure(this) { private static final long serialVersionUID = 1; + @Override public Object call(Object arguments) { - String envName = (String)arguments; + String envName = (String) arguments; Environment env = Environment.getEnvironment(envName); - if (env != null) return env.getName(); + if (env != null) { + return env.getName(); + } return arguments; } }); @@ -237,15 +248,14 @@ private Map evaluateIncludeExcludeProperty(String name, Closure converter) { Map resultMap = new HashMap(); Object propertyValue = GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(plugin, name); if (propertyValue instanceof Map) { - Map containedMap = (Map)propertyValue; + Map containedMap = (Map) propertyValue; Object includes = containedMap.get(INCLUDES); evaluateAndAddIncludeExcludeObject(resultMap, includes, true, converter); Object excludes = containedMap.get(EXCLUDES); evaluateAndAddIncludeExcludeObject(resultMap, excludes, false, converter); - } - else { + } else { evaluateAndAddIncludeExcludeObject(resultMap, propertyValue, true, converter); } return resultMap; @@ -254,11 +264,10 @@ private Map evaluateIncludeExcludeProperty(String name, Closure converter) { private void evaluateAndAddIncludeExcludeObject(Map targetMap, Object includeExcludeObject, boolean include, Closure converter) { if (includeExcludeObject instanceof String) { final String includeExcludeString = (String) includeExcludeObject; - evaluateAndAddToIncludeExcludeSet(targetMap,includeExcludeString, include, converter); - } - else if (includeExcludeObject instanceof List) { + evaluateAndAddToIncludeExcludeSet(targetMap, includeExcludeString, include, converter); + } else if (includeExcludeObject instanceof List) { List includeExcludeList = (List) includeExcludeObject; - evaluateAndAddListOfValues(targetMap,includeExcludeList, include, converter); + evaluateAndAddListOfValues(targetMap, includeExcludeList, include, converter); } } @@ -273,7 +282,7 @@ private void evaluateAndAddListOfValues(Map targetMap, List includeExcludeList, @SuppressWarnings("unchecked") private void evaluateAndAddToIncludeExcludeSet(Map targetMap, String includeExcludeString, boolean include, Closure converter) { - Set set = lazilyCreateIncludeOrExcludeSet(targetMap,include); + Set set = lazilyCreateIncludeOrExcludeSet(targetMap, include); set.add(converter.call(includeExcludeString)); } @@ -293,27 +302,22 @@ private void evaluateProvidedArtefacts() { Object result = GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(pluginBean, plugin, PROVIDED_ARTEFACTS); if (result instanceof Collection) { final Collection artefactList = (Collection) result; - providedArtefacts = (Class[])artefactList.toArray(new Class[artefactList.size()]); + providedArtefacts = (Class[]) artefactList.toArray(new Class[artefactList.size()]); } } private void evaluateProfiles() { Object result = GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(pluginBean, plugin, PROFILES); if (result instanceof Collection) { - profiles = (Collection) result; + profiles = (Collection) result; } } - - public DefaultGrailsPlugin(Class pluginClass, GrailsApplication application) { - this(pluginClass, null, application); - } - private void evaluateObservedPlugins() { if (pluginBean.isReadableProperty(OBSERVE)) { Object observeProperty = GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(pluginBean, plugin, OBSERVE); if (observeProperty instanceof Collection) { - Collection observeList = (Collection)observeProperty; + Collection observeList = (Collection) observeProperty; observedPlugins = new String[observeList.size()]; int j = 0; for (Object anObserveList : observeList) { @@ -340,17 +344,17 @@ private void evaluatePluginStatus() { private void evaluateOnChangeListener() { if (pluginBean.isReadableProperty(ON_SHUTDOWN)) { - onShutdownListener = (Closure)GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(plugin, ON_SHUTDOWN); + onShutdownListener = (Closure) GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(plugin, ON_SHUTDOWN); } if (pluginBean.isReadableProperty(ON_CONFIG_CHANGE)) { - onConfigChangeListener = (Closure)GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(plugin, ON_CONFIG_CHANGE); + onConfigChangeListener = (Closure) GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(plugin, ON_CONFIG_CHANGE); } if (pluginBean.isReadableProperty(ON_CHANGE)) { onChangeListener = (Closure) GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(plugin, ON_CHANGE); } Environment env = Environment.getCurrent(); - final boolean warDeployed = env.isWarDeployed(); + final boolean warDeployed = Environment.isWarDeployed(); final boolean reloadEnabled = env.isReloadEnabled(); if (!((reloadEnabled || !warDeployed))) { @@ -363,12 +367,11 @@ private void evaluateOnChangeListener() { List resourceList = null; if (referencedResources instanceof String) { if (LOG.isDebugEnabled()) { - LOG.debug("Configuring plugin "+this+" to watch resources with pattern: " + referencedResources); + LOG.debug("Configuring plugin " + this + " to watch resources with pattern: " + referencedResources); } resourceList = Collections.singletonList(referencedResources.toString()); - } - else if (referencedResources instanceof List) { - resourceList = (List)referencedResources; + } else if (referencedResources instanceof List) { + resourceList = (List) referencedResources; } if (resourceList == null) { @@ -382,8 +385,7 @@ else if (referencedResources instanceof List) { String stringRef = ref.toString(); if (warDeployed) { addBaseLocationPattern(resourceListTmp, baseLocation, stringRef); - } - else { + } else { addBaseLocationPattern(resourceListTmp, baseLocation, stringRef); } } @@ -395,8 +397,7 @@ else if (referencedResources instanceof List) { } watchedResourcePatterns = new WatchPatternParser().getWatchPatterns(Arrays.asList(watchedResourcePatternReferences)); - } - catch (IllegalArgumentException e) { + } catch (IllegalArgumentException e) { if (GrailsUtil.isDevelopmentEnv()) { LOG.debug("Cannot load plug-in resource watch list from [" + GrailsArrayUtils.toString(watchedResourcePatternReferences) + "]. This means that the plugin " + this + @@ -412,10 +413,12 @@ private void addBaseLocationPattern(List resourceList, final String base private String getResourcePatternForBaseLocation(String baseLocation, String resourcePath) { String location = baseLocation; - if (!location.endsWith(File.separator)) location = location + File.separator; + if (!location.endsWith(File.separator)) { + location = location + File.separator; + } if (resourcePath.startsWith("./")) { - return "file:" + location + resourcePath.substring(2); } - else if (resourcePath.startsWith("file:./")) { + return "file:" + location + resourcePath.substring(2); + } else if (resourcePath.startsWith("file:./")) { return "file:" + location + resourcePath.substring(7); } return resourcePath; @@ -456,13 +459,13 @@ private void evaluatePluginLoadAfters() { if (pluginBean.isReadableProperty(PLUGIN_LOAD_AFTER_NAMES)) { List loadAfterNamesList = (List) GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(pluginBean, plugin, PLUGIN_LOAD_AFTER_NAMES); if (loadAfterNamesList != null) { - loadAfterNames = (String[])loadAfterNamesList.toArray(new String[loadAfterNamesList.size()]); + loadAfterNames = (String[]) loadAfterNamesList.toArray(new String[loadAfterNamesList.size()]); } } if (pluginBean.isReadableProperty(PLUGIN_LOAD_BEFORE_NAMES)) { List loadBeforeNamesList = (List) GrailsClassUtils.getPropertyOrStaticPropertyOrFieldValue(pluginBean, plugin, PLUGIN_LOAD_BEFORE_NAMES); if (loadBeforeNamesList != null) { - loadBeforeNames = (String[])loadBeforeNamesList.toArray(new String[loadBeforeNamesList.size()]); + loadBeforeNames = (String[]) loadBeforeNamesList.toArray(new String[loadBeforeNamesList.size()]); } } } @@ -505,13 +508,12 @@ public BeanBuilder beans(Closure closure) { } public void doWithApplicationContext(ApplicationContext ctx) { - if(plugin instanceof Plugin) { + if (plugin instanceof Plugin) { Plugin pluginObject = (Plugin) plugin; pluginObject.setApplicationContext(ctx); pluginObject.doWithApplicationContext(); - } - else { + } else { Object[] args = {ctx}; invokePluginHook(DO_WITH_APPLICATION_CONTEXT, args, ctx); } @@ -519,13 +521,12 @@ public void doWithApplicationContext(ApplicationContext ctx) { private void invokePluginHook(String methodName, Object[] args, ApplicationContext ctx) { if (pluginBean.isReadableProperty(methodName)) { - Closure c = (Closure)plugin.getProperty(methodName); + Closure c = (Closure) plugin.getProperty(methodName); c.setDelegate(this); c.call(args); - } - else { + } else { MetaClass pluginMetaClass = pluginGrailsClass.getMetaClass(); - if(!pluginMetaClass.respondsTo(plugin, methodName, args).isEmpty()) { + if (!pluginMetaClass.respondsTo(plugin, methodName, args).isEmpty()) { pluginMetaClass.invokeMethod(plugin, methodName, ctx); } } @@ -540,10 +541,10 @@ public void doWithRuntimeConfiguration(RuntimeSpringConfiguration springConfig) b.setVariable("parentCtx", getParentCtx()); b.setVariable("resolver", getResolver()); - if(plugin instanceof Plugin) { + if (plugin instanceof Plugin) { Closure c = ((Plugin) plugin).doWithSpring(); - if(c != null) { - BeanBuilder bb = new BeanBuilder(getParentCtx(),springConfig, grailsApplication.getClassLoader()); + if (c != null) { + BeanBuilder bb = new BeanBuilder(getParentCtx(), springConfig, grailsApplication.getClassLoader()); bb.setBinding(b); c.setDelegate(bb); bb.invokeMethod("beans", new Object[]{c}); @@ -557,8 +558,8 @@ public void doWithRuntimeConfiguration(RuntimeSpringConfiguration springConfig) LOG.debug("Plugin " + this + " is participating in Spring configuration..."); } - Closure c = (Closure)plugin.getProperty(DO_WITH_SPRING); - BeanBuilder bb = new BeanBuilder(getParentCtx(),springConfig, grailsApplication.getClassLoader()); + Closure c = (Closure) plugin.getProperty(DO_WITH_SPRING); + BeanBuilder bb = new BeanBuilder(getParentCtx(), springConfig, grailsApplication.getClassLoader()); bb.setBinding(b); c.setDelegate(bb); bb.invokeMethod("beans", new Object[]{c}); @@ -579,7 +580,9 @@ private void addExcludeRuleInternal(Map map, Object o) { map.put(EXCLUDES, excludes); } Collection includes = (Collection) map.get(INCLUDES); - if (includes != null) includes.remove(o); + if (includes != null) { + includes.remove(o); + } excludes.add(o); } @@ -606,7 +609,7 @@ private boolean supportsValueInIncludeExcludeMap(Map includeExcludeMap, Object v return includes.contains(value); } - Set excludes = (Set)includeExcludeMap.get(EXCLUDES); + Set excludes = (Set) includeExcludeMap.get(EXCLUDES); return !(excludes != null && excludes.contains(value)); } @@ -624,10 +627,9 @@ public Resource[] getWatchedResources() { try { Resource[] resources = resolver.getResources(resourcesReference); if (resources.length > 0) { - watchedResources = (Resource[])GrailsArrayUtils.addAll(watchedResources, resources); + watchedResources = (Resource[]) GrailsArrayUtils.addAll(watchedResources, resources); } - } - catch (Exception ignored) { + } catch (Exception ignored) { // ignore } } @@ -693,20 +695,18 @@ public GroovyObject getInstance() { } public void doWithDynamicMethods(ApplicationContext ctx) { - if(plugin instanceof Plugin) { - ((Plugin)plugin).doWithDynamicMethods(); - } - else { + if (plugin instanceof Plugin) { + ((Plugin) plugin).doWithDynamicMethods(); + } else { Object[] args = {ctx}; invokePluginHook(DO_WITH_DYNAMIC_METHODS, args, ctx); } } public boolean isEnabled() { - if(plugin instanceof Plugin) { - return ((Plugin)plugin).isEnabled(); - } - else { + if (plugin instanceof Plugin) { + return ((Plugin) plugin).isEnabled(); + } else { return STATUS_ENABLED.equals(status); } } @@ -716,10 +716,9 @@ public String[] getObservedPluginNames() { } public void notifyOfEvent(Map event) { - if(plugin instanceof Plugin) { - ((Plugin)plugin).onChange(event); - } - else if(onChangeListener != null) { + if (plugin instanceof Plugin) { + ((Plugin) plugin).onChange(event); + } else if (onChangeListener != null) { invokeOnChangeListener(event); } } @@ -727,36 +726,33 @@ else if(onChangeListener != null) { public Map notifyOfEvent(int eventKind, final Object source) { @SuppressWarnings("unchecked") Map event = CollectionUtils.newMap( - PLUGIN_CHANGE_EVENT_SOURCE, source, - PLUGIN_CHANGE_EVENT_PLUGIN, plugin, - PLUGIN_CHANGE_EVENT_APPLICATION, grailsApplication, - PLUGIN_CHANGE_EVENT_MANAGER, getManager(), - PLUGIN_CHANGE_EVENT_CTX, applicationContext); + PLUGIN_CHANGE_EVENT_SOURCE, source, + PLUGIN_CHANGE_EVENT_PLUGIN, plugin, + PLUGIN_CHANGE_EVENT_APPLICATION, grailsApplication, + PLUGIN_CHANGE_EVENT_MANAGER, getManager(), + PLUGIN_CHANGE_EVENT_CTX, applicationContext); switch (eventKind) { case EVENT_ON_CHANGE: - if(plugin instanceof Plugin) { - ((Plugin)plugin).onChange(event); - } - else { + if (plugin instanceof Plugin) { + ((Plugin) plugin).onChange(event); + } else { notifyOfEvent(event); } getManager().informObservers(getName(), event); break; case EVENT_ON_SHUTDOWN: - if(plugin instanceof Plugin) { - ((Plugin)plugin).onShutdown(event); - } - else { + if (plugin instanceof Plugin) { + ((Plugin) plugin).onShutdown(event); + } else { invokeOnShutdownEventListener(event); } break; case EVENT_ON_CONFIG_CHANGE: - if(plugin instanceof Plugin) { - ((Plugin)plugin).onConfigChange(event); - } - else { + if (plugin instanceof Plugin) { + ((Plugin) plugin).onConfigChange(event); + } else { invokeOnConfigChangeListener(event); } @@ -769,11 +765,11 @@ PLUGIN_CHANGE_EVENT_MANAGER, getManager(), } private void invokeOnShutdownEventListener(Map event) { - callEvent(onShutdownListener,event); + callEvent(onShutdownListener, event); } private void invokeOnConfigChangeListener(Map event) { - callEvent(onConfigChangeListener,event); + callEvent(onConfigChangeListener, event); } private void callEvent(Closure closureHook, Map event) { @@ -811,14 +807,12 @@ public void doArtefactConfiguration() { return; } - List l; - if(plugin instanceof Plugin) { - l = ((Plugin)plugin).getArtefacts(); - } - else { + if (plugin instanceof Plugin) { + l = ((Plugin) plugin).getArtefacts(); + } else { - l = (List)plugin.getProperty(ARTEFACTS); + l = (List) plugin.getProperty(ARTEFACTS); } for (Object artefact : l) { if (artefact instanceof Class) { @@ -826,22 +820,17 @@ public void doArtefactConfiguration() { if (ArtefactHandler.class.isAssignableFrom(artefactClass)) { try { grailsApplication.registerArtefactHandler((ArtefactHandler) artefactClass.newInstance()); - } - catch (InstantiationException e) { + } catch (InstantiationException e) { LOG.error("Cannot instantiate an Artefact Handler:" + e.getMessage(), e); - } - catch (IllegalAccessException e) { + } catch (IllegalAccessException e) { LOG.error("The constructor of the Artefact Handler is not accessible:" + e.getMessage(), e); } - } - else { + } else { LOG.error("This class is not an ArtefactHandler:" + artefactClass.getName()); } - } - else if (artefact instanceof ArtefactHandler) { + } else if (artefact instanceof ArtefactHandler) { grailsApplication.registerArtefactHandler((ArtefactHandler) artefact); - } - else { + } else { LOG.error("This object is not an ArtefactHandler:" + artefact + "[" + artefact.getClass().getName() + "]"); } } @@ -874,8 +863,7 @@ public void setDescriptor(Resource descriptor) { public org.grails.io.support.Resource getPluginDir() { try { return new SpringResource(pluginDescriptor.createRelative(".")); - } - catch (IOException e) { + } catch (IOException e) { return null; } } diff --git a/grails-core/src/main/groovy/org/grails/plugins/ExcludingPluginFilter.java b/grails-core/src/main/groovy/org/grails/plugins/ExcludingPluginFilter.java index ebcc09de9ec..e19f5830461 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/ExcludingPluginFilter.java +++ b/grails-core/src/main/groovy/org/grails/plugins/ExcludingPluginFilter.java @@ -33,7 +33,7 @@ * * @author Phil Zoio */ -@SuppressWarnings({ "unchecked", "rawtypes" }) +@SuppressWarnings({"unchecked", "rawtypes"}) public class ExcludingPluginFilter extends BasePluginFilter { public ExcludingPluginFilter(Set excluded) { @@ -49,7 +49,7 @@ protected List getPluginList(List original, List pluginList) { // go through and remove ones that don't apply List newList = new ArrayList(original); - for (Iterator iter = newList.iterator(); iter.hasNext();) { + for (Iterator iter = newList.iterator(); iter.hasNext(); ) { GrailsPlugin element = iter.next(); // remove the excluded dependencies if (pluginList.contains(element)) { diff --git a/grails-core/src/main/groovy/org/grails/plugins/IdentityPluginFilter.java b/grails-core/src/main/groovy/org/grails/plugins/IdentityPluginFilter.java index e4d15ddebba..46fd9c31772 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/IdentityPluginFilter.java +++ b/grails-core/src/main/groovy/org/grails/plugins/IdentityPluginFilter.java @@ -32,7 +32,7 @@ public class IdentityPluginFilter implements PluginFilter { /** * Simply returns original list reference. */ - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) public List filterPluginList(List original) { return original; } diff --git a/grails-core/src/main/groovy/org/grails/plugins/IncludingPluginFilter.java b/grails-core/src/main/groovy/org/grails/plugins/IncludingPluginFilter.java index bbe97478578..77a34f50355 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/IncludingPluginFilter.java +++ b/grails-core/src/main/groovy/org/grails/plugins/IncludingPluginFilter.java @@ -30,7 +30,7 @@ * * @author Phil Zoio */ -@SuppressWarnings({ "unchecked", "rawtypes" }) +@SuppressWarnings({"unchecked", "rawtypes"}) public class IncludingPluginFilter extends BasePluginFilter { public IncludingPluginFilter(Set included) { diff --git a/grails-core/src/main/groovy/org/grails/plugins/MockGrailsPluginManager.java b/grails-core/src/main/groovy/org/grails/plugins/MockGrailsPluginManager.java index 3a464c17a53..9762ded9655 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/MockGrailsPluginManager.java +++ b/grails-core/src/main/groovy/org/grails/plugins/MockGrailsPluginManager.java @@ -18,17 +18,16 @@ */ package org.grails.plugins; +import grails.core.DefaultGrailsApplication; +import grails.core.GrailsApplication; import grails.plugins.GrailsPlugin; +import grails.plugins.exceptions.PluginException; import groovy.lang.GroovyClassLoader; import java.math.BigDecimal; import java.util.Collection; import java.util.Map; -import grails.core.DefaultGrailsApplication; -import grails.core.GrailsApplication; -import grails.plugins.exceptions.PluginException; - /** * @author Graeme Rocher * @since 0.4 diff --git a/grails-core/src/main/groovy/org/grails/plugins/PluginFilterRetriever.java b/grails-core/src/main/groovy/org/grails/plugins/PluginFilterRetriever.java index 5a695b90aac..96c35b5094a 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/PluginFilterRetriever.java +++ b/grails-core/src/main/groovy/org/grails/plugins/PluginFilterRetriever.java @@ -21,13 +21,12 @@ import grails.config.Config; import grails.config.Settings; import grails.plugins.PluginFilter; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; import java.util.Collection; import java.util.HashSet; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - /** * Implements mechanism for figuring out what PluginFilter * implementation to use based on a set of provided configuration properties. @@ -37,7 +36,6 @@ */ public class PluginFilterRetriever { - @SuppressWarnings("rawtypes") public PluginFilter getPluginFilter(Config config) { @@ -48,29 +46,25 @@ public PluginFilter getPluginFilter(Config config) { return getPluginFilter(includes, excludes); } - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) PluginFilter getPluginFilter(Object includes, Object excludes) { PluginFilter pluginFilter = null; if (includes != null) { if (includes instanceof Collection) { - pluginFilter = new IncludingPluginFilter(new HashSet((Collection)includes)); - } - else { + pluginFilter = new IncludingPluginFilter(new HashSet((Collection) includes)); + } else { String[] includesArray = StringUtils.commaDelimitedListToStringArray(includes.toString()); pluginFilter = new IncludingPluginFilter(includesArray); } - } - else if (excludes != null) { + } else if (excludes != null) { if (excludes instanceof Collection) { - pluginFilter = new ExcludingPluginFilter(new HashSet((Collection)excludes)); - } - else { + pluginFilter = new ExcludingPluginFilter(new HashSet((Collection) excludes)); + } else { String[] excludesArray = StringUtils.commaDelimitedListToStringArray(excludes.toString()); pluginFilter = new ExcludingPluginFilter(excludesArray); } - } - else { + } else { pluginFilter = new IdentityPluginFilter(); } return pluginFilter; diff --git a/grails-core/src/main/groovy/org/grails/plugins/ProfilingGrailsPluginManager.java b/grails-core/src/main/groovy/org/grails/plugins/ProfilingGrailsPluginManager.java index 93af327f43c..9f7a994b78f 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/ProfilingGrailsPluginManager.java +++ b/grails-core/src/main/groovy/org/grails/plugins/ProfilingGrailsPluginManager.java @@ -18,14 +18,14 @@ */ package org.grails.plugins; +import grails.core.GrailsApplication; import grails.plugins.DefaultGrailsPluginManager; import grails.plugins.GrailsPlugin; +import grails.plugins.exceptions.PluginException; import groovy.lang.GroovySystem; import groovy.lang.MetaClassRegistry; -import grails.core.GrailsApplication; import org.grails.core.exceptions.GrailsConfigurationException; import org.grails.spring.RuntimeSpringConfiguration; -import grails.plugins.exceptions.PluginException; import org.springframework.context.ApplicationContext; import org.springframework.core.io.Resource; @@ -72,8 +72,8 @@ public void doDynamicMethods() { checkInitialised(); // remove common meta classes just to be sure MetaClassRegistry registry = GroovySystem.getMetaClassRegistry(); - for (Class COMMON_CLASS : COMMON_CLASSES) { - registry.removeMetaClass(COMMON_CLASS); + for (Class commonClass : COMMON_CLASSES) { + registry.removeMetaClass(commonClass); } for (GrailsPlugin plugin : pluginList) { if (plugin.supportsCurrentScopeAndEnvironment()) { @@ -84,8 +84,7 @@ public void doDynamicMethods() { plugin.doWithDynamicMethods(applicationContext); System.out.println("doWithDynamicMethods for plugin [" + plugin.getName() + "] took " + (System.currentTimeMillis() - pluginTime)); - } - catch (Throwable t) { + } catch (Throwable t) { throw new GrailsConfigurationException("Error configuring dynamic methods for plugin " + plugin + ": " + t.getMessage(), t); } } diff --git a/grails-core/src/main/groovy/org/grails/plugins/core/CoreAutoConfiguration.java b/grails-core/src/main/groovy/org/grails/plugins/core/CoreAutoConfiguration.java index e914ac1b28a..3d29ed52416 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/core/CoreAutoConfiguration.java +++ b/grails-core/src/main/groovy/org/grails/plugins/core/CoreAutoConfiguration.java @@ -37,7 +37,7 @@ * @author graemerocher * @since 4.0 */ -@AutoConfiguration(before = { PropertyPlaceholderAutoConfiguration.class }) +@AutoConfiguration(before = {PropertyPlaceholderAutoConfiguration.class}) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) public class CoreAutoConfiguration { diff --git a/grails-core/src/main/groovy/org/grails/plugins/support/WatchPatternParser.java b/grails-core/src/main/groovy/org/grails/plugins/support/WatchPatternParser.java index 1677cbc460f..35ea4be305a 100644 --- a/grails-core/src/main/groovy/org/grails/plugins/support/WatchPatternParser.java +++ b/grails-core/src/main/groovy/org/grails/plugins/support/WatchPatternParser.java @@ -30,15 +30,15 @@ /** * Parses a Grails plugin's watchedResources property value into a list of * - * @since 2.0 * @author Graeme Rocher + * @since 2.0 */ public class WatchPatternParser { public static final String WILD_CARD = "*"; public List getWatchPatterns(List patterns) { - List watchPatterns = new ArrayList(); + List watchPatterns = new ArrayList(); for (String pattern : patterns) { WatchPattern watchPattern = new WatchPattern(); @@ -46,32 +46,29 @@ public List getWatchPatterns(List patterns) { boolean isClasspath = false; if (pattern.startsWith(ResourceUtils.FILE_URL_PREFIX)) { pattern = pattern.substring(ResourceUtils.FILE_URL_PREFIX.length()); - } - else if (pattern.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) { + } else if (pattern.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) { pattern = pattern.substring(ResourceUtils.CLASSPATH_URL_PREFIX.length()); isClasspath = true; } if (pattern.contains(WILD_CARD)) { String dirPath = pattern.substring(0, pattern.indexOf(WILD_CARD)); - if(!GrailsStringUtils.isBlank(dirPath)) { + if (!GrailsStringUtils.isBlank(dirPath)) { watchPattern.setDirectory(new File(dirPath)); - } - else if(isClasspath && BuildSettings.BASE_DIR != null) { + } else if (isClasspath && BuildSettings.BASE_DIR != null) { watchPattern.setDirectory(new File(BuildSettings.BASE_DIR, "src/main/resources")); } setExtension(pattern, watchPattern); watchPatterns.add(watchPattern); - } - else { + } else { setExtension(pattern, watchPattern); watchPattern.setFile(new File(pattern)); watchPatterns.add(watchPattern); } } - return watchPatterns; + return watchPatterns; } private void setExtension(String pattern, WatchPattern watchPattern) { @@ -82,8 +79,7 @@ private void setExtension(String pattern, WatchPattern watchPattern) { extension = extension.substring(1); } watchPattern.setExtension(extension); - } - else { + } else { String ext = StringUtils.getFilenameExtension(pattern); if (ext != null) { watchPattern.setExtension(ext); diff --git a/grails-core/src/main/groovy/org/grails/spring/RuntimeSpringConfigUtilities.java b/grails-core/src/main/groovy/org/grails/spring/RuntimeSpringConfigUtilities.java index 9c811577c16..5e611489168 100644 --- a/grails-core/src/main/groovy/org/grails/spring/RuntimeSpringConfigUtilities.java +++ b/grails-core/src/main/groovy/org/grails/spring/RuntimeSpringConfigUtilities.java @@ -18,6 +18,7 @@ */ package org.grails.spring; +import grails.core.GrailsApplication; import grails.spring.BeanBuilder; import grails.util.CollectionUtils; import groovy.lang.Binding; @@ -25,26 +26,23 @@ import groovy.lang.Script; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import grails.core.GrailsApplication; import org.springframework.context.support.GenericApplicationContext; import org.springframework.util.ClassUtils; -import org.grails.spring.RuntimeSpringConfiguration; /** - * @since 2.4 * @author Graeme Rocher + * @since 2.4 */ -public class RuntimeSpringConfigUtilities { +public final class RuntimeSpringConfigUtilities { - private static final Log LOG = LogFactory.getLog(RuntimeSpringConfigUtilities.class); public static final String GRAILS_URL_MAPPINGS = "grailsUrlMappings"; public static final String SPRING_RESOURCES_XML = "classpath:spring/resources.xml"; public static final String SPRING_RESOURCES_GROOVY = "classpath:spring/resources.groovy"; public static final String SPRING_RESOURCES_CLASS = "resources"; + private static final Log LOG = LogFactory.getLog(RuntimeSpringConfigUtilities.class); private static final String DEVELOPMENT_SPRING_RESOURCES_XML = "file:./grails-app/conf/spring/resources.xml"; - private static volatile BeanBuilder springGroovyResourcesBeanBuilder = null; private RuntimeSpringConfigUtilities() { @@ -66,6 +64,7 @@ private static void doLoadSpringGroovyResources(RuntimeSpringConfiguration confi /** * Loads any external Spring configuration into the given RuntimeSpringConfiguration object. + * * @param config The config instance */ public static void loadExternalSpringConfig(RuntimeSpringConfiguration config, final GrailsApplication application) { @@ -74,20 +73,17 @@ public static void loadExternalSpringConfig(RuntimeSpringConfiguration config, f Class groovySpringResourcesClass = null; try { groovySpringResourcesClass = ClassUtils.forName(SPRING_RESOURCES_CLASS, - application.getClassLoader()); - } - catch (ClassNotFoundException e) { + application.getClassLoader()); + } catch (ClassNotFoundException e) { // ignore } if (groovySpringResourcesClass != null) { reloadSpringResourcesConfig(config, application, groovySpringResourcesClass); } - } - catch (Exception ex) { + } catch (Exception ex) { LOG.error("[RuntimeConfiguration] Unable to load beans from resources.groovy", ex); } - } - else { + } else { if (!springGroovyResourcesBeanBuilder.getSpringConfig().equals(config)) { springGroovyResourcesBeanBuilder.registerBeans(config); } @@ -95,14 +91,14 @@ public static void loadExternalSpringConfig(RuntimeSpringConfiguration config, f } public static BeanBuilder reloadSpringResourcesConfig(RuntimeSpringConfiguration config, GrailsApplication application, Class groovySpringResourcesClass) throws InstantiationException, IllegalAccessException { - springGroovyResourcesBeanBuilder = new BeanBuilder(null, config,Thread.currentThread().getContextClassLoader()); + springGroovyResourcesBeanBuilder = new BeanBuilder(null, config, Thread.currentThread().getContextClassLoader()); springGroovyResourcesBeanBuilder.setBinding(new Binding(CollectionUtils.newMap( - "application", application, - "grailsApplication", application))); // GRAILS-7550 + "application", application, + "grailsApplication", application))); // GRAILS-7550 Script script = (Script) groovySpringResourcesClass.newInstance(); script.run(); Object beans = script.getProperty("beans"); - springGroovyResourcesBeanBuilder.beans((Closure)beans); + springGroovyResourcesBeanBuilder.beans((Closure) beans); return springGroovyResourcesBeanBuilder; } @@ -116,7 +112,6 @@ public static void loadSpringGroovyResourcesIntoContext(RuntimeSpringConfigurati doLoadSpringGroovyResources(config, application, context); } - /** * Resets the GrailsRumtimeConfigurator. */ diff --git a/grails-core/src/main/groovy/org/grails/spring/aop/autoproxy/GroovyAwareAspectJAwareAdvisorAutoProxyCreator.java b/grails-core/src/main/groovy/org/grails/spring/aop/autoproxy/GroovyAwareAspectJAwareAdvisorAutoProxyCreator.java index a5ee29027cc..4212e10d98e 100644 --- a/grails-core/src/main/groovy/org/grails/spring/aop/autoproxy/GroovyAwareAspectJAwareAdvisorAutoProxyCreator.java +++ b/grails-core/src/main/groovy/org/grails/spring/aop/autoproxy/GroovyAwareAspectJAwareAdvisorAutoProxyCreator.java @@ -20,10 +20,6 @@ import groovy.lang.GroovyObject; import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator; -import org.springframework.aop.config.AopConfigUtils; - -import java.lang.reflect.Field; -import java.util.List; /** * Enables AspectJ weaving from the application context. @@ -33,8 +29,6 @@ */ public class GroovyAwareAspectJAwareAdvisorAutoProxyCreator extends AnnotationAwareAspectJAutoProxyCreator { - - private static final long serialVersionUID = 1; @Override diff --git a/grails-core/src/main/groovy/org/grails/spring/beans/ClassLoaderAwareBeanPostProcessor.java b/grails-core/src/main/groovy/org/grails/spring/beans/ClassLoaderAwareBeanPostProcessor.java index fe8b58e6fa2..1e656832a85 100644 --- a/grails-core/src/main/groovy/org/grails/spring/beans/ClassLoaderAwareBeanPostProcessor.java +++ b/grails-core/src/main/groovy/org/grails/spring/beans/ClassLoaderAwareBeanPostProcessor.java @@ -32,7 +32,7 @@ public ClassLoaderAwareBeanPostProcessor(ClassLoader classLoader) { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof ClassLoaderAware) { - ((ClassLoaderAware)bean).setClassLoader(classLoader); + ((ClassLoaderAware) bean).setClassLoader(classLoader); } return bean; } diff --git a/grails-core/src/main/groovy/org/grails/spring/beans/GrailsApplicationAwareBeanPostProcessor.java b/grails-core/src/main/groovy/org/grails/spring/beans/GrailsApplicationAwareBeanPostProcessor.java index 7ade08e7392..eb195dbbfcb 100644 --- a/grails-core/src/main/groovy/org/grails/spring/beans/GrailsApplicationAwareBeanPostProcessor.java +++ b/grails-core/src/main/groovy/org/grails/spring/beans/GrailsApplicationAwareBeanPostProcessor.java @@ -47,10 +47,10 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro public static void processAwareInterfaces(GrailsApplication grailsApplication, Object bean) { if (bean instanceof GrailsApplicationAware) { - ((GrailsApplicationAware)bean).setGrailsApplication(grailsApplication); + ((GrailsApplicationAware) bean).setGrailsApplication(grailsApplication); } if (bean instanceof GrailsConfigurationAware) { - ((GrailsConfigurationAware)bean).setConfiguration(grailsApplication.getConfig()); + ((GrailsConfigurationAware) bean).setConfiguration(grailsApplication.getConfig()); } } } diff --git a/grails-core/src/main/groovy/org/grails/spring/beans/PluginManagerAwareBeanPostProcessor.java b/grails-core/src/main/groovy/org/grails/spring/beans/PluginManagerAwareBeanPostProcessor.java index e2ae41fca03..9ed49ed36ab 100644 --- a/grails-core/src/main/groovy/org/grails/spring/beans/PluginManagerAwareBeanPostProcessor.java +++ b/grails-core/src/main/groovy/org/grails/spring/beans/PluginManagerAwareBeanPostProcessor.java @@ -34,9 +34,9 @@ public class PluginManagerAwareBeanPostProcessor extends BeanPostProcessorAdapte private GrailsPluginManager pluginManager; private BeanFactory beanFactory; - + public PluginManagerAwareBeanPostProcessor() { - + } public PluginManagerAwareBeanPostProcessor(GrailsPluginManager pluginManager) { @@ -45,15 +45,15 @@ public PluginManagerAwareBeanPostProcessor(GrailsPluginManager pluginManager) { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - if(pluginManager == null) { - if(beanFactory.containsBean(GrailsPluginManager.BEAN_NAME)) { + if (pluginManager == null) { + if (beanFactory.containsBean(GrailsPluginManager.BEAN_NAME)) { pluginManager = beanFactory.getBean(GrailsPluginManager.BEAN_NAME, GrailsPluginManager.class); } } - if(pluginManager != null) { + if (pluginManager != null) { if (bean instanceof PluginManagerAware) { - ((PluginManagerAware)bean).setPluginManager(pluginManager); + ((PluginManagerAware) bean).setPluginManager(pluginManager); } } @@ -64,6 +64,5 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } - - + } diff --git a/grails-core/src/main/groovy/org/grails/spring/beans/factory/GenericBeanFactoryAccessor.java b/grails-core/src/main/groovy/org/grails/spring/beans/factory/GenericBeanFactoryAccessor.java index 68cff209398..620f56bfdec 100644 --- a/grails-core/src/main/groovy/org/grails/spring/beans/factory/GenericBeanFactoryAccessor.java +++ b/grails-core/src/main/groovy/org/grails/spring/beans/factory/GenericBeanFactoryAccessor.java @@ -15,10 +15,6 @@ */ package org.grails.spring.beans.factory; -import java.lang.annotation.Annotation; -import java.util.LinkedHashMap; -import java.util.Map; - import org.springframework.beans.BeansException; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.config.BeanDefinition; @@ -27,6 +23,10 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.Assert; +import java.lang.annotation.Annotation; +import java.util.LinkedHashMap; +import java.util.Map; + /** * A fork of the Spring 2.5.6 GenericBeanFactoryAccess class that was removed from Spring 3.0. * @@ -89,6 +89,7 @@ public Map getBeansOfType(Class type, boolean includeNonSingle /** * Find all beans whose Class has the supplied {@link Annotation} type. + * * @param annotationType the type of annotation to look for * @return a Map with the matching beans, containing the bean names as * keys and the corresponding bean instances as values @@ -108,7 +109,8 @@ public Map getBeansWithAnnotation(Class an * bean, traversing its interfaces and super classes if no annotation can be * found on the given class itself, as well as checking its raw bean class * if not found on the exposed bean reference (e.g. in case of a proxy). - * @param beanName the name of the bean to look for annotations on + * + * @param beanName the name of the bean to look for annotations on * @param annotationType the annotation class to look for * @return the annotation of the given type found, or null * @see org.springframework.core.annotation.AnnotationUtils#findAnnotation(Class, Class) diff --git a/grails-core/src/main/groovy/org/grails/spring/beans/factory/HotSwappableTargetSourceFactoryBean.groovy b/grails-core/src/main/groovy/org/grails/spring/beans/factory/HotSwappableTargetSourceFactoryBean.groovy index db81fd06e65..baaa4f73817 100644 --- a/grails-core/src/main/groovy/org/grails/spring/beans/factory/HotSwappableTargetSourceFactoryBean.groovy +++ b/grails-core/src/main/groovy/org/grails/spring/beans/factory/HotSwappableTargetSourceFactoryBean.groovy @@ -31,10 +31,10 @@ import org.springframework.beans.factory.InitializingBean */ @CompileStatic class HotSwappableTargetSourceFactoryBean implements FactoryBean, InitializingBean { + protected HotSwappableTargetSource targetSource protected Object target - @Override HotSwappableTargetSource getObject() throws Exception { return targetSource diff --git a/grails-core/src/main/groovy/org/grails/spring/beans/factory/InstanceFactoryBean.java b/grails-core/src/main/groovy/org/grails/spring/beans/factory/InstanceFactoryBean.java index ce035d0dbdf..faf818aeb92 100644 --- a/grails-core/src/main/groovy/org/grails/spring/beans/factory/InstanceFactoryBean.java +++ b/grails-core/src/main/groovy/org/grails/spring/beans/factory/InstanceFactoryBean.java @@ -16,25 +16,25 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.spring.beans.factory; import org.springframework.beans.factory.FactoryBean; /** * Simple singleton instance implementation of Spring's FactoryBean interface - * + *

* mainly useful in unit tests - * + * */ public class InstanceFactoryBean implements FactoryBean { + T object; Class objectType; - + public InstanceFactoryBean() { - + } - + public InstanceFactoryBean(T object, Class objectType) { this.object = object; this.objectType = objectType; @@ -55,7 +55,6 @@ public T getObject() { return object; } - public void setObject(T object) { this.object = object; } diff --git a/grails-core/src/main/groovy/org/grails/spring/context/ApplicationContextExtension.groovy b/grails-core/src/main/groovy/org/grails/spring/context/ApplicationContextExtension.groovy index a4c781a762e..c5b739b651e 100644 --- a/grails-core/src/main/groovy/org/grails/spring/context/ApplicationContextExtension.groovy +++ b/grails-core/src/main/groovy/org/grails/spring/context/ApplicationContextExtension.groovy @@ -37,11 +37,10 @@ class ApplicationContextExtension { * @param name The bean name * @return */ - public static Object propertyMissing(ApplicationContext applicationContext, String name ) { - if(applicationContext.containsBean(name)) { + public static Object propertyMissing(ApplicationContext applicationContext, String name) { + if (applicationContext.containsBean(name)) { return applicationContext.getBean(name); - } - else { + } else { return null; } } diff --git a/grails-core/src/main/groovy/org/grails/spring/context/annotation/ClosureClassIgnoringComponentScanBeanDefinitionParser.java b/grails-core/src/main/groovy/org/grails/spring/context/annotation/ClosureClassIgnoringComponentScanBeanDefinitionParser.java index da487063ae7..62fcc0e86fb 100644 --- a/grails-core/src/main/groovy/org/grails/spring/context/annotation/ClosureClassIgnoringComponentScanBeanDefinitionParser.java +++ b/grails-core/src/main/groovy/org/grails/spring/context/annotation/ClosureClassIgnoringComponentScanBeanDefinitionParser.java @@ -18,23 +18,12 @@ */ package org.grails.spring.context.annotation; +import grails.plugins.GrailsPluginManager; import grails.util.BuildSettings; import grails.util.Environment; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.net.URL; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - +import grails.util.GrailsStringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import grails.util.GrailsStringUtils; -import grails.plugins.GrailsPluginManager; import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.HierarchicalBeanFactory; @@ -51,6 +40,16 @@ import org.springframework.util.ReflectionUtils; import org.w3c.dom.Element; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + /** * Extends Spring's default <context:component-scan/> element to ignore * generated classes. @@ -87,6 +86,83 @@ protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerCo return scanner; } + @Override + protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) { + final ClassPathBeanDefinitionScanner scanner = super.configureScanner(parserContext, element); + + final ResourceLoader originalResourceLoader = parserContext.getReaderContext().getResourceLoader(); + if (LOG.isDebugEnabled()) { + LOG.debug("Scanning only this classloader:" + originalResourceLoader.getClassLoader()); + } + + ResourceLoader parentOnlyResourceLoader; + try { + parentOnlyResourceLoader = new ResourceLoader() { + ClassLoader parentOnlyGetResourcesClassLoader = new ParentOnlyGetResourcesClassLoader(originalResourceLoader.getClassLoader()); + + public Resource getResource(String location) { + return originalResourceLoader.getResource(location); + } + + public ClassLoader getClassLoader() { + return parentOnlyGetResourcesClassLoader; + } + }; + } catch (Throwable t) { + // restrictive classloading environment, use the original + parentOnlyResourceLoader = originalResourceLoader; + } + + final PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(parentOnlyResourceLoader) { + @Override + protected Resource[] findAllClassPathResources(String location) throws IOException { + Set result = new LinkedHashSet(16); + + if (BuildSettings.CLASSES_DIR != null) { + @SuppressWarnings("unused") + URL classesDir = BuildSettings.CLASSES_DIR.toURI().toURL(); + + // only scan classes from project classes directory + String path = location; + if (path.startsWith("/")) { + path = path.substring(1); + } + Enumeration resourceUrls = getClassLoader().getResources(path); + while (resourceUrls.hasMoreElements()) { + URL url = resourceUrls.nextElement(); + if (LOG.isDebugEnabled()) { + LOG.debug("Scanning URL " + url.toExternalForm() + " while searching for '" + location + "'"); + } + /* + if (!warDeployed && classesDir!= null && url.equals(classesDir)) { + result.add(convertClassLoaderURL(url)); + } + else if (warDeployed) { + result.add(convertClassLoaderURL(url)); + } + */ + result.add(convertClassLoaderURL(url)); + } + } + return result.toArray(new Resource[result.size()]); + } + }; + resourceResolver.setPathMatcher(new AntPathMatcher() { + @Override + public boolean match(String pattern, String path) { + if (path.endsWith(".class")) { + String filename = GrailsStringUtils.getFileBasename(path); + if (filename.contains("$")) { + return false; + } + } + return super.match(pattern, path); + } + }); + scanner.setResourceLoader(resourceResolver); + return scanner; + } + /** * This ClassLoader is used to restrict getResources & getResource methods only to the * parent ClassLoader. getResources/getResource usually search all parent level classloaders. @@ -95,8 +171,9 @@ protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerCo * @author Lari Hotari */ private static final class ParentOnlyGetResourcesClassLoader extends ClassLoader { - private final Method findResourcesMethod=ReflectionUtils.findMethod(ClassLoader.class, "findResources", String.class); - private final Method findResourceMethod=ReflectionUtils.findMethod(ClassLoader.class, "findResource", String.class); + + private final Method findResourcesMethod = ReflectionUtils.findMethod(ClassLoader.class, "findResources", String.class); + private final Method findResourceMethod = ReflectionUtils.findMethod(ClassLoader.class, "findResource", String.class); private ClassLoader rootLoader; @@ -109,10 +186,9 @@ public ParentOnlyGetResourcesClassLoader(ClassLoader parent) { @Override public Enumeration getResources(String name) throws IOException { - if(Environment.isFork()) { + if (Environment.isFork()) { return super.getResources(name); - } - else { + } else { if (rootLoader != null) { // search all parents up to rootLoader Collection urls = new LinkedHashSet(); @@ -136,15 +212,14 @@ private void findResourcesRecursive(ClassLoader parent, String name, Collection< @SuppressWarnings("unchecked") private Enumeration invokeFindResources(ClassLoader parent, String name) { - return (Enumeration)ReflectionUtils.invokeMethod(findResourcesMethod, parent, name); + return (Enumeration) ReflectionUtils.invokeMethod(findResourcesMethod, parent, name); } @Override public URL getResource(String name) { - if(Environment.isFork()) { + if (Environment.isFork()) { return super.getResource(name); - } - else { + } else { if (rootLoader != null) { return findResourceRecursive(getParent(), name); } @@ -167,83 +242,7 @@ private URL findResourceRecursive(ClassLoader parent, String name) { } private URL invokeFindResource(ClassLoader parent, String name) { - return (URL)ReflectionUtils.invokeMethod(findResourceMethod, parent, name); - } - } - - @Override - protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) { - final ClassPathBeanDefinitionScanner scanner = super.configureScanner(parserContext, element); - - final ResourceLoader originalResourceLoader = parserContext.getReaderContext().getResourceLoader(); - if (LOG.isDebugEnabled()) { - LOG.debug("Scanning only this classloader:" + originalResourceLoader.getClassLoader()); - } - - ResourceLoader parentOnlyResourceLoader; - try { - parentOnlyResourceLoader = new ResourceLoader() { - ClassLoader parentOnlyGetResourcesClassLoader = new ParentOnlyGetResourcesClassLoader(originalResourceLoader.getClassLoader()); - - public Resource getResource(String location) { - return originalResourceLoader.getResource(location); - } - - public ClassLoader getClassLoader() { - return parentOnlyGetResourcesClassLoader; - } - }; + return (URL) ReflectionUtils.invokeMethod(findResourceMethod, parent, name); } - catch (Throwable t) { - // restrictive classloading environment, use the original - parentOnlyResourceLoader = originalResourceLoader; - } - - final PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(parentOnlyResourceLoader) { - @Override - protected Resource[] findAllClassPathResources(String location) throws IOException { - Set result = new LinkedHashSet(16); - - if(BuildSettings.CLASSES_DIR != null) { - @SuppressWarnings("unused") - URL classesDir = BuildSettings.CLASSES_DIR.toURI().toURL(); - - // only scan classes from project classes directory - String path = location; - if (path.startsWith("/")) { - path = path.substring(1); - } - Enumeration resourceUrls = getClassLoader().getResources(path); - while (resourceUrls.hasMoreElements()) { - URL url = resourceUrls.nextElement(); - if (LOG.isDebugEnabled()) { - LOG.debug("Scanning URL " + url.toExternalForm() + " while searching for '" + location + "'"); - } - /* - if (!warDeployed && classesDir!= null && url.equals(classesDir)) { - result.add(convertClassLoaderURL(url)); - } - else if (warDeployed) { - result.add(convertClassLoaderURL(url)); - } - */ - result.add(convertClassLoaderURL(url)); - } - } - return result.toArray(new Resource[result.size()]); - } - }; - resourceResolver.setPathMatcher(new AntPathMatcher() { - @Override - public boolean match(String pattern, String path) { - if (path.endsWith(".class")) { - String filename = GrailsStringUtils.getFileBasename(path); - if (filename.contains("$")) return false; - } - return super.match(pattern, path); - } - }); - scanner.setResourceLoader(resourceResolver); - return scanner; } } diff --git a/grails-core/src/main/groovy/org/grails/spring/context/annotation/grails-context.xsd b/grails-core/src/main/groovy/org/grails/spring/context/annotation/grails-context.xsd index ed284553ea3..a213586f57b 100644 --- a/grails-core/src/main/groovy/org/grails/spring/context/annotation/grails-context.xsd +++ b/grails-core/src/main/groovy/org/grails/spring/context/annotation/grails-context.xsd @@ -7,7 +7,7 @@ ~ (the "License"); you may not use this file except in compliance with ~ the License. You may obtain a copy of the License at ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ 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, @@ -25,7 +25,6 @@ - mapVal) { - if(mapVal instanceof Config) return; + if (mapVal instanceof Config) { + return; + } super.visitMap(mapVal); } }; @@ -101,8 +101,7 @@ protected void visitMap(Map mapVal) { BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName); try { visitor.visitBeanDefinition(bd); - } - catch (Exception ex) { + } catch (Exception ex) { throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage(), ex); } } diff --git a/grails-core/src/main/groovy/org/grails/spring/context/support/MapBasedSmartPropertyOverrideConfigurer.groovy b/grails-core/src/main/groovy/org/grails/spring/context/support/MapBasedSmartPropertyOverrideConfigurer.groovy index e41b3993a71..d554ea62cfa 100644 --- a/grails-core/src/main/groovy/org/grails/spring/context/support/MapBasedSmartPropertyOverrideConfigurer.groovy +++ b/grails-core/src/main/groovy/org/grails/spring/context/support/MapBasedSmartPropertyOverrideConfigurer.groovy @@ -18,20 +18,16 @@ */ package org.grails.spring.context.support -import grails.config.Config +import grails.core.GrailsApplication import grails.core.support.GrailsApplicationAware import groovy.transform.CompileStatic import groovy.transform.TypeCheckingMode -import grails.core.GrailsApplication +import org.springframework.beans.factory.FactoryBean import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.config.BeanDefinition import org.springframework.beans.factory.config.BeanFactoryPostProcessor import org.springframework.beans.factory.config.ConfigurableListableBeanFactory -import org.springframework.beans.factory.config.BeanDefinition - import org.springframework.transaction.interceptor.TransactionProxyFactoryBean -import org.springframework.beans.factory.FactoryBean - -import org.springframework.beans.factory.BeanCreationException /** * Applies property configuration from a Map with bean names as keys and bean properties as name/value Maps diff --git a/grails-core/src/main/groovy/org/grails/spring/context/support/PluginAwareResourceBundleMessageSource.java b/grails-core/src/main/groovy/org/grails/spring/context/support/PluginAwareResourceBundleMessageSource.java index b070f4cffde..84170b8c0a9 100644 --- a/grails-core/src/main/groovy/org/grails/spring/context/support/PluginAwareResourceBundleMessageSource.java +++ b/grails-core/src/main/groovy/org/grails/spring/context/support/PluginAwareResourceBundleMessageSource.java @@ -57,6 +57,7 @@ * @since 1.1 */ public class PluginAwareResourceBundleMessageSource extends ReloadableResourceBundleMessageSource implements GrailsApplicationAware, PluginManagerAware, InitializingBean { + private static final String GRAILS_APP_I18N_PATH_COMPONENT = "/grails-app/i18n/"; protected GrailsApplication application; protected GrailsPluginManager pluginManager; @@ -93,47 +94,42 @@ public void afterPropertiesSet() throws Exception { if (pluginCacheMillis == Long.MIN_VALUE) { pluginCacheMillis = cacheMillis; } - + if (localResourceLoader == null) { return; } Resource[] resources; - if(Environment.isDevelopmentEnvironmentAvailable()) { + if (Environment.isDevelopmentEnvironmentAvailable()) { File[] propertiesFiles = new File(BuildSettings.BASE_DIR, GRAILS_APP_I18N_PATH_COMPONENT).listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.endsWith(".properties"); } }); - if(propertiesFiles != null && propertiesFiles.length > 0) { + if (propertiesFiles != null && propertiesFiles.length > 0) { List resourceList = new ArrayList(propertiesFiles.length); for (File propertiesFile : propertiesFiles) { resourceList.add(new FileSystemResource(propertiesFile)); } resources = resourceList.toArray(new Resource[resourceList.size()]); - } - else { + } else { resources = new Resource[0]; } - } - else { - if(searchClasspath) { + } else { + if (searchClasspath) { resources = resourceResolver.getResources(messageBundleLocationPattern); - } - else { + } else { DefaultGrailsApplication defaultGrailsApplication = (DefaultGrailsApplication) application; - if(defaultGrailsApplication != null) { + if (defaultGrailsApplication != null) { GrailsApplicationClass applicationClass = defaultGrailsApplication.getApplicationClass(); - if(applicationClass != null) { + if (applicationClass != null) { ResourcePatternResolver resourcePatternResolver = new ClassRelativeResourcePatternResolver(applicationClass.getClass()); resources = resourcePatternResolver.getResources(messageBundleLocationPattern); - } - else { + } else { resources = resourceResolver.getResources(messageBundleLocationPattern); } - } - else { + } else { resources = resourceResolver.getResources(messageBundleLocationPattern); } } @@ -144,18 +140,18 @@ public boolean accept(File dir, String name) { String filename = resource.getFilename(); String baseName = GrailsStringUtils.getFileBasename(filename); int i = baseName.indexOf('_'); - if(i > -1) { + if (i > -1) { baseName = baseName.substring(0, i); } - if(!basenames.contains(baseName) && !baseName.equals("")) + if (!basenames.contains(baseName) && !baseName.equals("")) { basenames.add(baseName); + } } - setBasenames(basenames.toArray( new String[basenames.size()])); + setBasenames(basenames.toArray(new String[basenames.size()])); } - @Override protected String resolveCodeWithoutArguments(String code, Locale locale) { String msg = super.resolveCodeWithoutArguments(code, locale); @@ -191,7 +187,7 @@ public PropertiesHolder call() throws Exception { /** * Attempts to resolve a String for the code from the list of plugin base names * - * @param code The code + * @param code The code * @param locale The locale * @return a MessageFormat */ @@ -202,15 +198,16 @@ protected String resolveCodeWithoutArgumentsFromPlugins(String code, Locale loca if (result != null) { return result; } - } - else { + } else { String result = findCodeInBinaryPlugins(code, locale); - if (result != null) return result; + if (result != null) { + return result; + } } return null; } - + protected PropertiesHolder getMergedBinaryPluginProperties(final Locale locale) { return CacheEntry.getValue(cachedMergedBinaryPluginProperties, locale, cacheMillis, new Callable() { @Override @@ -248,7 +245,7 @@ private MessageFormat findMessageFormatInBinaryPlugins(String code, Locale local /** * Attempts to resolve a MessageFormat for the code from the list of plugin base names * - * @param code The code + * @param code The code * @param locale The locale * @return a MessageFormat */ @@ -259,10 +256,11 @@ protected MessageFormat resolveCodeFromPlugins(String code, Locale locale) { if (result != null) { return result; } - } - else { + } else { MessageFormat result = findMessageFormatInBinaryPlugins(code, locale); - if (result != null) return result; + if (result != null) { + return result; + } } return null; } @@ -277,7 +275,6 @@ public void setResourceLoader(ResourceLoader resourceLoader) { } } - /** * Set the number of seconds to cache the list of matching properties files loaded from plugin. *

    diff --git a/grails-core/src/main/groovy/org/grails/spring/context/support/ReloadableResourceBundleMessageSource.java b/grails-core/src/main/groovy/org/grails/spring/context/support/ReloadableResourceBundleMessageSource.java index 5855f521528..3311aa17985 100644 --- a/grails-core/src/main/groovy/org/grails/spring/context/support/ReloadableResourceBundleMessageSource.java +++ b/grails-core/src/main/groovy/org/grails/spring/context/support/ReloadableResourceBundleMessageSource.java @@ -20,19 +20,8 @@ import grails.util.CacheEntry; import grails.util.Pair; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.text.MessageFormat; -import java.util.*; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - import org.springframework.context.ResourceLoaderAware; import org.springframework.context.support.AbstractMessageSource; -import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; @@ -41,19 +30,34 @@ import org.springframework.util.PropertiesPersister; import org.springframework.util.StringUtils; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + /** * Spring-specific {@link org.springframework.context.MessageSource} implementation * that accesses resource bundles using specified basenames, participating in the * Spring {@link org.springframework.context.ApplicationContext}'s resource loading. * - *

    In contrast to the JDK-based {@link ResourceBundleMessageSource}, this class uses + *

    In contrast to the JDK-based {@link org.springframework.context.support.ResourceBundleMessageSource}, this class uses * {@link java.util.Properties} instances as its custom data structure for messages, * loading them via a {@link org.springframework.util.PropertiesPersister} strategy * from Spring {@link Resource} handles. This strategy is not only capable of * reloading files based on timestamp changes, but also of loading properties files * with a specific character encoding. It will detect XML property files as well. * - *

    In contrast to {@link ResourceBundleMessageSource}, this class supports + *

    In contrast to {@link org.springframework.context.support.ResourceBundleMessageSource}, this class supports * reloading of properties files through the {@link #setCacheSeconds "cacheSeconds"} * setting, and also through programmatically clearing the properties cache. * Since application servers typically cache all files loaded from the classpath, @@ -63,14 +67,14 @@ * *

    Note that the base names set as {@link #setBasenames "basenames"} property * are treated in a slightly different fashion than the "basenames" property of - * {@link ResourceBundleMessageSource}. It follows the basic ResourceBundle rule of not + * {@link org.springframework.context.support.ResourceBundleMessageSource}. It follows the basic ResourceBundle rule of not * specifying file extension or language codes, but can refer to any Spring resource * location (instead of being restricted to classpath resources). With a "classpath:" * prefix, resources can still be loaded from the classpath, but "cacheSeconds" values * other than "-1" (caching forever) will not work in this case. * *

    This MessageSource implementation is usually slightly faster than - * {@link ResourceBundleMessageSource}, which builds on {@link java.util.ResourceBundle} + * {@link org.springframework.context.support.ResourceBundleMessageSource}, which builds on {@link java.util.ResourceBundle} * - in the default mode, i.e. when caching forever. With "cacheSeconds" set to 1, * message lookup takes about twice as long - with the benefit that changes in * individual properties files are detected with a maximum delay of 1 second. @@ -98,330 +102,334 @@ * @see ResourceBundleMessageSource * @see java.util.ResourceBundle */ -public class ReloadableResourceBundleMessageSource extends AbstractMessageSource - implements ResourceLoaderAware { +public class ReloadableResourceBundleMessageSource extends AbstractMessageSource implements ResourceLoaderAware { - private static final String PROPERTIES_SUFFIX = ".properties"; + private static final String PROPERTIES_SUFFIX = ".properties"; - private static final String XML_SUFFIX = ".xml"; + private static final String XML_SUFFIX = ".xml"; + protected long cacheMillis = -1; - private String[] basenames = new String[0]; + protected long fileCacheMillis = Long.MIN_VALUE; - private String defaultEncoding; + private String[] basenames = new String[0]; - private Properties fileEncodings; + private String defaultEncoding; - private boolean fallbackToSystemLocale = true; + private Properties fileEncodings; - protected long cacheMillis = -1; + private boolean fallbackToSystemLocale = true; - protected long fileCacheMillis = Long.MIN_VALUE; + private PropertiesPersister propertiesPersister = new DefaultPropertiesPersister(); + + private ResourceLoader resourceLoader = new DefaultResourceLoader(); + + /** + * Cache to hold filename lists per Locale + */ + private final ConcurrentMap, CacheEntry>>> cachedFilenames = new ConcurrentHashMap, CacheEntry>>>(); + + /** + * Cache to hold already loaded properties per filename + */ + private final ConcurrentMap> cachedProperties = new ConcurrentHashMap>(); - private PropertiesPersister propertiesPersister = new DefaultPropertiesPersister(); - - private ResourceLoader resourceLoader = new DefaultResourceLoader(); - - /** Cache to hold filename lists per Locale */ - private final ConcurrentMap, CacheEntry>>> cachedFilenames = - new ConcurrentHashMap, CacheEntry>>>(); - - /** Cache to hold already loaded properties per filename */ - private final ConcurrentMap> cachedProperties = new ConcurrentHashMap>(); - - /** Cache to hold merged loaded properties per locale */ - private final ConcurrentMap> cachedMergedProperties = new ConcurrentHashMap>(); - - private final ConcurrentMap> cachedResources = new ConcurrentHashMap>(); - - - /** - * Set a single basename, following the basic ResourceBundle convention of - * not specifying file extension or language codes, but in contrast to - * {@link ResourceBundleMessageSource} referring to a Spring resource location: - * e.g. "WEB-INF/messages" for "WEB-INF/messages.properties", - * "WEB-INF/messages_en.properties", etc. - *

    XML properties files are also supported: .g. "WEB-INF/messages" will find - * and load "WEB-INF/messages.xml", "WEB-INF/messages_en.xml", etc as well. - * @param basename the single basename - * @see #setBasenames - * @see org.springframework.core.io.ResourceEditor - * @see java.util.ResourceBundle - */ - public void setBasename(String basename) { - setBasenames(basename); - } - - /** - * Retrieves all codes from one or multiple basenames - * @param locale the locale - * @param basenames the basenames of the bundle - * @return a list with all codes from valid registered bundles - */ - public Set getBundleCodes(Locale locale,String...basenames){ - List validBaseNames = getValidBasenames(basenames); - - Set codes = new HashSet<>(); - for(String basename: validBaseNames){ - List> filenamesAndResources = calculateAllFilenames(basename,locale); - for (Pair filenameAndResource : filenamesAndResources) { - if(filenameAndResource.getbValue() != null) { - PropertiesHolder propHolder = getProperties(filenameAndResource.getaValue(), filenameAndResource.getbValue()); - codes.addAll(propHolder.getProperties().stringPropertyNames()); - } - } - } - return codes; - } - - protected List getValidBasenames(String[] basenames){ - List validBaseNames = new LinkedList<>(); - for(String basename:basenames){ - for(int i=0;iXML properties files are also supported: .g. "WEB-INF/messages" will find - * and load "WEB-INF/messages.xml", "WEB-INF/messages_en.xml", etc as well. - *

    The associated resource bundles will be checked sequentially when resolving - * a message code. Note that message definitions in a previous resource - * bundle will override ones in a later bundle, due to the sequential lookup. - * @param basenames an array of basenames - * @see #setBasename - * @see java.util.ResourceBundle - */ - public void setBasenames(String... basenames) { - if (basenames != null) { - this.basenames = new String[basenames.length]; - for (int i = 0; i < basenames.length; i++) { - String basename = basenames[i]; - Assert.hasText(basename, "Basename must not be empty"); - this.basenames[i] = basename.trim(); - } - } - else { - this.basenames = new String[0]; - } - } - - /** - * Set the default charset to use for parsing properties files. - * Used if no file-specific charset is specified for a file. - *

    Default is none, using the {@code java.util.Properties} - * default encoding: ISO-8859-1. - *

    Only applies to classic properties files, not to XML files. - * @param defaultEncoding the default charset - * @see #setFileEncodings - * @see org.springframework.util.PropertiesPersister#load - */ - public void setDefaultEncoding(String defaultEncoding) { - this.defaultEncoding = defaultEncoding; - } - - /** - * Set per-file charsets to use for parsing properties files. - *

    Only applies to classic properties files, not to XML files. - * @param fileEncodings Properties with filenames as keys and charset - * names as values. Filenames have to match the basename syntax, - * with optional locale-specific appendices: e.g. "WEB-INF/messages" - * or "WEB-INF/messages_en". - * @see #setBasenames - * @see org.springframework.util.PropertiesPersister#load - */ - public void setFileEncodings(Properties fileEncodings) { - this.fileEncodings = fileEncodings; - } - - /** - * Set whether to fall back to the system Locale if no files for a specific - * Locale have been found. Default is "true"; if this is turned off, the only - * fallback will be the default file (e.g. "messages.properties" for - * basename "messages"). - *

    Falling back to the system Locale is the default behavior of - * {@code java.util.ResourceBundle}. However, this is often not desirable - * in an application server environment, where the system Locale is not relevant - * to the application at all: Set this flag to "false" in such a scenario. - */ - public void setFallbackToSystemLocale(boolean fallbackToSystemLocale) { - this.fallbackToSystemLocale = fallbackToSystemLocale; - } - - /** - * Set the number of seconds to cache the list of matching properties files. - *

      - *
    • Default is "-1", indicating to cache forever (just like - * {@code java.util.ResourceBundle}). - *
    • A positive number will cache the list of matching properties files for the given - * number of seconds. This is essentially the interval between refresh checks. - *
    • A value of "0" will attemp to list the matching properties files on - * every message access. Do not use this in a production environment! - *
    - */ - public void setCacheSeconds(int cacheSeconds) { - this.cacheMillis = (cacheSeconds * 1000); - if(fileCacheMillis==Long.MIN_VALUE) { - this.fileCacheMillis = this.cacheMillis; - } - } - - /** + /** + * Cache to hold merged loaded properties per locale + */ + private final ConcurrentMap> cachedMergedProperties = new ConcurrentHashMap>(); + + private final ConcurrentMap> cachedResources = new ConcurrentHashMap>(); + + /** + * Set a single basename, following the basic ResourceBundle convention of + * not specifying file extension or language codes, but in contrast to + * {@link org.springframework.context.support.ResourceBundleMessageSource} referring to a Spring resource location: + * e.g. "WEB-INF/messages" for "WEB-INF/messages.properties", + * "WEB-INF/messages_en.properties", etc. + *

    XML properties files are also supported: .g. "WEB-INF/messages" will find + * and load "WEB-INF/messages.xml", "WEB-INF/messages_en.xml", etc as well. + * + * @param basename the single basename + * @see #setBasenames + * @see org.springframework.core.io.ResourceEditor + * @see java.util.ResourceBundle + */ + public void setBasename(String basename) { + setBasenames(basename); + } + + /** + * Retrieves all codes from one or multiple basenames + * + * @param locale the locale + * @param basenames the basenames of the bundle + * @return a list with all codes from valid registered bundles + */ + public Set getBundleCodes(Locale locale, String... basenames) { + List validBaseNames = getValidBasenames(basenames); + + Set codes = new HashSet<>(); + for (String basename : validBaseNames) { + List> filenamesAndResources = calculateAllFilenames(basename, locale); + for (Pair filenameAndResource : filenamesAndResources) { + if (filenameAndResource.getbValue() != null) { + PropertiesHolder propHolder = getProperties(filenameAndResource.getaValue(), filenameAndResource.getbValue()); + codes.addAll(propHolder.getProperties().stringPropertyNames()); + } + } + } + return codes; + } + + protected List getValidBasenames(String[] basenames) { + List validBaseNames = new LinkedList<>(); + for (String basename : basenames) { + for (int i = 0; i < this.basenames.length; i++) { + if (basenames[i].equals(basename)) { + validBaseNames.add(basename); + break; + } + } + } + return validBaseNames; + } + + /** + * Set an array of basenames, each following the basic ResourceBundle convention + * of not specifying file extension or language codes, but in contrast to + * {@link org.springframework.context.support.ResourceBundleMessageSource} referring to a Spring resource location: + * e.g. "WEB-INF/messages" for "WEB-INF/messages.properties", + * "WEB-INF/messages_en.properties", etc. + *

    XML properties files are also supported: .g. "WEB-INF/messages" will find + * and load "WEB-INF/messages.xml", "WEB-INF/messages_en.xml", etc as well. + *

    The associated resource bundles will be checked sequentially when resolving + * a message code. Note that message definitions in a previous resource + * bundle will override ones in a later bundle, due to the sequential lookup. + * + * @param basenames an array of basenames + * @see #setBasename + * @see java.util.ResourceBundle + */ + public void setBasenames(String... basenames) { + if (basenames != null) { + this.basenames = new String[basenames.length]; + for (int i = 0; i < basenames.length; i++) { + String basename = basenames[i]; + Assert.hasText(basename, "Basename must not be empty"); + this.basenames[i] = basename.trim(); + } + } else { + this.basenames = new String[0]; + } + } + + /** + * Set the default charset to use for parsing properties files. + * Used if no file-specific charset is specified for a file. + *

    Default is none, using the {@code java.util.Properties} + * default encoding: ISO-8859-1. + *

    Only applies to classic properties files, not to XML files. + * + * @param defaultEncoding the default charset + * @see #setFileEncodings + * @see org.springframework.util.PropertiesPersister#load + */ + public void setDefaultEncoding(String defaultEncoding) { + this.defaultEncoding = defaultEncoding; + } + + /** + * Set per-file charsets to use for parsing properties files. + *

    Only applies to classic properties files, not to XML files. + * + * @param fileEncodings Properties with filenames as keys and charset + * names as values. Filenames have to match the basename syntax, + * with optional locale-specific appendices: e.g. "WEB-INF/messages" + * or "WEB-INF/messages_en". + * @see #setBasenames + * @see org.springframework.util.PropertiesPersister#load + */ + public void setFileEncodings(Properties fileEncodings) { + this.fileEncodings = fileEncodings; + } + + /** + * Set whether to fall back to the system Locale if no files for a specific + * Locale have been found. Default is "true"; if this is turned off, the only + * fallback will be the default file (e.g. "messages.properties" for + * basename "messages"). + *

    Falling back to the system Locale is the default behavior of + * {@code java.util.ResourceBundle}. However, this is often not desirable + * in an application server environment, where the system Locale is not relevant + * to the application at all: Set this flag to "false" in such a scenario. + */ + public void setFallbackToSystemLocale(boolean fallbackToSystemLocale) { + this.fallbackToSystemLocale = fallbackToSystemLocale; + } + + /** + * Set the number of seconds to cache the list of matching properties files. + *

      + *
    • Default is "-1", indicating to cache forever (just like + * {@code java.util.ResourceBundle}). + *
    • A positive number will cache the list of matching properties files for the given + * number of seconds. This is essentially the interval between refresh checks. + *
    • A value of "0" will attemp to list the matching properties files on + * every message access. Do not use this in a production environment! + *
    + */ + public void setCacheSeconds(int cacheSeconds) { + this.cacheMillis = (cacheSeconds * 1000); + if (fileCacheMillis == Long.MIN_VALUE) { + this.fileCacheMillis = this.cacheMillis; + } + } + + /** * Set the number of seconds to cache loaded properties files. *
      *
    • Default value is the same value as cacheSeconds - *
    • A positive number will cache loaded properties files for the given - * number of seconds. This is essentially the interval between refresh checks. - * Note that a refresh attempt will first check the last-modified timestamp - * of the file before actually reloading it; so if files don't change, this - * interval can be set rather low, as refresh attempts will not actually reload. - *
    • A value of "0" will check the last-modified timestamp of the file on - * every message access. Do not use this in a production environment! - *
    - */ - public void setFileCacheSeconds(int fileCacheSeconds) { - this.fileCacheMillis = (fileCacheSeconds * 1000); - } - - /** - * Set the PropertiesPersister to use for parsing properties files. - *

    The default is a DefaultPropertiesPersister. - * @see org.springframework.util.DefaultPropertiesPersister - */ - public void setPropertiesPersister(PropertiesPersister propertiesPersister) { - this.propertiesPersister = - (propertiesPersister != null ? propertiesPersister : new DefaultPropertiesPersister()); - } - - /** - * Set the ResourceLoader to use for loading bundle properties files. - *

    The default is a DefaultResourceLoader. Will get overridden by the - * ApplicationContext if running in a context, as it implements the - * ResourceLoaderAware interface. Can be manually overridden when - * running outside of an ApplicationContext. - * @see org.springframework.core.io.DefaultResourceLoader - * @see org.springframework.context.ResourceLoaderAware - */ - public void setResourceLoader(ResourceLoader resourceLoader) { - this.resourceLoader = (resourceLoader != null ? resourceLoader : new DefaultResourceLoader()); - } - - - /** - * Resolves the given message code as key in the retrieved bundle files, - * returning the value found in the bundle as-is (without MessageFormat parsing). - */ - @Override - protected String resolveCodeWithoutArguments(String code, Locale locale) { - if (this.cacheMillis < 0) { - PropertiesHolder propHolder = getMergedProperties(locale); - String result = propHolder.getProperty(code); - if (result != null) { - return result; - } - } - else { - for (String basename : this.basenames) { + *

  • A positive number will cache loaded properties files for the given + * number of seconds. This is essentially the interval between refresh checks. + * Note that a refresh attempt will first check the last-modified timestamp + * of the file before actually reloading it; so if files don't change, this + * interval can be set rather low, as refresh attempts will not actually reload. + *
  • A value of "0" will check the last-modified timestamp of the file on + * every message access. Do not use this in a production environment! + *
+ */ + public void setFileCacheSeconds(int fileCacheSeconds) { + this.fileCacheMillis = (fileCacheSeconds * 1000); + } + + /** + * Set the PropertiesPersister to use for parsing properties files. + *

The default is a DefaultPropertiesPersister. + * + * @see org.springframework.util.DefaultPropertiesPersister + */ + public void setPropertiesPersister(PropertiesPersister propertiesPersister) { + this.propertiesPersister = (propertiesPersister != null ? propertiesPersister : new DefaultPropertiesPersister()); + } + + /** + * Set the ResourceLoader to use for loading bundle properties files. + *

The default is a DefaultResourceLoader. Will get overridden by the + * ApplicationContext if running in a context, as it implements the + * ResourceLoaderAware interface. Can be manually overridden when + * running outside of an ApplicationContext. + * + * @see org.springframework.core.io.DefaultResourceLoader + * @see org.springframework.context.ResourceLoaderAware + */ + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = (resourceLoader != null ? resourceLoader : new DefaultResourceLoader()); + } + + /** + * Resolves the given message code as key in the retrieved bundle files, + * returning the value found in the bundle as-is (without MessageFormat parsing). + */ + @Override + protected String resolveCodeWithoutArguments(String code, Locale locale) { + if (this.cacheMillis < 0) { + PropertiesHolder propHolder = getMergedProperties(locale); + String result = propHolder.getProperty(code); + if (result != null) { + return result; + } + } else { + for (String basename : this.basenames) { List> filenamesAndResources = calculateAllFilenames(basename, locale); for (Pair filenameAndResource : filenamesAndResources) { - if(filenameAndResource.getbValue() != null) { + if (filenameAndResource.getbValue() != null) { PropertiesHolder propHolder = getProperties(filenameAndResource.getaValue(), filenameAndResource.getbValue()); String result = propHolder.getProperty(code); - if (result != null) { - return result; - } + if (result != null) { + return result; + } } - } - } - } - return null; - } - - /** - * Resolves the given message code as key in the retrieved bundle files, - * using a cached MessageFormat instance per message code. - */ - @Override - protected MessageFormat resolveCode(String code, Locale locale) { - if (this.cacheMillis < 0) { - PropertiesHolder propHolder = getMergedProperties(locale); - MessageFormat result = propHolder.getMessageFormat(code, locale); - if (result != null) { - return result; - } - } - else { - for (String basename : this.basenames) { - List> filenamesAndResources = calculateAllFilenames(basename, locale); - for (Pair filenameAndResource : filenamesAndResources) { - if(filenameAndResource.getbValue() != null) { - PropertiesHolder propHolder = getProperties(filenameAndResource.getaValue(), filenameAndResource.getbValue()); - MessageFormat result = propHolder.getMessageFormat(code, locale); - if (result != null) { - return result; - } - } - } - } - } - return null; - } - - - /** - * Get a PropertiesHolder that contains the actually visible properties - * for a Locale, after merging all specified resource bundles. - * Either fetches the holder from the cache or freshly loads it. - *

Only used when caching resource bundle contents forever, i.e. - * with {@code cacheSeconds < 0}. Therefore, merged properties are always - * cached forever. - */ - protected PropertiesHolder getMergedProperties(final Locale locale) { - return CacheEntry.getValue(cachedMergedProperties, locale, cacheMillis, new Callable() { - @Override - public PropertiesHolder call() throws Exception { - Properties mergedProps = new Properties(); - PropertiesHolder mergedHolder = new PropertiesHolder(mergedProps); - for (int i = basenames.length - 1; i >= 0; i--) { - List> filenamesAndResources = calculateAllFilenames(basenames[i], locale); - for (int j = filenamesAndResources.size() - 1; j >= 0; j--) { - Pair filenameAndResource = filenamesAndResources.get(j); - if(filenameAndResource.getbValue() != null) { - PropertiesHolder propHolder = getProperties(filenameAndResource.getaValue(), filenameAndResource.getbValue()); - mergedProps.putAll(propHolder.getProperties()); - } - } - } - return mergedHolder; - } - }); - } - - /** - * Calculate all filenames for the given bundle basename and Locale. - * Will calculate filenames for the given Locale, the system Locale - * (if applicable), and the default file. - * @param basename the basename of the bundle - * @param locale the locale - * @return the List of filenames to check - * @see #setFallbackToSystemLocale - * @see #calculateFilenamesForLocale - */ - protected List> calculateAllFilenames(final String basename, final Locale locale) { - Pair cacheKey = new Pair(basename, locale); - return CacheEntry.getValue(cachedFilenames, cacheKey, cacheMillis, new Callable>>() { - @Override - public List> call() throws Exception { + } + } + } + return null; + } + + /** + * Resolves the given message code as key in the retrieved bundle files, + * using a cached MessageFormat instance per message code. + */ + @Override + protected MessageFormat resolveCode(String code, Locale locale) { + if (this.cacheMillis < 0) { + PropertiesHolder propHolder = getMergedProperties(locale); + MessageFormat result = propHolder.getMessageFormat(code, locale); + if (result != null) { + return result; + } + } else { + for (String basename : this.basenames) { + List> filenamesAndResources = calculateAllFilenames(basename, locale); + for (Pair filenameAndResource : filenamesAndResources) { + if (filenameAndResource.getbValue() != null) { + PropertiesHolder propHolder = getProperties(filenameAndResource.getaValue(), filenameAndResource.getbValue()); + MessageFormat result = propHolder.getMessageFormat(code, locale); + if (result != null) { + return result; + } + } + } + } + } + return null; + } + + /** + * Get a PropertiesHolder that contains the actually visible properties + * for a Locale, after merging all specified resource bundles. + * Either fetches the holder from the cache or freshly loads it. + *

Only used when caching resource bundle contents forever, i.e. + * with {@code cacheSeconds < 0}. Therefore, merged properties are always + * cached forever. + */ + protected PropertiesHolder getMergedProperties(final Locale locale) { + return CacheEntry.getValue(cachedMergedProperties, locale, cacheMillis, new Callable() { + @Override + public PropertiesHolder call() throws Exception { + Properties mergedProps = new Properties(); + PropertiesHolder mergedHolder = new PropertiesHolder(mergedProps); + for (int i = basenames.length - 1; i >= 0; i--) { + List> filenamesAndResources = calculateAllFilenames(basenames[i], locale); + for (int j = filenamesAndResources.size() - 1; j >= 0; j--) { + Pair filenameAndResource = filenamesAndResources.get(j); + if (filenameAndResource.getbValue() != null) { + PropertiesHolder propHolder = getProperties(filenameAndResource.getaValue(), filenameAndResource.getbValue()); + mergedProps.putAll(propHolder.getProperties()); + } + } + } + return mergedHolder; + } + }); + } + + /** + * Calculate all filenames for the given bundle basename and Locale. + * Will calculate filenames for the given Locale, the system Locale + * (if applicable), and the default file. + * + * @param basename the basename of the bundle + * @param locale the locale + * @return the List of filenames to check + * @see #setFallbackToSystemLocale + * @see #calculateFilenamesForLocale + */ + protected List> calculateAllFilenames(final String basename, final Locale locale) { + Pair cacheKey = new Pair(basename, locale); + return CacheEntry.getValue(cachedFilenames, cacheKey, cacheMillis, new Callable>>() { + @Override + public List> call() throws Exception { List filenames = new ArrayList(7); filenames.addAll(calculateFilenamesForLocale(basename, locale)); if (fallbackToSystemLocale && !locale.equals(Locale.getDefault())) { @@ -434,62 +442,63 @@ public List> call() throws Exception { } } filenames.add(basename); - List> filenamesAndResources = new ArrayList>(filenames.size()); - for(String filename : filenames) { + List> filenamesAndResources = new ArrayList>(filenames.size()); + for (String filename : filenames) { filenamesAndResources.add(new Pair(filename, locateResource(filename))); } return filenamesAndResources; - } - }); - } - - /** - * Calculate the filenames for the given bundle basename and Locale, - * appending language code, country code, and variant code. - * E.g.: basename "messages", Locale "de_AT_oo" -> "messages_de_AT_OO", - * "messages_de_AT", "messages_de". - *

Follows the rules defined by {@link java.util.Locale#toString()}. - * @param basename the basename of the bundle - * @param locale the locale - * @return the List of filenames to check - */ - protected List calculateFilenamesForLocale(String basename, Locale locale) { - List result = new ArrayList(3); - String language = locale.getLanguage(); - String country = locale.getCountry(); - String variant = locale.getVariant(); - StringBuilder temp = new StringBuilder(basename); - - temp.append('_'); - if (language.length() > 0) { - temp.append(language); - result.add(0, temp.toString()); - } - - temp.append('_'); - if (country.length() > 0) { - temp.append(country); - result.add(0, temp.toString()); - } - - if (variant.length() > 0 && (language.length() > 0 || country.length() > 0)) { - temp.append('_').append(variant); - result.add(0, temp.toString()); - } - - return result; - } - - - /** - * Get a PropertiesHolder for the given filename, either from the - * cache or freshly loaded. - * @param filename the bundle filename (basename + Locale) - * @return the current PropertiesHolder for the bundle - */ - @SuppressWarnings("rawtypes") + } + }); + } + + /** + * Calculate the filenames for the given bundle basename and Locale, + * appending language code, country code, and variant code. + * E.g.: basename "messages", Locale "de_AT_oo" -> "messages_de_AT_OO", + * "messages_de_AT", "messages_de". + *

Follows the rules defined by {@link java.util.Locale#toString()}. + * + * @param basename the basename of the bundle + * @param locale the locale + * @return the List of filenames to check + */ + protected List calculateFilenamesForLocale(String basename, Locale locale) { + List result = new ArrayList(3); + String language = locale.getLanguage(); + String country = locale.getCountry(); + String variant = locale.getVariant(); + StringBuilder temp = new StringBuilder(basename); + + temp.append('_'); + if (language.length() > 0) { + temp.append(language); + result.add(0, temp.toString()); + } + + temp.append('_'); + if (country.length() > 0) { + temp.append(country); + result.add(0, temp.toString()); + } + + if (variant.length() > 0 && (language.length() > 0 || country.length() > 0)) { + temp.append('_').append(variant); + result.add(0, temp.toString()); + } + + return result; + } + + /** + * Get a PropertiesHolder for the given filename, either from the + * cache or freshly loaded. + * + * @param filename the bundle filename (basename + Locale) + * @return the current PropertiesHolder for the bundle + */ + @SuppressWarnings("rawtypes") protected PropertiesHolder getProperties(final String filename, final Resource resource) { - return CacheEntry.getValue(cachedProperties, filename, fileCacheMillis, new Callable() { + return CacheEntry.getValue(cachedProperties, filename, fileCacheMillis, new Callable() { @Override public PropertiesHolder call() throws Exception { return new PropertiesHolder(filename, resource); @@ -500,113 +509,94 @@ public CacheEntry call() throws Exception { return new PropertiesHolderCacheEntry(); } }, true, null); - } - - protected static class PropertiesHolderCacheEntry extends CacheEntry { - public PropertiesHolderCacheEntry() { - super(); - } + } - @Override - protected PropertiesHolder updateValue(PropertiesHolder oldValue, Callable updater, Object cacheRequestObject) - throws Exception { - if(oldValue != null) { - oldValue.update(); - return oldValue; + /** + * Load the properties from the given resource. + * + * @param resource the resource to load from + * @param filename the original bundle filename (basename + Locale) + * @return the populated Properties instance + * @throws IOException if properties loading failed + */ + protected Properties loadProperties(Resource resource, String filename) throws IOException { + InputStream is = resource.getInputStream(); + Properties props = new Properties(); + try { + if (resource.getFilename().endsWith(XML_SUFFIX)) { + if (logger.isDebugEnabled()) { + logger.debug("Loading properties [" + resource.getFilename() + "]"); + } + this.propertiesPersister.loadFromXml(props, is); + } else { + String encoding = null; + if (this.fileEncodings != null) { + encoding = this.fileEncodings.getProperty(filename); + } + if (encoding == null) { + encoding = this.defaultEncoding; + } + if (encoding != null) { + if (logger.isDebugEnabled()) { + logger.debug("Loading properties [" + resource.getFilename() + "] with encoding '" + encoding + "'"); + } + this.propertiesPersister.load(props, new InputStreamReader(is, encoding)); + } else { + if (logger.isDebugEnabled()) { + logger.debug("Loading properties [" + resource.getFilename() + "]"); + } + this.propertiesPersister.load(props, is); + } } - return updater.call(); + return props; + } finally { + is.close(); } } - - - /** - * Load the properties from the given resource. - * @param resource the resource to load from - * @param filename the original bundle filename (basename + Locale) - * @return the populated Properties instance - * @throws IOException if properties loading failed - */ - protected Properties loadProperties(Resource resource, String filename) throws IOException { - InputStream is = resource.getInputStream(); - Properties props = new Properties(); - try { - if (resource.getFilename().endsWith(XML_SUFFIX)) { - if (logger.isDebugEnabled()) { - logger.debug("Loading properties [" + resource.getFilename() + "]"); - } - this.propertiesPersister.loadFromXml(props, is); - } - else { - String encoding = null; - if (this.fileEncodings != null) { - encoding = this.fileEncodings.getProperty(filename); - } - if (encoding == null) { - encoding = this.defaultEncoding; - } - if (encoding != null) { - if (logger.isDebugEnabled()) { - logger.debug("Loading properties [" + resource.getFilename() + "] with encoding '" + encoding + "'"); - } - this.propertiesPersister.load(props, new InputStreamReader(is, encoding)); - } - else { - if (logger.isDebugEnabled()) { - logger.debug("Loading properties [" + resource.getFilename() + "]"); - } - this.propertiesPersister.load(props, is); - } - } - return props; - } - finally { - is.close(); - } - } - - - /** - * Clear the resource bundle cache. - * Subsequent resolve calls will lead to reloading of the properties files. - */ - public void clearCache() { - logger.debug("Clearing entire resource bundle cache"); - this.cachedProperties.clear(); - this.cachedMergedProperties.clear(); - this.cachedFilenames.clear(); - this.cachedResources.clear(); - } - - /** - * Clear the resource bundle caches of this MessageSource and all its ancestors. - * @see #clearCache - */ - public void clearCacheIncludingAncestors() { - clearCache(); - if (getParentMessageSource() instanceof ReloadableResourceBundleMessageSource) { - ((ReloadableResourceBundleMessageSource) getParentMessageSource()).clearCacheIncludingAncestors(); - } else if (getParentMessageSource() instanceof org.springframework.context.support.ReloadableResourceBundleMessageSource) { + + /** + * Clear the resource bundle cache. + * Subsequent resolve calls will lead to reloading of the properties files. + */ + public void clearCache() { + logger.debug("Clearing entire resource bundle cache"); + this.cachedProperties.clear(); + this.cachedMergedProperties.clear(); + this.cachedFilenames.clear(); + this.cachedResources.clear(); + } + + /** + * Clear the resource bundle caches of this MessageSource and all its ancestors. + * + * @see #clearCache + */ + public void clearCacheIncludingAncestors() { + clearCache(); + if (getParentMessageSource() instanceof ReloadableResourceBundleMessageSource) { + ((ReloadableResourceBundleMessageSource) getParentMessageSource()).clearCacheIncludingAncestors(); + } else if (getParentMessageSource() instanceof org.springframework.context.support.ReloadableResourceBundleMessageSource) { ((org.springframework.context.support.ReloadableResourceBundleMessageSource) getParentMessageSource()).clearCacheIncludingAncestors(); - } - } - - @Override - public String toString() { - return getClass().getName() + ": basenames=[" + StringUtils.arrayToCommaDelimitedString(this.basenames) + "]"; - } - - protected Resource locateResource(final String filename) { - return CacheEntry.getValue(cachedResources, filename, cacheMillis, new Callable() { - @Override - public Resource call() throws Exception { - return locateResourceWithoutCache(filename); - } - }); - } - + } + } + + @Override + public String toString() { + return getClass().getName() + ": basenames=[" + StringUtils.arrayToCommaDelimitedString(this.basenames) + "]"; + } + + protected Resource locateResource(final String filename) { + return CacheEntry.getValue(cachedResources, filename, cacheMillis, new Callable() { + @Override + public Resource call() throws Exception { + return locateResourceWithoutCache(filename); + } + }); + } + protected Resource locateResourceWithoutCache(String filename) { Resource resource = resourceLoader.getResource(org.grails.io.support.ResourceLoader.CLASSPATH_URL_PREFIX + filename + PROPERTIES_SUFFIX); - if(!resource.exists()) { + if (!resource.exists()) { resource = resourceLoader.getResource(filename + PROPERTIES_SUFFIX); } if (!resource.exists()) { @@ -617,121 +607,136 @@ protected Resource locateResourceWithoutCache(String filename) { } else { return null; } - } - - /** - * PropertiesHolder for caching. - * Stores the last-modified timestamp of the source file for efficient - * change detection, and the timestamp of the last refresh attempt - * (updated every time the cache entry gets re-validated). - */ - protected class PropertiesHolder { - private Properties properties; - - private String filename; - private Resource resource; - - private long fileTimestamp = -1; - - /** Cache to hold already generated MessageFormats per message code */ - private final ConcurrentMap, CacheEntry> cachedMessageFormats = - new ConcurrentHashMap, CacheEntry>(); - - public PropertiesHolder(String filename, Resource resource) { - this.filename = filename; - this.resource = resource; - doUpdate(true); - } - - public PropertiesHolder(Properties properties) { - this.properties = properties; - } - - public boolean update() { - return doUpdate(false); - } - + } + + protected static class PropertiesHolderCacheEntry extends CacheEntry { + + public PropertiesHolderCacheEntry() { + super(); + } + + @Override + protected PropertiesHolder updateValue(PropertiesHolder oldValue, Callable updater, Object cacheRequestObject) throws Exception { + if (oldValue != null) { + oldValue.update(); + return oldValue; + } + return updater.call(); + } + } + + /** + * PropertiesHolder for caching. + * Stores the last-modified timestamp of the source file for efficient + * change detection, and the timestamp of the last refresh attempt + * (updated every time the cache entry gets re-validated). + */ + protected class PropertiesHolder { + + private Properties properties; + + private String filename; + private Resource resource; + + private long fileTimestamp = -1; + + /** + * Cache to hold already generated MessageFormats per message code + */ + private final ConcurrentMap, CacheEntry> cachedMessageFormats = new ConcurrentHashMap, CacheEntry>(); + + public PropertiesHolder(String filename, Resource resource) { + this.filename = filename; + this.resource = resource; + doUpdate(true); + } + + public PropertiesHolder(Properties properties) { + this.properties = properties; + } + + public boolean update() { + return doUpdate(false); + } + private boolean doUpdate(boolean initialization) { - if(filename == null) { + if (filename == null) { return false; } - if(!initialization && cacheMillis >= 0) { + if (!initialization && cacheMillis >= 0) { resource = locateResource(filename); } - if(resource != null) { + if (resource != null) { long newFileTimestamp; try { newFileTimestamp = resource.lastModified(); } catch (IOException ex) { if (logger.isDebugEnabled()) { - logger.debug( - resource + " could not be resolved in the file system - assuming that is hasn't changed", ex); + logger.debug(resource + " could not be resolved in the file system - assuming that is hasn't changed", ex); } newFileTimestamp = -1; } - if (fileCacheMillis >= 0 && newFileTimestamp == fileTimestamp && this.properties != null) { - return false; - } - try { - this.properties = loadProperties(resource, filename); - this.fileTimestamp = newFileTimestamp; - this.cachedMessageFormats.clear(); - } - catch (IOException ex) { - if (logger.isWarnEnabled()) { - logger.warn("Could not parse properties file [" + resource.getFilename() + "]", ex); - } - } - return true; - } - else { - // Resource does not exist. - if (logger.isDebugEnabled()) { - logger.debug("No properties file found for [" + filename + "] - neither plain properties nor XML"); - } + if (fileCacheMillis >= 0 && newFileTimestamp == fileTimestamp && this.properties != null) { + return false; + } + try { + this.properties = loadProperties(resource, filename); + this.fileTimestamp = newFileTimestamp; + this.cachedMessageFormats.clear(); + } catch (IOException ex) { + if (logger.isWarnEnabled()) { + logger.warn("Could not parse properties file [" + resource.getFilename() + "]", ex); + } + } + return true; + } else { + // Resource does not exist. + if (logger.isDebugEnabled()) { + logger.debug("No properties file found for [" + filename + "] - neither plain properties nor XML"); + } this.properties = new Properties(); this.fileTimestamp = -1; this.cachedMessageFormats.clear(); - return true; - } - } + return true; + } + } - public String getFilename() { + public String getFilename() { return filename; } - public Properties getProperties() { - return properties; - } - - public long getFileTimestamp() { - return fileTimestamp; - } - - public String getProperty(String code) { - if (this.properties == null) { - return null; - } - return this.properties.getProperty(code); - } - - public MessageFormat getMessageFormat(final String code, final Locale locale) { - if (this.properties == null) { - return null; - } - Pair cacheKey = new Pair(code, locale); - return CacheEntry.getValue(cachedMessageFormats, cacheKey, -1, new Callable() { - @Override - public MessageFormat call() throws Exception { - String msg = properties.getProperty(code); - if (msg != null) { - return createMessageFormat(msg, locale); - } else { - return null; - } - } - }); - } - } + public Properties getProperties() { + return properties; + } + + public long getFileTimestamp() { + return fileTimestamp; + } + + public String getProperty(String code) { + if (this.properties == null) { + return null; + } + return this.properties.getProperty(code); + } + + public MessageFormat getMessageFormat(final String code, final Locale locale) { + if (this.properties == null) { + return null; + } + Pair cacheKey = new Pair(code, locale); + return CacheEntry.getValue(cachedMessageFormats, cacheKey, -1, new Callable() { + @Override + public MessageFormat call() throws Exception { + String msg = properties.getProperty(code); + if (msg != null) { + return createMessageFormat(msg, locale); + } else { + return null; + } + } + }); + } + } } diff --git a/grails-core/src/main/groovy/org/grails/transaction/ChainedTransactionManager.java b/grails-core/src/main/groovy/org/grails/transaction/ChainedTransactionManager.java index cb57334e153..db01036b503 100644 --- a/grails-core/src/main/groovy/org/grails/transaction/ChainedTransactionManager.java +++ b/grails-core/src/main/groovy/org/grails/transaction/ChainedTransactionManager.java @@ -18,13 +18,6 @@ */ package org.grails.transaction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.transaction.CannotCreateTransactionException; @@ -36,6 +29,13 @@ import org.springframework.transaction.UnexpectedRollbackException; import org.springframework.util.Assert; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + /** * {@link PlatformTransactionManager} implementation that orchestrates transaction creation, commits and rollbacks to a * list of delegates. Using this implementation assumes that errors causing a transaction rollback will usually happen @@ -45,196 +45,195 @@ * which means the {@link PlatformTransactionManager} most likely to break the transaction should be the last * in the list configured. A {@link PlatformTransactionManager} throwing an exception during commit will automatically * cause the remaining transaction managers to roll back instead of committing. - * + *

* original source: https://github.com/spring-projects/spring-data-commons/blob/master/src/main/java/org/springframework/data/transaction/ChainedTransactionManager.java - * + * * @author Michael Hunger * @author Oliver Gierke * @author Lari Hotari * @author Graeme Rocher - * - * @since 2.3.6 + * @since 2.3.6 */ public class ChainedTransactionManager implements PlatformTransactionManager { - private final static Logger LOGGER = LoggerFactory.getLogger(ChainedTransactionManager.class); - - private final List transactionManagers; - private final SynchronizationManager synchronizationManager; - - /** - * Creates a new {@link ChainedTransactionManager} delegating to the given {@link PlatformTransactionManager}s. - * - * @param transactionManagers must not be {@literal null} or empty. - */ - public ChainedTransactionManager(PlatformTransactionManager... transactionManagers) { - this(SpringTransactionSynchronizationManager.INSTANCE, transactionManagers); - } - - /** - * Creates a new {@link ChainedTransactionManager} using the given {@link SynchronizationManager} and - * {@link PlatformTransactionManager}s. - * - * @param synchronizationManager must not be {@literal null}. - * @param transactionManagers must not be {@literal null} or empty. - */ - ChainedTransactionManager(SynchronizationManager synchronizationManager, - PlatformTransactionManager... transactionManagers) { - - Assert.notNull(synchronizationManager, "SynchronizationManager must not be null!"); - Assert.notNull(transactionManagers, "Transaction managers must not be null!"); - Assert.isTrue(transactionManagers.length > 0, "At least one PlatformTransactionManager must be given!"); - - this.synchronizationManager = synchronizationManager; - this.transactionManagers = new ArrayList(); - this.transactionManagers.addAll(Arrays.asList(transactionManagers)); - } - - /* - * (non-Javadoc) - * @see org.springframework.transaction.PlatformTransactionManager#getTransaction(org.springframework.transaction.TransactionDefinition) - */ - public MultiTransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { - - MultiTransactionStatus mts = new MultiTransactionStatus(transactionManagers.get(0)); - - if (!synchronizationManager.isSynchronizationActive() && canCreateTransaction(definition)) { - synchronizationManager.initSynchronization(); - mts.setNewSynchronization(); - } - - try { - - for (PlatformTransactionManager transactionManager : transactionManagers) { - mts.registerTransactionManager(definition, transactionManager); - } - - } catch (Exception ex) { - - Map transactionStatuses = mts.getTransactionStatuses(); - - for (PlatformTransactionManager transactionManager : transactionManagers) { - try { - if (transactionStatuses.get(transactionManager) != null) { - transactionManager.rollback(transactionStatuses.get(transactionManager)); - } - } catch (Exception ex2) { - LOGGER.warn("Rollback exception (" + transactionManager + ") " + ex2.getMessage(), ex2); - } - } - - if (mts.isNewSynchronization()) { - synchronizationManager.clearSynchronization(); - } - - throw new CannotCreateTransactionException(ex.getMessage(), ex); - } - - return mts; - } - - protected boolean canCreateTransaction(TransactionDefinition definition) { - return definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || - definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || - definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED; - } - - /* - * (non-Javadoc) - * @see org.springframework.transaction.PlatformTransactionManager#commit(org.springframework.transaction.TransactionStatus) - */ - public void commit(TransactionStatus status) throws TransactionException { - - MultiTransactionStatus multiTransactionStatus = (MultiTransactionStatus) status; - - boolean commit = true; - Exception commitException = null; - PlatformTransactionManager commitExceptionTransactionManager = null; - - for (PlatformTransactionManager transactionManager : reverse(transactionManagers)) { - - if (commit) { - - try { - multiTransactionStatus.commit(transactionManager); - } catch (Exception ex) { - commit = false; - commitException = ex; - commitExceptionTransactionManager = transactionManager; - } - - } else { - - // after unsucessfull commit we must try to rollback remaining transaction managers - - try { - multiTransactionStatus.rollback(transactionManager); - } catch (Exception ex) { - LOGGER.warn("Rollback exception (after commit) (" + transactionManager + ") " + ex.getMessage(), ex); - } - } - } - - if (multiTransactionStatus.isNewSynchronization()) { - synchronizationManager.clearSynchronization(); - } - - if (commitException != null) { - boolean firstTransactionManagerFailed = commitExceptionTransactionManager == getLastTransactionManager(); - int transactionState = firstTransactionManagerFailed ? HeuristicCompletionException.STATE_ROLLED_BACK - : HeuristicCompletionException.STATE_MIXED; - throw new HeuristicCompletionException(transactionState, commitException); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.transaction.PlatformTransactionManager#rollback(org.springframework.transaction.TransactionStatus) - */ - public void rollback(TransactionStatus status) throws TransactionException { - - Exception rollbackException = null; - PlatformTransactionManager rollbackExceptionTransactionManager = null; - - MultiTransactionStatus multiTransactionStatus = (MultiTransactionStatus) status; - - for (PlatformTransactionManager transactionManager : reverse(transactionManagers)) { - try { - multiTransactionStatus.rollback(transactionManager); - } catch (Exception ex) { - if (rollbackException == null) { - rollbackException = ex; - rollbackExceptionTransactionManager = transactionManager; - } else { - LOGGER.warn("Rollback exception (" + transactionManager + ") " + ex.getMessage(), ex); - } - } - } - - if (multiTransactionStatus.isNewSynchronization()) { - synchronizationManager.clearSynchronization(); - } - - if (rollbackException != null) { - throw new UnexpectedRollbackException("Rollback exception, originated at (" + rollbackExceptionTransactionManager - + ") " + rollbackException.getMessage(), rollbackException); - } - } - - private Iterable reverse(Collection collection) { - - List list = new ArrayList(collection); - Collections.reverse(list); - return list; - } - - private PlatformTransactionManager getLastTransactionManager() { - return transactionManagers.get(lastTransactionManagerIndex()); - } - - private int lastTransactionManagerIndex() { - return transactionManagers.size() - 1; - } + private static final Logger LOGGER = LoggerFactory.getLogger(ChainedTransactionManager.class); + + private final List transactionManagers; + private final SynchronizationManager synchronizationManager; + + /** + * Creates a new {@link ChainedTransactionManager} delegating to the given {@link PlatformTransactionManager}s. + * + * @param transactionManagers must not be {@literal null} or empty. + */ + public ChainedTransactionManager(PlatformTransactionManager... transactionManagers) { + this(SpringTransactionSynchronizationManager.INSTANCE, transactionManagers); + } + + /** + * Creates a new {@link ChainedTransactionManager} using the given {@link SynchronizationManager} and + * {@link PlatformTransactionManager}s. + * + * @param synchronizationManager must not be {@literal null}. + * @param transactionManagers must not be {@literal null} or empty. + */ + ChainedTransactionManager(SynchronizationManager synchronizationManager, + PlatformTransactionManager... transactionManagers) { + + Assert.notNull(synchronizationManager, "SynchronizationManager must not be null!"); + Assert.notNull(transactionManagers, "Transaction managers must not be null!"); + Assert.isTrue(transactionManagers.length > 0, "At least one PlatformTransactionManager must be given!"); + + this.synchronizationManager = synchronizationManager; + this.transactionManagers = new ArrayList(); + this.transactionManagers.addAll(Arrays.asList(transactionManagers)); + } + + /* + * (non-Javadoc) + * @see org.springframework.transaction.PlatformTransactionManager#getTransaction(org.springframework.transaction.TransactionDefinition) + */ + public MultiTransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { + + MultiTransactionStatus mts = new MultiTransactionStatus(transactionManagers.get(0)); + + if (!synchronizationManager.isSynchronizationActive() && canCreateTransaction(definition)) { + synchronizationManager.initSynchronization(); + mts.setNewSynchronization(); + } + + try { + + for (PlatformTransactionManager transactionManager : transactionManagers) { + mts.registerTransactionManager(definition, transactionManager); + } + + } catch (Exception ex) { + + Map transactionStatuses = mts.getTransactionStatuses(); + + for (PlatformTransactionManager transactionManager : transactionManagers) { + try { + if (transactionStatuses.get(transactionManager) != null) { + transactionManager.rollback(transactionStatuses.get(transactionManager)); + } + } catch (Exception ex2) { + LOGGER.warn("Rollback exception (" + transactionManager + ") " + ex2.getMessage(), ex2); + } + } + + if (mts.isNewSynchronization()) { + synchronizationManager.clearSynchronization(); + } + + throw new CannotCreateTransactionException(ex.getMessage(), ex); + } + + return mts; + } + + protected boolean canCreateTransaction(TransactionDefinition definition) { + return definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || + definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || + definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED; + } + + /* + * (non-Javadoc) + * @see org.springframework.transaction.PlatformTransactionManager#commit(org.springframework.transaction.TransactionStatus) + */ + public void commit(TransactionStatus status) throws TransactionException { + + MultiTransactionStatus multiTransactionStatus = (MultiTransactionStatus) status; + + boolean commit = true; + Exception commitException = null; + PlatformTransactionManager commitExceptionTransactionManager = null; + + for (PlatformTransactionManager transactionManager : reverse(transactionManagers)) { + + if (commit) { + + try { + multiTransactionStatus.commit(transactionManager); + } catch (Exception ex) { + commit = false; + commitException = ex; + commitExceptionTransactionManager = transactionManager; + } + + } else { + + // after unsucessfull commit we must try to rollback remaining transaction managers + + try { + multiTransactionStatus.rollback(transactionManager); + } catch (Exception ex) { + LOGGER.warn("Rollback exception (after commit) (" + transactionManager + ") " + ex.getMessage(), ex); + } + } + } + + if (multiTransactionStatus.isNewSynchronization()) { + synchronizationManager.clearSynchronization(); + } + + if (commitException != null) { + boolean firstTransactionManagerFailed = commitExceptionTransactionManager == getLastTransactionManager(); + int transactionState = firstTransactionManagerFailed ? HeuristicCompletionException.STATE_ROLLED_BACK + : HeuristicCompletionException.STATE_MIXED; + throw new HeuristicCompletionException(transactionState, commitException); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.transaction.PlatformTransactionManager#rollback(org.springframework.transaction.TransactionStatus) + */ + public void rollback(TransactionStatus status) throws TransactionException { + + Exception rollbackException = null; + PlatformTransactionManager rollbackExceptionTransactionManager = null; + + MultiTransactionStatus multiTransactionStatus = (MultiTransactionStatus) status; + + for (PlatformTransactionManager transactionManager : reverse(transactionManagers)) { + try { + multiTransactionStatus.rollback(transactionManager); + } catch (Exception ex) { + if (rollbackException == null) { + rollbackException = ex; + rollbackExceptionTransactionManager = transactionManager; + } else { + LOGGER.warn("Rollback exception (" + transactionManager + ") " + ex.getMessage(), ex); + } + } + } + + if (multiTransactionStatus.isNewSynchronization()) { + synchronizationManager.clearSynchronization(); + } + + if (rollbackException != null) { + throw new UnexpectedRollbackException("Rollback exception, originated at (" + rollbackExceptionTransactionManager + + ") " + rollbackException.getMessage(), rollbackException); + } + } + + private Iterable reverse(Collection collection) { + + List list = new ArrayList(collection); + Collections.reverse(list); + return list; + } + + private PlatformTransactionManager getLastTransactionManager() { + return transactionManagers.get(lastTransactionManagerIndex()); + } + + private int lastTransactionManagerIndex() { + return transactionManagers.size() - 1; + } public List getTransactionManagers() { return transactionManagers; diff --git a/grails-core/src/main/groovy/org/grails/transaction/ChainedTransactionManagerPostProcessor.java b/grails-core/src/main/groovy/org/grails/transaction/ChainedTransactionManagerPostProcessor.java index 027991530aa..84dd5df8f28 100644 --- a/grails-core/src/main/groovy/org/grails/transaction/ChainedTransactionManagerPostProcessor.java +++ b/grails-core/src/main/groovy/org/grails/transaction/ChainedTransactionManagerPostProcessor.java @@ -16,15 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.transaction; import grails.config.Config; - -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import org.grails.config.PropertySourcesConfig; import org.springframework.beans.BeansException; import org.springframework.beans.factory.ListableBeanFactory; @@ -41,50 +35,57 @@ import org.springframework.transaction.jta.JtaTransactionManager; import org.springframework.util.ClassUtils; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** - * A {@link BeanDefinitionRegistryPostProcessor} for using the "Best Effort 1 Phase Commit" (BE1PC) in Grails - * applications when there are multiple data sources. - * - * When the context contains multiple transactionManager beans, the bean with the name "transactionManager" - * will be renamed to "$primaryTransactionManager" and a new ChainedTransactionManager bean will be added with the name - * "transactionManager". All transactionManager beans will be registered in the ChainedTransactionManager bean. + * A {@link BeanDefinitionRegistryPostProcessor} for using the "Best Effort 1 Phase Commit" (BE1PC) in Grails + * applications when there are multiple data sources. + *

+ * When the context contains multiple transactionManager beans, the bean with the name "transactionManager" + * will be renamed to "$primaryTransactionManager" and a new ChainedTransactionManager bean will be added with the name + * "transactionManager". All transactionManager beans will be registered in the ChainedTransactionManager bean. + *

+ * The post processor checks if the previous transactionManager bean is an instance of {@link JtaTransactionManager}. + * In that case it will not do anything since it's assumed that JTA/XA is handling transactions spanning multiple datasources. + *

+ * For performance reasons an additional dataSource can be marked as non-transactional by adding a property 'transactional = false' in + * it's dataSource configuration. This will leave the dataSource out of the transactions initiated by Grails transactions. + * This is the default behaviour in Grails versions before Grails 2.3.6 . * - * The post processor checks if the previous transactionManager bean is an instance of {@link JtaTransactionManager}. - * In that case it will not do anything since it's assumed that JTA/XA is handling transactions spanning multiple datasources. - * - * For performance reasons an additional dataSource can be marked as non-transactional by adding a property 'transactional = false' in - * it's dataSource configuration. This will leave the dataSource out of the transactions initiated by Grails transactions. - * This is the default behaviour in Grails versions before Grails 2.3.6 . - * - * * @author Lari Hotari * @since 2.3.6 * */ public class ChainedTransactionManagerPostProcessor implements BeanDefinitionRegistryPostProcessor, Ordered { - private static final String TRANSACTIONAL = "transactional"; - private static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME_WHITELIST_PATTERN = "(?i).*transactionManager(_.+)?"; - private static final String DEFAULT_TRANSACTION_MANAGER_INTERNAL_BEAN_NAME_BLACKLIST_PATTERN = "(?i)chainedTransactionManagerPostProcessor|transactionManagerPostProcessor|.*PostProcessor"; + public static final String DATA_SOURCE_SETTING = "dataSource"; public static final String DATA_SOURCES_SETTING = "dataSources"; public static final String DATA_SOURCES_PREFIX = "dataSources."; - private String beanNameWhitelistPattern = DEFAULT_TRANSACTION_MANAGER_BEAN_NAME_WHITELIST_PATTERN; - private String beanNameBlacklistPattern = null; - private String beanNameInternalBlacklistPattern = DEFAULT_TRANSACTION_MANAGER_INTERNAL_BEAN_NAME_BLACKLIST_PATTERN; + private static final String TRANSACTIONAL = "transactional"; + private static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME_WHITELIST_PATTERN = "(?i).*transactionManager(_.+)?"; + private static final String DEFAULT_TRANSACTION_MANAGER_INTERNAL_BEAN_NAME_BLACKLIST_PATTERN = "(?i)chainedTransactionManagerPostProcessor|transactionManagerPostProcessor|.*PostProcessor"; private static final Pattern SUFFIX_PATTERN = Pattern.compile("^transactionManager_(.+)$"); private static final String PRIMARY_TRANSACTION_MANAGER = "$primaryTransactionManager"; private static final String TRANSACTION_MANAGER = "transactionManager"; private static final String READONLY = "readOnly"; - + private static String[] transactionManagerBeanNames = null; + + private String beanNameWhitelistPattern = DEFAULT_TRANSACTION_MANAGER_BEAN_NAME_WHITELIST_PATTERN; + private String beanNameBlacklistPattern = null; + private String beanNameInternalBlacklistPattern = DEFAULT_TRANSACTION_MANAGER_INTERNAL_BEAN_NAME_BLACKLIST_PATTERN; + private Config config; private Map dsConfigs; - private static String[] transactionManagerBeanNames = null; public ChainedTransactionManagerPostProcessor(Config config) { this(config, null, null); } - + public ChainedTransactionManagerPostProcessor(Config config, String whitelistPattern, String blacklistPattern) { transactionManagerBeanNames = null; this.config = config; @@ -95,22 +96,21 @@ public ChainedTransactionManagerPostProcessor(Config config, String whitelistPat beanNameBlacklistPattern = blacklistPattern; } } - + public ChainedTransactionManagerPostProcessor() { this(new PropertySourcesConfig(), null, null); } - @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - + } protected void registerAdditionalTransactionManagers(BeanDefinitionRegistry registry, BeanDefinition chainedTransactionManagerBeanDefinition, ManagedList transactionManagerRefs) { String[] allBeanNames = getTransactionManagerBeanNames(registry); for (String beanName : allBeanNames) { BeanDefinition beanDefinition = registry.getBeanDefinition(beanName); - if(!TRANSACTION_MANAGER.equals(beanName) && !PRIMARY_TRANSACTION_MANAGER.equals(beanName) && isValidTransactionManagerBeanDefinition(beanName, beanDefinition)) { + if (!TRANSACTION_MANAGER.equals(beanName) && !PRIMARY_TRANSACTION_MANAGER.equals(beanName) && isValidTransactionManagerBeanDefinition(beanName, beanDefinition)) { String suffix = resolveDataSourceSuffix(beanName); if (!isNotTransactional(suffix)) { transactionManagerRefs.add(new RuntimeBeanReference(beanName)); @@ -119,14 +119,12 @@ protected void registerAdditionalTransactionManagers(BeanDefinitionRegistry regi } } - protected static String[] getTransactionManagerBeanNames(BeanDefinitionRegistry registry) { - if(transactionManagerBeanNames == null) { + if (transactionManagerBeanNames == null) { - if(registry instanceof ListableBeanFactory) { - transactionManagerBeanNames = ((ListableBeanFactory)registry).getBeanNamesForType(PlatformTransactionManager.class, false, false); - } - else { + if (registry instanceof ListableBeanFactory) { + transactionManagerBeanNames = ((ListableBeanFactory) registry).getBeanNamesForType(PlatformTransactionManager.class, false, false); + } else { transactionManagerBeanNames = registry.getBeanDefinitionNames(); } } @@ -145,7 +143,7 @@ public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) t protected ManagedList createTransactionManagerBeanReferences( BeanDefinition chainedTransactionManagerBeanDefinition) { ManagedList transactionManagerRefs = new ManagedList(); - ConstructorArgumentValues constructorValues=chainedTransactionManagerBeanDefinition.getConstructorArgumentValues(); + ConstructorArgumentValues constructorValues = chainedTransactionManagerBeanDefinition.getConstructorArgumentValues(); constructorValues.addIndexedArgumentValue(0, transactionManagerRefs); transactionManagerRefs.add(new RuntimeBeanReference(PRIMARY_TRANSACTION_MANAGER)); return transactionManagerRefs; @@ -170,20 +168,20 @@ protected boolean hasJtaOrChainedTransactionManager(BeanDefinitionRegistry regis } protected Class resolveTransactionManagerClass(BeanDefinitionRegistry registry) { - if(!registry.containsBeanDefinition(TRANSACTION_MANAGER)) { + if (!registry.containsBeanDefinition(TRANSACTION_MANAGER)) { return null; } BeanDefinition transactionManagerBeanDefinition = registry.getBeanDefinition(TRANSACTION_MANAGER); - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Class transactionManagerBeanClass = ClassUtils.resolveClassName(transactionManagerBeanDefinition.getBeanClassName(), classLoader); return transactionManagerBeanClass; } protected int countChainableTransactionManagerBeans(BeanDefinitionRegistry registry) { - int transactionManagerBeanCount=0; + int transactionManagerBeanCount = 0; for (String beanName : getTransactionManagerBeanNames(registry)) { BeanDefinition beanDefinition = registry.getBeanDefinition(beanName); - if(isValidTransactionManagerBeanDefinition(beanName, beanDefinition)) { + if (isValidTransactionManagerBeanDefinition(beanName, beanDefinition)) { String suffix = resolveDataSourceSuffix(beanName); if (beanName.equals(TRANSACTION_MANAGER) || !isNotTransactional(suffix)) { transactionManagerBeanCount++; @@ -194,34 +192,33 @@ protected int countChainableTransactionManagerBeans(BeanDefinitionRegistry regis } protected boolean isValidTransactionManagerBeanDefinition(String beanName, BeanDefinition beanDefinition) { - return beanName.matches(beanNameWhitelistPattern) && (beanNameBlacklistPattern==null || !beanName.matches(beanNameBlacklistPattern)) && !beanName.matches(beanNameInternalBlacklistPattern); + return beanName.matches(beanNameWhitelistPattern) && (beanNameBlacklistPattern == null || !beanName.matches(beanNameBlacklistPattern)) && !beanName.matches(beanNameInternalBlacklistPattern); } - + protected boolean isNotTransactional(String suffix) { if (suffix == null || config == null) { return false; } Boolean transactional = config.getProperty(DATA_SOURCES_PREFIX + suffix + "." + TRANSACTIONAL, Boolean.class, null); - if(transactional == null) { - Boolean isReadOnly = config.getProperty(DATA_SOURCES_PREFIX + suffix + "." + READONLY, Boolean.class, null); - if (isReadOnly != null && isReadOnly == true) { + if (transactional == null) { + Boolean isReadOnly = config.getProperty(DATA_SOURCES_PREFIX + suffix + "." + READONLY, Boolean.class, null); + if (isReadOnly != null && isReadOnly) { transactional = false; } } - if(transactional != null){ + if (transactional != null) { return !transactional; - } - else { + } else { return false; } } protected String resolveDataSourceSuffix(String transactionManagerBeanName) { - if(TRANSACTION_MANAGER.equals(transactionManagerBeanName)) { + if (TRANSACTION_MANAGER.equals(transactionManagerBeanName)) { return ""; } else { - Matcher matcher=SUFFIX_PATTERN.matcher(transactionManagerBeanName); - if(matcher.matches()) { + Matcher matcher = SUFFIX_PATTERN.matcher(transactionManagerBeanName); + if (matcher.matches()) { return matcher.group(1); } } @@ -229,7 +226,7 @@ protected String resolveDataSourceSuffix(String transactionManagerBeanName) { } private static boolean renameBean(String oldName, String newName, BeanDefinitionRegistry registry) { - if(!registry.containsBeanDefinition(oldName)) { + if (!registry.containsBeanDefinition(oldName)) { return false; } // remove link to child beans @@ -248,7 +245,7 @@ private static boolean renameBean(String oldName, String newName, BeanDefinition registry.removeBeanDefinition(oldName); registry.registerBeanDefinition(newName, oldBeanDefinition); // re-link possible child beans to new parent name - for(String bdName : previousChildBeans) { + for (String bdName : previousChildBeans) { BeanDefinition bd = registry.getBeanDefinition(bdName); bd.setParentName(newName); } diff --git a/grails-core/src/main/groovy/org/grails/transaction/GrailsTransactionAttribute.java b/grails-core/src/main/groovy/org/grails/transaction/GrailsTransactionAttribute.java index 89ed9fb4d1a..6e3e18f5d76 100644 --- a/grails-core/src/main/groovy/org/grails/transaction/GrailsTransactionAttribute.java +++ b/grails-core/src/main/groovy/org/grails/transaction/GrailsTransactionAttribute.java @@ -16,11 +16,8 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.transaction; -import java.util.List; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.transaction.TransactionDefinition; @@ -29,6 +26,8 @@ import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute; import org.springframework.transaction.interceptor.TransactionAttribute; +import java.util.List; + /** * Extended version of {@link RuleBasedTransactionAttribute} that ensures all exception types are rolled back and allows inheritance of setRollbackOnly * @@ -37,7 +36,7 @@ */ public class GrailsTransactionAttribute extends RuleBasedTransactionAttribute { - private static final Logger log = LoggerFactory.getLogger(GrailsTransactionAttribute.class); + private static final Logger LOG = LoggerFactory.getLogger(GrailsTransactionAttribute.class); private static final long serialVersionUID = 1L; private boolean inheritRollbackOnly = true; @@ -49,7 +48,7 @@ public GrailsTransactionAttribute() { public GrailsTransactionAttribute(int propagationBehavior, List rollbackRules) { super(propagationBehavior, rollbackRules); } - + public GrailsTransactionAttribute(TransactionAttribute other) { super(); setPropagationBehavior(other.getPropagationBehavior()); @@ -67,22 +66,22 @@ public GrailsTransactionAttribute(TransactionDefinition other) { setReadOnly(other.isReadOnly()); setName(other.getName()); } - + public GrailsTransactionAttribute(GrailsTransactionAttribute other) { - this((RuleBasedTransactionAttribute)other); + this((RuleBasedTransactionAttribute) other); } - + public GrailsTransactionAttribute(RuleBasedTransactionAttribute other) { super(other); - if(other instanceof GrailsTransactionAttribute) { - this.inheritRollbackOnly = ((GrailsTransactionAttribute)other).inheritRollbackOnly; + if (other instanceof GrailsTransactionAttribute) { + this.inheritRollbackOnly = ((GrailsTransactionAttribute) other).inheritRollbackOnly; } } @Override public boolean rollbackOn(Throwable ex) { - if (log.isTraceEnabled()) { - log.trace("Applying rules to determine whether transaction should rollback on $ex"); + if (LOG.isTraceEnabled()) { + LOG.trace("Applying rules to determine whether transaction should rollback on $ex"); } RollbackRuleAttribute winner = null; @@ -99,13 +98,13 @@ public boolean rollbackOn(Throwable ex) { } } - if (log.isTraceEnabled()) { - log.trace("Winning rollback rule is: $winner" ); + if (LOG.isTraceEnabled()) { + LOG.trace("Winning rollback rule is: $winner"); } // User superclass behavior (rollback on unchecked) if no rule matches. if (winner == null) { - log.trace("No relevant rollback rule found: applying default rules"); + LOG.trace("No relevant rollback rule found: applying default rules"); // always rollback regardless if it is a checked or unchecked exception since Groovy doesn't differentiate those return true; @@ -113,6 +112,7 @@ public boolean rollbackOn(Throwable ex) { return !(winner instanceof NoRollbackRuleAttribute); } + public boolean isInheritRollbackOnly() { return inheritRollbackOnly; } diff --git a/grails-core/src/main/groovy/org/grails/transaction/GroovyAwareNamedTransactionAttributeSource.java b/grails-core/src/main/groovy/org/grails/transaction/GroovyAwareNamedTransactionAttributeSource.java index a870eeceb55..ae1e5171f81 100644 --- a/grails-core/src/main/groovy/org/grails/transaction/GroovyAwareNamedTransactionAttributeSource.java +++ b/grails-core/src/main/groovy/org/grails/transaction/GroovyAwareNamedTransactionAttributeSource.java @@ -19,14 +19,13 @@ package org.grails.transaction; import grails.util.CollectionUtils; +import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource; +import org.springframework.transaction.interceptor.TransactionAttribute; import java.lang.reflect.Method; import java.util.Properties; import java.util.Set; -import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource; -import org.springframework.transaction.interceptor.TransactionAttribute; - /** * @author Graeme Rocher * @since 1.1.1 Don't match Groovy synthetic methods @@ -43,13 +42,17 @@ public class GroovyAwareNamedTransactionAttributeSource extends NameMatchTransac @SuppressWarnings("rawtypes") @Override public TransactionAttribute getTransactionAttribute(Method method, Class targetClass) { - if (method.isSynthetic()) return null; + if (method.isSynthetic()) { + return null; + } return super.getTransactionAttribute(method, targetClass); } @Override protected boolean isMatch(String methodName, String mappedName) { - if (NONTRANSACTIONAL_GROOVY_METHODS.contains(methodName)) return false; + if (NONTRANSACTIONAL_GROOVY_METHODS.contains(methodName)) { + return false; + } return super.isMatch(methodName, mappedName); } diff --git a/grails-core/src/main/groovy/org/grails/transaction/MultiTransactionStatus.java b/grails-core/src/main/groovy/org/grails/transaction/MultiTransactionStatus.java index 8ad3ef72551..d197b6eb993 100644 --- a/grails-core/src/main/groovy/org/grails/transaction/MultiTransactionStatus.java +++ b/grails-core/src/main/groovy/org/grails/transaction/MultiTransactionStatus.java @@ -18,193 +18,193 @@ */ package org.grails.transaction; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionException; import org.springframework.transaction.TransactionStatus; import org.springframework.util.Assert; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + /** * {@link TransactionStatus} implementation to orchestrate {@link TransactionStatus} instances for multiple * {@link PlatformTransactionManager} instances. - * + * * @author Michael Hunger * @author Oliver Gierke * @since 2.3.6 */ class MultiTransactionStatus implements TransactionStatus { - private final PlatformTransactionManager mainTransactionManager; - private final Map transactionStatuses = Collections - .synchronizedMap(new HashMap()); - - private boolean newSynchronization; - - /** - * Creates a new {@link MultiTransactionStatus} for the given {@link PlatformTransactionManager}. - * - * @param mainTransactionManager must not be {@literal null}. - */ - public MultiTransactionStatus(PlatformTransactionManager mainTransactionManager) { - - Assert.notNull(mainTransactionManager, "TransactionManager must not be null!"); - this.mainTransactionManager = mainTransactionManager; - } - - public Map getTransactionStatuses() { - return transactionStatuses; - } - - public void setNewSynchronization() { - this.newSynchronization = true; - } - - public boolean isNewSynchronization() { - return newSynchronization; - } - - public void registerTransactionManager(TransactionDefinition definition, PlatformTransactionManager transactionManager) { - getTransactionStatuses().put(transactionManager, transactionManager.getTransaction(definition)); - } - - public void commit(PlatformTransactionManager transactionManager) { - TransactionStatus transactionStatus = getTransactionStatus(transactionManager); - transactionManager.commit(transactionStatus); - } - - /** - * Rolls back the {@link TransactionStatus} registered for the given {@link PlatformTransactionManager}. - * - * @param transactionManager must not be {@literal null}. - */ - public void rollback(PlatformTransactionManager transactionManager) { - transactionManager.rollback(getTransactionStatus(transactionManager)); - } - - /* - * (non-Javadoc) - * @see org.springframework.transaction.TransactionStatus#isRollbackOnly() - */ - public boolean isRollbackOnly() { - return getMainTransactionStatus().isRollbackOnly(); - } - - /* - * (non-Javadoc) - * @see org.springframework.transaction.TransactionStatus#isCompleted() - */ - public boolean isCompleted() { - return getMainTransactionStatus().isCompleted(); - } - - /* - * (non-Javadoc) - * @see org.springframework.transaction.TransactionStatus#isNewTransaction() - */ - public boolean isNewTransaction() { - return getMainTransactionStatus().isNewTransaction(); - } - - /* - * (non-Javadoc) - * @see org.springframework.transaction.TransactionStatus#hasSavepoint() - */ - public boolean hasSavepoint() { - return getMainTransactionStatus().hasSavepoint(); - } - - /* - * (non-Javadoc) - * @see org.springframework.transaction.TransactionStatus#setRollbackOnly() - */ - public void setRollbackOnly() { - for (TransactionStatus ts : transactionStatuses.values()) { - ts.setRollbackOnly(); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.transaction.SavepointManager#createSavepoint() - */ - public Object createSavepoint() throws TransactionException { - - SavePoints savePoints = new SavePoints(); - - for (TransactionStatus transactionStatus : transactionStatuses.values()) { - savePoints.save(transactionStatus); - } - return savePoints; - } - - /* - * (non-Javadoc) - * @see org.springframework.transaction.SavepointManager#rollbackToSavepoint(java.lang.Object) - */ - public void rollbackToSavepoint(Object savepoint) throws TransactionException { - SavePoints savePoints = (SavePoints) savepoint; - savePoints.rollback(); - } - - /* - * (non-Javadoc) - * @see org.springframework.transaction.SavepointManager#releaseSavepoint(java.lang.Object) - */ - public void releaseSavepoint(Object savepoint) throws TransactionException { - ((SavePoints) savepoint).release(); - } - - /* - * (non-Javadoc) - * @see org.springframework.transaction.TransactionStatus#flush() - */ - public void flush() { - for (TransactionStatus transactionStatus : transactionStatuses.values()) { - transactionStatus.flush(); - } - } - - private TransactionStatus getMainTransactionStatus() { - return transactionStatuses.get(mainTransactionManager); - } - - private TransactionStatus getTransactionStatus(PlatformTransactionManager transactionManager) { - return this.getTransactionStatuses().get(transactionManager); - } - - private static class SavePoints { - - private final Map savepoints = new HashMap(); - - private void addSavePoint(TransactionStatus status, Object savepoint) { - - Assert.notNull(status, "TransactionStatus must not be null!"); - this.savepoints.put(status, savepoint); - } - - private void save(TransactionStatus transactionStatus) { - Object savepoint = transactionStatus.createSavepoint(); - addSavePoint(transactionStatus, savepoint); - } - - public void rollback() { - for (TransactionStatus transactionStatus : savepoints.keySet()) { - transactionStatus.rollbackToSavepoint(savepointFor(transactionStatus)); - } - } - - private Object savepointFor(TransactionStatus transactionStatus) { - return savepoints.get(transactionStatus); - } - - public void release() { - for (TransactionStatus transactionStatus : savepoints.keySet()) { - transactionStatus.releaseSavepoint(savepointFor(transactionStatus)); - } - } - } + private final PlatformTransactionManager mainTransactionManager; + private final Map transactionStatuses = Collections + .synchronizedMap(new HashMap()); + + private boolean newSynchronization; + + /** + * Creates a new {@link MultiTransactionStatus} for the given {@link PlatformTransactionManager}. + * + * @param mainTransactionManager must not be {@literal null}. + */ + public MultiTransactionStatus(PlatformTransactionManager mainTransactionManager) { + + Assert.notNull(mainTransactionManager, "TransactionManager must not be null!"); + this.mainTransactionManager = mainTransactionManager; + } + + public Map getTransactionStatuses() { + return transactionStatuses; + } + + public void setNewSynchronization() { + this.newSynchronization = true; + } + + public boolean isNewSynchronization() { + return newSynchronization; + } + + public void registerTransactionManager(TransactionDefinition definition, PlatformTransactionManager transactionManager) { + getTransactionStatuses().put(transactionManager, transactionManager.getTransaction(definition)); + } + + public void commit(PlatformTransactionManager transactionManager) { + TransactionStatus transactionStatus = getTransactionStatus(transactionManager); + transactionManager.commit(transactionStatus); + } + + /** + * Rolls back the {@link TransactionStatus} registered for the given {@link PlatformTransactionManager}. + * + * @param transactionManager must not be {@literal null}. + */ + public void rollback(PlatformTransactionManager transactionManager) { + transactionManager.rollback(getTransactionStatus(transactionManager)); + } + + /* + * (non-Javadoc) + * @see org.springframework.transaction.TransactionStatus#isRollbackOnly() + */ + public boolean isRollbackOnly() { + return getMainTransactionStatus().isRollbackOnly(); + } + + /* + * (non-Javadoc) + * @see org.springframework.transaction.TransactionStatus#isCompleted() + */ + public boolean isCompleted() { + return getMainTransactionStatus().isCompleted(); + } + + /* + * (non-Javadoc) + * @see org.springframework.transaction.TransactionStatus#isNewTransaction() + */ + public boolean isNewTransaction() { + return getMainTransactionStatus().isNewTransaction(); + } + + /* + * (non-Javadoc) + * @see org.springframework.transaction.TransactionStatus#hasSavepoint() + */ + public boolean hasSavepoint() { + return getMainTransactionStatus().hasSavepoint(); + } + + /* + * (non-Javadoc) + * @see org.springframework.transaction.TransactionStatus#setRollbackOnly() + */ + public void setRollbackOnly() { + for (TransactionStatus ts : transactionStatuses.values()) { + ts.setRollbackOnly(); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.transaction.SavepointManager#createSavepoint() + */ + public Object createSavepoint() throws TransactionException { + + SavePoints savePoints = new SavePoints(); + + for (TransactionStatus transactionStatus : transactionStatuses.values()) { + savePoints.save(transactionStatus); + } + return savePoints; + } + + /* + * (non-Javadoc) + * @see org.springframework.transaction.SavepointManager#rollbackToSavepoint(java.lang.Object) + */ + public void rollbackToSavepoint(Object savepoint) throws TransactionException { + SavePoints savePoints = (SavePoints) savepoint; + savePoints.rollback(); + } + + /* + * (non-Javadoc) + * @see org.springframework.transaction.SavepointManager#releaseSavepoint(java.lang.Object) + */ + public void releaseSavepoint(Object savepoint) throws TransactionException { + ((SavePoints) savepoint).release(); + } + + /* + * (non-Javadoc) + * @see org.springframework.transaction.TransactionStatus#flush() + */ + public void flush() { + for (TransactionStatus transactionStatus : transactionStatuses.values()) { + transactionStatus.flush(); + } + } + + private TransactionStatus getMainTransactionStatus() { + return transactionStatuses.get(mainTransactionManager); + } + + private TransactionStatus getTransactionStatus(PlatformTransactionManager transactionManager) { + return this.getTransactionStatuses().get(transactionManager); + } + + private static class SavePoints { + + private final Map savepoints = new HashMap(); + + private void addSavePoint(TransactionStatus status, Object savepoint) { + + Assert.notNull(status, "TransactionStatus must not be null!"); + this.savepoints.put(status, savepoint); + } + + private void save(TransactionStatus transactionStatus) { + Object savepoint = transactionStatus.createSavepoint(); + addSavePoint(transactionStatus, savepoint); + } + + public void rollback() { + for (TransactionStatus transactionStatus : savepoints.keySet()) { + transactionStatus.rollbackToSavepoint(savepointFor(transactionStatus)); + } + } + + private Object savepointFor(TransactionStatus transactionStatus) { + return savepoints.get(transactionStatus); + } + + public void release() { + for (TransactionStatus transactionStatus : savepoints.keySet()) { + transactionStatus.releaseSavepoint(savepointFor(transactionStatus)); + } + } + } } diff --git a/grails-core/src/main/groovy/org/grails/transaction/SpringTransactionSynchronizationManager.java b/grails-core/src/main/groovy/org/grails/transaction/SpringTransactionSynchronizationManager.java index 4c0b0cd10c1..f58e12c265f 100644 --- a/grails-core/src/main/groovy/org/grails/transaction/SpringTransactionSynchronizationManager.java +++ b/grails-core/src/main/groovy/org/grails/transaction/SpringTransactionSynchronizationManager.java @@ -22,36 +22,36 @@ /** * {@link SynchronizationManager} delegating calls to Spring's {@link TransactionSynchronizationManager}. - * + * * @author Michael Hunger * @author Oliver Gierke * @since 2.3.6 */ enum SpringTransactionSynchronizationManager implements SynchronizationManager { - INSTANCE; + INSTANCE; - /* - * (non-Javadoc) - * @see org.grails.transaction.SynchronizationManager#initSynchronization() - */ - public void initSynchronization() { - TransactionSynchronizationManager.initSynchronization(); - } + /* + * (non-Javadoc) + * @see org.grails.transaction.SynchronizationManager#initSynchronization() + */ + public void initSynchronization() { + TransactionSynchronizationManager.initSynchronization(); + } - /* - * (non-Javadoc) - * @see org.grails.transaction.SynchronizationManager#isSynchronizationActive() - */ - public boolean isSynchronizationActive() { - return TransactionSynchronizationManager.isSynchronizationActive(); - } + /* + * (non-Javadoc) + * @see org.grails.transaction.SynchronizationManager#isSynchronizationActive() + */ + public boolean isSynchronizationActive() { + return TransactionSynchronizationManager.isSynchronizationActive(); + } - /* - * (non-Javadoc) - * @see org.grails.transaction.SynchronizationManager#clearSynchronization() - */ - public void clearSynchronization() { - TransactionSynchronizationManager.clear(); - } + /* + * (non-Javadoc) + * @see org.grails.transaction.SynchronizationManager#clearSynchronization() + */ + public void clearSynchronization() { + TransactionSynchronizationManager.clear(); + } } diff --git a/grails-core/src/main/groovy/org/grails/transaction/SynchronizationManager.java b/grails-core/src/main/groovy/org/grails/transaction/SynchronizationManager.java index cb53d9e7752..16dc7089d09 100644 --- a/grails-core/src/main/groovy/org/grails/transaction/SynchronizationManager.java +++ b/grails-core/src/main/groovy/org/grails/transaction/SynchronizationManager.java @@ -16,12 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.transaction; /** * Strategy interface to allow providing a dedicated synchronization mechanism. - * + * * @author Michael Hunger * @author Oliver Gierke * @see SpringTransactionSynchronizationManager @@ -29,9 +28,9 @@ */ interface SynchronizationManager { - void initSynchronization(); + void initSynchronization(); - boolean isSynchronizationActive(); + boolean isSynchronizationActive(); - void clearSynchronization(); + void clearSynchronization(); } diff --git a/grails-core/src/main/groovy/org/grails/transaction/TransactionManagerPostProcessor.java b/grails-core/src/main/groovy/org/grails/transaction/TransactionManagerPostProcessor.java index 67c4d8e62bb..9becb7c97b4 100644 --- a/grails-core/src/main/groovy/org/grails/transaction/TransactionManagerPostProcessor.java +++ b/grails-core/src/main/groovy/org/grails/transaction/TransactionManagerPostProcessor.java @@ -37,6 +37,7 @@ * @since 0.4 */ public class TransactionManagerPostProcessor implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware, Ordered { + private ConfigurableListableBeanFactory beanFactory; private PlatformTransactionManager transactionManager; private int order = Ordered.LOWEST_PRECEDENCE; @@ -45,6 +46,7 @@ public class TransactionManagerPostProcessor implements SmartInstantiationAwareB /** * Gets the platform transaction manager from the bean factory if * there is one. + * * @param beanFactory The bean factory handling this post processor. * @throws BeansException */ @@ -58,6 +60,7 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException { /** * Injects the platform transaction manager into the given bean if * that bean implements the {@link grails.transaction.TransactionManagerAware} interface. + * * @param bean The bean to process. * @param name The name of the bean. * @return The bean after the transaction manager has been injected. @@ -67,7 +70,7 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException { public boolean postProcessAfterInstantiation(Object bean, String name) throws BeansException { if (bean instanceof TransactionManagerAware) { initialize(); - if(transactionManager != null) { + if (transactionManager != null) { TransactionManagerAware tma = (TransactionManagerAware) bean; tma.setTransactionManager(transactionManager); } @@ -76,7 +79,7 @@ public boolean postProcessAfterInstantiation(Object bean, String name) throws Be } private void initialize() { - if(transactionManager == null && beanFactory != null && !initialized) { + if (transactionManager == null && beanFactory != null && !initialized) { if (beanFactory.containsBean(GrailsApplication.TRANSACTION_MANAGER_BEAN)) { transactionManager = beanFactory.getBean(GrailsApplication.TRANSACTION_MANAGER_BEAN, PlatformTransactionManager.class); } else { @@ -90,7 +93,7 @@ private void initialize() { // If at least one is found, use the first of them as the // transaction manager for the application. if (beanNames.length > 0) { - transactionManager = (PlatformTransactionManager)beanFactory.getBean(beanNames[0]); + transactionManager = (PlatformTransactionManager) beanFactory.getBean(beanNames[0]); } } initialized = true; diff --git a/grails-core/src/main/groovy/org/grails/validation/ConstraintEvalUtils.groovy b/grails-core/src/main/groovy/org/grails/validation/ConstraintEvalUtils.groovy index e47003a4363..4fcb5e75f4c 100644 --- a/grails-core/src/main/groovy/org/grails/validation/ConstraintEvalUtils.groovy +++ b/grails-core/src/main/groovy/org/grails/validation/ConstraintEvalUtils.groovy @@ -52,8 +52,7 @@ class ConstraintEvalUtils { def constraints = config.getProperty(Settings.GORM_DEFAULT_CONSTRAINTS, Closure) if (constraints) { defaultConstraintsMap = new ClosureToMapPopulator().populate((Closure) constraints) - } - else { + } else { defaultConstraintsMap = Collections.emptyMap() } } @@ -61,7 +60,7 @@ class ConstraintEvalUtils { } static void clearDefaultConstraints() { - defaultConstraintsMap = null + defaultConstraintsMap = null configId = null } } diff --git a/grails-core/src/main/resources/META-INF/NOTICE b/grails-core/src/main/resources/META-INF/NOTICE index e2a4101a01f..246cb9bf1b5 100644 --- a/grails-core/src/main/resources/META-INF/NOTICE +++ b/grails-core/src/main/resources/META-INF/NOTICE @@ -2,4 +2,4 @@ Apache Grails Copyright 2005-2025 The Apache Software Foundation This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). \ No newline at end of file +The Apache Software Foundation (https://www.apache.org/). \ No newline at end of file diff --git a/grails-core/src/test/groovy/grails/artefact/EnhancesSpec.groovy b/grails-core/src/test/groovy/grails/artefact/EnhancesSpec.groovy index 4d28a113400..9ec472ff53d 100644 --- a/grails-core/src/test/groovy/grails/artefact/EnhancesSpec.groovy +++ b/grails-core/src/test/groovy/grails/artefact/EnhancesSpec.groovy @@ -22,7 +22,6 @@ package grails.artefact import grails.compiler.traits.TraitInjector import spock.lang.Specification - /** * @author graemerocher */ diff --git a/grails-core/src/test/groovy/grails/config/PropertySourceConfigSpec.groovy b/grails-core/src/test/groovy/grails/config/PropertySourceConfigSpec.groovy index 1692535b6d1..0ba5755cd39 100644 --- a/grails-core/src/test/groovy/grails/config/PropertySourceConfigSpec.groovy +++ b/grails-core/src/test/groovy/grails/config/PropertySourceConfigSpec.groovy @@ -58,7 +58,6 @@ class PropertySourceConfigSpec extends Specification { !(config.getProperty("grails.mongodb.connections", List.class).get(0) instanceof NavigableMap) } - void "should merge sub-documents in yaml file to single config"() { given: diff --git a/grails-core/src/test/groovy/org/grails/compiler/injection/ArtefactTypeAstTransformationSpec.groovy b/grails-core/src/test/groovy/org/grails/compiler/injection/ArtefactTypeAstTransformationSpec.groovy index 36cd60939ff..3b542a252a9 100644 --- a/grails-core/src/test/groovy/org/grails/compiler/injection/ArtefactTypeAstTransformationSpec.groovy +++ b/grails-core/src/test/groovy/org/grails/compiler/injection/ArtefactTypeAstTransformationSpec.groovy @@ -37,7 +37,6 @@ import spock.lang.Specification */ class ArtefactTypeAstTransformationSpec extends Specification { - void "test resolveArtefactType with string literal"() { given: ArtefactTypeAstTransformation ast = new ArtefactTypeAstTransformation() @@ -131,7 +130,6 @@ class ArtefactTypeAstTransformationSpec extends Specification { then: thrown(MissingMethodException) - when: "Supports returns true" TraitInjectionUtils.@traitInjectors = [new TestTraitInjectorForSupportsClassNode(true)] clazz = gcl.parseClass """ @@ -147,7 +145,6 @@ class ArtefactTypeAstTransformationSpec extends Specification { t instanceof Test10531Trait t.hello10531() == "Hello" - cleanup: TraitInjectionUtils.@traitInjectors = null diff --git a/grails-core/src/test/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformationSpec.groovy b/grails-core/src/test/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformationSpec.groovy index 9e5077197a4..ccf6595a450 100644 --- a/grails-core/src/test/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformationSpec.groovy +++ b/grails-core/src/test/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformationSpec.groovy @@ -53,7 +53,6 @@ class FooGrailsPlugin { },Phases.CONVERSION) cu.compile(Phases.CONVERSION) - expect:"the file doesn't exist" !pluginXml.exists() diff --git a/grails-core/src/test/groovy/org/grails/config/NavigableMapNestedEqualitySpec.groovy b/grails-core/src/test/groovy/org/grails/config/NavigableMapNestedEqualitySpec.groovy index c5339ef93a7..64359f124b9 100644 --- a/grails-core/src/test/groovy/org/grails/config/NavigableMapNestedEqualitySpec.groovy +++ b/grails-core/src/test/groovy/org/grails/config/NavigableMapNestedEqualitySpec.groovy @@ -172,6 +172,5 @@ grails: config.getProperty('grails.mime.types', Object) == ( config.grails.mime.types ) config.getProperty('grails.mime.types', Object).is( config.grails.mime.types ) - } } diff --git a/grails-core/src/test/groovy/org/grails/plugins/BinaryPluginSpec.groovy b/grails-core/src/test/groovy/org/grails/plugins/BinaryPluginSpec.groovy index 97dd110c29e..767b7a6babf 100644 --- a/grails-core/src/test/groovy/org/grails/plugins/BinaryPluginSpec.groovy +++ b/grails-core/src/test/groovy/org/grails/plugins/BinaryPluginSpec.groovy @@ -54,7 +54,6 @@ class BinaryPluginSpec extends Specification { binaryPlugin.binaryDescriptor != null } - def "Test load static resource from binary plugin"() { when: def resource = new MockBinaryPluginResource(testBinary.getBytes('UTF-8')) diff --git a/grails-data-graphql/core/src/main/groovy/org/grails/gorm/graphql/types/input/AbstractInputObjectTypeBuilder.groovy b/grails-data-graphql/core/src/main/groovy/org/grails/gorm/graphql/types/input/AbstractInputObjectTypeBuilder.groovy index 964b878e754..52617507a9e 100644 --- a/grails-data-graphql/core/src/main/groovy/org/grails/gorm/graphql/types/input/AbstractInputObjectTypeBuilder.groovy +++ b/grails-data-graphql/core/src/main/groovy/org/grails/gorm/graphql/types/input/AbstractInputObjectTypeBuilder.groovy @@ -26,8 +26,8 @@ import groovy.transform.CompileStatic import org.grails.datastore.mapping.model.PersistentEntity import org.grails.gorm.graphql.GraphQLEntityHelper import org.grails.gorm.graphql.entity.property.GraphQLDomainProperty -import org.grails.gorm.graphql.types.GraphQLPropertyType import org.grails.gorm.graphql.entity.property.manager.GraphQLDomainPropertyManager +import org.grails.gorm.graphql.types.GraphQLPropertyType import org.grails.gorm.graphql.types.GraphQLTypeManager import static graphql.schema.GraphQLInputObjectField.newInputObjectField diff --git a/grails-data-graphql/docs/src/main/docs/guide/gettingStarted.adoc b/grails-data-graphql/docs/src/main/docs/guide/gettingStarted.adoc index 6af6a313cfb..0f6fe7b7c99 100644 --- a/grails-data-graphql/docs/src/main/docs/guide/gettingStarted.adoc +++ b/grails-data-graphql/docs/src/main/docs/guide/gettingStarted.adoc @@ -19,7 +19,7 @@ under the License. == Standalone Projects -For standalone projects, it is up to the developer how and when the schema gets created. A mapping context is required to create a schema. The mapping context is available on all link:{gormapi}/org/grails/datastore/mapping/core/Datastore.html#getMappingContext()[datastore implementations]. See the link:http://gorm.grails.org/latest/hibernate/manual/index.html#outsideGrails[GORM documentation] for information on creating a datastore. +For standalone projects, it is up to the developer how and when the schema gets created. A mapping context is required to create a schema. The mapping context is available on all link:{gormapi}/org/grails/datastore/mapping/core/Datastore.html#getMappingContext()[datastore implementations]. See the link:https://gorm.grails.org/latest/hibernate/manual/index.html#outsideGrails[GORM documentation] for information on creating a datastore. The example below is the simplest way possible to generate a schema. @@ -66,7 +66,7 @@ Just by adding the `graphql = true` property on your domain, full CRUD capabilit Imagine you are building an API for a Conference. A talk can be presented by a single speaker. A speaker can have many talks within the conference. -A typical one-to-many relationship which in http://gorm.grails.org[GORM] +A typical one-to-many relationship which in https://gorm.grails.org[GORM] could be expressed with: [source, groovy] @@ -84,4 +84,4 @@ include::{sourcedir}/examples/grails-docs-app/grails-app/domain/demo/Talk.groovy ---- -TIP: GORM GraphQL plugin supports http://gorm.grails.org/latest/hibernate/manual/index.html#derivedProperties[Derived Properties] as illustrated in the previous example; `name` is derived property which concatenates `firstName` and `lastName` +TIP: GORM GraphQL plugin supports https://gorm.grails.org/latest/hibernate/manual/index.html#derivedProperties[Derived Properties] as illustrated in the previous example; `name` is derived property which concatenates `firstName` and `lastName` diff --git a/grails-data-graphql/docs/src/main/docs/guide/introduction.adoc b/grails-data-graphql/docs/src/main/docs/guide/introduction.adoc index 727d7a8c709..8e17636fd5e 100644 --- a/grails-data-graphql/docs/src/main/docs/guide/introduction.adoc +++ b/grails-data-graphql/docs/src/main/docs/guide/introduction.adoc @@ -19,9 +19,9 @@ under the License. image::logo.svg[GraphQL,100,100,float="left"] -The GORM GraphQL library provides functionality to generate a GraphQL schema based on your GORM entities. If you aren't sure what GraphQL is, please take a look at their link:http://graphql.org/[homepage]. +The GORM GraphQL library provides functionality to generate a GraphQL schema based on your GORM entities. If you aren't sure what GraphQL is, please take a look at their link:https://graphql.org/[homepage]. -The underlying implementation of the GraphQL specification used by this library is link:http://graphql-java.readthedocs.io/en/stable/[graphql-java]. +The underlying implementation of the GraphQL specification used by this library is link:https://graphql-java.readthedocs.io/en/stable/[graphql-java]. There are two different binaries available for use. The first is the core library which contains all of the logic for building the schema. The second is a Grails plugin which, on top of core, provides several features. @@ -35,7 +35,7 @@ CAUTION: Requires Java 8. Effort has been made to support GORM 6.0.x, however th == Grails Plugin -- A controller to receive and respond to GraphQL requests through HTTP, based on their link:http://graphql.org/learn/serving-over-http/[guidelines]. +- A controller to receive and respond to GraphQL requests through HTTP, based on their link:https://graphql.org/learn/serving-over-http/[guidelines]. - Generates the schema at startup with spring bean configuration to make it easy to extend. diff --git a/grails-data-graphql/docs/src/main/docs/guide/types.adoc b/grails-data-graphql/docs/src/main/docs/guide/types.adoc index 588b00b60eb..a3e98bbe64c 100644 --- a/grails-data-graphql/docs/src/main/docs/guide/types.adoc +++ b/grails-data-graphql/docs/src/main/docs/guide/types.adoc @@ -70,7 +70,7 @@ TIP: If you need to customize more than 1 manager, only a single bean needs to b Once you have access to the manager, registration of your own type is easy. In this example a type is being registered to handle a Mongo `ObjectId`. The type will be used to do conversion of arguments in GraphQL. -NOTE: This process only handles how an ObjectId will be created from either Java arguments, or arguments passed inline in the GraphQL query or mutation. For Grails applications, the process of rendering the ObjectID as json is handled by link:http://views.grails.org[JSON views]. To supply behavior for how an ObjectId is rendered, see the documentation for json views. For standalone projects, you are responsible for any conversions that may need to happen. +NOTE: This process only handles how an ObjectId will be created from either Java arguments, or arguments passed inline in the GraphQL query or mutation. For Grails applications, the process of rendering the ObjectID as json is handled by link:https://views.grails.org[JSON views]. To supply behavior for how an ObjectId is rendered, see the documentation for json views. For standalone projects, you are responsible for any conversions that may need to happen. [source,groovy] ---- diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages.properties index 6d72d209d5d..a1ac5a2fd78 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_cs_CZ.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_cs_CZ.properties index dc71c205fe9..24799b956a5 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_cs_CZ.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_cs_CZ.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_da.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_da.properties index c3ac9b19299..8effe79084c 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_da.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_da.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_de.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_de.properties index 18cd4a68b23..fccc6d561e3 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_de.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_de.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_es.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_es.properties index f8d257c24ac..c76df877613 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_es.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_es.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_fr.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_fr.properties index 93d4bc05f73..686f8722431 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_fr.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_fr.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_it.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_it.properties index 22353b03366..3bb0abe4030 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_it.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_it.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_ja.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_ja.properties index 10abcd38737..c23f5d014b9 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_ja.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_ja.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_nb.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_nb.properties index b2bcb4cfa5c..8485b66145e 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_nb.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_nb.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_nl.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_nl.properties index eb5245ccf5a..57360d5c39d 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_nl.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_nl.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_pl.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_pl.properties index efb954c5fff..199f7d26e0e 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_pl.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_pl.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_pt_BR.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_pt_BR.properties index 2244a405398..474cf326f9a 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_pt_BR.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_pt_BR.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_pt_PT.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_pt_PT.properties index d432eb5f6e0..27aa38dd2b2 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_pt_PT.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_pt_PT.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_ru.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_ru.properties index 2c7e7cdde79..c5e1d93446f 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_ru.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_ru.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_sv.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_sv.properties index 694ac13f23b..49079027e54 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_sv.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_sv.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_th.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_th.properties index 1219a71e4b4..9d2ba5ea9d5 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_th.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_th.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_zh_CN.properties b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_zh_CN.properties index 61a0705aef2..181f0a372e2 100644 --- a/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_zh_CN.properties +++ b/grails-data-graphql/examples/grails-docs-app/grails-app/i18n/messages_zh_CN.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages.properties index 6d72d209d5d..a1ac5a2fd78 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_cs_CZ.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_cs_CZ.properties index dc71c205fe9..24799b956a5 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_cs_CZ.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_cs_CZ.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_da.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_da.properties index c3ac9b19299..8effe79084c 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_da.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_da.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_de.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_de.properties index 18cd4a68b23..fccc6d561e3 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_de.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_de.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_es.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_es.properties index f8d257c24ac..c76df877613 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_es.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_es.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_fr.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_fr.properties index 93d4bc05f73..686f8722431 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_fr.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_fr.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_it.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_it.properties index 22353b03366..3bb0abe4030 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_it.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_it.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_ja.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_ja.properties index 10abcd38737..c23f5d014b9 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_ja.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_ja.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_nb.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_nb.properties index b2bcb4cfa5c..8485b66145e 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_nb.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_nb.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_nl.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_nl.properties index eb5245ccf5a..57360d5c39d 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_nl.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_nl.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_pl.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_pl.properties index efb954c5fff..199f7d26e0e 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_pl.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_pl.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_pt_BR.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_pt_BR.properties index 2244a405398..474cf326f9a 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_pt_BR.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_pt_BR.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_pt_PT.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_pt_PT.properties index d432eb5f6e0..27aa38dd2b2 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_pt_PT.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_pt_PT.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_ru.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_ru.properties index 2c7e7cdde79..c5e1d93446f 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_ru.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_ru.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_sv.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_sv.properties index 694ac13f23b..49079027e54 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_sv.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_sv.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_th.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_th.properties index 1219a71e4b4..9d2ba5ea9d5 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_th.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_th.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_zh_CN.properties b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_zh_CN.properties index 61a0705aef2..181f0a372e2 100644 --- a/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_zh_CN.properties +++ b/grails-data-graphql/examples/grails-multi-datastore-app/grails-app/i18n/messages_zh_CN.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages.properties index 6d72d209d5d..a1ac5a2fd78 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_cs_CZ.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_cs_CZ.properties index dc71c205fe9..24799b956a5 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_cs_CZ.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_cs_CZ.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_da.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_da.properties index c3ac9b19299..8effe79084c 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_da.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_da.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_de.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_de.properties index 18cd4a68b23..fccc6d561e3 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_de.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_de.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_es.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_es.properties index f8d257c24ac..c76df877613 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_es.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_es.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_fr.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_fr.properties index 93d4bc05f73..686f8722431 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_fr.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_fr.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_it.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_it.properties index 22353b03366..3bb0abe4030 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_it.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_it.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_ja.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_ja.properties index 10abcd38737..c23f5d014b9 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_ja.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_ja.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_nb.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_nb.properties index b2bcb4cfa5c..8485b66145e 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_nb.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_nb.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_nl.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_nl.properties index eb5245ccf5a..57360d5c39d 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_nl.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_nl.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_pl.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_pl.properties index efb954c5fff..199f7d26e0e 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_pl.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_pl.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_pt_BR.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_pt_BR.properties index 2244a405398..474cf326f9a 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_pt_BR.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_pt_BR.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_pt_PT.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_pt_PT.properties index d432eb5f6e0..27aa38dd2b2 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_pt_PT.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_pt_PT.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_ru.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_ru.properties index 2c7e7cdde79..c5e1d93446f 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_ru.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_ru.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_sv.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_sv.properties index 694ac13f23b..49079027e54 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_sv.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_sv.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_th.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_th.properties index 1219a71e4b4..9d2ba5ea9d5 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_th.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_th.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_zh_CN.properties b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_zh_CN.properties index 61a0705aef2..181f0a372e2 100644 --- a/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_zh_CN.properties +++ b/grails-data-graphql/examples/grails-tenant-app/grails-app/i18n/messages_zh_CN.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages.properties index 6d72d209d5d..a1ac5a2fd78 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_cs_CZ.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_cs_CZ.properties index dc71c205fe9..24799b956a5 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_cs_CZ.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_cs_CZ.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_da.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_da.properties index c3ac9b19299..8effe79084c 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_da.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_da.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_de.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_de.properties index 18cd4a68b23..fccc6d561e3 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_de.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_de.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_es.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_es.properties index f8d257c24ac..c76df877613 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_es.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_es.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_fr.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_fr.properties index 93d4bc05f73..686f8722431 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_fr.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_fr.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_it.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_it.properties index 22353b03366..3bb0abe4030 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_it.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_it.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_ja.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_ja.properties index 10abcd38737..c23f5d014b9 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_ja.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_ja.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_nb.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_nb.properties index b2bcb4cfa5c..8485b66145e 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_nb.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_nb.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_nl.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_nl.properties index eb5245ccf5a..57360d5c39d 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_nl.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_nl.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_pl.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_pl.properties index efb954c5fff..199f7d26e0e 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_pl.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_pl.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_pt_BR.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_pt_BR.properties index 2244a405398..474cf326f9a 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_pt_BR.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_pt_BR.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_pt_PT.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_pt_PT.properties index d432eb5f6e0..27aa38dd2b2 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_pt_PT.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_pt_PT.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_ru.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_ru.properties index 2c7e7cdde79..c5e1d93446f 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_ru.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_ru.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_sv.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_sv.properties index 694ac13f23b..49079027e54 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_sv.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_sv.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_th.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_th.properties index 1219a71e4b4..9d2ba5ea9d5 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_th.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_th.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_zh_CN.properties b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_zh_CN.properties index 61a0705aef2..181f0a372e2 100644 --- a/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_zh_CN.properties +++ b/grails-data-graphql/examples/grails-test-app/grails-app/i18n/messages_zh_CN.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-graphql/gradle.properties b/grails-data-graphql/gradle.properties index da3818dd2e7..f640df81f2e 100644 --- a/grails-data-graphql/gradle.properties +++ b/grails-data-graphql/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-hibernate5/boot-plugin/build.gradle b/grails-data-hibernate5/boot-plugin/build.gradle index 5a054dca254..5c7cc56ca44 100644 --- a/grails-data-hibernate5/boot-plugin/build.gradle +++ b/grails-data-hibernate5/boot-plugin/build.gradle @@ -62,4 +62,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/hibernate5-test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-data-hibernate5/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/autoconfigure/HibernateGormAutoConfiguration.groovy b/grails-data-hibernate5/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/autoconfigure/HibernateGormAutoConfiguration.groovy index 72fd05dfb0d..8e5a5e581e4 100644 --- a/grails-data-hibernate5/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/autoconfigure/HibernateGormAutoConfiguration.groovy +++ b/grails-data-hibernate5/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/autoconfigure/HibernateGormAutoConfiguration.groovy @@ -24,9 +24,7 @@ import org.springframework.beans.BeansException import org.springframework.beans.factory.BeanFactory import org.springframework.beans.factory.BeanFactoryAware import org.springframework.beans.factory.annotation.Autowired -import org.springframework.beans.factory.config.ConfigurableBeanFactory import org.springframework.beans.factory.config.ConfigurableListableBeanFactory -import org.springframework.beans.factory.support.BeanDefinitionRegistry import org.springframework.boot.autoconfigure.AutoConfigurationPackages import org.springframework.boot.autoconfigure.AutoConfigureAfter import org.springframework.boot.autoconfigure.AutoConfigureBefore @@ -38,14 +36,8 @@ import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfigurat import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContextAware import org.springframework.context.ConfigurableApplicationContext -import org.springframework.context.EnvironmentAware -import org.springframework.context.ResourceLoaderAware import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.ImportBeanDefinitionRegistrar -import org.springframework.core.env.Environment -import org.springframework.core.io.ResourceLoader -import org.springframework.core.type.AnnotationMetadata import org.springframework.transaction.PlatformTransactionManager import javax.sql.DataSource @@ -64,7 +56,7 @@ import java.beans.Introspector @ConditionalOnMissingBean(type = "grails.orm.bootstrap.HibernateDatastoreSpringInitializer") @AutoConfigureAfter(DataSourceAutoConfiguration) @AutoConfigureBefore([HibernateJpaAutoConfiguration]) -class HibernateGormAutoConfiguration implements ApplicationContextAware,BeanFactoryAware { +class HibernateGormAutoConfiguration implements ApplicationContextAware, BeanFactoryAware { BeanFactory beanFactory @@ -77,24 +69,23 @@ class HibernateGormAutoConfiguration implements ApplicationContextAware,BeanFact HibernateDatastore hibernateDatastore() { List packageNames = AutoConfigurationPackages.get(this.beanFactory) List packages = [] - for(name in packageNames) { + for (name in packageNames) { Package pkg = Package.getPackage(name) - if(pkg != null) { + if (pkg != null) { packages.add(pkg) } } ConfigurableListableBeanFactory beanFactory = applicationContext.beanFactory HibernateDatastore datastore - if(dataSource == null) { + if (dataSource == null) { datastore = new HibernateDatastore( applicationContext.getEnvironment(), new ConfigurableApplicationContextEventPublisher(applicationContext), packages as Package[] ) beanFactory.registerSingleton("dataSource", datastore.getDataSource()) - } - else { + } else { datastore = new HibernateDatastore( dataSource, applicationContext.getEnvironment(), @@ -103,17 +94,17 @@ class HibernateGormAutoConfiguration implements ApplicationContextAware,BeanFact ) } - for(Service service in datastore.getServices()) { + for (Service service in datastore.getServices()) { Class serviceClass = service.getClass() grails.gorm.services.Service ann = serviceClass.getAnnotation(grails.gorm.services.Service) String serviceName = ann?.name() - if(serviceName == null) { + if (serviceName == null) { serviceName = Introspector.decapitalize(serviceClass.simpleName) } - if(!applicationContext.containsBean(serviceName)) { + if (!applicationContext.containsBean(serviceName)) { applicationContext.beanFactory.registerSingleton( - serviceName, - service + serviceName, + service ) } } @@ -132,9 +123,9 @@ class HibernateGormAutoConfiguration implements ApplicationContextAware,BeanFact @Override void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - if(!(applicationContext instanceof ConfigurableApplicationContext)) { + if (!(applicationContext instanceof ConfigurableApplicationContext)) { throw new IllegalArgumentException("Neo4jAutoConfiguration requires an instance of ConfigurableApplicationContext") } - this.applicationContext = (ConfigurableApplicationContext)applicationContext + this.applicationContext = (ConfigurableApplicationContext) applicationContext } } diff --git a/grails-data-hibernate5/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/compiler/GormCompilerAutoConfiguration.groovy b/grails-data-hibernate5/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/compiler/GormCompilerAutoConfiguration.groovy index 860c85cbec0..0e998f3c1fc 100644 --- a/grails-data-hibernate5/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/compiler/GormCompilerAutoConfiguration.groovy +++ b/grails-data-hibernate5/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/compiler/GormCompilerAutoConfiguration.groovy @@ -31,16 +31,17 @@ import org.grails.cli.compiler.DependencyCustomizer * */ @CompileStatic -class GormCompilerAutoConfiguration extends CompilerAutoConfiguration{ +class GormCompilerAutoConfiguration extends CompilerAutoConfiguration { + @Override boolean matches(ClassNode classNode) { - return AstUtils.hasAtLeastOneAnnotation(classNode, "grails.persistence.Entity", "grails.gorm.annotation.Entity" ,"Entity") + return AstUtils.hasAtLeastOneAnnotation(classNode, "grails.persistence.Entity", "grails.gorm.annotation.Entity", "Entity") } @Override void applyDependencies(DependencyCustomizer dependencies) throws CompilationFailedException { dependencies.ifAnyMissingClasses("grails.persistence.Entity", "grails.gorm.annotation.Entity") - .add("grails-data-hibernate5-core") + .add("grails-data-hibernate5-core") } @Override diff --git a/grails-data-hibernate5/core/build.gradle b/grails-data-hibernate5/core/build.gradle index 33fb9277d4c..59984c45af0 100644 --- a/grails-data-hibernate5/core/build.gradle +++ b/grails-data-hibernate5/core/build.gradle @@ -93,4 +93,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/grails-data-tck-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-data-hibernate5/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-data-hibernate5/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java index c4dea433d0c..6ea79b562eb 100644 --- a/grails-data-hibernate5/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java +++ b/grails-data-hibernate5/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java @@ -19,28 +19,29 @@ package grails.orm; import groovy.lang.GroovySystem; +import jakarta.persistence.metamodel.Attribute; +import jakarta.persistence.metamodel.PluralAttribute; import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.orm.hibernate.GrailsHibernateTemplate; import org.grails.orm.hibernate.HibernateDatastore; import org.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.grails.orm.hibernate.query.*; -import org.grails.datastore.mapping.query.api.QueryableCriteria; +import org.grails.orm.hibernate.query.AbstractHibernateCriteriaBuilder; +import org.grails.orm.hibernate.query.AbstractHibernateQuery; +import org.grails.orm.hibernate.query.HibernateProjectionAdapter; +import org.grails.orm.hibernate.query.HibernateQuery; import org.hibernate.Criteria; -import org.hibernate.HibernateException; import org.hibernate.SessionFactory; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.Projection; import org.hibernate.criterion.ProjectionList; import org.hibernate.criterion.Projections; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.sql.JoinType; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.Type; import org.springframework.orm.hibernate5.SessionHolder; import org.springframework.transaction.support.TransactionSynchronizationManager; -import jakarta.persistence.metamodel.Attribute; -import jakarta.persistence.metamodel.PluralAttribute; import java.util.List; import java.util.Map; @@ -72,6 +73,7 @@ * @author Graeme Rocher */ public class HibernateCriteriaBuilder extends AbstractHibernateCriteriaBuilder { + /* * Define constants which may be used inside of criteria queries * to refer to standard Hibernate Type instances. @@ -136,7 +138,7 @@ public HibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory * @param alias The alias to assign to the joined association (for later reference). * @param joinType The type of join to use. * @return this (for method chaining) - * @throws HibernateException Indicates a problem creating the sub criteria + * @throws org.hibernate.HibernateException Indicates a problem creating the sub criteria * @see #createAlias(String, String) */ public Criteria createAlias(String associationPath, String alias, int joinType) { @@ -155,7 +157,7 @@ protected void cacheCriteriaMapping() { protected Class getClassForAssociationType(Attribute type) { if (type instanceof PluralAttribute) { - return ((PluralAttribute)type).getElementType().getJavaType(); + return ((PluralAttribute) type).getElementType().getJavaType(); } return type.getJavaType(); } @@ -188,19 +190,16 @@ public org.grails.datastore.mapping.query.api.Criteria rlike(String propertyName @Override protected void createCriteriaInstance() { - { - if (TransactionSynchronizationManager.hasResource(sessionFactory)) { - participate = true; - hibernateSession = ((SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory)).getSession(); - } - else { - hibernateSession = sessionFactory.openSession(); - } - - criteria = hibernateSession.createCriteria(targetClass); - cacheCriteriaMapping(); - criteriaMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(criteria.getClass()); + if (TransactionSynchronizationManager.hasResource(sessionFactory)) { + participate = true; + hibernateSession = ((SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory)).getSession(); + } else { + hibernateSession = sessionFactory.openSession(); } + + criteria = hibernateSession.createCriteria(targetClass); + cacheCriteriaMapping(); + criteriaMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(criteria.getClass()); } @Override @@ -218,13 +217,12 @@ public static org.hibernate.criterion.DetachedCriteria getHibernateDetachedCrite Class targetClass = persistentEntity.getJavaClass(); org.hibernate.criterion.DetachedCriteria detachedCriteria; - if(alias != null) { + if (alias != null) { detachedCriteria = org.hibernate.criterion.DetachedCriteria.forClass(targetClass, alias); - } - else { + } else { detachedCriteria = org.hibernate.criterion.DetachedCriteria.forClass(targetClass); } - populateHibernateDetachedCriteria(new HibernateQuery(detachedCriteria,persistentEntity), detachedCriteria, queryableCriteria); + populateHibernateDetachedCriteria(new HibernateQuery(detachedCriteria, persistentEntity), detachedCriteria, queryableCriteria); return detachedCriteria; } diff --git a/grails-data-hibernate5/core/src/main/groovy/grails/orm/PagedResultList.java b/grails-data-hibernate5/core/src/main/groovy/grails/orm/PagedResultList.java index 6332bdefcbc..4cef3be5ff0 100644 --- a/grails-data-hibernate5/core/src/main/groovy/grails/orm/PagedResultList.java +++ b/grails-data-hibernate5/core/src/main/groovy/grails/orm/PagedResultList.java @@ -37,7 +37,7 @@ * @since 1.0 * @deprecated Use {@link org.grails.orm.hibernate.query.PagedResultList} instead. */ -@SuppressWarnings({"unchecked","rawtypes"}) +@SuppressWarnings({"unchecked", "rawtypes"}) @Deprecated public class PagedResultList extends grails.gorm.PagedResultList { @@ -84,7 +84,7 @@ public Integer doInHibernate(Session session) throws HibernateException, SQLExce } totalCriteria.setProjection(impl.getProjection()); totalCriteria.setProjection(Projections.rowCount()); - return ((Number)totalCriteria.uniqueResult()).intValue(); + return ((Number) totalCriteria.uniqueResult()).intValue(); } }); } diff --git a/grails-data-hibernate5/core/src/main/groovy/grails/orm/RlikeExpression.java b/grails-data-hibernate5/core/src/main/groovy/grails/orm/RlikeExpression.java index d16c458f031..3c10f6e2201 100644 --- a/grails-data-hibernate5/core/src/main/groovy/grails/orm/RlikeExpression.java +++ b/grails-data-hibernate5/core/src/main/groovy/grails/orm/RlikeExpression.java @@ -23,7 +23,11 @@ import org.hibernate.criterion.CriteriaQuery; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.MatchMode; -import org.hibernate.dialect.*; +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.H2Dialect; +import org.hibernate.dialect.MySQLDialect; +import org.hibernate.dialect.Oracle8iDialect; +import org.hibernate.dialect.PostgreSQL81Dialect; import org.hibernate.engine.spi.TypedValue; /** @@ -79,7 +83,7 @@ private boolean isOracleDialect(Dialect dialect) { } public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { - return new TypedValue[] { criteriaQuery.getTypedValue(criteria, propertyName, value.toString()) }; + return new TypedValue[]{criteriaQuery.getTypedValue(criteria, propertyName, value.toString())}; } @Override diff --git a/grails-data-hibernate5/core/src/main/groovy/grails/orm/hibernate/HibernateEntity.groovy b/grails-data-hibernate5/core/src/main/groovy/grails/orm/hibernate/HibernateEntity.groovy index 7339430b01a..38ebc1cc8a6 100644 --- a/grails-data-hibernate5/core/src/main/groovy/grails/orm/hibernate/HibernateEntity.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/grails/orm/hibernate/HibernateEntity.groovy @@ -82,6 +82,6 @@ trait HibernateEntity extends GormEntity { @Generated private static AbstractHibernateGormStaticApi currentHibernateStaticApi() { - (AbstractHibernateGormStaticApi)GormEnhancer.findStaticApi(this) + (AbstractHibernateGormStaticApi) GormEnhancer.findStaticApi(this) } } \ No newline at end of file diff --git a/grails-data-hibernate5/core/src/main/groovy/grails/orm/hibernate/annotation/ManagedEntity.java b/grails-data-hibernate5/core/src/main/groovy/grails/orm/hibernate/annotation/ManagedEntity.java index 5dc5f3488bc..0bcb799908d 100644 --- a/grails-data-hibernate5/core/src/main/groovy/grails/orm/hibernate/annotation/ManagedEntity.java +++ b/grails-data-hibernate5/core/src/main/groovy/grails/orm/hibernate/annotation/ManagedEntity.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package grails.gorm.hibernate.annotation; import org.codehaus.groovy.transform.GroovyASTTransformationClass; diff --git a/grails-data-hibernate5/core/src/main/groovy/grails/orm/hibernate/mapping/MappingBuilder.groovy b/grails-data-hibernate5/core/src/main/groovy/grails/orm/hibernate/mapping/MappingBuilder.groovy index fb16cc64046..f43e2db8e31 100644 --- a/grails-data-hibernate5/core/src/main/groovy/grails/orm/hibernate/mapping/MappingBuilder.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/grails/orm/hibernate/mapping/MappingBuilder.groovy @@ -55,6 +55,7 @@ class MappingBuilder { @CompileStatic private static class ClosureMappingDefinition implements MappingDefinition { + final Closure definition private Mapping mapping @@ -69,7 +70,7 @@ class MappingBuilder { @Override Mapping build() { - if(mapping == null) { + if (mapping == null) { mapping = Mapping.configureNew(definition) } return mapping diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateDatastore.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateDatastore.java index 425bf01dc9e..66031a74a99 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateDatastore.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateDatastore.java @@ -20,16 +20,25 @@ import grails.gorm.multitenancy.Tenants; import groovy.lang.Closure; -import org.grails.datastore.gorm.validation.registry.support.ValidatorRegistries; +import jakarta.annotation.PreDestroy; import org.grails.datastore.gorm.events.AutoTimestampEventListener; +import org.grails.datastore.gorm.jdbc.schema.DefaultSchemaHandler; +import org.grails.datastore.gorm.jdbc.schema.SchemaHandler; +import org.grails.datastore.gorm.validation.registry.support.ValidatorRegistries; import org.grails.datastore.mapping.config.Settings; import org.grails.datastore.mapping.core.AbstractDatastore; import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.DatastoreAware; -import org.grails.datastore.mapping.core.connections.*; +import org.grails.datastore.mapping.core.connections.ConnectionSource; +import org.grails.datastore.mapping.core.connections.ConnectionSources; +import org.grails.datastore.mapping.core.connections.MultipleConnectionSourceCapableDatastore; +import org.grails.datastore.mapping.core.connections.SingletonConnectionSources; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.multitenancy.*; +import org.grails.datastore.mapping.multitenancy.AllTenantsResolver; +import org.grails.datastore.mapping.multitenancy.MultiTenancySettings; +import org.grails.datastore.mapping.multitenancy.SchemaMultiTenantCapableDatastore; +import org.grails.datastore.mapping.multitenancy.TenantResolver; import org.grails.datastore.mapping.multitenancy.exceptions.TenantNotFoundException; import org.grails.datastore.mapping.multitenancy.resolvers.FixedTenantResolver; import org.grails.datastore.mapping.transactions.TransactionCapableDatastore; @@ -37,16 +46,17 @@ import org.grails.orm.hibernate.cfg.HibernateMappingContext; import org.grails.orm.hibernate.connections.HibernateConnectionSource; import org.grails.orm.hibernate.connections.HibernateConnectionSourceSettings; -import org.grails.datastore.gorm.jdbc.schema.DefaultSchemaHandler; -import org.grails.datastore.gorm.jdbc.schema.SchemaHandler; import org.grails.orm.hibernate.event.listener.AbstractHibernateEventListener; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.beans.BeanUtils; -import org.springframework.context.*; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.MessageSource; +import org.springframework.context.MessageSourceAware; import org.springframework.core.env.PropertyResolver; -import jakarta.annotation.PreDestroy; import javax.sql.DataSource; import java.io.Closeable; import java.io.IOException; @@ -109,18 +119,18 @@ protected AbstractHibernateDatastore(ConnectionSources schemaHandlerClass = settings.getDataSource().getSchemaHandler(); this.schemaHandler = BeanUtils.instantiateClass(schemaHandlerClass); this.tenantResolver = multiTenantResolver; - if(multiTenantResolver instanceof DatastoreAware) { + if (multiTenantResolver instanceof DatastoreAware) { ((DatastoreAware) multiTenantResolver).setDatastore(this); } } protected AbstractHibernateDatastore(MappingContext mappingContext, SessionFactory sessionFactory, PropertyResolver config, ApplicationContext applicationContext, String dataSourceName) { super(mappingContext, config, (ConfigurableApplicationContext) applicationContext); - this.connectionSources = new SingletonConnectionSources<>(new HibernateConnectionSource(dataSourceName, sessionFactory, null, null ), config); + this.connectionSources = new SingletonConnectionSources<>(new HibernateConnectionSource(dataSourceName, sessionFactory, null, null), config); this.sessionFactory = sessionFactory; this.dataSourceName = dataSourceName; initializeConverters(mappingContext); - if(applicationContext != null) { + if (applicationContext != null) { setApplicationContext(applicationContext); } @@ -128,11 +138,10 @@ protected AbstractHibernateDatastore(MappingContext mappingContext, SessionFacto passReadOnlyToHibernate = config.getProperty(CONFIG_PROPERTY_PASS_READONLY_TO_HIBERNATE, Boolean.class, false); isCacheQueries = config.getProperty(CONFIG_PROPERTY_CACHE_QUERIES, Boolean.class, false); - if( config.getProperty(SETTING_AUTO_FLUSH, Boolean.class, false) ) { + if (config.getProperty(SETTING_AUTO_FLUSH, Boolean.class, false)) { this.defaultFlushModeName = FlushMode.AUTO.name(); defaultFlushMode = FlushMode.AUTO.level; - } - else { + } else { FlushMode flushMode = config.getProperty(SETTING_FLUSH_MODE, FlushMode.class, FlushMode.COMMIT); this.defaultFlushModeName = flushMode.name(); defaultFlushMode = flushMode.level; @@ -167,10 +176,9 @@ public MultiTenancySettings.MultiTenancyMode getMultiTenancyMode() { @Override public Datastore getDatastoreForTenantId(Serializable tenantId) { - if(getMultiTenancyMode() == MultiTenancySettings.MultiTenancyMode.DATABASE) { + if (getMultiTenancyMode() == MultiTenancySettings.MultiTenancyMode.DATABASE) { return getDatastoreForConnection(tenantId.toString()); - } - else { + } else { return this; } } @@ -191,22 +199,20 @@ public ConnectionSources getC * @param connectionName The name of the connection * @return The child data store */ - public abstract AbstractHibernateDatastore getDatastoreForConnection(String connectionName); + public abstract AbstractHibernateDatastore getDatastoreForConnection(String connectionName); public Iterable resolveTenantIds() { - if(this.tenantResolver instanceof AllTenantsResolver) { - return ((AllTenantsResolver)tenantResolver).resolveTenantIds(); - } - else if(this.multiTenantMode == MultiTenancySettings.MultiTenancyMode.DATABASE) { + if (this.tenantResolver instanceof AllTenantsResolver) { + return ((AllTenantsResolver) tenantResolver).resolveTenantIds(); + } else if (this.multiTenantMode == MultiTenancySettings.MultiTenancyMode.DATABASE) { List tenantIds = new ArrayList<>(); for (ConnectionSource connectionSource : this.connectionSources.getAllConnectionSources()) { - if(!ConnectionSource.DEFAULT.equals(connectionSource.getName())) { + if (!ConnectionSource.DEFAULT.equals(connectionSource.getName())) { tenantIds.add(connectionSource.getName()); } } return tenantIds; - } - else { + } else { return Collections.emptyList(); } } @@ -260,7 +266,7 @@ public SessionFactory getSessionFactory() { * @return The {@link DataSource} being used by this datastore instance */ public DataSource getDataSource() { - return ((HibernateConnectionSource)this.connectionSources.getDefaultConnectionSource()).getDataSource(); + return ((HibernateConnectionSource) this.connectionSources.getDefaultConnectionSource()).getDataSource(); } // for testing @@ -286,7 +292,7 @@ public String getDataSourceName() { * Execute the given operation with the given flush mode * * @param flushMode - * @param callable The callable + * @param callable The callable */ public abstract void withFlushMode(FlushMode flushMode, Callable callable); @@ -366,28 +372,25 @@ public T withNewSession(final Closure callable) { @Override public T1 withNewSession(Serializable tenantId, Closure callable) { - if(getMultiTenancyMode() == MultiTenancySettings.MultiTenancyMode.DATABASE) { + if (getMultiTenancyMode() == MultiTenancySettings.MultiTenancyMode.DATABASE) { AbstractHibernateDatastore datastore = getDatastoreForConnection(tenantId.toString()); SessionFactory sessionFactory = datastore.getSessionFactory(); - return datastore.getHibernateTemplate().executeWithExistingOrCreateNewSession( sessionFactory, callable); - } - else { + return datastore.getHibernateTemplate().executeWithExistingOrCreateNewSession(sessionFactory, callable); + } else { return withNewSession(callable); } } - /** * Enable the tenant id filter for the given datastore and entity * */ public void enableMultiTenancyFilter() { Serializable currentId = Tenants.currentId(this); - if(ConnectionSource.DEFAULT.equals(currentId)) { + if (ConnectionSource.DEFAULT.equals(currentId)) { disableMultiTenancyFilter(); - } - else { + } else { getHibernateTemplate() .getSessionFactory() .getCurrentSession() @@ -396,21 +399,20 @@ public void enableMultiTenancyFilter() { } } - /** * Disable the tenant id filter for the given datastore and entity */ public void disableMultiTenancyFilter() { getHibernateTemplate() - .getSessionFactory() - .getCurrentSession() - .disableFilter(GormProperties.TENANT_IDENTITY); + .getSessionFactory() + .getCurrentSession() + .disableFilter(GormProperties.TENANT_IDENTITY); } protected Closure prepareMultiTenantClosure(final Closure callable) { final boolean isMultiTenant = getMultiTenancyMode() == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR; Closure multiTenantCallable; - if(isMultiTenant) { + if (isMultiTenant) { multiTenantCallable = new Closure(this) { @Override public T call(Object... args) { @@ -422,8 +424,7 @@ public T call(Object... args) { } } }; - } - else { + } else { multiTenantCallable = callable; } return multiTenantCallable; diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy index 7adadd48231..4d9d9c7e5f8 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy @@ -21,29 +21,32 @@ package org.grails.orm.hibernate import grails.gorm.validation.CascadingValidator import groovy.transform.CompileDynamic import groovy.transform.CompileStatic +import org.grails.datastore.gorm.GormInstanceApi import org.grails.datastore.gorm.GormValidateable import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.dirty.checking.DirtyCheckable +import org.grails.datastore.mapping.engine.event.ValidationEvent +import org.grails.datastore.mapping.model.PersistentEntity +import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.mapping.model.config.GormProperties +import org.grails.datastore.mapping.model.types.Association import org.grails.datastore.mapping.model.types.Embedded +import org.grails.datastore.mapping.model.types.ToOne import org.grails.datastore.mapping.proxy.ProxyHandler import org.grails.datastore.mapping.reflect.ClassUtils import org.grails.datastore.mapping.reflect.EntityReflector import org.grails.orm.hibernate.support.HibernateRuntimeUtils -import org.grails.datastore.gorm.GormInstanceApi -import org.grails.datastore.mapping.engine.event.ValidationEvent -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.mapping.model.types.Association -import org.grails.datastore.mapping.model.types.ToOne -import org.hibernate.* +import org.hibernate.FlushMode +import org.hibernate.HibernateException +import org.hibernate.LockMode +import org.hibernate.Session +import org.hibernate.SessionFactory import org.springframework.beans.BeanWrapperImpl import org.springframework.beans.InvalidPropertyException import org.springframework.dao.DataAccessException import org.springframework.validation.Errors import org.springframework.validation.Validator - /** * Abstract extension of the {@link GormInstanceApi} class that provides common logic shared by Hibernate 3 and Hibernate 4 * @@ -52,6 +55,7 @@ import org.springframework.validation.Validator */ @CompileStatic abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { + private static final String ARGUMENT_VALIDATE = "validate" private static final String ARGUMENT_DEEP_VALIDATE = "deepValidate" private static final String ARGUMENT_FLUSH = "flush" @@ -79,7 +83,6 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { static final ThreadLocal insertActiveThreadLocal = new ThreadLocal() - protected SessionFactory sessionFactory protected ClassLoader classLoader protected IHibernateTemplate hibernateTemplate @@ -122,7 +125,7 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { datastore.applicationEventPublisher?.publishEvent new ValidationEvent(datastore, target) if (validator instanceof CascadingValidator) { - ((CascadingValidator)validator).validate target, errors, deepValidate + ((CascadingValidator) validator).validate target, errors, deepValidate } else if (validator instanceof org.grails.datastore.gorm.validation.CascadingValidator) { ((org.grails.datastore.gorm.validation.CascadingValidator) validator).validate target, errors, deepValidate } else { @@ -130,7 +133,7 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { } if (errors.hasErrors()) { - handleValidationError(domainClass,target,errors) + handleValidationError(domainClass, target, errors) if (shouldFail(arguments)) { throw validationException.newInstance("Validation Error(s) occurred during save()", errors) } @@ -154,11 +157,9 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { try { if (shouldInsert(arguments)) { return performInsert(target, shouldFlush) - } - else if(shouldMerge(arguments)) { + } else if (shouldMerge(arguments)) { return performMerge(target, shouldFlush) - } - else { + } else { if (target instanceof DirtyCheckable && markDirty) { target.markDirty() } @@ -202,7 +203,7 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { try { hibernateTemplate.execute { Session session -> session.delete instance - if(flush) { + if (flush) { session.flush() } } @@ -264,7 +265,7 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { if (flush) { flushSession session } - return (D)merged + return (D) merged } } @@ -303,8 +304,8 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { EntityReflector reflector = datastore.mappingContext.getEntityReflector(entity) IHibernateTemplate t = this.hibernateTemplate for (PersistentProperty prop in entity.associations) { - if(prop instanceof ToOne && !(prop instanceof Embedded)) { - ToOne toOne = (ToOne)prop + if (prop instanceof ToOne && !(prop instanceof Embedded)) { + ToOne toOne = (ToOne) prop def propertyName = prop.name def propValue = reflector.getProperty(target, propertyName) @@ -318,13 +319,13 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { } def identity = otherSide.identity - if(identity == null) { + if (identity == null) { continue } def otherSideReflector = datastore.mappingContext.getEntityReflector(otherSide) try { - def id = (Serializable)otherSideReflector.getProperty(propValue, identity.name); + def id = (Serializable) otherSideReflector.getProperty(propValue, identity.name); if (id) { final Object associatedInstance = t.get(prop.type, id) if (associatedInstance) { @@ -343,7 +344,7 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { /** * Checks whether validation should be performed * @return true if the domain class should be validated - * @param arguments The arguments to the validate method + * @param arguments The arguments to the validate method * @param domainClass The domain class */ private boolean shouldValidate(Map arguments, PersistentEntity entity) { @@ -395,7 +396,7 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { if (entity) { for (Association association in entity.associations) { if (association instanceof ToOne && !association instanceof Embedded) { - if(proxyHandler.isInitialized(target, association.name)) { + if (proxyHandler.isInitialized(target, association.name)) { def bean = new BeanWrapperImpl(target) def propertyValue = bean.getPropertyValue(association.name) if (propertyValue != null) { @@ -444,10 +445,9 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { */ @CompileDynamic protected void setErrorsOnInstance(Object target, Errors errors) { - if(target instanceof GormValidateable) { - ((GormValidateable)target).setErrors(errors) - } - else { + if (target instanceof GormValidateable) { + ((GormValidateable) target).setErrors(errors) + } else { target."$GormProperties.ERRORS" = errors } } @@ -476,7 +476,7 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { if (target.hasProperty(GormProperties.VERSION)) { Object version = target."${GormProperties.VERSION}" if (version instanceof Long) { - target."${GormProperties.VERSION}" = ++((Long)version) + target."${GormProperties.VERSION}" = ++((Long) version) } } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy index 0f396c24ca1..4749664ea00 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy @@ -21,18 +21,21 @@ package org.grails.orm.hibernate import groovy.transform.CompileDynamic import groovy.transform.CompileStatic +import jakarta.persistence.criteria.CriteriaBuilder +import jakarta.persistence.criteria.CriteriaQuery +import jakarta.persistence.criteria.Expression +import jakarta.persistence.criteria.Root +import org.grails.datastore.gorm.GormStaticApi +import org.grails.datastore.gorm.finders.DynamicFinder +import org.grails.datastore.gorm.finders.FinderMethod import org.grails.datastore.mapping.proxy.ProxyHandler import org.grails.datastore.mapping.reflect.ClassUtils import org.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder import org.grails.orm.hibernate.cfg.CompositeIdentity import org.grails.orm.hibernate.exceptions.GrailsQueryException - import org.grails.orm.hibernate.query.GrailsHibernateQueryUtils import org.grails.orm.hibernate.query.HibernateHqlQuery import org.grails.orm.hibernate.support.HibernateRuntimeUtils -import org.grails.datastore.gorm.GormStaticApi -import org.grails.datastore.gorm.finders.DynamicFinder -import org.grails.datastore.gorm.finders.FinderMethod import org.hibernate.Criteria import org.hibernate.FlushMode import org.hibernate.Session @@ -45,11 +48,6 @@ import org.hibernate.transform.DistinctRootEntityResultTransformer import org.springframework.core.convert.ConversionService import org.springframework.transaction.PlatformTransactionManager -import jakarta.persistence.criteria.CriteriaBuilder -import jakarta.persistence.criteria.CriteriaQuery -import jakarta.persistence.criteria.Expression -import jakarta.persistence.criteria.Root - /** * Abstract implementation of the Hibernate static API for GORM, providing String-based method implementations * @@ -73,7 +71,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { AbstractHibernateGormStaticApi( Class persistentClass, - HibernateDatastore datastore, + HibernateDatastore datastore, List finders, PlatformTransactionManager transactionManager) { super(persistentClass, datastore, finders, transactionManager) @@ -81,7 +79,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { this.conversionService = datastore.mappingContext.conversionService this.proxyHandler = datastore.mappingContext.proxyHandler this.hibernateSession = new HibernateSession( - (HibernateDatastore)datastore, + (HibernateDatastore) datastore, hibernateTemplate.getSessionFactory(), hibernateTemplate.getFlushMode() ) @@ -111,32 +109,31 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { } id = convertIdentifier(id) - + if (id == null) { return null } - if(persistentEntity.isMultiTenant()) { + if (persistentEntity.isMultiTenant()) { // for multi-tenant entities we process get(..) via a query - (D)hibernateTemplate.execute( { Session session -> + (D) hibernateTemplate.execute({ Session session -> CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder() CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass) Root queryRoot = criteriaQuery.from(persistentEntity.javaClass) - criteriaQuery = criteriaQuery.where ( + criteriaQuery = criteriaQuery.where( //TODO: Remove explicit type cast once GROOVY-9460 criteriaBuilder.equal((Expression) queryRoot.get(persistentEntity.identity.name), id) ) Query criteria = session.createQuery(criteriaQuery) HibernateHqlQuery hibernateHqlQuery = new HibernateHqlQuery( hibernateSession, persistentEntity, criteria) - return proxyHandler.unwrap( hibernateHqlQuery.singleResult() ) - } ) - } - else { + return proxyHandler.unwrap(hibernateHqlQuery.singleResult()) + }) + } else { // for non multi-tenant entities we process get(..) via the second level cache - return (D)proxyHandler.unwrap( - hibernateTemplate.get(persistentEntity.javaClass, id) + return (D) proxyHandler.unwrap( + hibernateTemplate.get(persistentEntity.javaClass, id) ) } @@ -152,39 +149,38 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { if (id == null) { return null } - - (D)hibernateTemplate.execute( { Session session -> + + (D) hibernateTemplate.execute({ Session session -> CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder() CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass) Root queryRoot = criteriaQuery.from(persistentEntity.javaClass) - criteriaQuery = criteriaQuery.where ( + criteriaQuery = criteriaQuery.where( //TODO: Remove explicit type cast once GROOVY-9460 - criteriaBuilder.equal((Expression) queryRoot.get(persistentEntity.identity.name), id) + criteriaBuilder.equal((Expression) queryRoot.get(persistentEntity.identity.name), id) ) Query criteria = session.createQuery(criteriaQuery) - .setHint(QueryHints.HINT_READONLY, true) + .setHint(QueryHints.HINT_READONLY, true) HibernateHqlQuery hibernateHqlQuery = new HibernateHqlQuery( hibernateSession, persistentEntity, criteria) - return proxyHandler.unwrap( hibernateHqlQuery.singleResult() ) + return proxyHandler.unwrap(hibernateHqlQuery.singleResult()) - } ) + }) } @Override D load(Serializable id) { id = convertIdentifier(id) if (id != null) { - return (D) hibernateTemplate.load((Class)persistentClass, id) - } - else { + return (D) hibernateTemplate.load((Class) persistentClass, id) + } else { return null } } @Override List getAll() { - (List)hibernateTemplate.execute({ Session session -> + (List) hibernateTemplate.execute({ Session session -> CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder() CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass) Query criteria = session.createQuery(criteriaQuery) @@ -196,13 +192,14 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { @Override Integer count() { - (Integer)hibernateTemplate.execute({ Session session -> + (Integer) hibernateTemplate.execute({ Session session -> CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder() CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass) criteriaQuery.select(criteriaBuilder.count(criteriaQuery.from(persistentEntity.javaClass))) Query criteria = session.createQuery(criteriaQuery) HibernateHqlQuery hibernateHqlQuery = new HibernateHqlQuery( hibernateSession, persistentEntity, criteria) { + @Override protected void flushBeforeQuery() { // no-op @@ -210,7 +207,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { } hibernateTemplate.applySettings(criteria) def result = hibernateHqlQuery.singleResult() - Number num = result == null ? 0 : (Number)result + Number num = result == null ? 0 : (Number) result return num }) } @@ -235,12 +232,12 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { @Override boolean exists(Serializable id) { id = convertIdentifier(id) - hibernateTemplate.execute { Session session -> + hibernateTemplate.execute { Session session -> CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder() CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass) Root queryRoot = criteriaQuery.from(persistentEntity.javaClass) def idProp = queryRoot.get(persistentEntity.identity.name) - criteriaQuery = criteriaQuery.where ( + criteriaQuery = criteriaQuery.where( //TODO: Remove explicit type cast once GROOVY-9460 criteriaBuilder.equal((Expression) idProp, id) ) @@ -283,7 +280,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { D find(CharSequence query, Map queryNamedArgs, Map args) { queryNamedArgs = new LinkedHashMap(queryNamedArgs) args = new LinkedHashMap(args) - if(query instanceof GString) { + if (query instanceof GString) { query = buildNamedParameterQueryFromGString((GString) query, queryNamedArgs) } @@ -299,7 +296,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { populateQueryArguments(q, queryNamedArgs) populateQueryArguments(q, args) populateQueryWithNamedArguments(q, queryNamedArgs) - proxyHandler.unwrap( createHqlQuery(session, q).singleResult() ) + proxyHandler.unwrap(createHqlQuery(session, q).singleResult()) } } @@ -307,7 +304,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { @Override D find(CharSequence query, Collection params, Map args) { - if(query instanceof GString) { + if (query instanceof GString) { throw new GrailsQueryException("Unsafe query [$query]. GORM cannot automatically escape a GString value when combined with ordinal parameters, so this query is potentially vulnerable to HQL injection attacks. Please embed the parameters within the GString so they can be safely escaped."); } @@ -323,13 +320,12 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { params.eachWithIndex { val, int i -> if (val instanceof CharSequence) { q.setParameter i, val.toString() - } - else { + } else { q.setParameter i, val } } populateQueryArguments(q, args) - proxyHandler.unwrap( createHqlQuery(session, q).singleResult() ) + proxyHandler.unwrap(createHqlQuery(session, q).singleResult()) } } @@ -337,7 +333,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { List findAll(CharSequence query, Map params, Map args) { params = new LinkedHashMap(params) args = new LinkedHashMap(args) - if(query instanceof GString) { + if (query instanceof GString) { query = buildNamedParameterQueryFromGString((GString) query, params) } @@ -357,17 +353,18 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { } } - @CompileDynamic // required for Hibernate 5.2 compatibility + @CompileDynamic + // required for Hibernate 5.2 compatibility def D findWithSql(CharSequence sql, Map args = Collections.emptyMap()) { IHibernateTemplate template = hibernateTemplate return (D) template.execute { Session session -> List params = [] - if(sql instanceof GString) { - sql = buildOrdinalParameterQueryFromGString((GString)sql, params) + if (sql instanceof GString) { + sql = buildOrdinalParameterQueryFromGString((GString) sql, params) } - NativeQuery q = (NativeQuery)session.createNativeQuery(sql.toString()) + NativeQuery q = (NativeQuery) session.createNativeQuery(sql.toString()) template.applySettings(q) @@ -375,8 +372,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { i++ if (val instanceof CharSequence) { q.setParameter i, val.toString() - } - else { + } else { q.setParameter i, val } } @@ -384,10 +380,9 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { populateQueryArguments(q, args) q.setMaxResults(1) def results = createHqlQuery(session, q).list() - if(results.isEmpty()) { + if (results.isEmpty()) { return null - } - else { + } else { return results.get(0) } } @@ -400,17 +395,18 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { * @param args The arguments * @return All entities matching the SQL query */ - @CompileDynamic // required for Hibernate 5.2 compatibility + @CompileDynamic + // required for Hibernate 5.2 compatibility List findAllWithSql(CharSequence sql, Map args = Collections.emptyMap()) { IHibernateTemplate template = hibernateTemplate return (List) template.execute { Session session -> List params = [] - if(sql instanceof GString) { - sql = buildOrdinalParameterQueryFromGString((GString)sql, params) + if (sql instanceof GString) { + sql = buildOrdinalParameterQueryFromGString((GString) sql, params) } - NativeQuery q = (NativeQuery)session.createNativeQuery(sql.toString()) + NativeQuery q = (NativeQuery) session.createNativeQuery(sql.toString()) template.applySettings(q) @@ -418,8 +414,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { i++ if (val instanceof CharSequence) { q.setParameter i, val.toString() - } - else { + } else { q.setParameter i, val } } @@ -431,105 +426,96 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { @Override List findAll(CharSequence query) { - if(query instanceof GString) { + if (query instanceof GString) { Map params = [:] - String hql = buildNamedParameterQueryFromGString((GString)query, params) + String hql = buildNamedParameterQueryFromGString((GString) query, params) return findAll(hql, params, Collections.emptyMap()) - } - else { + } else { return super.findAll(query) } } @Override List executeQuery(CharSequence query) { - if(query instanceof GString) { + if (query instanceof GString) { Map params = [:] - String hql = buildNamedParameterQueryFromGString((GString)query, params) + String hql = buildNamedParameterQueryFromGString((GString) query, params) return executeQuery(hql, params, Collections.emptyMap()) - } - else { + } else { return super.executeQuery(query) } } @Override Integer executeUpdate(CharSequence query) { - if(query instanceof GString) { + if (query instanceof GString) { Map params = [:] - String hql = buildNamedParameterQueryFromGString((GString)query, params) + String hql = buildNamedParameterQueryFromGString((GString) query, params) return executeUpdate(hql, params, Collections.emptyMap()) - } - else { + } else { return super.executeUpdate(query) } } @Override D find(CharSequence query) { - if(query instanceof GString) { + if (query instanceof GString) { Map params = [:] - String hql = buildNamedParameterQueryFromGString((GString)query, params) + String hql = buildNamedParameterQueryFromGString((GString) query, params) return find(hql, params, Collections.emptyMap()) - } - else { - return (D)super.find(query) + } else { + return (D) super.find(query) } } @Override D find(CharSequence query, Map params) { - if(query instanceof GString) { + if (query instanceof GString) { Map newParams = new LinkedHashMap(params) - String hql = buildNamedParameterQueryFromGString((GString)query, newParams) + String hql = buildNamedParameterQueryFromGString((GString) query, newParams) return find(hql, newParams, newParams) - } - else { - return (D)super.find(query, params) + } else { + return (D) super.find(query, params) } } - @Override List findAll(CharSequence query, Map params) { - if(query instanceof GString) { + if (query instanceof GString) { Map newParams = new LinkedHashMap(params) - String hql = buildNamedParameterQueryFromGString((GString)query, newParams) + String hql = buildNamedParameterQueryFromGString((GString) query, newParams) return findAll(hql, newParams, newParams) - } - else { + } else { return super.findAll(query, params) } } @Override List executeQuery(CharSequence query, Map args) { - if(query instanceof GString) { + if (query instanceof GString) { Map newParams = new LinkedHashMap(args) - String hql = buildNamedParameterQueryFromGString((GString)query, newParams) + String hql = buildNamedParameterQueryFromGString((GString) query, newParams) return executeQuery(hql, newParams, newParams) - } - else { + } else { return super.executeQuery(query, args) } } @Override Integer executeUpdate(CharSequence query, Map args) { - if(query instanceof GString) { + if (query instanceof GString) { Map newParams = new LinkedHashMap(args) - String hql = buildNamedParameterQueryFromGString((GString)query, newParams) + String hql = buildNamedParameterQueryFromGString((GString) query, newParams) return executeUpdate(hql, newParams, newParams) - } - else { + } else { return super.executeUpdate(query, args) } } @Override List findAll(CharSequence query, Collection params, Map args) { - if(query instanceof GString) { + if (query instanceof GString) { throw new GrailsQueryException("Unsafe query [$query]. GORM cannot automatically escape a GString value when combined with ordinal parameters, so this query is potentially vulnerable to HQL injection attacks. Please embed the parameters within the GString so they can be safely escaped.") } @@ -546,8 +532,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { params.eachWithIndex { val, int i -> if (val instanceof CharSequence) { q.setParameter i, val.toString() - } - else { + } else { q.setParameter i, val } } @@ -571,7 +556,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { List results = crit.list() firePostQueryEvent(session, crit, results) if (results) { - return proxyHandler.unwrap( results.get(0) ) + return proxyHandler.unwrap(results.get(0)) } } } @@ -596,9 +581,9 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { @Override List findAllWhere(Map queryMap, Map args) { if (!queryMap) return null - (List)hibernateTemplate.execute { Session session -> + (List) hibernateTemplate.execute { Session session -> Map processedQueryMap = [:] - queryMap.each{ key, value -> processedQueryMap[key.toString()] = value } + queryMap.each { key, value -> processedQueryMap[key.toString()] = value } Map queryArgs = filterQueryArgumentMap(processedQueryMap) List nullNames = removeNullNames(queryArgs) Criteria criteria = session.createCriteria(persistentClass) @@ -624,7 +609,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { args = new HashMap(args) params = new HashMap(params) - if(query instanceof GString) { + if (query instanceof GString) { query = buildNamedParameterQueryFromGString((GString) query, params) } @@ -642,7 +627,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { @Override List executeQuery(CharSequence query, Collection params, Map args) { - if(query instanceof GString) { + if (query instanceof GString) { throw new GrailsQueryException("Unsafe query [$query]. GORM cannot automatically escape a GString value when combined with ordinal parameters, so this query is potentially vulnerable to HQL injection attacks. Please embed the parameters within the GString so they can be safely escaped."); } @@ -656,8 +641,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { params.eachWithIndex { val, int i -> if (val instanceof CharSequence) { q.setParameter i, val.toString() - } - else { + } else { q.setParameter i, val } } @@ -669,9 +653,9 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { @Override D findWhere(Map queryMap, Map args) { if (!queryMap) return null - (D)hibernateTemplate.execute { Session session -> + (D) hibernateTemplate.execute { Session session -> Map processedQueryMap = [:] - queryMap.each{ key, value -> processedQueryMap[key.toString()] = value } + queryMap.each { key, value -> processedQueryMap[key.toString()] = value } Map queryArgs = filterQueryArgumentMap(processedQueryMap) List nullNames = removeNullNames(queryArgs) Criteria criteria = session.createCriteria(persistentClass) @@ -694,7 +678,6 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { } - List getAll(Long... ids) { getAllInternal(ids as List) } @@ -708,9 +691,9 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { private List getAllInternal(List ids) { if (!ids) return [] - (List)hibernateTemplate.execute { Session session -> + (List) hibernateTemplate.execute { Session session -> def identityType = persistentEntity.identity.type - ids = ids.collect { HibernateRuntimeUtils.convertValueToType((Serializable)it, identityType, conversionService) } + ids = ids.collect { HibernateRuntimeUtils.convertValueToType((Serializable) it, identityType, conversionService) } def criteria = session.createCriteria(persistentClass) hibernateTemplate.applySettings(criteria) def identityName = persistentEntity.identity.name @@ -735,8 +718,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { for (entry in query.entrySet()) { if (entry.value instanceof CharSequence) { queryArgs[entry.key] = entry.value.toString() - } - else { + } else { queryArgs[entry.key] = entry.value } } @@ -802,23 +784,21 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { protected Serializable convertIdentifier(Serializable id) { def identity = persistentEntity.identity - if(identity != null) { + if (identity != null) { ConversionService conversionService = persistentEntity.mappingContext.conversionService - if(id != null) { + if (id != null) { Class identityType = identity.type Class idInstanceType = id.getClass() - if(identityType.isAssignableFrom(idInstanceType)) { + if (identityType.isAssignableFrom(idInstanceType)) { return id - } - else if(conversionService.canConvert(idInstanceType, identityType)) { + } else if (conversionService.canConvert(idInstanceType, identityType)) { try { - return (Serializable)conversionService.convert(id, identityType) + return (Serializable) conversionService.convert(id, identityType) } catch (Throwable e) { // unconvertable id, return null return null } - } - else { + } else { // unconvertable id, return null return null } @@ -838,7 +818,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { String stringKey = key.toString() def value = entry.value - if(value == null) { + if (value == null) { q.setParameter stringKey, null } else if (value instanceof CharSequence) { q.setParameter stringKey, value.toString() @@ -857,7 +837,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { protected Integer intValue(Map args, String key) { def value = args.get(key) - if(value) { + if (value) { return conversionService.convert(value, Integer.class) } return null @@ -889,10 +869,10 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { q.setTimeout(timeoutParam.intValue()); } if (args.containsKey(DynamicFinder.ARGUMENT_READ_ONLY)) { - q.setReadOnly((Boolean)args.remove(DynamicFinder.ARGUMENT_READ_ONLY)); + q.setReadOnly((Boolean) args.remove(DynamicFinder.ARGUMENT_READ_ONLY)); } if (args.containsKey(DynamicFinder.ARGUMENT_FLUSH_MODE)) { - q.setHibernateFlushMode((FlushMode)args.remove(DynamicFinder.ARGUMENT_FLUSH_MODE)); + q.setHibernateFlushMode((FlushMode) args.remove(DynamicFinder.ARGUMENT_FLUSH_MODE)); } args.remove(DynamicFinder.ARGUMENT_CACHE) @@ -900,7 +880,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { private String normalizeMultiLineQueryString(String query) { if (query.indexOf('\n') != -1) - return query.trim().replace('\n', ' ') + return query.trim().replace('\n', ' ') return query } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormValidationApi.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormValidationApi.groovy index 685a2ae6900..d542cb90b47 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormValidationApi.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormValidationApi.groovy @@ -19,12 +19,12 @@ package org.grails.orm.hibernate import groovy.transform.CompileStatic +import org.grails.datastore.gorm.GormValidationApi import org.grails.datastore.gorm.validation.CascadingValidator +import org.grails.datastore.mapping.engine.event.ValidationEvent import org.grails.datastore.mapping.reflect.ClassUtils import org.grails.datastore.mapping.validation.ValidationErrors import org.grails.orm.hibernate.support.HibernateRuntimeUtils -import org.grails.datastore.gorm.GormValidationApi -import org.grails.datastore.mapping.engine.event.ValidationEvent import org.hibernate.Session import org.springframework.validation.Errors import org.springframework.validation.FieldError @@ -58,14 +58,14 @@ abstract class AbstractHibernateGormValidationApi extends GormValidationApi extends GormValidationApi eventListeners; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; - public EventListenerIntegrator(HibernateEventListeners hibernateEventListeners, Map eventListeners) { - this.hibernateEventListeners = hibernateEventListeners; - this.eventListeners = eventListeners; - } +public class EventListenerIntegrator implements Integrator { @SuppressWarnings("unchecked") protected static final List> TYPES = Arrays.asList( @@ -76,8 +72,15 @@ public EventListenerIntegrator(HibernateEventListeners hibernateEventListeners, EventType.POST_COLLECTION_REMOVE, EventType.POST_COLLECTION_UPDATE); + protected HibernateEventListeners hibernateEventListeners; + protected Map eventListeners; + + public EventListenerIntegrator(HibernateEventListeners hibernateEventListeners, Map eventListeners) { + this.hibernateEventListeners = hibernateEventListeners; + this.eventListeners = eventListeners; + } - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) @Override public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { @@ -88,16 +91,15 @@ public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactor EventType type = EventType.resolveEventTypeByName(entry.getKey()); Object listenerObject = entry.getValue(); if (listenerObject instanceof Collection) { - appendListeners(listenerRegistry, type, (Collection)listenerObject); - } - else if (listenerObject != null) { + appendListeners(listenerRegistry, type, (Collection) listenerObject); + } else if (listenerObject != null) { appendListeners(listenerRegistry, type, Collections.singleton(listenerObject)); } } } if (hibernateEventListeners != null && hibernateEventListeners.getListenerMap() != null) { - Map listenerMap = hibernateEventListeners.getListenerMap(); + Map listenerMap = hibernateEventListeners.getListenerMap(); for (EventType type : TYPES) { appendListeners(listenerRegistry, type, listenerMap); } @@ -111,13 +113,12 @@ protected void appendListeners(EventListenerRegistry listenerRegistry, EventListenerGroup group = listenerRegistry.getEventListenerGroup(eventType); for (T listener : listeners) { if (listener != null) { - if(shouldOverrideListeners(eventType, listener)) { + if (shouldOverrideListeners(eventType, listener)) { // since ClosureEventTriggeringInterceptor extends DefaultSaveOrUpdateEventListener we want to override instead of append the listener here // to avoid there being 2 implementations which would impact performance too group.clear(); group.appendListener(listener); - } - else { + } else { group.appendListener(listener); } } @@ -135,20 +136,17 @@ protected void appendListeners(final EventListenerRegistry listenerRegistry, Object listener = listeners.get(eventType.eventName()); if (listener != null) { - if(shouldOverrideListeners(eventType, listener)) { + if (shouldOverrideListeners(eventType, listener)) { // since ClosureEventTriggeringInterceptor extends DefaultSaveOrUpdateEventListener we want to override instead of append the listener here // to avoid there being 2 implementations which would impact performance too listenerRegistry.setListeners(eventType, (T) listener); - } - else { - listenerRegistry.appendListeners(eventType, (T)listener); + } else { + listenerRegistry.appendListeners(eventType, (T) listener); } } } - - public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { // nothing to do } -} \ No newline at end of file +} diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java index 796bd695ece..41b1a0852e0 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java @@ -19,8 +19,19 @@ package org.grails.orm.hibernate; import groovy.lang.Closure; +import jakarta.persistence.PersistenceException; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.codehaus.groovy.runtime.DefaultGroovyMethods; -import org.hibernate.*; +import org.hibernate.Criteria; +import org.hibernate.FlushMode; +import org.hibernate.HibernateException; +import org.hibernate.JDBCException; +import org.hibernate.LockMode; +import org.hibernate.LockOptions; +import org.hibernate.Session; +import org.hibernate.SessionFactory; import org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.spi.SessionFactoryImplementor; @@ -44,10 +55,6 @@ import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; -import jakarta.persistence.PersistenceException; -import jakarta.persistence.criteria.CriteriaBuilder; -import jakarta.persistence.criteria.CriteriaQuery; -import jakarta.persistence.criteria.Root; import javax.sql.DataSource; import java.io.Serializable; import java.lang.reflect.InvocationHandler; @@ -62,10 +69,78 @@ public class GrailsHibernateTemplate implements IHibernateTemplate { + /** + * Never flush is a good strategy for read-only units of work. + * Hibernate will not track and look for changes in this case, + * avoiding any overhead of modification detection. + *

In case of an existing Session, FLUSH_NEVER will turn the flush mode + * to NEVER for the scope of the current operation, resetting the previous + * flush mode afterwards. + * + * @see #setFlushMode + */ + public static final int FLUSH_NEVER = 0; + + /** + * Automatic flushing is the default mode for a Hibernate Session. + * A session will get flushed on transaction commit, and on certain find + * operations that might involve already modified instances, but not + * after each unit of work like with eager flushing. + *

In case of an existing Session, FLUSH_AUTO will participate in the + * existing flush mode, not modifying it for the current operation. + * This in particular means that this setting will not modify an existing + * flush mode NEVER, in contrast to FLUSH_EAGER. + * + * @see #setFlushMode + */ + public static final int FLUSH_AUTO = 1; + + /** + * Eager flushing leads to immediate synchronization with the database, + * even if in a transaction. This causes inconsistencies to show up and throw + * a respective exception immediately, and JDBC access code that participates + * in the same transaction will see the changes as the database is already + * aware of them then. But the drawbacks are: + *

    + *
  • additional communication roundtrips with the database, instead of a + * single batch at transaction commit; + *
  • the fact that an actual database rollback is needed if the Hibernate + * transaction rolls back (due to already submitted SQL statements). + *
+ *

In case of an existing Session, FLUSH_EAGER will turn the flush mode + * to AUTO for the scope of the current operation and issue a flush at the + * end, resetting the previous flush mode afterwards. + * + * @see #setFlushMode + */ + public static final int FLUSH_EAGER = 2; + + /** + * Flushing at commit only is intended for units of work where no + * intermediate flushing is desired, not even for find operations + * that might involve already modified instances. + *

In case of an existing Session, FLUSH_COMMIT will turn the flush mode + * to COMMIT for the scope of the current operation, resetting the previous + * flush mode afterwards. The only exception is an existing flush mode + * NEVER, which will not be modified through this setting. + * + * @see #setFlushMode + */ + public static final int FLUSH_COMMIT = 3; + + /** + * Flushing before every query statement is rarely necessary. + * It is only available for special needs. + *

In case of an existing Session, FLUSH_ALWAYS will turn the flush mode + * to ALWAYS for the scope of the current operation, resetting the previous + * flush mode afterwards. + * + * @see #setFlushMode + */ + public static final int FLUSH_ALWAYS = 4; + private static final Logger LOG = LoggerFactory.getLogger(GrailsHibernateTemplate.class); - private boolean osivReadOnly; - private boolean passReadOnlyToHibernate = false; protected boolean exposeNativeSession = true; protected boolean cacheQueries = false; @@ -73,28 +148,27 @@ public class GrailsHibernateTemplate implements IHibernateTemplate { protected DataSource dataSource = null; protected SQLExceptionTranslator jdbcExceptionTranslator; protected int flushMode = FLUSH_AUTO; - private boolean applyFlushModeOnlyToNonExistingTransactions = false; - public interface HibernateCallback { - T doInHibernate(Session session) throws HibernateException, SQLException; - } + private boolean osivReadOnly; + private boolean passReadOnlyToHibernate = false; + private boolean applyFlushModeOnlyToNonExistingTransactions = false; protected GrailsHibernateTemplate() { // for testing } + public GrailsHibernateTemplate(SessionFactory sessionFactory) { Assert.notNull(sessionFactory, "Property 'sessionFactory' is required"); this.sessionFactory = sessionFactory; ConnectionProvider connectionProvider = ((SessionFactoryImplementor) sessionFactory).getServiceRegistry().getService(ConnectionProvider.class); - if(connectionProvider instanceof DatasourceConnectionProviderImpl) { + if (connectionProvider instanceof DatasourceConnectionProviderImpl) { this.dataSource = ((DatasourceConnectionProviderImpl) connectionProvider).getDataSource(); - if(dataSource instanceof TransactionAwareDataSourceProxy) { + if (dataSource instanceof TransactionAwareDataSourceProxy) { this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource(); } jdbcExceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource); - } - else { + } else { // must be in unit test mode, setup default translator SQLErrorCodeSQLExceptionTranslator sqlErrorCodeSQLExceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(); sqlErrorCodeSQLExceptionTranslator.setDatabaseProductName("H2"); @@ -108,7 +182,7 @@ public GrailsHibernateTemplate(SessionFactory sessionFactory, HibernateDatastore public GrailsHibernateTemplate(SessionFactory sessionFactory, HibernateDatastore datastore, int defaultFlushMode) { this(sessionFactory); - if(datastore != null) { + if (datastore != null) { cacheQueries = datastore.isCacheQueries(); this.osivReadOnly = datastore.isOsivReadOnly(); this.passReadOnlyToHibernate = datastore.isPassReadOnlyToHibernate(); @@ -116,7 +190,6 @@ public GrailsHibernateTemplate(SessionFactory sessionFactory, HibernateDatastore this.flushMode = defaultFlushMode; } - @Override public T execute(Closure callable) { HibernateCallback hibernateCallback = DefaultGroovyMethods.asType(callable, HibernateCallback.class); @@ -125,15 +198,15 @@ public T execute(Closure callable) { @Override public T executeWithNewSession(final Closure callable) { - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory); + SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); SessionHolder previousHolder = sessionHolder; - ConnectionHolder previousConnectionHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(dataSource); + ConnectionHolder previousConnectionHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); Session newSession = null; boolean previousActiveSynchronization = TransactionSynchronizationManager.isSynchronizationActive(); List transactionSynchronizations = previousActiveSynchronization ? TransactionSynchronizationManager.getSynchronizations() : null; try { // if there are any previous synchronizations active we need to clear them and restore them later (see finally block) - if(previousActiveSynchronization) { + if (previousActiveSynchronization) { TransactionSynchronizationManager.clearSynchronization(); // init a new synchronization to ensure that any opened database connections are closed by the synchronization TransactionSynchronizationManager.initSynchronization(); @@ -142,7 +215,7 @@ public T executeWithNewSession(final Closure callable) { // if there are already bound holders, unbind them so they can be restored later if (sessionHolder != null) { TransactionSynchronizationManager.unbindResource(sessionFactory); - if(previousConnectionHolder != null) { + if (previousConnectionHolder != null) { TransactionSynchronizationManager.unbindResource(dataSource); } } @@ -154,15 +227,14 @@ public T executeWithNewSession(final Closure callable) { TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder); return execute(callable::call); - } - finally { + } finally { try { // if an active synchronization was registered during the life time of the new session clear it - if(TransactionSynchronizationManager.isSynchronizationActive()) { + if (TransactionSynchronizationManager.isSynchronizationActive()) { TransactionSynchronizationManager.clearSynchronization(); } // If there is a synchronization active then leave it to the synchronization to close the session - if(newSession != null) { + if (newSession != null) { SessionFactoryUtils.closeSession(newSession); } @@ -171,20 +243,19 @@ public T executeWithNewSession(final Closure callable) { ConnectionHolder connectionHolder = (ConnectionHolder) TransactionSynchronizationManager.unbindResourceIfPossible(dataSource); // if there is a connection holder and it holds an open connection close it try { - if(connectionHolder != null && !connectionHolder.getConnection().isClosed()) { + if (connectionHolder != null && !connectionHolder.getConnection().isClosed()) { Connection conn = connectionHolder.getConnection(); DataSourceUtils.releaseConnection(conn, dataSource); } } catch (SQLException e) { // ignore, connection closed already? - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("Could not close opened JDBC connection. Did the application close the connection manually?: " + e.getMessage()); } } - } - finally { + } finally { // if there were previously active synchronizations then register those again - if(previousActiveSynchronization) { + if (previousActiveSynchronization) { TransactionSynchronizationManager.initSynchronization(); for (TransactionSynchronization transactionSynchronization : transactionSynchronizations) { TransactionSynchronizationManager.registerSynchronization(transactionSynchronization); @@ -192,9 +263,9 @@ public T executeWithNewSession(final Closure callable) { } // now restore any previous state - if(previousHolder != null) { + if (previousHolder != null) { TransactionSynchronizationManager.bindResource(sessionFactory, previousHolder); - if(previousConnectionHolder != null) { + if (previousConnectionHolder != null) { TransactionSynchronizationManager.bindResource(dataSource, previousConnectionHolder); } } @@ -206,10 +277,9 @@ public T executeWithNewSession(final Closure callable) { @Override public T1 executeWithExistingOrCreateNewSession(SessionFactory sessionFactory, Closure callable) { SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); - if(sessionHolder == null) { + if (sessionHolder == null) { return executeWithNewSession(callable); - } - else { + } else { return callable.call(sessionHolder.getSession()); } } @@ -253,8 +323,8 @@ public List executeFind(HibernateCallback action) throws DataAccessExcepti } protected boolean shouldPassReadOnlyToHibernate() { - if((passReadOnlyToHibernate || osivReadOnly) && TransactionSynchronizationManager.hasResource(getSessionFactory())) { - if(TransactionSynchronizationManager.isActualTransactionActive()) { + if ((passReadOnlyToHibernate || osivReadOnly) && TransactionSynchronizationManager.hasResource(getSessionFactory())) { + if (TransactionSynchronizationManager.isActualTransactionActive()) { return passReadOnlyToHibernate && TransactionSynchronizationManager.isCurrentTransactionReadOnly(); } else { return osivReadOnly; @@ -302,14 +372,12 @@ protected T doExecute(HibernateCallback action, boolean enforceNativeSess return result; } catch (HibernateException ex) { throw convertHibernateAccessException(ex); - } - catch (PersistenceException ex) { + } catch (PersistenceException ex) { if (ex.getCause() instanceof HibernateException) { throw SessionFactoryUtils.convertHibernateAccessException((HibernateException) ex.getCause()); } throw ex; - } - catch (SQLException ex) { + } catch (SQLException ex) { throw jdbcExceptionTranslator.translate("Hibernate-related JDBC operation", null, ex); } catch (RuntimeException ex) { // Callback code threw application exception... @@ -417,7 +485,7 @@ public void evict(final Object entity) throws DataAccessException { public void lock(final Object entity, final LockMode lockMode) throws DataAccessException { doExecute(session -> { - session.buildLockRequest(new LockOptions(lockMode)).lock(entity);//LockMode.PESSIMISTIC_WRITE + session.buildLockRequest(new LockOptions(lockMode)).lock(entity); //LockMode.PESSIMISTIC_WRITE return null; }, true); } @@ -504,129 +572,6 @@ protected void prepareCriteria(Query jpaQuery) { } } - - /** - * Invocation handler that suppresses close calls on Hibernate Sessions. - * Also prepares returned Query and Criteria objects. - * - * @see org.hibernate.Session#close - */ - protected class CloseSuppressingInvocationHandler implements InvocationHandler { - - protected final Session target; - - protected CloseSuppressingInvocationHandler(Session target) { - this.target = target; - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - // Invocation on Session interface coming in... - - if (method.getName().equals("equals")) { - // Only consider equal when proxies are identical. - return (proxy == args[0]); - } - if (method.getName().equals("hashCode")) { - // Use hashCode of Session proxy. - return System.identityHashCode(proxy); - } - if (method.getName().equals("close")) { - // Handle close method: suppress, not valid. - return null; - } - - // Invoke method on target Session. - try { - Object retVal = method.invoke(target, args); - - // If return value is a Query or Criteria, apply transaction timeout. - // Applies to createQuery, getNamedQuery, createCriteria. - if (retVal instanceof org.hibernate.query.Query) { - prepareQuery(((org.hibernate.query.Query) retVal)); - } - if (retVal instanceof Criteria) { - prepareCriteria(((Criteria) retVal)); - } else if (retVal instanceof Query) { - prepareCriteria(((Query) retVal)); - } - - return retVal; - } catch (InvocationTargetException ex) { - throw ex.getTargetException(); - } - } - } - - /** - * Never flush is a good strategy for read-only units of work. - * Hibernate will not track and look for changes in this case, - * avoiding any overhead of modification detection. - *

In case of an existing Session, FLUSH_NEVER will turn the flush mode - * to NEVER for the scope of the current operation, resetting the previous - * flush mode afterwards. - * - * @see #setFlushMode - */ - public static final int FLUSH_NEVER = 0; - - /** - * Automatic flushing is the default mode for a Hibernate Session. - * A session will get flushed on transaction commit, and on certain find - * operations that might involve already modified instances, but not - * after each unit of work like with eager flushing. - *

In case of an existing Session, FLUSH_AUTO will participate in the - * existing flush mode, not modifying it for the current operation. - * This in particular means that this setting will not modify an existing - * flush mode NEVER, in contrast to FLUSH_EAGER. - * - * @see #setFlushMode - */ - public static final int FLUSH_AUTO = 1; - - /** - * Eager flushing leads to immediate synchronization with the database, - * even if in a transaction. This causes inconsistencies to show up and throw - * a respective exception immediately, and JDBC access code that participates - * in the same transaction will see the changes as the database is already - * aware of them then. But the drawbacks are: - *

    - *
  • additional communication roundtrips with the database, instead of a - * single batch at transaction commit; - *
  • the fact that an actual database rollback is needed if the Hibernate - * transaction rolls back (due to already submitted SQL statements). - *
- *

In case of an existing Session, FLUSH_EAGER will turn the flush mode - * to AUTO for the scope of the current operation and issue a flush at the - * end, resetting the previous flush mode afterwards. - * - * @see #setFlushMode - */ - public static final int FLUSH_EAGER = 2; - - /** - * Flushing at commit only is intended for units of work where no - * intermediate flushing is desired, not even for find operations - * that might involve already modified instances. - *

In case of an existing Session, FLUSH_COMMIT will turn the flush mode - * to COMMIT for the scope of the current operation, resetting the previous - * flush mode afterwards. The only exception is an existing flush mode - * NEVER, which will not be modified through this setting. - * - * @see #setFlushMode - */ - public static final int FLUSH_COMMIT = 3; - - /** - * Flushing before every query statement is rarely necessary. - * It is only available for special needs. - *

In case of an existing Session, FLUSH_ALWAYS will turn the flush mode - * to ALWAYS for the scope of the current operation, resetting the previous - * flush mode afterwards. - * - * @see #setFlushMode - */ - public static final int FLUSH_ALWAYS = 4; - /** * Set the flush behavior to one of the constants in this class. Default is * FLUSH_AUTO. @@ -654,7 +599,7 @@ public int getFlushMode() { * @see org.hibernate.Session#setFlushMode */ protected FlushMode applyFlushMode(Session session, boolean existingTransaction) { - if(isApplyFlushModeOnlyToNonExistingTransactions() && existingTransaction) { + if (isApplyFlushModeOnlyToNonExistingTransactions() && existingTransaction) { return null; } @@ -675,9 +620,8 @@ protected FlushMode applyFlushMode(Session session, boolean existingTransaction) session.setHibernateFlushMode(FlushMode.AUTO); return previousFlushMode; } - } else { - // rely on default FlushMode.AUTO } + // else rely on default FlushMode.AUTO } else if (getFlushMode() == FLUSH_COMMIT) { if (existingTransaction) { FlushMode previousFlushMode = session.getHibernateFlushMode(); @@ -762,12 +706,69 @@ protected Collection getIterableAsCollection(Iterable objects) { } return list; } - + public boolean isApplyFlushModeOnlyToNonExistingTransactions() { return applyFlushModeOnlyToNonExistingTransactions; } - + public void setApplyFlushModeOnlyToNonExistingTransactions(boolean applyFlushModeOnlyToNonExistingTransactions) { this.applyFlushModeOnlyToNonExistingTransactions = applyFlushModeOnlyToNonExistingTransactions; } + + public interface HibernateCallback { + + T doInHibernate(Session session) throws HibernateException, SQLException; + } + + /** + * Invocation handler that suppresses close calls on Hibernate Sessions. + * Also prepares returned Query and Criteria objects. + * + * @see org.hibernate.Session#close + */ + protected class CloseSuppressingInvocationHandler implements InvocationHandler { + + protected final Session target; + + protected CloseSuppressingInvocationHandler(Session target) { + this.target = target; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + // Invocation on Session interface coming in... + + if (method.getName().equals("equals")) { + // Only consider equal when proxies are identical. + return (proxy == args[0]); + } + if (method.getName().equals("hashCode")) { + // Use hashCode of Session proxy. + return System.identityHashCode(proxy); + } + if (method.getName().equals("close")) { + // Handle close method: suppress, not valid. + return null; + } + + // Invoke method on target Session. + try { + Object retVal = method.invoke(target, args); + + // If return value is a Query or Criteria, apply transaction timeout. + // Applies to createQuery, getNamedQuery, createCriteria. + if (retVal instanceof org.hibernate.query.Query) { + prepareQuery(((org.hibernate.query.Query) retVal)); + } + if (retVal instanceof Criteria) { + prepareCriteria(((Criteria) retVal)); + } else if (retVal instanceof Query) { + prepareCriteria(((Query) retVal)); + } + + return retVal; + } catch (InvocationTargetException ex) { + throw ex.getTargetException(); + } + } + } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy index 8540f7646b9..04afeeaf243 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy @@ -71,11 +71,10 @@ class GrailsHibernateTransactionManager extends HibernateTransactionManager { // transaction is HibernateTransactionManager.HibernateTransactionObject private class instance // always set to manual; the base class doesn't because the OSIV has already registered a session - SessionHolder holder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory) + SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory) holder.session.setHibernateFlushMode(FlushMode.MANUAL) - } - else if(defaultFlushMode != FlushMode.AUTO) { - SessionHolder holder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory) + } else if (defaultFlushMode != FlushMode.AUTO) { + SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory) holder.session.setHibernateFlushMode(defaultFlushMode) } } @@ -83,10 +82,10 @@ class GrailsHibernateTransactionManager extends HibernateTransactionManager { @Override protected void doRollback(DefaultTransactionStatus status) { super.doRollback(status) - if(isJdbcBatchVersionedData) { + if (isJdbcBatchVersionedData) { try { - SessionHolder holder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory) - if(holder != null) { + SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory) + if (holder != null) { Session session = holder.getSession() JdbcCoordinator jdbcCoordinator = ((SessionImplementor) session).getJdbcCoordinator() jdbcCoordinator.abortBatch() diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/GrailsSessionContext.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/GrailsSessionContext.java index 156442ace38..7d36cc9e278 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/GrailsSessionContext.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/GrailsSessionContext.java @@ -18,6 +18,9 @@ */ package org.grails.orm.hibernate; +import jakarta.transaction.Status; +import jakarta.transaction.Transaction; +import jakarta.transaction.TransactionManager; import org.hibernate.FlushMode; import org.hibernate.HibernateException; import org.hibernate.Session; @@ -37,10 +40,6 @@ import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; -import jakarta.transaction.Status; -import jakarta.transaction.Transaction; -import jakarta.transaction.TransactionManager; - /** * Based on org.springframework.orm.hibernate4.SpringSessionContext. * @@ -61,6 +60,7 @@ public class GrailsSessionContext implements CurrentSessionContext { /** * Constructor. + * * @param sessionFactory the SessionFactory to provide current Sessions for */ public GrailsSessionContext(SessionFactoryImplementor sessionFactory) { @@ -125,28 +125,26 @@ private Session createSession(Object resource) { // Use same Session for further Hibernate actions within the transaction. // Thread object will get removed by synchronization at transaction completion. if (TransactionSynchronizationManager.isSynchronizationActive()) { - // We're within a Spring-managed transaction, possibly from JtaTransactionManager. - LOG.debug("Registering Spring transaction synchronization for new Hibernate Session"); - SessionHolder holderToUse = sessionHolder; - if (holderToUse == null) { - holderToUse = new SessionHolder(session); - } - else { - // it's up to the caller to manage concurrent sessions - // holderToUse.addSession(session); - } - if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { - session.setHibernateFlushMode(FlushMode.MANUAL); - } - TransactionSynchronizationManager.registerSynchronization(createSpringSessionSynchronization(holderToUse)); - holderToUse.setSynchronizedWithTransaction(true); - if (holderToUse != sessionHolder) { - TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse); - } - } - else { - // No Spring transaction management active -> try JTA transaction synchronization. - registerJtaSynchronization(session, sessionHolder); + // We're within a Spring-managed transaction, possibly from JtaTransactionManager. + LOG.debug("Registering Spring transaction synchronization for new Hibernate Session"); + SessionHolder holderToUse = sessionHolder; + if (holderToUse == null) { + holderToUse = new SessionHolder(session); + } + // else it's up to the caller to manage concurrent sessions + // holderToUse.addSession(session); + + if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { + session.setHibernateFlushMode(FlushMode.MANUAL); + } + TransactionSynchronizationManager.registerSynchronization(createSpringSessionSynchronization(holderToUse)); + holderToUse.setSynchronizedWithTransaction(true); + if (holderToUse != sessionHolder) { + TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse); + } + } else { + // No Spring transaction management active -> try JTA transaction synchronization. + registerJtaSynchronization(session, sessionHolder); } /* // Check whether we are allowed to return the Session. @@ -187,17 +185,15 @@ protected void registerJtaSynchronization(Session session, SessionHolder session if (holderToUse == null) { holderToUse = new SessionHolder(session); } - else { - // it's up to the caller to manage concurrent sessions - // holderToUse.addSession(session); - } + // else it's up to the caller to manage concurrent sessions + // holderToUse.addSession(session); + jtaTx.registerSynchronization(new SpringJtaSynchronizationAdapter(createSpringSessionSynchronization(holderToUse), jtaTm)); holderToUse.setSynchronizedWithTransaction(true); if (holderToUse != sessionHolder) { TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse); } - } - catch (Throwable ex) { + } catch (Throwable ex) { throw new DataAccessResourceFailureException("Could not register synchronization with JTA TransactionManager", ex); } } @@ -206,8 +202,7 @@ protected TransactionManager getJtaTransactionManager(Session session) { SessionFactoryImplementor sessionFactoryImpl = null; if (sessionFactory instanceof SessionFactoryImplementor) { sessionFactoryImpl = ((SessionFactoryImplementor) sessionFactory); - } - else if (session != null) { + } else if (session != null) { SessionFactory internalFactory = session.getSessionFactory(); if (internalFactory instanceof SessionFactoryImplementor) { sessionFactoryImpl = (SessionFactoryImplementor) internalFactory; diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateDatastore.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateDatastore.java index c22560276b7..cdd643002a1 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateDatastore.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateDatastore.java @@ -36,7 +36,11 @@ import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.DatastoreUtils; import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.core.connections.*; +import org.grails.datastore.mapping.core.connections.ConnectionSource; +import org.grails.datastore.mapping.core.connections.ConnectionSources; +import org.grails.datastore.mapping.core.connections.ConnectionSourcesInitializer; +import org.grails.datastore.mapping.core.connections.DefaultConnectionSource; +import org.grails.datastore.mapping.core.connections.SingletonConnectionSources; import org.grails.datastore.mapping.core.exceptions.ConfigurationException; import org.grails.datastore.mapping.engine.event.DatastoreInitializedEvent; import org.grails.datastore.mapping.model.DatastoreConfigurationException; @@ -65,7 +69,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; -import org.springframework.context.*; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.MessageSource; +import org.springframework.context.MessageSourceAware; import org.springframework.context.support.StaticMessageSource; import org.springframework.core.env.PropertyResolver; import org.springframework.jdbc.datasource.ConnectionHolder; @@ -77,7 +85,11 @@ import java.io.Serializable; import java.sql.Connection; import java.sql.SQLException; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.Callable; /** @@ -87,6 +99,7 @@ * @since 2.0 */ public class HibernateDatastore extends AbstractHibernateDatastore implements MessageSourceAware { + private static final Logger LOG = LoggerFactory.getLogger(HibernateDatastore.class); protected final GrailsHibernateTransactionManager transactionManager; @@ -99,8 +112,8 @@ public class HibernateDatastore extends AbstractHibernateDatastore implements Me * Create a new HibernateDatastore for the given connection sources and mapping context * * @param connectionSources The {@link ConnectionSources} instance - * @param mappingContext The {@link MappingContext} instance - * @param eventPublisher The {@link ConfigurableApplicationEventPublisher} instance + * @param mappingContext The {@link MappingContext} instance + * @param eventPublisher The {@link ConfigurableApplicationEventPublisher} instance */ public HibernateDatastore(final ConnectionSources connectionSources, final HibernateMappingContext mappingContext, final ConfigurableApplicationEventPublisher eventPublisher) { super(connectionSources, mappingContext); @@ -109,9 +122,9 @@ public HibernateDatastore(final ConnectionSources> allConnectionSources = connectionSources.getAllConnectionSources(); @@ -158,16 +170,15 @@ public void persistentEntityAdded(PersistentEntity entity) { registerAllEntitiesWithEnhancer(); }); - if(multiTenantMode == MultiTenancySettings.MultiTenancyMode.SCHEMA) { - if(this.tenantResolver instanceof AllTenantsResolver) { + if (multiTenantMode == MultiTenancySettings.MultiTenancyMode.SCHEMA) { + if (this.tenantResolver instanceof AllTenantsResolver) { AllTenantsResolver allTenantsResolver = (AllTenantsResolver) tenantResolver; Iterable tenantIds = allTenantsResolver.resolveTenantIds(); for (Serializable tenantId : tenantIds) { addTenantForSchemaInternal(tenantId.toString()); } - } - else { + } else { Collection allSchemas = schemaHandler.resolveSchemaNames(defaultConnectionSource.getDataSource()); for (String schema : allSchemas) { addTenantForSchemaInternal(schema); @@ -176,41 +187,15 @@ public void persistentEntityAdded(PersistentEntity entity) { } } - this.gormEnhancer = initialize(); } - private HibernateDatastore createChildDatastore(HibernateMappingContext mappingContext, - ConfigurableApplicationEventPublisher eventPublisher, - HibernateDatastore parent, - SingletonConnectionSources singletonConnectionSources) { - return new HibernateDatastore(singletonConnectionSources, mappingContext, eventPublisher) { - @Override - protected HibernateGormEnhancer initialize() { - return null; - } - - @Override - public HibernateDatastore getDatastoreForConnection(String connectionName) { - if (connectionName.equals(Settings.SETTING_DATASOURCE) || connectionName.equals(ConnectionSource.DEFAULT)) { - return parent; - } else { - HibernateDatastore hibernateDatastore = parent.datastoresByConnectionSource.get(connectionName); - if (hibernateDatastore == null) { - throw new ConfigurationException("DataSource not found for name [" + connectionName + "] in configuration. Please check your multiple data sources configuration and try again."); - } - return hibernateDatastore; - } - } - }; - } - /** * Create a new HibernateDatastore for the given connection sources and mapping context * - * @param configuration The configuration + * @param configuration The configuration * @param connectionSourceFactory The {@link HibernateConnectionSourceFactory} instance - * @param eventPublisher The {@link ConfigurableApplicationEventPublisher} instance + * @param eventPublisher The {@link ConfigurableApplicationEventPublisher} instance */ public HibernateDatastore(PropertyResolver configuration, HibernateConnectionSourceFactory connectionSourceFactory, ConfigurableApplicationEventPublisher eventPublisher) { this(ConnectionSourcesInitializer.create(connectionSourceFactory, DatastoreUtils.preparePropertyResolver(configuration, "dataSource", "hibernate", "grails")), connectionSourceFactory.getMappingContext(), eventPublisher); @@ -219,7 +204,7 @@ public HibernateDatastore(PropertyResolver configuration, HibernateConnectionSou /** * Create a new HibernateDatastore for the given connection sources and mapping context * - * @param configuration The configuration + * @param configuration The configuration * @param connectionSourceFactory The {@link HibernateConnectionSourceFactory} instance */ public HibernateDatastore(PropertyResolver configuration, HibernateConnectionSourceFactory connectionSourceFactory) { @@ -229,44 +214,44 @@ public HibernateDatastore(PropertyResolver configuration, HibernateConnectionSou /** * Create a new HibernateDatastore for the given connection sources and mapping context * - * @param configuration The configuration + * @param configuration The configuration * @param eventPublisher The {@link ConfigurableApplicationEventPublisher} instance - * @param classes The persistent classes + * @param classes The persistent classes */ - public HibernateDatastore(PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Class...classes) { + public HibernateDatastore(PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Class... classes) { this(configuration, new HibernateConnectionSourceFactory(classes), eventPublisher); } /** * Create a new HibernateDatastore for the given connection sources and mapping context * - * @param configuration The configuration + * @param configuration The configuration * @param eventPublisher The {@link ConfigurableApplicationEventPublisher} instance - * @param classes The persistent classes + * @param classes The persistent classes */ - public HibernateDatastore(DataSource dataSource, PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Class...classes) { + public HibernateDatastore(DataSource dataSource, PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Class... classes) { this(configuration, createConnectionFactoryForDataSource(dataSource, classes), eventPublisher); } /** * Construct a Hibernate datastore scanning the given packages * - * @param configuration The configuration + * @param configuration The configuration * @param eventPublisher The event publisher * @param packagesToScan The packages to scan */ - public HibernateDatastore(PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Package...packagesToScan) { + public HibernateDatastore(PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Package... packagesToScan) { this(configuration, eventPublisher, new ClasspathEntityScanner().scan(packagesToScan)); } /** * Construct a Hibernate datastore scanning the given packages for the given datasource * - * @param configuration The configuration + * @param configuration The configuration * @param eventPublisher The event publisher * @param packagesToScan The packages to scan */ - public HibernateDatastore(DataSource dataSource, PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Package...packagesToScan) { + public HibernateDatastore(DataSource dataSource, PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Package... packagesToScan) { this(dataSource, configuration, eventPublisher, new ClasspathEntityScanner().scan(packagesToScan)); } @@ -274,18 +259,19 @@ public HibernateDatastore(DataSource dataSource, PropertyResolver configuration, * Create a new HibernateDatastore for the given connection sources and mapping context * * @param configuration The configuration - * @param classes The persistent classes + * @param classes The persistent classes */ - public HibernateDatastore(PropertyResolver configuration, Class...classes) { + public HibernateDatastore(PropertyResolver configuration, Class... classes) { this(configuration, new HibernateConnectionSourceFactory(classes)); } + /** * Construct a Hibernate datastore scanning the given packages * - * @param configuration The configuration + * @param configuration The configuration * @param packagesToScan The packages to scan */ - public HibernateDatastore(PropertyResolver configuration, Package...packagesToScan) { + public HibernateDatastore(PropertyResolver configuration, Package... packagesToScan) { this(configuration, new ClasspathEntityScanner().scan(packagesToScan)); } @@ -294,16 +280,17 @@ public HibernateDatastore(PropertyResolver configuration, Package...packagesToSc * * @param classes The classes */ - public HibernateDatastore(Map configuration, Class...classes) { + public HibernateDatastore(Map configuration, Class... classes) { this(DatastoreUtils.createPropertyResolver(configuration), new HibernateConnectionSourceFactory(classes)); } + /** * Construct a Hibernate datastore scanning the given packages * - * @param configuration The configuration + * @param configuration The configuration * @param packagesToScan The packages to scan */ - public HibernateDatastore(Map configuration, Package...packagesToScan) { + public HibernateDatastore(Map configuration, Package... packagesToScan) { this(DatastoreUtils.createPropertyResolver(configuration), packagesToScan); } @@ -312,7 +299,7 @@ public HibernateDatastore(Map configuration, Package...packagesTo * * @param classes The classes */ - public HibernateDatastore(Class...classes) { + public HibernateDatastore(Class... classes) { this(DatastoreUtils.createPropertyResolver(Collections.singletonMap(Settings.SETTING_DB_CREATE, "create-drop")), new HibernateConnectionSourceFactory(classes)); } @@ -321,7 +308,7 @@ public HibernateDatastore(Class...classes) { * * @param packagesToScan The packages to scan */ - public HibernateDatastore(Package...packagesToScan) { + public HibernateDatastore(Package... packagesToScan) { this(new ClasspathEntityScanner().scan(packagesToScan)); } @@ -334,6 +321,31 @@ public HibernateDatastore(Package packageToScan) { this(new ClasspathEntityScanner().scan(packageToScan)); } + private HibernateDatastore createChildDatastore(HibernateMappingContext mappingContext, + ConfigurableApplicationEventPublisher eventPublisher, + HibernateDatastore parent, + SingletonConnectionSources singletonConnectionSources) { + return new HibernateDatastore(singletonConnectionSources, mappingContext, eventPublisher) { + @Override + protected HibernateGormEnhancer initialize() { + return null; + } + + @Override + public HibernateDatastore getDatastoreForConnection(String connectionName) { + if (connectionName.equals(Settings.SETTING_DATASOURCE) || connectionName.equals(ConnectionSource.DEFAULT)) { + return parent; + } else { + HibernateDatastore hibernateDatastore = parent.datastoresByConnectionSource.get(connectionName); + if (hibernateDatastore == null) { + throw new ConfigurationException("DataSource not found for name [" + connectionName + "] in configuration. Please check your multiple data sources configuration and try again."); + } + return hibernateDatastore; + } + } + }; + } + @Override public ApplicationEventPublisher getApplicationEventPublisher() { return this.eventPublisher; @@ -346,21 +358,19 @@ public GrailsHibernateTransactionManager getTransactionManager() { return transactionManager; } - /** * Obtain a child {@link HibernateDatastore} by connection name * * @param connectionName The connection name - * * @return The {@link HibernateDatastore} */ public HibernateDatastore getDatastoreForConnection(String connectionName) { - if(connectionName.equals(Settings.SETTING_DATASOURCE) || connectionName.equals(ConnectionSource.DEFAULT)) { + if (connectionName.equals(Settings.SETTING_DATASOURCE) || connectionName.equals(ConnectionSource.DEFAULT)) { return this; } else { HibernateDatastore hibernateDatastore = this.datastoresByConnectionSource.get(connectionName); - if(hibernateDatastore == null) { - throw new ConfigurationException("DataSource not found for name ["+connectionName+"] in configuration. Please check your multiple data sources configuration and try again."); + if (hibernateDatastore == null) { + throw new ConfigurationException("DataSource not found for name [" + connectionName + "] in configuration. Please check your multiple data sources configuration and try again."); } return hibernateDatastore; } @@ -386,7 +396,7 @@ public void setMessageSource(MessageSource messageSource) { protected void registerEventListeners(ConfigurableApplicationEventPublisher eventPublisher) { eventPublisher.addApplicationListener(autoTimestampEventListener); - if(multiTenantMode == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) { + if (multiTenantMode == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) { eventPublisher.addApplicationListener(new MultiTenantEventListener()); } eventPublisher.addApplicationListener(eventTriggeringInterceptor); @@ -399,8 +409,8 @@ protected void configureValidatorRegistry(HibernateConnectionSourceSettings sett } protected void configureValidatorRegistry(HibernateConnectionSourceSettings settings, HibernateMappingContext mappingContext, ValidatorRegistry validatorRegistry, MessageSource messageSource) { - if(validatorRegistry instanceof ConstraintRegistry) { - ((ConstraintRegistry)validatorRegistry).addConstraintFactory( + if (validatorRegistry instanceof ConstraintRegistry) { + ((ConstraintRegistry) validatorRegistry).addConstraintFactory( new MappingContextAwareConstraintFactory(UniqueConstraint.class, messageSource, mappingContext) ); } @@ -411,25 +421,26 @@ protected void configureValidatorRegistry(HibernateConnectionSourceSettings sett protected HibernateGormEnhancer initialize() { final HibernateConnectionSource defaultConnectionSource = (HibernateConnectionSource) getConnectionSources().getDefaultConnectionSource(); - if(multiTenantMode == MultiTenancySettings.MultiTenancyMode.SCHEMA) { + if (multiTenantMode == MultiTenancySettings.MultiTenancyMode.SCHEMA) { return new HibernateGormEnhancer(this, transactionManager, defaultConnectionSource.getSettings()) { @Override public List allQualifiers(Datastore datastore, PersistentEntity entity) { List allQualifiers = super.allQualifiers(datastore, entity); - if( MultiTenant.class.isAssignableFrom(entity.getJavaClass()) ) { - if(tenantResolver instanceof AllTenantsResolver) { + if (MultiTenant.class.isAssignableFrom(entity.getJavaClass())) { + if (tenantResolver instanceof AllTenantsResolver) { Iterable tenantIds = ((AllTenantsResolver) tenantResolver).resolveTenantIds(); - for(Serializable id : tenantIds) { + for (Serializable id : tenantIds) { allQualifiers.add(id.toString()); } - } - else { + } else { Collection schemaNames = schemaHandler.resolveSchemaNames(defaultConnectionSource.getDataSource()); for (String schemaName : schemaNames) { // skip common internal schemas - if(schemaName.equals("INFORMATION_SCHEMA") || schemaName.equals("PUBLIC")) continue; + if (schemaName.equals("INFORMATION_SCHEMA") || schemaName.equals("PUBLIC")) { + continue; + } for (String connectionName : datastoresByConnectionSource.keySet()) { - if(schemaName.equalsIgnoreCase(connectionName)) { + if (schemaName.equalsIgnoreCase(connectionName)) { allQualifiers.add(connectionName); } } @@ -440,8 +451,7 @@ public List allQualifiers(Datastore datastore, PersistentEntity entity) return allQualifiers; } }; - } - else { + } else { return new HibernateGormEnhancer(this, transactionManager, defaultConnectionSource.getSettings()); } } @@ -457,11 +467,11 @@ protected Session createSession(PropertyResolver connectionDetails) { } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - if(applicationContext instanceof ConfigurableApplicationContext) { + if (applicationContext instanceof ConfigurableApplicationContext) { super.setApplicationContext(applicationContext); for (HibernateDatastore hibernateDatastore : datastoresByConnectionSource.values()) { - if(hibernateDatastore != this) { + if (hibernateDatastore != this) { hibernateDatastore.setApplicationContext(applicationContext); } } @@ -480,7 +490,7 @@ public void setApplicationContext(ApplicationContext applicationContext) throws ); registerEventListeners(eventPublisher); - this.eventPublisher.publishEvent( new DatastoreInitializedEvent(this) ); + this.eventPublisher.publishEvent(new DatastoreInitializedEvent(this)); } } @@ -504,8 +514,7 @@ public void withFlushMode(FlushMode flushMode, Callable callable) { } catch (Exception e) { reset = false; } - } - finally { + } finally { if (session != null && previousMode != null && reset) { session.setHibernateFlushMode(previousMode); } @@ -545,15 +554,15 @@ public void addTenantForSchema(String schemaName) { registerAllEntitiesWithEnhancer(); HibernateConnectionSource defaultConnectionSource = (HibernateConnectionSource) connectionSources.getDefaultConnectionSource(); DataSource dataSource = defaultConnectionSource.getDataSource(); - if(dataSource instanceof TransactionAwareDataSourceProxy) { + if (dataSource instanceof TransactionAwareDataSourceProxy) { dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource(); } Object existing = TransactionSynchronizationManager.getResource(dataSource); - if(existing instanceof ConnectionHolder) { + if (existing instanceof ConnectionHolder) { ConnectionHolder connectionHolder = (ConnectionHolder) existing; Connection connection = connectionHolder.getConnection(); try { - if(!connection.isClosed() && !connection.isReadOnly()) { + if (!connection.isClosed() && !connection.isReadOnly()) { schemaHandler.useDefaultSchema(connection); } } catch (SQLException e) { @@ -574,14 +583,14 @@ protected void registerAllEntitiesWithEnhancer() { } private void addTenantForSchemaInternal(final String schemaName) { - if( multiTenantMode != MultiTenancySettings.MultiTenancyMode.SCHEMA ) { + if (multiTenantMode != MultiTenancySettings.MultiTenancyMode.SCHEMA) { throw new ConfigurationException("The method [addTenantForSchema] can only be called with multi-tenancy mode SCHEMA. Current mode is: " + multiTenantMode); } HibernateConnectionSourceFactory factory = (HibernateConnectionSourceFactory) connectionSources.getFactory(); HibernateConnectionSource defaultConnectionSource = (HibernateConnectionSource) connectionSources.getDefaultConnectionSource(); HibernateConnectionSourceSettings tenantSettings; try { - tenantSettings = (HibernateConnectionSourceSettings)connectionSources.getDefaultConnectionSource().getSettings().clone(); + tenantSettings = (HibernateConnectionSourceSettings) connectionSources.getDefaultConnectionSource().getSettings().clone(); } catch (CloneNotSupportedException e) { throw new ConfigurationException("Couldn't clone default Hibernate settings! " + e.getMessage(), e); } @@ -589,8 +598,8 @@ private void addTenantForSchemaInternal(final String schemaName) { String dbCreate = tenantSettings.getDataSource().getDbCreate(); - SchemaAutoTooling schemaAutoTooling = dbCreate != null ? SchemaAutoTooling.interpret(dbCreate) : null; - if(schemaAutoTooling != null && schemaAutoTooling != SchemaAutoTooling.VALIDATE && schemaAutoTooling != SchemaAutoTooling.NONE) { + SchemaAutoTooling schemaAutoTooling = dbCreate != null ? SchemaAutoTooling.interpret(dbCreate) : null; + if (schemaAutoTooling != null && schemaAutoTooling != SchemaAutoTooling.VALIDATE && schemaAutoTooling != SchemaAutoTooling.NONE) { Connection connection = null; try { @@ -604,9 +613,8 @@ private void addTenantForSchemaInternal(final String schemaName) { } catch (SQLException e) { throw new DatastoreConfigurationException(String.format("Failed to create schema for name [%s]", schemaName)); - } - finally { - if(connection != null) { + } finally { + if (connection != null) { try { schemaHandler.useDefaultSchema(connection); connection.close(); @@ -663,10 +671,9 @@ private static HibernateConnectionSourceFactory createConnectionFactoryForDataSo new DataSourceConnectionSourceFactory() { @Override public ConnectionSource create(String name, DataSourceSettings settings) { - if(ConnectionSource.DEFAULT.equals(name)) { + if (ConnectionSource.DEFAULT.equals(name)) { return new DataSourceConnectionSource(ConnectionSource.DEFAULT, dataSource, settings); - } - else { + } else { return super.create(name, settings); } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormEnhancer.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormEnhancer.groovy index 2b2cf7b6530..072662512d4 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormEnhancer.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormEnhancer.groovy @@ -26,6 +26,7 @@ import org.grails.datastore.gorm.GormValidationApi import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.core.connections.ConnectionSourceSettings import org.springframework.transaction.PlatformTransactionManager + /** * Extended GORM Enhancer that fills out the remaining GORM for Hibernate methods * and implements string-based query support via HQL. diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormInstanceApi.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormInstanceApi.groovy index ff07d05b937..ea738148d58 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormInstanceApi.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormInstanceApi.groovy @@ -40,7 +40,7 @@ class HibernateGormInstanceApi extends AbstractHibernateGormInstanceApi { HibernateGormInstanceApi(Class persistentClass, HibernateDatastore datastore, ClassLoader classLoader) { super(persistentClass, datastore, classLoader, null) hibernateTemplate = new GrailsHibernateTemplate(sessionFactory, datastore) - instanceApiHelper = new InstanceApiHelper((GrailsHibernateTemplate)hibernateTemplate) + instanceApiHelper = new InstanceApiHelper((GrailsHibernateTemplate) hibernateTemplate) } /** @@ -54,7 +54,7 @@ class HibernateGormInstanceApi extends AbstractHibernateGormInstanceApi { @CompileDynamic boolean isDirty(D instance, String fieldName) { - SessionImplementor session = (SessionImplementor)sessionFactory.currentSession + SessionImplementor session = (SessionImplementor) sessionFactory.currentSession def entry = findEntityEntry(instance, session) if (!entry || !entry.loadedState) { return false @@ -63,16 +63,16 @@ class HibernateGormInstanceApi extends AbstractHibernateGormInstanceApi { EntityPersister persister = entry.persister Object[] values = persister.getPropertyValues(instance) def dirtyProperties = findDirty(persister, values, entry, instance, session) - if(dirtyProperties == null) { + if (dirtyProperties == null) { return false - } - else { + } else { int fieldIndex = persister.getEntityMetamodel().getProperties().findIndexOf { NonIdentifierAttribute attribute -> fieldName == attribute.name } return fieldIndex in dirtyProperties } } - @CompileDynamic // required for Hibernate 5.2 compatibility + @CompileDynamic + // required for Hibernate 5.2 compatibility private def findDirty(EntityPersister persister, Object[] values, EntityEntry entry, D instance, SessionImplementor session) { persister.findDirty(values, entry.loadedState, instance, session) } @@ -85,7 +85,7 @@ class HibernateGormInstanceApi extends AbstractHibernateGormInstanceApi { */ @CompileDynamic boolean isDirty(D instance) { - SessionImplementor session = (SessionImplementor)sessionFactory.currentSession + SessionImplementor session = (SessionImplementor) sessionFactory.currentSession def entry = findEntityEntry(instance, session) if (!entry || !entry.loadedState) { return false @@ -105,7 +105,7 @@ class HibernateGormInstanceApi extends AbstractHibernateGormInstanceApi { @CompileDynamic List getDirtyPropertyNames(D instance) { - SessionImplementor session = (SessionImplementor)sessionFactory.currentSession + SessionImplementor session = (SessionImplementor) sessionFactory.currentSession def entry = findEntityEntry(instance, session) if (!entry || !entry.loadedState) { return [] @@ -129,7 +129,7 @@ class HibernateGormInstanceApi extends AbstractHibernateGormInstanceApi { * @return The original persisted value */ Object getPersistentValue(D instance, String fieldName) { - SessionImplementor session = (SessionImplementor)sessionFactory.currentSession + SessionImplementor session = (SessionImplementor) sessionFactory.currentSession def entry = findEntityEntry(instance, session, false) if (!entry || !entry.loadedState) { return null diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy index c35e7e5e7d1..b11788a1cfc 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy @@ -21,6 +21,10 @@ package org.grails.orm.hibernate import grails.orm.HibernateCriteriaBuilder import groovy.transform.CompileDynamic import groovy.transform.CompileStatic +import jakarta.persistence.FlushModeType +import jakarta.persistence.criteria.CriteriaBuilder +import jakarta.persistence.criteria.CriteriaQuery +import jakarta.persistence.criteria.Root import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.gorm.finders.DynamicFinder import org.grails.datastore.gorm.finders.FinderMethod @@ -30,20 +34,19 @@ import org.grails.datastore.mapping.query.event.PreQueryEvent import org.grails.orm.hibernate.exceptions.GrailsQueryException import org.grails.orm.hibernate.query.GrailsHibernateQueryUtils import org.grails.orm.hibernate.query.HibernateHqlQuery -import org.grails.orm.hibernate.query.PagedResultList import org.grails.orm.hibernate.query.HibernateQuery -import org.hibernate.* +import org.grails.orm.hibernate.query.PagedResultList +import org.hibernate.Criteria +import org.hibernate.FlushMode +import org.hibernate.LockMode +import org.hibernate.Session +import org.hibernate.SessionFactory import org.hibernate.query.Query import org.springframework.core.convert.ConversionService import org.springframework.orm.hibernate5.SessionHolder import org.springframework.transaction.PlatformTransactionManager import org.springframework.transaction.support.TransactionSynchronizationManager -import jakarta.persistence.FlushModeType -import jakarta.persistence.criteria.CriteriaBuilder -import jakarta.persistence.criteria.CriteriaQuery -import jakarta.persistence.criteria.Root - /** * The implementation of the GORM static method contract for Hibernate * @@ -52,6 +55,7 @@ import jakarta.persistence.criteria.Root */ @CompileStatic class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { + protected SessionFactory sessionFactory protected ConversionService conversionService protected Class identityType @@ -60,7 +64,7 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { private int defaultFlushMode HibernateGormStaticApi(Class persistentClass, HibernateDatastore datastore, List finders, - ClassLoader classLoader, PlatformTransactionManager transactionManager) { + ClassLoader classLoader, PlatformTransactionManager transactionManager) { super(persistentClass, datastore, finders, transactionManager) this.classLoader = classLoader sessionFactory = datastore.getSessionFactory() @@ -73,7 +77,7 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { @Override GrailsHibernateTemplate getHibernateTemplate() { - return (GrailsHibernateTemplate)super.getHibernateTemplate() + return (GrailsHibernateTemplate) super.getHibernateTemplate() } @Override @@ -102,14 +106,14 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { ) HibernateHqlQuery hibernateQuery = new HibernateHqlQuery( - new HibernateSession((HibernateDatastore)datastore, sessionFactory), + new HibernateSession((HibernateDatastore) datastore, sessionFactory), persistentEntity, query ) hibernateTemplate.applySettings(query) params = params ? new HashMap(params) : Collections.emptyMap() - if(params.containsKey(DynamicFinder.ARGUMENT_MAX)) { + if (params.containsKey(DynamicFinder.ARGUMENT_MAX)) { return new PagedResultList( hibernateTemplate, persistentEntity, @@ -118,8 +122,7 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { queryRoot, criteriaBuilder ) - } - else { + } else { return hibernateQuery.list() } } @@ -130,24 +133,23 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { return GormEnhancer.findStaticApi(persistentClass, name) } - @Override GrailsCriteria createCriteria() { def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory) - builder.datastore = (AbstractHibernateDatastore)datastore + builder.datastore = (AbstractHibernateDatastore) datastore builder.conversionService = conversionService return builder } @Override D lock(Serializable id) { - (D)hibernateTemplate.lock((Class)persistentClass, convertIdentifier(id), LockMode.PESSIMISTIC_WRITE) + (D) hibernateTemplate.lock((Class) persistentClass, convertIdentifier(id), LockMode.PESSIMISTIC_WRITE) } @Override Integer executeUpdate(CharSequence query, Map params, Map args) { - if(query instanceof GString) { + if (query instanceof GString) { params = new LinkedHashMap(params) query = buildNamedParameterQueryFromGString((GString) query, params) } @@ -157,7 +159,7 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { return (Integer) template.execute { Session session -> Query q = (Query) session.createQuery(query.toString()) template.applySettings(q) - def sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource( sessionFactory ) + def sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory) if (sessionHolder && sessionHolder.hasTimeout()) { q.timeout = sessionHolder.timeToLiveInSeconds } @@ -174,7 +176,7 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { @Override Integer executeUpdate(CharSequence query, Collection params, Map args) { - if(query instanceof GString) { + if (query instanceof GString) { throw new GrailsQueryException("Unsafe query [$query]. GORM cannot automatically escape a GString value when combined with ordinal parameters, so this query is potentially vulnerable to HQL injection attacks. Please embed the parameters within the GString so they can be safely escaped."); } @@ -184,17 +186,15 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { return (Integer) template.execute { Session session -> Query q = (Query) session.createQuery(query.toString()) template.applySettings(q) - def sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource( sessionFactory ) + def sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory) if (sessionHolder && sessionHolder.hasTimeout()) { q.timeout = sessionHolder.timeToLiveInSeconds } - params.eachWithIndex { val, int i -> if (val instanceof CharSequence) { q.setParameter i, val.toString() - } - else { + } else { q.setParameter i, val } } @@ -206,7 +206,7 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { } protected T withQueryEvents(Query query, Closure callable) { - HibernateDatastore hibernateDatastore = (HibernateDatastore)datastore + HibernateDatastore hibernateDatastore = (HibernateDatastore) datastore def eventPublisher = hibernateDatastore.applicationEventPublisher @@ -221,17 +221,16 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { @Override protected void firePostQueryEvent(Session session, Criteria criteria, Object result) { - if(result instanceof List) { - datastore.applicationEventPublisher.publishEvent( new PostQueryEvent(datastore, new HibernateQuery(criteria, persistentEntity), (List)result)) - } - else { - datastore.applicationEventPublisher.publishEvent( new PostQueryEvent(datastore, new HibernateQuery(criteria, persistentEntity), Collections.singletonList(result))) + if (result instanceof List) { + datastore.applicationEventPublisher.publishEvent(new PostQueryEvent(datastore, new HibernateQuery(criteria, persistentEntity), (List) result)) + } else { + datastore.applicationEventPublisher.publishEvent(new PostQueryEvent(datastore, new HibernateQuery(criteria, persistentEntity), Collections.singletonList(result))) } } @Override protected void firePreQueryEvent(Session session, Criteria criteria) { - datastore.applicationEventPublisher.publishEvent( new PreQueryEvent(datastore, new HibernateQuery(criteria, persistentEntity))) + datastore.applicationEventPublisher.publishEvent(new PreQueryEvent(datastore, new HibernateQuery(criteria, persistentEntity))) } @Override diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy index 34ed12f59fa..28749e834a4 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy @@ -32,8 +32,8 @@ class HibernateGormValidationApi extends AbstractHibernateGormValidationApi, ResourceLoaderAware, DisposableBean, ApplicationContextAware, InitializingBean, BeanClassLoaderAware { + + private static final Log LOG = LogFactory.getLog(HibernateMappingContextSessionFactoryBean.class); + protected Class configClass = HibernateMappingContextConfiguration.class; protected HibernateMappingContext hibernateMappingContext; protected PlatformTransactionManager transactionManager; + protected Class currentSessionContextClass; + protected Map eventListeners; + protected HibernateEventListeners hibernateEventListeners; + protected ApplicationContext applicationContext; + protected boolean proxyIfReloadEnabled = false; + protected String sessionFactoryBeanName = "sessionFactory"; + protected String dataSourceName = ConnectionSource.DEFAULT; + protected ClassLoader classLoader; private DataSource dataSource; private Resource[] configLocations; @@ -85,17 +95,6 @@ public class HibernateMappingContextSessionFactoryBean extends HibernateExceptio private HibernateMappingContextConfiguration configuration; private SessionFactory sessionFactory; - private static final Log LOG = LogFactory.getLog(HibernateMappingContextSessionFactoryBean.class); - protected Class currentSessionContextClass; - protected Map eventListeners; - protected HibernateEventListeners hibernateEventListeners; - protected ApplicationContext applicationContext; - protected boolean proxyIfReloadEnabled = false; - protected String sessionFactoryBeanName = "sessionFactory"; - protected String dataSourceName = ConnectionSource.DEFAULT; - protected ClassLoader classLoader; - - @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; @@ -107,8 +106,7 @@ public void afterPropertiesSet() throws Exception { try { thread.setContextClassLoader(classLoader); buildSessionFactory(); - } - finally { + } finally { thread.setContextClassLoader(cl); } } @@ -127,11 +125,13 @@ public void setHibernateMappingContext(HibernateMappingContext hibernateMappingC /** * Sets the class to be used for Hibernate Configuration. + * * @param configClass A subclass of the Hibernate Configuration class */ public void setConfigClass(Class configClass) { this.configClass = configClass; } + /** * Set the DataSource to be used by the SessionFactory. * If set, this will override corresponding settings in Hibernate properties. @@ -141,6 +141,7 @@ public void setConfigClass(Class public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } + public DataSource getDataSource() { return dataSource; } @@ -150,10 +151,11 @@ public DataSource getDataSource() { * classpath resource "classpath:hibernate.cfg.xml". *

Note: Can be omitted when all necessary properties and mapping * resources are specified locally via this bean. + * * @see org.hibernate.cfg.Configuration#configure(java.net.URL) */ public void setConfigLocation(Resource configLocation) { - configLocations = new Resource[] {configLocation}; + configLocations = new Resource[]{configLocation}; } /** @@ -161,11 +163,13 @@ public void setConfigLocation(Resource configLocation) { * classpath resources "classpath:hibernate.cfg.xml,classpath:extension.cfg.xml". *

Note: Can be omitted when all necessary properties and mapping * resources are specified locally via this bean. + * * @see org.hibernate.cfg.Configuration#configure(java.net.URL) */ public void setConfigLocations(Resource[] configLocations) { this.configLocations = configLocations; } + public Resource[] getConfigLocations() { return configLocations; } @@ -177,12 +181,14 @@ public Resource[] getConfigLocations() { * Alternative to the more generic setMappingLocations method. *

Can be used to add to mappings from a Hibernate XML config file, * or to specify all mappings locally. + * * @see #setMappingLocations * @see org.hibernate.cfg.Configuration#addResource */ public void setMappingResources(String[] mappingResources) { this.mappingResources = mappingResources; } + public String[] getMappingResources() { return mappingResources; } @@ -194,11 +200,13 @@ public String[] getMappingResources() { * "WEB-INF/mappings/example.hbm.xml" when running in an application context. *

Can be used to add to mappings from a Hibernate XML config file, * or to specify all mappings locally. + * * @see org.hibernate.cfg.Configuration#addInputStream */ public void setMappingLocations(Resource[] mappingLocations) { this.mappingLocations = mappingLocations; } + public Resource[] getMappingLocations() { return mappingLocations; } @@ -210,11 +218,13 @@ public Resource[] getMappingLocations() { * in the file system. *

Can be used to add to mappings from a Hibernate XML config file, * or to specify all mappings locally. + * * @see org.hibernate.cfg.Configuration#addCacheableFile(java.io.File) */ public void setCacheableMappingLocations(Resource[] cacheableMappingLocations) { this.cacheableMappingLocations = cacheableMappingLocations; } + public Resource[] getCacheableMappingLocations() { return cacheableMappingLocations; } @@ -224,11 +234,13 @@ public Resource[] getCacheableMappingLocations() { * like "WEB-INF/lib/example.hbm.jar". *

Can be used to add to mappings from a Hibernate XML config file, * or to specify all mappings locally. + * * @see org.hibernate.cfg.Configuration#addJar(java.io.File) */ public void setMappingJarLocations(Resource[] mappingJarLocations) { this.mappingJarLocations = mappingJarLocations; } + public Resource[] getMappingJarLocations() { return mappingJarLocations; } @@ -238,11 +250,13 @@ public Resource[] getMappingJarLocations() { * like "WEB-INF/mappings". *

Can be used to add to mappings from a Hibernate XML config file, * or to specify all mappings locally. + * * @see org.hibernate.cfg.Configuration#addDirectory(java.io.File) */ public void setMappingDirectoryLocations(Resource[] mappingDirectoryLocations) { this.mappingDirectoryLocations = mappingDirectoryLocations; } + public Resource[] getMappingDirectoryLocations() { return mappingDirectoryLocations; } @@ -251,11 +265,13 @@ public Resource[] getMappingDirectoryLocations() { * Set a Hibernate entity interceptor that allows to inspect and change * property values before writing to and reading from the database. * Will get applied to any new Session created by this factory. + * * @see org.hibernate.cfg.Configuration#setInterceptor */ public void setEntityInterceptor(Interceptor entityInterceptor) { this.entityInterceptor = entityInterceptor; } + public Interceptor getEntityInterceptor() { return entityInterceptor; } @@ -267,6 +283,7 @@ public Interceptor getEntityInterceptor() { public void setNamingStrategy(NamingStrategy namingStrategy) { this.namingStrategy = namingStrategy; } + public NamingStrategy getNamingStrategy() { return namingStrategy; } @@ -276,6 +293,7 @@ public NamingStrategy getNamingStrategy() { *

Note: Do not specify a transaction provider here when using * Spring-driven transactions. It is also advisable to omit connection * provider settings and use a Spring-set DataSource instead. + * * @see #setDataSource */ public void setHibernateProperties(Properties hibernateProperties) { @@ -295,11 +313,13 @@ public Properties getHibernateProperties() { /** * Specify annotated entity classes to register with this Hibernate SessionFactory. + * * @see org.hibernate.cfg.Configuration#addAnnotatedClass(Class) */ public void setAnnotatedClasses(Class[] annotatedClasses) { this.annotatedClasses = annotatedClasses; } + public Class[] getAnnotatedClasses() { return annotatedClasses; } @@ -307,11 +327,13 @@ public Class[] getAnnotatedClasses() { /** * Specify the names of annotated packages, for which package-level * annotation metadata will be read. + * * @see org.hibernate.cfg.Configuration#addPackage(String) */ public void setAnnotatedPackages(String[] annotatedPackages) { this.annotatedPackages = annotatedPackages; } + public String[] getAnnotatedPackages() { return annotatedPackages; } @@ -324,6 +346,7 @@ public String[] getAnnotatedPackages() { public void setPackagesToScan(String... packagesToScan) { this.packagesToScan = packagesToScan; } + public String[] getPackagesToScan() { return packagesToScan; } @@ -338,6 +361,7 @@ public void setResourceLoader(ResourceLoader resourceLoader) { public void setProxyIfReloadEnabled(boolean proxyIfReloadEnabled) { this.proxyIfReloadEnabled = proxyIfReloadEnabled; } + public boolean isProxyIfReloadEnabled() { return proxyIfReloadEnabled; } @@ -350,6 +374,7 @@ public boolean isProxyIfReloadEnabled() { public void setCurrentSessionContextClass(Class currentSessionContextClass) { this.currentSessionContextClass = currentSessionContextClass; } + public Class getCurrentSessionContextClass() { return currentSessionContextClass; } @@ -361,6 +386,7 @@ public Class getConfigClass() { public void setHibernateEventListeners(final HibernateEventListeners listeners) { hibernateEventListeners = listeners; } + public HibernateEventListeners getHibernateEventListeners() { return hibernateEventListeners; } @@ -368,6 +394,7 @@ public HibernateEventListeners getHibernateEventListeners() { public void setSessionFactoryBeanName(String name) { sessionFactoryBeanName = name; } + public String getSessionFactoryBeanName() { return sessionFactoryBeanName; } @@ -375,6 +402,7 @@ public String getSessionFactoryBeanName() { public void setDataSourceName(String name) { dataSourceName = name; } + public String getDataSourceName() { return dataSourceName; } @@ -385,12 +413,14 @@ public String getDataSourceName() { * you can also pass in a list or set of listeners objects as value. *

See the Hibernate documentation for further details on listener types * and associated listener interfaces. + * * @param eventListeners Map with listener type Strings as keys and - * listener objects as values + * listener objects as values */ public void setEventListeners(Map eventListeners) { this.eventListeners = eventListeners; } + public Map getEventListeners() { return eventListeners; } @@ -399,7 +429,7 @@ protected void buildSessionFactory() throws Exception { configuration = newConfiguration(); - if(hibernateMappingContext == null) { + if (hibernateMappingContext == null) { throw new IllegalArgumentException("HibernateMappingContext is required."); } @@ -457,9 +487,9 @@ protected void buildSessionFactory() throws Exception { configuration.setInterceptor(entityInterceptor); } - if (namingStrategy != null) { +// if (namingStrategy != null) { // configuration.setNamingStrategy(namingStrategy); - } +// } if (hibernateProperties != null) { configuration.addProperties(hibernateProperties); @@ -492,6 +522,7 @@ protected SessionFactory doBuildSessionFactory() { /** * Return the Hibernate Configuration object used to build the SessionFactory. * Allows for access to configuration metadata stored there (rarely needed). + * * @throws IllegalStateException if the Configuration object has not been initialized yet */ public final Configuration getConfiguration() { @@ -514,12 +545,10 @@ public boolean isSingleton() { public void destroy() { try { sessionFactory.close(); - } - catch (HibernateException e) { + } catch (HibernateException e) { if (e.getCause() instanceof NameNotFoundException) { LOG.debug(e.getCause().getMessage(), e); - } - else { + } else { throw e; } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java index dd492c08d6d..ba4e672b32f 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java @@ -18,35 +18,36 @@ */ package org.grails.orm.hibernate; -import java.io.Serializable; -import java.util.Collections; -import java.util.List; -import java.util.Map; - import jakarta.persistence.FlushModeType; import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Root; - import org.grails.datastore.gorm.timestamp.DefaultTimestampProvider; +import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.config.GormProperties; import org.grails.datastore.mapping.proxy.ProxyHandler; -import org.grails.datastore.mapping.query.event.PostQueryEvent; -import org.grails.datastore.mapping.query.event.PreQueryEvent; -import org.grails.orm.hibernate.proxy.HibernateProxyHandler; -import org.grails.orm.hibernate.query.HibernateHqlQuery; -import org.grails.orm.hibernate.query.HibernateQuery; -import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.api.QueryableCriteria; +import org.grails.datastore.mapping.query.event.PostQueryEvent; +import org.grails.datastore.mapping.query.event.PreQueryEvent; import org.grails.datastore.mapping.query.jpa.JpaQueryBuilder; import org.grails.datastore.mapping.query.jpa.JpaQueryInfo; import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.hibernate.*; +import org.grails.orm.hibernate.proxy.HibernateProxyHandler; +import org.grails.orm.hibernate.query.HibernateHqlQuery; +import org.grails.orm.hibernate.query.HibernateQuery; +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.SessionFactory; import org.hibernate.proxy.HibernateProxy; import org.springframework.context.ApplicationEventPublisher; +import java.io.Serializable; +import java.util.Collections; +import java.util.List; +import java.util.Map; + /** * Session implementation that wraps a Hibernate {@link org.hibernate.Session}. * @@ -71,14 +72,16 @@ public HibernateSession(HibernateDatastore hibernateDatastore, SessionFactory se @Override public Serializable getObjectIdentifier(Object instance) { - if(instance == null) return null; - if(proxyHandler.isProxy(instance)) { - return ((HibernateProxy)instance).getHibernateLazyInitializer().getIdentifier(); + if (instance == null) { + return null; + } + if (proxyHandler.isProxy(instance)) { + return ((HibernateProxy) instance).getHibernateLazyInitializer().getIdentifier(); } Class type = instance.getClass(); ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(type); final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(type.getName()); - if(persistentEntity != null) { + if (persistentEntity != null) { return (Serializable) cpf.getPropertyValue(instance, persistentEntity.getIdentity().getName()); } return null; @@ -103,7 +106,7 @@ public long deleteAll(final QueryableCriteria criteria) { List parameters = jpaQueryInfo.getParameters(); if (parameters != null) { for (int i = 0, count = parameters.size(); i < count; i++) { - query.setParameter(JpaQueryBuilder.PARAMETER_NAME_PREFIX + (i+1), parameters.get(i)); + query.setParameter(JpaQueryBuilder.PARAMETER_NAME_PREFIX + (i + 1), parameters.get(i)); } } @@ -119,7 +122,7 @@ public long deleteAll(final QueryableCriteria criteria) { /** * Updates all objects matching the given criteria and property values. * - * @param criteria The criteria + * @param criteria The criteria * @param properties The properties * @return The total number of records updated */ @@ -130,7 +133,7 @@ public long updateAll(final QueryableCriteria criteria, final Map, Mapping> MAPPING_CACHE = new HashMap<>(); + protected static final Map, Mapping> MAPPING_CACHE = new HashMap<>(); /** * Obtains a mapping object for the given domain class nam @@ -46,10 +46,9 @@ public static Mapping getMapping(Class theClass) { } /** - * Obtains a mapping object for the given domain class nam + * Obtains a mapping object for the given domain class name and caches it * * @param theClass The domain class in question - * @return A Mapping object or null */ static void cacheMapping(Class theClass, Mapping mapping) { MAPPING_CACHE.put(theClass, mapping); @@ -71,7 +70,7 @@ public static void clearMappingCache() { public static void clearMappingCache(Class theClass) { String className = theClass.getName(); - for(Iterator, Mapping>> it = MAPPING_CACHE.entrySet().iterator(); it.hasNext();) { + for (Iterator, Mapping>> it = MAPPING_CACHE.entrySet().iterator(); it.hasNext(); ) { Map.Entry, Mapping> entry = it.next(); if (className.equals(entry.getKey().getName())) { it.remove(); diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/CacheConfig.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/CacheConfig.groovy index 15aeb6827d1..666e189e38f 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/CacheConfig.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/CacheConfig.groovy @@ -35,7 +35,8 @@ import org.springframework.validation.DataBinder @CompileStatic @Builder(builderStrategy = SimpleStrategy, prefix = '') class CacheConfig implements Cloneable { - static final List USAGE_OPTIONS = ['read-only', 'read-write','nonstrict-read-write','transactional'] + + static final List USAGE_OPTIONS = ['read-only', 'read-write', 'nonstrict-read-write', 'transactional'] static final List INCLUDE_OPTIONS = ['all', 'non-lazy'] /** diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/ColumnConfig.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/ColumnConfig.groovy index c26f8c7b643..5cb3bf5f969 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/ColumnConfig.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/ColumnConfig.groovy @@ -35,6 +35,7 @@ import org.springframework.validation.DataBinder @CompileStatic @Builder(builderStrategy = SimpleStrategy, prefix = '') class ColumnConfig { + /** * The column name */ diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/CompositeIdentity.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/CompositeIdentity.groovy index 234d9c659e6..e5df39b7a69 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/CompositeIdentity.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/CompositeIdentity.groovy @@ -34,6 +34,7 @@ import org.grails.datastore.mapping.config.Property @Builder(builderStrategy = SimpleStrategy, prefix = '') @CompileStatic class CompositeIdentity extends Property { + /** * The property names that make up the custom identity */ diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/DiscriminatorConfig.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/DiscriminatorConfig.groovy index 53842c800d1..46351684fff 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/DiscriminatorConfig.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/DiscriminatorConfig.groovy @@ -32,6 +32,7 @@ import groovy.transform.builder.SimpleStrategy @CompileStatic @Builder(builderStrategy = SimpleStrategy, prefix = '') class DiscriminatorConfig { + /** * The discriminator value */ diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java index 13c7983e5cb..409caaf13b2 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java @@ -19,14 +19,22 @@ package org.grails.orm.hibernate.cfg; import groovy.lang.Closure; -import groovy.transform.Trait; +import jakarta.persistence.Entity; import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.codehaus.groovy.transform.trait.Traits; import org.grails.datastore.mapping.core.connections.ConnectionSource; import org.grails.datastore.mapping.core.connections.ConnectionSourcesSupport; -import org.grails.datastore.mapping.model.*; +import org.grails.datastore.mapping.model.DatastoreConfigurationException; +import org.grails.datastore.mapping.model.MappingContext; +import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.model.types.*; +import org.grails.datastore.mapping.model.types.Association; +import org.grails.datastore.mapping.model.types.Basic; +import org.grails.datastore.mapping.model.types.Embedded; +import org.grails.datastore.mapping.model.types.ManyToMany; +import org.grails.datastore.mapping.model.types.TenantId; +import org.grails.datastore.mapping.model.types.ToMany; import org.grails.datastore.mapping.model.types.ToOne; import org.grails.datastore.mapping.reflect.EntityReflector; import org.grails.datastore.mapping.reflect.NameUtils; @@ -36,39 +44,76 @@ import org.hibernate.boot.internal.MetadataBuildingContextRootImpl; import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.boot.spi.*; -import org.hibernate.cfg.*; +import org.hibernate.boot.spi.InFlightMetadataCollector; +import org.hibernate.boot.spi.MetadataBuildingContext; +import org.hibernate.boot.spi.MetadataBuildingOptions; +import org.hibernate.boot.spi.MetadataContributor; +import org.hibernate.cfg.AccessType; +import org.hibernate.cfg.BinderHelper; +import org.hibernate.cfg.ImprovedNamingStrategy; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.cfg.SecondPass; import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.engine.spi.PersistentAttributeInterceptable; import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.id.enhanced.SequenceStyleGenerator; -import org.hibernate.mapping.*; +import org.hibernate.mapping.Backref; +import org.hibernate.mapping.Bag; import org.hibernate.mapping.Collection; +import org.hibernate.mapping.Column; +import org.hibernate.mapping.Component; +import org.hibernate.mapping.DependantValue; +import org.hibernate.mapping.Formula; +import org.hibernate.mapping.IndexBackref; +import org.hibernate.mapping.IndexedCollection; +import org.hibernate.mapping.JoinedSubclass; +import org.hibernate.mapping.KeyValue; import org.hibernate.mapping.ManyToOne; import org.hibernate.mapping.OneToMany; import org.hibernate.mapping.OneToOne; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.Property; +import org.hibernate.mapping.RootClass; +import org.hibernate.mapping.Selectable; +import org.hibernate.mapping.SimpleValue; +import org.hibernate.mapping.SingleTableSubclass; +import org.hibernate.mapping.Subclass; import org.hibernate.mapping.Table; +import org.hibernate.mapping.UnionSubclass; +import org.hibernate.mapping.UniqueKey; +import org.hibernate.mapping.Value; import org.hibernate.persister.entity.UnionSubclassEntityPersister; -import org.hibernate.type.*; +import org.hibernate.type.EnumType; +import org.hibernate.type.ForeignKeyDirection; +import org.hibernate.type.IntegerType; +import org.hibernate.type.LongType; +import org.hibernate.type.StandardBasicTypes; +import org.hibernate.type.TimestampType; +import org.hibernate.type.Type; import org.hibernate.usertype.UserCollectionType; import org.jboss.jandex.IndexView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; -import jakarta.persistence.Entity; -import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.sql.Types; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; +import java.util.SortedSet; +import java.util.StringTokenizer; /** * Handles the binding Grails domain classes and properties to the Hibernate runtime meta model. @@ -80,6 +125,13 @@ @SuppressWarnings("WeakerAccess") public class GrailsDomainBinder implements MetadataContributor { + /** + * Overrideable naming strategy. Defaults to ImprovedNamingStrategy but can + * be configured in DataSource.groovy via hibernate.naming_strategy = .... + */ + public static final Map NAMING_STRATEGIES = new HashMap<>(); + public static final String SEQUENCE_KEY = "sequence"; + protected static final String CASCADE_ALL_DELETE_ORPHAN = "all-delete-orphan"; protected static final String FOREIGN_KEY_SUFFIX = "_id"; protected static final String STRING_TYPE = "string"; @@ -95,12 +147,7 @@ public class GrailsDomainBinder implements MetadataContributor { protected static final String ENUM_TYPE_PROP = "type"; protected static final String DEFAULT_ENUM_TYPE = "default"; protected static final Logger LOG = LoggerFactory.getLogger(GrailsDomainBinder.class); - public static final String SEQUENCE_KEY = "sequence"; - /** - * Overrideable naming strategy. Defaults to ImprovedNamingStrategy but can - * be configured in DataSource.groovy via hibernate.naming_strategy = .... - */ - public static Map NAMING_STRATEGIES = new HashMap<>(); + static { NAMING_STRATEGIES.put(ConnectionSource.DEFAULT, ImprovedNamingStrategy.INSTANCE); } @@ -118,10 +165,7 @@ public Collection create(ToMany property, PersistentClass owner, String path, In protected PersistentEntityNamingStrategy namingStrategy; protected MetadataBuildingContext metadataBuildingContext; - public GrailsDomainBinder( - String dataSourceName, - String sessionFactoryName, - HibernateMappingContext hibernateMappingContext) { + public GrailsDomainBinder(String dataSourceName, String sessionFactoryName, HibernateMappingContext hibernateMappingContext) { this.sessionFactoryName = sessionFactoryName; this.dataSourceName = dataSourceName; this.hibernateMappingContext = hibernateMappingContext; @@ -133,6 +177,7 @@ public GrailsDomainBinder( /** * The default mapping defined by {@link org.grails.datastore.mapping.config.Settings#SETTING_DEFAULT_MAPPING} + * * @param defaultMapping The default mapping */ public void setDefaultMapping(Closure defaultMapping) { @@ -153,26 +198,21 @@ public void contribute(InFlightMetadataCollector metadataCollector, IndexView ja ClassLoaderService classLoaderService = options.getServiceRegistry().getService(ClassLoaderService.class); - this.metadataBuildingContext = new MetadataBuildingContextRootImpl( - metadataCollector.getBootstrapContext(), - options, - metadataCollector - ); + this.metadataBuildingContext = new MetadataBuildingContextRootImpl(metadataCollector.getBootstrapContext(), options, metadataCollector); - java.util.Collection persistentEntities = hibernateMappingContext.getPersistentEntities(); + java.util.Collection persistentEntities = hibernateMappingContext.getPersistentEntities(); for (PersistentEntity persistentEntity : persistentEntities) { - if(!persistentEntity.getJavaClass().isAnnotationPresent(Entity.class)) { - if(ConnectionSourcesSupport.usesConnectionSource(persistentEntity, dataSourceName) && persistentEntity.isRoot()) { + if (!persistentEntity.getJavaClass().isAnnotationPresent(Entity.class)) { + if (ConnectionSourcesSupport.usesConnectionSource(persistentEntity, dataSourceName) && persistentEntity.isRoot()) { bindRoot((HibernatePersistentEntity) persistentEntity, metadataCollector, sessionFactoryName); } } } } - - /** * Override the default naming strategy for the default datasource given a Class or a full class name. + * * @param strategy the class or name * @throws ClassNotFoundException When the class was not found for specified strategy * @throws InstantiationException When an error occurred instantiating the strategy @@ -187,7 +227,7 @@ public static void configureNamingStrategy(final Object strategy) throws ClassNo * or an instance of a NamingStrategy. * * @param datasourceName the datasource name - * @param strategy the class, name, or instance + * @param strategy the class, name, or instance * @throws ClassNotFoundException When the class was not found for specified strategy * @throws InstantiationException When an error occurred instantiating the strategy * @throws IllegalAccessException When an error occurred instantiating the strategy @@ -196,30 +236,26 @@ public static void configureNamingStrategy(final String datasourceName, final Ob Class namingStrategyClass = null; NamingStrategy namingStrategy; if (strategy instanceof Class) { - namingStrategyClass = (Class)strategy; - } - else if (strategy instanceof CharSequence) { + namingStrategyClass = (Class) strategy; + } else if (strategy instanceof CharSequence) { namingStrategyClass = Thread.currentThread().getContextClassLoader().loadClass(strategy.toString()); } if (namingStrategyClass == null) { - namingStrategy = (NamingStrategy)strategy; - } - else { - namingStrategy = (NamingStrategy)namingStrategyClass.newInstance(); + namingStrategy = (NamingStrategy) strategy; + } else { + namingStrategy = (NamingStrategy) namingStrategyClass.newInstance(); } NAMING_STRATEGIES.put(datasourceName, namingStrategy); } - protected void bindMapSecondPass(ToMany property, InFlightMetadataCollector mappings, - Map persistentClasses, org.hibernate.mapping.Map map, String sessionFactoryBeanName) { + protected void bindMapSecondPass(ToMany property, InFlightMetadataCollector mappings, Map persistentClasses, org.hibernate.mapping.Map map, String sessionFactoryBeanName) { bindCollectionSecondPass(property, mappings, persistentClasses, map, sessionFactoryBeanName); SimpleValue value = new SimpleValue(metadataBuildingContext, map.getCollectionTable()); - bindSimpleValue(getIndexColumnType(property, STRING_TYPE), value, true, - getIndexColumnName(property, sessionFactoryBeanName), mappings); + bindSimpleValue(getIndexColumnType(property, STRING_TYPE), value, true, getIndexColumnName(property, sessionFactoryBeanName), mappings); PropertyConfig pc = getPropertyConfig(property); if (pc != null && pc.getIndexColumn() != null) { bindColumnConfigToColumn(property, getColumnForSimpleValue(value), getSingleColumnConfig(pc.getIndexColumn())); @@ -230,20 +266,20 @@ protected void bindMapSecondPass(ToMany property, InFlightMetadataCollector mapp } map.setIndex(value); - if(!(property instanceof org.grails.datastore.mapping.model.types.OneToMany) && !(property instanceof ManyToMany)) { + if (!(property instanceof org.grails.datastore.mapping.model.types.OneToMany) && !(property instanceof ManyToMany)) { SimpleValue elt = new SimpleValue(metadataBuildingContext, map.getCollectionTable()); map.setElement(elt); - String typeName = getTypeName(property,getPropertyConfig(property), getMapping(property.getOwner())); - if (typeName == null ) { + String typeName = getTypeName(property, getPropertyConfig(property), getMapping(property.getOwner())); + if (typeName == null) { - if(property instanceof Basic) { + if (property instanceof Basic) { Basic basic = (Basic) property; typeName = basic.getComponentType().getName(); } } - if(typeName == null || typeName.equals(Object.class.getName())) { + if (typeName == null || typeName.equals(Object.class.getName())) { typeName = StandardBasicTypes.STRING.getName(); } bindSimpleValue(typeName, elt, false, getMapElementName(property, sessionFactoryBeanName), mappings); @@ -264,8 +300,7 @@ protected ColumnConfig getSingleColumnConfig(PropertyConfig propertyConfig) { return null; } - protected void bindListSecondPass(ToMany property, InFlightMetadataCollector mappings, - Map persistentClasses, org.hibernate.mapping.List list, String sessionFactoryBeanName) { + protected void bindListSecondPass(ToMany property, InFlightMetadataCollector mappings, Map persistentClasses, org.hibernate.mapping.List list, String sessionFactoryBeanName) { bindCollectionSecondPass(property, mappings, persistentClasses, list, sessionFactoryBeanName); @@ -273,8 +308,7 @@ protected void bindListSecondPass(ToMany property, InFlightMetadataCollector map final boolean isManyToMany = property instanceof ManyToMany; if (isManyToMany && !property.isOwningSide()) { - throw new MappingException("Invalid association [" + property + - "]. List collection types only supported on the owning side of a many-to-many relationship."); + throw new MappingException("Invalid association [" + property + "]. List collection types only supported on the owning side of a many-to-many relationship."); } Table collectionTable = list.getCollectionTable(); @@ -344,24 +378,20 @@ protected void bindListSecondPass(ToMany property, InFlightMetadataCollector map } } - protected void bindCollectionSecondPass(ToMany property, InFlightMetadataCollector mappings, - Map persistentClasses, Collection collection, String sessionFactoryBeanName) { + protected void bindCollectionSecondPass(ToMany property, InFlightMetadataCollector mappings, Map persistentClasses, Collection collection, String sessionFactoryBeanName) { PersistentClass associatedClass = null; - if (LOG.isDebugEnabled()) - LOG.debug("Mapping collection: " - + collection.getRole() - + " -> " - + collection.getCollectionTable().getName()); + if (LOG.isDebugEnabled()) { + LOG.debug("Mapping collection: " + collection.getRole() + " -> " + collection.getCollectionTable().getName()); + } PropertyConfig propConfig = getPropertyConfig(property); PersistentEntity referenced = property.getAssociatedEntity(); if (propConfig != null && StringUtils.hasText(propConfig.getSort())) { if (!property.isBidirectional() && (property instanceof org.grails.datastore.mapping.model.types.OneToMany)) { - throw new DatastoreConfigurationException("Default sort for associations ["+property.getOwner().getName()+"->" + property.getName() + - "] are not supported with unidirectional one to many relationships."); + throw new DatastoreConfigurationException("Default sort for associations [" + property.getOwner().getName() + "->" + property.getName() + "] are not supported with unidirectional one to many relationships."); } if (referenced != null) { PersistentProperty propertyToSortBy = referenced.getPropertyByName(propConfig.getSort()); @@ -370,8 +400,7 @@ protected void bindCollectionSecondPass(ToMany property, InFlightMetadataCollect associatedClass = (PersistentClass) persistentClasses.get(associatedClassName); if (associatedClass != null) { - collection.setOrderBy(buildOrderByClause(propertyToSortBy.getName(), associatedClass, collection.getRole(), - propConfig.getOrder() != null ? propConfig.getOrder() : "asc")); + collection.setOrderBy(buildOrderByClause(propertyToSortBy.getName(), associatedClass, collection.getRole(), propConfig.getOrder() != null ? propConfig.getOrder() : "asc")); } } } @@ -388,7 +417,7 @@ protected void bindCollectionSecondPass(ToMany property, InFlightMetadataCollect if (rootMapping != null) { DiscriminatorConfig discriminatorConfig = rootMapping.getDiscriminator(); - if(discriminatorConfig != null) { + if (discriminatorConfig != null) { final ColumnConfig discriminatorColumn = discriminatorConfig.getColumn(); if (discriminatorColumn != null) { discriminatorColumnName = discriminatorColumn.getName(); @@ -424,9 +453,9 @@ protected void bindCollectionSecondPass(ToMany property, InFlightMetadataCollect } final boolean isManyToMany = property instanceof ManyToMany; - if(referenced != null && !isManyToMany && referenced.isMultiTenant()) { + if (referenced != null && !isManyToMany && referenced.isMultiTenant()) { String filterCondition = getMultiTenantFilterCondition(sessionFactoryBeanName, referenced); - if(filterCondition != null) { + if (filterCondition != null) { if (isUnidirectionalOneToMany(property)) { collection.addManyToManyFilter(GormProperties.TENANT_IDENTITY, filterCondition, true, Collections.emptyMap(), Collections.emptyMap()); } else { @@ -452,7 +481,7 @@ protected void bindCollectionSecondPass(ToMany property, InFlightMetadataCollect } } else { if (hasJoinKeyMapping(propConfig)) { - bindSimpleValue("long", key,false, propConfig.getJoinTable().getKey().getName(), mappings); + bindSimpleValue("long", key, false, propConfig.getJoinTable().getKey().getName(), mappings); } else { bindDependentKeyValue(property, key, mappings, sessionFactoryBeanName); } @@ -472,18 +501,18 @@ protected void bindCollectionSecondPass(ToMany property, InFlightMetadataCollect PersistentProperty otherSide = property.getInverseSide(); if (property.isBidirectional()) { - if (LOG.isDebugEnabled()) + if (LOG.isDebugEnabled()) { LOG.debug("[GrailsDomainBinder] Mapping other side " + otherSide.getOwner().getName() + "." + otherSide.getName() + " -> " + collection.getCollectionTable().getName() + " as ManyToOne"); + } ManyToOne element = new ManyToOne(metadataBuildingContext, collection.getCollectionTable()); - bindManyToMany((Association)otherSide, element, mappings, sessionFactoryBeanName); + bindManyToMany((Association) otherSide, element, mappings, sessionFactoryBeanName); collection.setElement(element); bindCollectionForPropertyConfig(collection, propConfig); if (property.isCircular()) { collection.setInverse(false); } - } else { - // TODO support unidirectional many-to-many } + // else TODO support unidirectional many-to-many } else if (shouldCollectionBindWithJoinColumn(property)) { bindCollectionWithJoinTable(property, mappings, collection, propConfig, sessionFactoryBeanName); @@ -497,11 +526,10 @@ protected void bindCollectionSecondPass(ToMany property, InFlightMetadataCollect private String getMultiTenantFilterCondition(String sessionFactoryBeanName, PersistentEntity referenced) { TenantId tenantId = referenced.getTenantId(); - if(tenantId != null) { + if (tenantId != null) { String defaultColumnName = getDefaultColumnName(tenantId, sessionFactoryBeanName); return ":tenantId = " + defaultColumnName; - } - else { + } else { return null; } } @@ -520,8 +548,7 @@ protected String buildOrderByClause(String hqlOrderBy, PersistentClass associate Selectable col = (Selectable) it.next(); orderByBuffer.append(col.getText()).append(" asc").append(", "); } - } - else { + } else { StringTokenizer st = new StringTokenizer(hqlOrderBy, " ,", false); String currentOrdering = defaultOrder; //FIXME make this code decent @@ -529,20 +556,15 @@ protected String buildOrderByClause(String hqlOrderBy, PersistentClass associate String token = st.nextToken(); if (isNonPropertyToken(token)) { if (currentOrdering != null) { - throw new DatastoreConfigurationException( - "Error while parsing sort clause: " + hqlOrderBy - + " (" + role + ")" - ); + throw new DatastoreConfigurationException("Error while parsing sort clause: " + hqlOrderBy + " (" + role + ")"); } currentOrdering = token; - } - else { + } else { //Add ordering of the previous if (currentOrdering == null) { //default ordering ordering.add("asc"); - } - else { + } else { ordering.add(currentOrdering); currentOrdering = null; } @@ -554,8 +576,7 @@ protected String buildOrderByClause(String hqlOrderBy, PersistentClass associate if (currentOrdering == null) { //default ordering ordering.add(defaultOrder); - } - else { + } else { ordering.add(currentOrdering); currentOrdering = null; } @@ -564,20 +585,13 @@ protected String buildOrderByClause(String hqlOrderBy, PersistentClass associate for (String property : properties) { Property p = BinderHelper.findPropertyByName(associatedClass, property); if (p == null) { - throw new DatastoreConfigurationException( - "property from sort clause not found: " - + associatedClass.getEntityName() + "." + property - ); + throw new DatastoreConfigurationException("property from sort clause not found: " + associatedClass.getEntityName() + "." + property); } PersistentClass pc = p.getPersistentClass(); String table; if (pc == null) { table = ""; - } - - else if (pc == associatedClass - || (associatedClass instanceof SingleTableSubclass && - pc.getMappedClass().isAssignableFrom(associatedClass.getMappedClass()))) { + } else if (pc == associatedClass || (associatedClass instanceof SingleTableSubclass && pc.getMappedClass().isAssignableFrom(associatedClass.getMappedClass()))) { table = ""; } else { table = pc.getTable().getQuotedName() + "."; @@ -586,11 +600,7 @@ else if (pc == associatedClass Iterator propertyColumns = p.getColumnIterator(); while (propertyColumns.hasNext()) { Selectable column = (Selectable) propertyColumns.next(); - orderByBuffer.append(table) - .append(column.getText()) - .append(" ") - .append(ordering.get(index)) - .append(", "); + orderByBuffer.append(table).append(column.getText()).append(" ").append(ordering.get(index)).append(", "); } index++; } @@ -601,10 +611,18 @@ else if (pc == associatedClass } protected boolean isNonPropertyToken(String token) { - if (" ".equals(token)) return true; - if (",".equals(token)) return true; - if (token.equalsIgnoreCase("desc")) return true; - if (token.equalsIgnoreCase("asc")) return true; + if (" ".equals(token)) { + return true; + } + if (",".equals(token)) { + return true; + } + if (token.equalsIgnoreCase("desc")) { + return true; + } + if (token.equalsIgnoreCase("asc")) { + return true; + } return false; } @@ -615,7 +633,7 @@ protected Set buildDiscriminatorSet(HibernatePersistentEntity domainClas String discriminator = domainClass.getName(); if (mapping != null && mapping.getDiscriminator() != null) { DiscriminatorConfig discriminatorConfig = mapping.getDiscriminator(); - if(discriminatorConfig.getValue() != null) { + if (discriminatorConfig.getValue() != null) { discriminator = discriminatorConfig.getValue(); } } @@ -623,8 +641,9 @@ protected Set buildDiscriminatorSet(HibernatePersistentEntity domainClas String quote = "'"; if (rootMapping != null && rootMapping.getDatasources() != null) { DiscriminatorConfig discriminatorConfig = rootMapping.getDiscriminator(); - if(discriminatorConfig != null && discriminatorConfig.getType() != null && !discriminatorConfig.getType().equals("string")) + if (discriminatorConfig != null && discriminatorConfig.getType() != null && !discriminatorConfig.getType().equals("string")) { quote = ""; + } } theSet.add(quote + discriminator + quote); @@ -636,11 +655,15 @@ protected Set buildDiscriminatorSet(HibernatePersistentEntity domainClas } protected Mapping getRootMapping(PersistentEntity referenced) { - if (referenced == null) return null; + if (referenced == null) { + return null; + } Class current = referenced.getJavaClass(); while (true) { Class superClass = current.getSuperclass(); - if (Object.class.equals(superClass)) break; + if (Object.class.equals(superClass)) { + break; + } current = superClass; } @@ -651,8 +674,7 @@ protected boolean isBidirectionalOneToManyMap(Association property) { return Map.class.isAssignableFrom(property.getType()) && property.isBidirectional(); } - protected void bindCollectionWithJoinTable(ToMany property, - InFlightMetadataCollector mappings, Collection collection, PropertyConfig config, String sessionFactoryBeanName) { + protected void bindCollectionWithJoinTable(ToMany property, InFlightMetadataCollector mappings, Collection collection, PropertyConfig config, String sessionFactoryBeanName) { NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName); @@ -660,8 +682,7 @@ protected void bindCollectionWithJoinTable(ToMany property, final boolean isBasicCollectionType = property instanceof Basic; if (isBasicCollectionType) { element = new SimpleValue(metadataBuildingContext, collection.getCollectionTable()); - } - else { + } else { // for a normal unidirectional one-to-many we use a join column element = new ManyToOne(metadataBuildingContext, collection.getCollectionTable()); bindUnidirectionalOneToManyInverseValues(property, (ManyToOne) element); @@ -672,22 +693,18 @@ protected void bindCollectionWithJoinTable(ToMany property, final boolean hasJoinColumnMapping = hasJoinColumnMapping(config); if (isBasicCollectionType) { - final Class referencedType = ((Basic)property).getComponentType(); + final Class referencedType = ((Basic) property).getComponentType(); String className = referencedType.getName(); final boolean isEnum = referencedType.isEnum(); if (hasJoinColumnMapping) { columnName = config.getJoinTable().getColumn().getName(); - } - else { - columnName = isEnum ? namingStrategy.propertyToColumnName(className) : - addUnderscore(namingStrategy.propertyToColumnName(property.getName()), - namingStrategy.propertyToColumnName(className)); + } else { + columnName = isEnum ? namingStrategy.propertyToColumnName(className) : addUnderscore(namingStrategy.propertyToColumnName(property.getName()), namingStrategy.propertyToColumnName(className)); } if (isEnum) { - bindEnumType(property, referencedType,element,columnName); - } - else { + bindEnumType(property, referencedType, element, columnName); + } else { String typeName = getTypeName(property, config, getMapping(property.getOwner())); if (typeName == null) { @@ -698,10 +715,10 @@ protected void bindCollectionWithJoinTable(ToMany property, } if (typeName == null) { String domainName = property.getOwner().getName(); - throw new MappingException("Missing type or column for column["+columnName+"] on domain["+domainName+"] referencing["+className+"]"); + throw new MappingException("Missing type or column for column[" + columnName + "] on domain[" + domainName + "] referencing[" + className + "]"); } - bindSimpleValue(typeName, element,true, columnName, mappings); + bindSimpleValue(typeName, element, true, columnName, mappings); if (hasJoinColumnMapping) { bindColumnConfigToColumn(property, getColumnForSimpleValue(element), config.getJoinTable().getColumn()); } @@ -712,18 +729,15 @@ protected void bindCollectionWithJoinTable(ToMany property, Mapping m = getMapping(domainClass); if (hasCompositeIdentifier(m)) { CompositeIdentity ci = (CompositeIdentity) m.getIdentity(); - bindCompositeIdentifierToManyToOne(property, element, ci, domainClass, - EMPTY_PATH, sessionFactoryBeanName); - } - else { + bindCompositeIdentifierToManyToOne(property, element, ci, domainClass, EMPTY_PATH, sessionFactoryBeanName); + } else { if (hasJoinColumnMapping) { columnName = config.getJoinTable().getColumn().getName(); - } - else { + } else { columnName = namingStrategy.propertyToColumnName(NameUtils.decapitalize(domainClass.getName())) + FOREIGN_KEY_SUFFIX; } - bindSimpleValue("long", element,true, columnName, mappings); + bindSimpleValue("long", element, true, columnName, mappings); } } @@ -741,14 +755,14 @@ protected String removeBackticks(String s) { } protected Column getColumnForSimpleValue(SimpleValue element) { - return (Column)element.getColumnIterator().next(); + return (Column) element.getColumnIterator().next(); } protected String getTypeName(PersistentProperty property, PropertyConfig config, Mapping mapping) { if (config != null && config.getType() != null) { final Object typeObj = config.getType(); if (typeObj instanceof Class) { - return ((Class)typeObj).getName(); + return ((Class) typeObj).getName(); } return typeObj.toString(); } @@ -780,7 +794,7 @@ protected void bindColumnConfigToColumn(PersistentProperty property, Column colu if (columnConfig.getSqlType() != null && !columnConfig.getSqlType().isEmpty()) { column.setSqlType(columnConfig.getSqlType()); } - if(allowUnique) { + if (allowUnique) { column.setUnique(columnConfig.getUnique()); } } @@ -797,7 +811,7 @@ protected boolean shouldCollectionBindWithJoinColumn(ToMany property) { } /** - * @param property The property to bind + * @param property The property to bind * @param manyToOne The inverse side */ protected void bindUnidirectionalOneToManyInverseValues(ToMany property, ManyToOne manyToOne) { @@ -807,12 +821,12 @@ protected void bindUnidirectionalOneToManyInverseValues(ToMany property, ManyToO } else { manyToOne.setIgnoreNotFound(config.getIgnoreNotFound()); final FetchMode fetch = config.getFetchMode(); - if(!fetch.equals(FetchMode.JOIN) && !fetch.equals(FetchMode.EAGER)) { + if (!fetch.equals(FetchMode.JOIN) && !fetch.equals(FetchMode.EAGER)) { manyToOne.setLazy(true); } final Boolean lazy = config.getLazy(); - if(lazy != null) { + if (lazy != null) { manyToOne.setLazy(lazy); } } @@ -827,11 +841,11 @@ protected void bindCollectionForPropertyConfig(Collection collection, PropertyCo collection.setExtraLazy(false); } else { final FetchMode fetch = config.getFetchMode(); - if(!fetch.equals(FetchMode.JOIN) && !fetch.equals(FetchMode.EAGER)) { + if (!fetch.equals(FetchMode.JOIN) && !fetch.equals(FetchMode.EAGER)) { collection.setLazy(true); } final Boolean lazy = config.getLazy(); - if(lazy != null) { + if (lazy != null) { collection.setExtraLazy(lazy); } } @@ -848,19 +862,18 @@ public PropertyConfig getPropertyConfig(PersistentProperty property) { * @return true if it is unidirectional and a one-to-many */ protected boolean isUnidirectionalOneToMany(PersistentProperty property) { - return ((property instanceof org.grails.datastore.mapping.model.types.OneToMany) && !((Association)property).isBidirectional()); + return ((property instanceof org.grails.datastore.mapping.model.types.OneToMany) && !((Association) property).isBidirectional()); } /** * Binds the primary key value column * - * @param property The property - * @param key The key - * @param mappings The mappings + * @param property The property + * @param key The key + * @param mappings The mappings * @param sessionFactoryBeanName The name of the session factory */ - protected void bindDependentKeyValue(PersistentProperty property, DependantValue key, - InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected void bindDependentKeyValue(PersistentProperty property, DependantValue key, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { if (LOG.isDebugEnabled()) { LOG.debug("[GrailsDomainBinder] binding [" + property.getName() + "] with dependant key"); @@ -869,12 +882,10 @@ protected void bindDependentKeyValue(PersistentProperty property, DependantValue PersistentEntity refDomainClass = property.getOwner(); final Mapping mapping = getMapping(refDomainClass.getJavaClass()); boolean hasCompositeIdentifier = hasCompositeIdentifier(mapping); - if ((shouldCollectionBindWithJoinColumn((ToMany) property) && hasCompositeIdentifier) || - (hasCompositeIdentifier && ( property instanceof ManyToMany))) { + if ((shouldCollectionBindWithJoinColumn((ToMany) property) && hasCompositeIdentifier) || (hasCompositeIdentifier && (property instanceof ManyToMany))) { CompositeIdentity ci = (CompositeIdentity) mapping.getIdentity(); bindCompositeIdentifierToManyToOne((Association) property, key, ci, refDomainClass, EMPTY_PATH, sessionFactoryBeanName); - } - else { + } else { bindSimpleValue(property, null, key, EMPTY_PATH, mappings, sessionFactoryBeanName); } } @@ -888,8 +899,7 @@ protected void bindDependentKeyValue(PersistentProperty property, DependantValue * @param persistentClasses * @return The DependantValue (key) */ - protected DependantValue createPrimaryKeyValue(InFlightMetadataCollector mappings, PersistentProperty property, - Collection collection, Map persistentClasses) { + protected DependantValue createPrimaryKeyValue(InFlightMetadataCollector mappings, PersistentProperty property, Collection collection, Map persistentClasses) { KeyValue keyValue; DependantValue key; String propertyRef = collection.getReferencedPropertyName(); @@ -900,8 +910,9 @@ protected DependantValue createPrimaryKeyValue(InFlightMetadataCollector mapping keyValue = (KeyValue) collection.getOwner().getProperty(propertyRef).getValue(); } - if (LOG.isDebugEnabled()) + if (LOG.isDebugEnabled()) { LOG.debug("[GrailsDomainBinder] creating dependant key value to table [" + keyValue.getTable().getName() + "]"); + } key = new DependantValue(metadataBuildingContext, collection.getCollectionTable(), keyValue); @@ -948,8 +959,7 @@ protected void bindUnidirectionalOneToMany(org.grails.datastore.mapping.model.ty protected Property getProperty(PersistentClass associatedClass, String propertyName) throws MappingException { try { return associatedClass.getProperty(propertyName); - } - catch (MappingException e) { + } catch (MappingException e) { //maybe it's squirreled away in a composite primary key if (associatedClass.getKey() instanceof Component) { return ((Component) associatedClass.getKey()).getProperty(propertyName); @@ -991,15 +1001,14 @@ protected boolean isSorted(PersistentProperty property) { * Binds a many-to-many relationship. A many-to-many consists of * - a key (a DependentValue) * - an element - * + *

* The element is a ManyToOne from the association table to the target entity * * @param property The grails property * @param element The ManyToOne element * @param mappings The mappings */ - protected void bindManyToMany(Association property, ManyToOne element, - InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected void bindManyToMany(Association property, ManyToOne element, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { bindManyToOne(property, element, EMPTY_PATH, mappings, sessionFactoryBeanName); element.setReferencedEntityName(property.getOwner().getName()); } @@ -1025,8 +1034,7 @@ protected void linkValueUsingAColumnCopy(PersistentProperty prop, Column column, * @param mappings The Hibernate mappings instance * @param path */ - protected void bindCollection(ToMany property, Collection collection, - PersistentClass owner, InFlightMetadataCollector mappings, String path, String sessionFactoryBeanName) { + protected void bindCollection(ToMany property, Collection collection, PersistentClass owner, InFlightMetadataCollector mappings, String path, String sessionFactoryBeanName) { // set role String propertyName = getNameForPropertyAndPath(property, path); @@ -1037,11 +1045,9 @@ protected void bindCollection(ToMany property, Collection collection, final FetchMode fetchMode = pc.getFetchMode(); if (fetchMode == FetchMode.JOIN) { collection.setFetchMode(FetchMode.JOIN); - } - else if (pc.getFetchMode() != null) { + } else if (pc.getFetchMode() != null) { collection.setFetchMode(pc.getFetchMode()); - } - else { + } else { collection.setFetchMode(FetchMode.DEFAULT); } @@ -1068,14 +1074,11 @@ else if (pc.getFetchMode() != null) { // set up second pass if (collection instanceof org.hibernate.mapping.Set) { mappings.addSecondPass(new GrailsCollectionSecondPass(property, mappings, collection, sessionFactoryBeanName)); - } - else if (collection instanceof org.hibernate.mapping.List) { + } else if (collection instanceof org.hibernate.mapping.List) { mappings.addSecondPass(new ListSecondPass(property, mappings, collection, sessionFactoryBeanName)); - } - else if (collection instanceof org.hibernate.mapping.Map) { + } else if (collection instanceof org.hibernate.mapping.Map) { mappings.addSecondPass(new MapSecondPass(property, mappings, collection, sessionFactoryBeanName)); - } - else { // Collection -> Bag + } else { // Collection -> Bag mappings.addSecondPass(new GrailsCollectionSecondPass(property, mappings, collection, sessionFactoryBeanName)); } } @@ -1085,11 +1088,7 @@ else if (collection instanceof org.hibernate.mapping.Map) { * it is a unidirectional one-to-many that is. */ protected boolean shouldBindCollectionWithForeignKey(ToMany property) { - return ((property instanceof org.grails.datastore.mapping.model.types.OneToMany) && property.isBidirectional() || - !shouldCollectionBindWithJoinColumn(property)) && - !Map.class.isAssignableFrom(property.getType()) && - !(property instanceof ManyToMany) && - !(property instanceof Basic); + return ((property instanceof org.grails.datastore.mapping.model.types.OneToMany) && property.isBidirectional() || !shouldCollectionBindWithJoinColumn(property)) && !Map.class.isAssignableFrom(property.getType()) && !(property instanceof ManyToMany) && !(property instanceof Basic); } protected String getNameForPropertyAndPath(PersistentProperty property, String path) { @@ -1099,8 +1098,7 @@ protected String getNameForPropertyAndPath(PersistentProperty property, String p return property.getName(); } - protected void bindCollectionTable(ToMany property, InFlightMetadataCollector mappings, - Collection collection, Table ownerTable, String sessionFactoryBeanName) { + protected void bindCollectionTable(ToMany property, InFlightMetadataCollector mappings, Collection collection, Table ownerTable, String sessionFactoryBeanName) { String owningTableSchema = ownerTable.getSchema(); PropertyConfig config = getPropertyConfig(property); @@ -1110,22 +1108,20 @@ protected void bindCollectionTable(ToMany property, InFlightMetadataCollector ma String tableName = (jt != null && jt.getName() != null ? jt.getName() : namingStrategy.tableName(calculateTableForMany(property, sessionFactoryBeanName))); String schemaName = getSchemaName(mappings); String catalogName = getCatalogName(mappings); - if(jt != null) { - if(jt.getSchema() != null) { + if (jt != null) { + if (jt.getSchema() != null) { schemaName = jt.getSchema(); } - if(jt.getCatalog() != null) { + if (jt.getCatalog() != null) { catalogName = jt.getCatalog(); } } - if(schemaName == null && owningTableSchema != null) { + if (schemaName == null && owningTableSchema != null) { schemaName = owningTableSchema; } - collection.setCollectionTable(mappings.addTable( - schemaName, catalogName, - tableName, null, false)); + collection.setCollectionTable(mappings.addTable(schemaName, catalogName, tableName, null, false)); } /** @@ -1158,7 +1154,7 @@ protected String calculateTableForMany(ToMany property, String sessionFactoryBea } if (property.getAssociatedEntity() == null) { - throw new MappingException("Expected an entity to be associated with the association (" + property + ") and none was found. "); + throw new MappingException("Expected an entity to be associated with the association (" + property + ") and none was found. "); } String right = getTableName(property.getAssociatedEntity(), sessionFactoryBeanName); @@ -1211,10 +1207,10 @@ protected String getTableName(PersistentEntity domainClass, String sessionFactor String shortName = domainClass.getJavaClass().getSimpleName(); PersistentEntityNamingStrategy namingStrategy = this.namingStrategy; - if(namingStrategy != null) { + if (namingStrategy != null) { tableName = namingStrategy.resolveTableName(domainClass); } - if(tableName == null) { + if (tableName == null) { tableName = getNamingStrategy(sessionFactoryBeanName).classToTableName(shortName); } } @@ -1222,9 +1218,7 @@ protected String getTableName(PersistentEntity domainClass, String sessionFactor } protected NamingStrategy getNamingStrategy(String sessionFactoryBeanName) { - String key = "sessionFactory".equals(sessionFactoryBeanName) ? - ConnectionSource.DEFAULT : - sessionFactoryBeanName.substring("sessionFactory_".length()); + String key = "sessionFactory".equals(sessionFactoryBeanName) ? ConnectionSource.DEFAULT : sessionFactoryBeanName.substring("sessionFactory_".length()); NamingStrategy namingStrategy = NAMING_STRATEGIES.get(key); return namingStrategy != null ? namingStrategy : new ImprovedNamingStrategy(); } @@ -1232,13 +1226,12 @@ protected NamingStrategy getNamingStrategy(String sessionFactoryBeanName) { /** * Binds a Grails domain class to the Hibernate runtime meta model * - * @param entity The domain class to bind - * @param mappings The existing mappings - * @param sessionFactoryBeanName the session factory bean name + * @param entity The domain class to bind + * @param mappings The existing mappings + * @param sessionFactoryBeanName the session factory bean name * @throws MappingException Thrown if the domain class uses inheritance which is not supported */ - public void bindClass(PersistentEntity entity, InFlightMetadataCollector mappings, String sessionFactoryBeanName) - throws MappingException { + public void bindClass(PersistentEntity entity, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { //if (domainClass.getClazz().getSuperclass() == Object.class) { if (entity.isRoot()) { bindRoot((HibernatePersistentEntity) entity, mappings, sessionFactoryBeanName); @@ -1268,14 +1261,14 @@ public Mapping evaluateMapping(PersistentEntity domainClass, Closure defaultM } return m; } catch (Exception e) { - throw new DatastoreConfigurationException("Error evaluating ORM mappings block for domain [" + - domainClass.getName() + "]: " + e.getMessage(), e); + throw new DatastoreConfigurationException("Error evaluating ORM mappings block for domain [" + domainClass.getName() + "]: " + e.getMessage(), e); } } /** * Checks for any custom cascading saves set up via the mapping DSL and records them within the persistent property. - * @param mapping The Mapping. + * + * @param mapping The Mapping. * @param persistentProperties The persistent properties of the domain class. */ protected void trackCustomCascadingSaves(Mapping mapping, Iterable persistentProperties) { @@ -1290,6 +1283,7 @@ protected void trackCustomCascadingSaves(Mapping mapping, Iterable children = mappingContext.getDirectChildEntities(entity); if (children.isEmpty()) { root.setPolymorphic(false); @@ -1423,33 +1416,21 @@ public void bindRoot(HibernatePersistentEntity entity, InFlightMetadataCollector /** * Add a Hibernate filter for multitenancy if the persistent class is multitenant * - * @param entity target persistent entity for get tenant information - * @param persistentClass persistent class for add the filter and get tenant property info - * @param mappings mappings to add the filter + * @param entity target persistent entity for get tenant information + * @param persistentClass persistent class for add the filter and get tenant property info + * @param mappings mappings to add the filter * @param sessionFactoryBeanName the session factory bean name */ - protected void addMultiTenantFilterIfNecessary( - HibernatePersistentEntity entity, PersistentClass persistentClass, - InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected void addMultiTenantFilterIfNecessary(HibernatePersistentEntity entity, PersistentClass persistentClass, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { if (entity.isMultiTenant()) { TenantId tenantId = entity.getTenantId(); if (tenantId != null) { String filterCondition = getMultiTenantFilterCondition(sessionFactoryBeanName, entity); - persistentClass.addFilter( - GormProperties.TENANT_IDENTITY, - filterCondition, - true, - Collections.emptyMap(), - Collections.emptyMap() - ); + persistentClass.addFilter(GormProperties.TENANT_IDENTITY, filterCondition, true, Collections.emptyMap(), Collections.emptyMap()); - mappings.addFilterDefinition(new FilterDefinition( - GormProperties.TENANT_IDENTITY, - filterCondition, - Collections.singletonMap(GormProperties.TENANT_IDENTITY, getProperty(persistentClass, tenantId.getName()).getType()) - )); + mappings.addFilterDefinition(new FilterDefinition(GormProperties.TENANT_IDENTITY, filterCondition, Collections.singletonMap(GormProperties.TENANT_IDENTITY, getProperty(persistentClass, tenantId.getName()).getType()))); } } } @@ -1457,19 +1438,18 @@ protected void addMultiTenantFilterIfNecessary( /** * Binds the sub classes of a root class using table-per-heirarchy inheritance mapping * - * @param domainClass The root domain class to bind - * @param parent The parent class instance - * @param mappings The mappings instance - * @param sessionFactoryBeanName the session factory bean name + * @param domainClass The root domain class to bind + * @param parent The parent class instance + * @param mappings The mappings instance + * @param sessionFactoryBeanName the session factory bean name */ - protected void bindSubClasses(HibernatePersistentEntity domainClass, PersistentClass parent, - InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected void bindSubClasses(HibernatePersistentEntity domainClass, PersistentClass parent, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { final java.util.Collection subClasses = domainClass.getMappingContext().getDirectChildEntities(domainClass); for (PersistentEntity sub : subClasses) { final Class javaClass = sub.getJavaClass(); if (javaClass.getSuperclass().equals(domainClass.getJavaClass()) && ConnectionSourcesSupport.usesConnectionSource(sub, dataSourceName)) { - bindSubClass((HibernatePersistentEntity)sub, parent, mappings, sessionFactoryBeanName); + bindSubClass((HibernatePersistentEntity) sub, parent, mappings, sessionFactoryBeanName); } } } @@ -1477,13 +1457,12 @@ protected void bindSubClasses(HibernatePersistentEntity domainClass, PersistentC /** * Binds a sub class. * - * @param sub The sub domain class instance - * @param parent The parent persistent class instance - * @param mappings The mappings instance - * @param sessionFactoryBeanName the session factory bean name + * @param sub The sub domain class instance + * @param parent The parent persistent class instance + * @param mappings The mappings instance + * @param sessionFactoryBeanName the session factory bean name */ - protected void bindSubClass(HibernatePersistentEntity sub, PersistentClass parent, - InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected void bindSubClass(HibernatePersistentEntity sub, PersistentClass parent, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { evaluateMapping(sub, defaultMapping); Mapping m = getMapping(parent.getMappedClass()); Subclass subClass; @@ -1491,12 +1470,10 @@ protected void bindSubClass(HibernatePersistentEntity sub, PersistentClass paren boolean tablePerConcreteClass = m != null && m.isTablePerConcreteClass(); final String fullName = sub.getName(); if (tablePerSubclass) { - subClass = new JoinedSubclass( parent, this.metadataBuildingContext); - } - else if(tablePerConcreteClass) { + subClass = new JoinedSubclass(parent, this.metadataBuildingContext); + } else if (tablePerConcreteClass) { subClass = new UnionSubclass(parent, this.metadataBuildingContext); - } - else { + } else { subClass = new SingleTableSubclass(parent, this.metadataBuildingContext); // set the descriminator value as the name of the class. This is the // value used by Hibernate to decide what the type of the class is @@ -1533,11 +1510,9 @@ else if(tablePerConcreteClass) { if (tablePerSubclass) { bindJoinedSubClass(sub, (JoinedSubclass) subClass, mappings, m, sessionFactoryBeanName); - } - else if( tablePerConcreteClass) { + } else if (tablePerConcreteClass) { bindUnionSubclass(sub, (UnionSubclass) subClass, mappings, sessionFactoryBeanName); - } - else { + } else { bindSubClass(sub, subClass, mappings, sessionFactoryBeanName); } @@ -1550,68 +1525,49 @@ else if( tablePerConcreteClass) { } } - - public void bindUnionSubclass(HibernatePersistentEntity subClass, UnionSubclass unionSubclass, - InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { + public void bindUnionSubclass(HibernatePersistentEntity subClass, UnionSubclass unionSubclass, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { bindClass(subClass, unionSubclass, mappings); Mapping subMapping = getMapping(subClass.getJavaClass()); - if ( unionSubclass.getEntityPersisterClass() == null ) { - unionSubclass.getRootClass().setEntityPersisterClass( - UnionSubclassEntityPersister.class ); + if (unionSubclass.getEntityPersisterClass() == null) { + unionSubclass.getRootClass().setEntityPersisterClass(UnionSubclassEntityPersister.class); } - String schema = subMapping != null && subMapping.getTable().getSchema() != null ? - subMapping.getTable().getSchema() : null; + String schema = subMapping != null && subMapping.getTable().getSchema() != null ? subMapping.getTable().getSchema() : null; - String catalog = subMapping != null && subMapping.getTable().getCatalog() != null ? - subMapping.getTable().getCatalog() : null; + String catalog = subMapping != null && subMapping.getTable().getCatalog() != null ? subMapping.getTable().getCatalog() : null; Table denormalizedSuperTable = unionSubclass.getSuperclass().getTable(); - Table mytable = mappings.addDenormalizedTable( - schema, - catalog, - getTableName(subClass, sessionFactoryBeanName), - unionSubclass.isAbstract() != null && unionSubclass.isAbstract(), - null, - denormalizedSuperTable - ); - unionSubclass.setTable( mytable ); + Table mytable = mappings.addDenormalizedTable(schema, catalog, getTableName(subClass, sessionFactoryBeanName), unionSubclass.isAbstract() != null && unionSubclass.isAbstract(), null, denormalizedSuperTable); + unionSubclass.setTable(mytable); unionSubclass.setClassName(subClass.getName()); - LOG.info( - "Mapping union-subclass: " + unionSubclass.getEntityName() + - " -> " + unionSubclass.getTable().getName() - ); + LOG.info("Mapping union-subclass: " + unionSubclass.getEntityName() + " -> " + unionSubclass.getTable().getName()); createClassProperties(subClass, unionSubclass, mappings, sessionFactoryBeanName); } + /** * Binds a joined sub-class mapping using table-per-subclass * - * @param sub The Grails sub class - * @param joinedSubclass The Hibernate Subclass object - * @param mappings The mappings Object - * @param gormMapping The GORM mapping object - * @param sessionFactoryBeanName the session factory bean name + * @param sub The Grails sub class + * @param joinedSubclass The Hibernate Subclass object + * @param mappings The mappings Object + * @param gormMapping The GORM mapping object + * @param sessionFactoryBeanName the session factory bean name */ - protected void bindJoinedSubClass(HibernatePersistentEntity sub, JoinedSubclass joinedSubclass, - InFlightMetadataCollector mappings, Mapping gormMapping, String sessionFactoryBeanName) { + protected void bindJoinedSubClass(HibernatePersistentEntity sub, JoinedSubclass joinedSubclass, InFlightMetadataCollector mappings, Mapping gormMapping, String sessionFactoryBeanName) { bindClass(sub, joinedSubclass, mappings); String schemaName = getSchemaName(mappings); String catalogName = getCatalogName(mappings); - Table mytable = mappings.addTable( - schemaName, catalogName, - getJoinedSubClassTableName(sub, joinedSubclass, null, mappings, sessionFactoryBeanName), - null, false); + Table mytable = mappings.addTable(schemaName, catalogName, getJoinedSubClassTableName(sub, joinedSubclass, null, mappings, sessionFactoryBeanName), null, false); joinedSubclass.setTable(mytable); - LOG.info("Mapping joined-subclass: " + joinedSubclass.getEntityName() + - " -> " + joinedSubclass.getTable().getName()); + LOG.info("Mapping joined-subclass: " + joinedSubclass.getEntityName() + " -> " + joinedSubclass.getTable().getName()); SimpleValue key = new DependantValue(metadataBuildingContext, mytable, joinedSubclass.getIdentifier()); joinedSubclass.setKey(key); @@ -1626,9 +1582,7 @@ protected void bindJoinedSubClass(HibernatePersistentEntity sub, JoinedSubclass createClassProperties(sub, joinedSubclass, mappings, sessionFactoryBeanName); } - protected String getJoinedSubClassTableName( - HibernatePersistentEntity sub, PersistentClass model, Table denormalizedSuperTable, - InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected String getJoinedSubClassTableName(HibernatePersistentEntity sub, PersistentClass model, Table denormalizedSuperTable, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { String logicalTableName = unqualify(model.getEntityName()); String physicalTableName = getTableName(sub, sessionFactoryBeanName); @@ -1647,13 +1601,12 @@ protected String getJoinedSubClassTableName( * @param subClass The Hibernate SubClass instance * @param mappings The mappings instance */ - protected void bindSubClass(HibernatePersistentEntity sub, Subclass subClass, InFlightMetadataCollector mappings, - String sessionFactoryBeanName) { + protected void bindSubClass(HibernatePersistentEntity sub, Subclass subClass, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { bindClass(sub, subClass, mappings); - if (LOG.isDebugEnabled()) - LOG.debug("Mapping subclass: " + subClass.getEntityName() + - " -> " + subClass.getTable().getName()); + if (LOG.isDebugEnabled()) { + LOG.debug("Mapping subclass: " + subClass.getEntityName() + " -> " + subClass.getTable().getName()); + } // properties createClassProperties(sub, subClass, mappings, sessionFactoryBeanName); @@ -1676,16 +1629,15 @@ protected void bindDiscriminatorProperty(Table table, RootClass entity, InFlight boolean hasDiscriminatorConfig = discriminatorConfig != null; entity.setDiscriminatorValue(hasDiscriminatorConfig ? discriminatorConfig.getValue() : entity.getClassName()); - if(hasDiscriminatorConfig) { + if (hasDiscriminatorConfig) { if (discriminatorConfig.getInsertable() != null) { entity.setDiscriminatorInsertable(discriminatorConfig.getInsertable()); } Object type = discriminatorConfig.getType(); if (type != null) { - if(type instanceof Class) { - d.setTypeName(((Class)type).getName()); - } - else { + if (type instanceof Class) { + d.setTypeName(((Class) type).getName()); + } else { d.setTypeName(type.toString()); } } @@ -1696,8 +1648,7 @@ protected void bindDiscriminatorProperty(Table table, RootClass entity, InFlight Formula formula = new Formula(); formula.setFormula(discriminatorConfig.getFormula()); d.addFormula(formula); - } - else{ + } else { bindSimpleValue(STRING_TYPE, d, false, RootClass.DEFAULT_DISCRIMINATOR_COLUMN_NAME, mappings); ColumnConfig cc = !hasDiscriminatorConfig ? null : discriminatorConfig.getColumn(); @@ -1725,8 +1676,7 @@ protected void configureDerivedProperties(PersistentEntity domainClass, Mapping /* * Binds a persistent classes to the table representation and binds the class properties */ - protected void bindRootPersistentClassCommonValues(HibernatePersistentEntity domainClass, - RootClass root, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected void bindRootPersistentClassCommonValues(HibernatePersistentEntity domainClass, RootClass root, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { // get the schema and catalog names from the configuration Mapping m = getMapping(domainClass.getJavaClass()); @@ -1761,7 +1711,7 @@ protected void bindRootPersistentClassCommonValues(HibernatePersistentEntity dom final boolean hasTableDefinition = m != null && m.getTable() != null; if (hasTableDefinition && m.getTable().getSchema() != null) { - schema = m.getTable().getSchema(); + schema = m.getTable().getSchema(); } if (hasTableDefinition && m.getTable().getCatalog() != null) { catalog = m.getTable().getCatalog(); @@ -1769,9 +1719,7 @@ protected void bindRootPersistentClassCommonValues(HibernatePersistentEntity dom final boolean isAbstract = m != null && !m.getTablePerHierarchy() && m.isTablePerConcreteClass() && root.isAbstract(); // create the table - Table table = mappings.addTable(schema, catalog, - getTableName(domainClass, sessionFactoryBeanName), - null, isAbstract); + Table table = mappings.addTable(schema, catalog, getTableName(domainClass, sessionFactoryBeanName), null, isAbstract); root.setTable(table); if (LOG.isDebugEnabled()) { @@ -1782,12 +1730,10 @@ protected void bindRootPersistentClassCommonValues(HibernatePersistentEntity dom if (m == null) { bindVersion(domainClass.getVersion(), root, mappings, sessionFactoryBeanName); - } - else { + } else { if (m.getVersioned()) { bindVersion(domainClass.getVersion(), root, mappings, sessionFactoryBeanName); - } - else { + } else { root.setOptimisticLockStyle(OptimisticLockStyle.NONE); } } @@ -1797,18 +1743,11 @@ protected void bindRootPersistentClassCommonValues(HibernatePersistentEntity dom createClassProperties(domainClass, root, mappings, sessionFactoryBeanName); } - - - protected void bindIdentity( - HibernatePersistentEntity domainClass, - RootClass root, - InFlightMetadataCollector mappings, - Mapping gormMapping, - String sessionFactoryBeanName) { + protected void bindIdentity(HibernatePersistentEntity domainClass, RootClass root, InFlightMetadataCollector mappings, Mapping gormMapping, String sessionFactoryBeanName) { PersistentProperty identifierProp = domainClass.getIdentity(); if (gormMapping == null) { - if(identifierProp != null) { + if (identifierProp != null) { bindSimpleId(identifierProp, root, mappings, null, sessionFactoryBeanName); } return; @@ -1823,7 +1762,7 @@ protected void bindIdentity( if (propertyName != null) { PersistentProperty namedIdentityProp = domainClass.getPropertyByName(propertyName); if (namedIdentityProp == null) { - throw new MappingException("Mapping specifies an identifier property name that doesn't exist ["+propertyName+"]"); + throw new MappingException("Mapping specifies an identifier property name that doesn't exist [" + propertyName + "]"); } if (!namedIdentityProp.equals(identifierProp)) { identifierProp = namedIdentityProp; @@ -1833,8 +1772,7 @@ protected void bindIdentity( } } - protected void bindCompositeId(PersistentEntity domainClass, RootClass root, - CompositeIdentity compositeIdentity, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected void bindCompositeId(PersistentEntity domainClass, RootClass root, CompositeIdentity compositeIdentity, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { HibernatePersistentEntity hibernatePersistentEntity = (HibernatePersistentEntity) domainClass; Component id = new Component(metadataBuildingContext, root); id.setNullValue("undefined"); @@ -1852,8 +1790,7 @@ protected void bindCompositeId(PersistentEntity domainClass, RootClass root, final PersistentProperty[] composite = hibernatePersistentEntity.getCompositeIdentity(); for (PersistentProperty property : composite) { if (property == null) { - throw new MappingException("Property referenced in composite-id mapping of class [" + domainClass.getName() + - "] is not a valid property!"); + throw new MappingException("Property referenced in composite-id mapping of class [" + domainClass.getName() + "] is not a valid property!"); } bindComponentProperty(id, null, property, root, "", root.getTable(), mappings, sessionFactoryBeanName); @@ -1864,13 +1801,12 @@ protected void bindCompositeId(PersistentEntity domainClass, RootClass root, * Creates and binds the properties for the specified Grails domain class and PersistentClass * and binds them to the Hibernate runtime meta model * - * @param domainClass The Grails domain class - * @param persistentClass The Hibernate PersistentClass instance - * @param mappings The Hibernate Mappings instance - * @param sessionFactoryBeanName the session factory bean name + * @param domainClass The Grails domain class + * @param persistentClass The Hibernate PersistentClass instance + * @param mappings The Hibernate Mappings instance + * @param sessionFactoryBeanName the session factory bean name */ - protected void createClassProperties(HibernatePersistentEntity domainClass, PersistentClass persistentClass, - InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected void createClassProperties(HibernatePersistentEntity domainClass, PersistentClass persistentClass, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { final List persistentProperties = domainClass.getPersistentProperties(); Table table = persistentClass.getTable(); @@ -1889,9 +1825,15 @@ protected void createClassProperties(HibernatePersistentEntity domainClass, Pers if (currentGrailsProp.isInherited()) { continue; } - if(currentGrailsProp.getName().equals(GormProperties.VERSION) ) continue; - if (isCompositeIdProperty(gormMapping, currentGrailsProp)) continue; - if (isIdentityProperty(gormMapping, currentGrailsProp)) continue; + if (currentGrailsProp.getName().equals(GormProperties.VERSION)) { + continue; + } + if (isCompositeIdProperty(gormMapping, currentGrailsProp)) { + continue; + } + if (isIdentityProperty(gormMapping, currentGrailsProp)) { + continue; + } if (LOG.isDebugEnabled()) { LOG.debug("[GrailsDomainBinder] Binding persistent property [" + currentGrailsProp.getName() + "]"); @@ -1910,67 +1852,54 @@ protected void createClassProperties(HibernatePersistentEntity domainClass, Pers } value = new SimpleValue(metadataBuildingContext, table); bindSimpleValue(currentGrailsProp, null, (SimpleValue) value, EMPTY_PATH, mappings, sessionFactoryBeanName); - } - else if (collectionType != null) { - String typeName = getTypeName(currentGrailsProp, getPropertyConfig(currentGrailsProp),gormMapping); + } else if (collectionType != null) { + String typeName = getTypeName(currentGrailsProp, getPropertyConfig(currentGrailsProp), gormMapping); if ("serializable".equals(typeName)) { value = new SimpleValue(metadataBuildingContext, table); - bindSimpleValue(typeName, (SimpleValue) value, currentGrailsProp.isNullable(), - getColumnNameForPropertyAndPath(currentGrailsProp, EMPTY_PATH, null, sessionFactoryBeanName), mappings); - } - else { + bindSimpleValue(typeName, (SimpleValue) value, currentGrailsProp.isNullable(), getColumnNameForPropertyAndPath(currentGrailsProp, EMPTY_PATH, null, sessionFactoryBeanName), mappings); + } else { // create collection - Collection collection = collectionType.create((ToMany) currentGrailsProp, persistentClass, - EMPTY_PATH, mappings, sessionFactoryBeanName); + Collection collection = collectionType.create((ToMany) currentGrailsProp, persistentClass, EMPTY_PATH, mappings, sessionFactoryBeanName); mappings.addCollectionBinding(collection); value = collection; } - } - else if (currentGrailsProp.getType().isEnum()) { + } else if (currentGrailsProp.getType().isEnum()) { value = new SimpleValue(metadataBuildingContext, table); bindEnumType(currentGrailsProp, (SimpleValue) value, EMPTY_PATH, sessionFactoryBeanName); - } - else if(currentGrailsProp instanceof Association) { + } else if (currentGrailsProp instanceof Association) { Association association = (Association) currentGrailsProp; if (currentGrailsProp instanceof org.grails.datastore.mapping.model.types.ManyToOne) { - if (LOG.isDebugEnabled()) + if (LOG.isDebugEnabled()) { LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as ManyToOne"); + } value = new ManyToOne(metadataBuildingContext, table); bindManyToOne((Association) currentGrailsProp, (ManyToOne) value, EMPTY_PATH, mappings, sessionFactoryBeanName); - } - else if (currentGrailsProp instanceof org.grails.datastore.mapping.model.types.OneToOne && userType == null) { + } else if (currentGrailsProp instanceof org.grails.datastore.mapping.model.types.OneToOne && userType == null) { if (LOG.isDebugEnabled()) { LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as OneToOne"); } final boolean isHasOne = isHasOne(association); if (isHasOne && !association.isBidirectional()) { - throw new MappingException("hasOne property [" + currentGrailsProp.getOwner().getName() + - "." + currentGrailsProp.getName() + "] is not bidirectional. Specify the other side of the relationship!"); - } - else if (canBindOneToOneWithSingleColumnAndForeignKey((Association) currentGrailsProp)) { + throw new MappingException("hasOne property [" + currentGrailsProp.getOwner().getName() + "." + currentGrailsProp.getName() + "] is not bidirectional. Specify the other side of the relationship!"); + } else if (canBindOneToOneWithSingleColumnAndForeignKey((Association) currentGrailsProp)) { value = new OneToOne(metadataBuildingContext, table, persistentClass); bindOneToOne((org.grails.datastore.mapping.model.types.OneToOne) currentGrailsProp, (OneToOne) value, EMPTY_PATH, sessionFactoryBeanName); - } - else { + } else { if (isHasOne && association.isBidirectional()) { value = new OneToOne(metadataBuildingContext, table, persistentClass); bindOneToOne((org.grails.datastore.mapping.model.types.OneToOne) currentGrailsProp, (OneToOne) value, EMPTY_PATH, sessionFactoryBeanName); - } - else { + } else { value = new ManyToOne(metadataBuildingContext, table); bindManyToOne((Association) currentGrailsProp, (ManyToOne) value, EMPTY_PATH, mappings, sessionFactoryBeanName); } } - } - else if (currentGrailsProp instanceof Embedded) { - embedded.add((Embedded)currentGrailsProp); + } else if (currentGrailsProp instanceof Embedded) { + embedded.add((Embedded) currentGrailsProp); continue; } - } - // work out what type of relationship it is and bind value - else { + } else { // work out what type of relationship it is and bind value if (LOG.isDebugEnabled()) { LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as SimpleValue"); } @@ -1995,7 +1924,7 @@ else if (currentGrailsProp instanceof Embedded) { } private boolean isHasOne(Association association) { - return association instanceof org.grails.datastore.mapping.model.types.OneToOne && ((org.grails.datastore.mapping.model.types.OneToOne)association).isForeignKeyInChild(); + return association instanceof org.grails.datastore.mapping.model.types.OneToOne && ((org.grails.datastore.mapping.model.types.OneToOne) association).isForeignKeyInChild(); } protected void bindNaturalIdentifier(Table table, Mapping mapping, PersistentClass persistentClass) { @@ -2019,7 +1948,9 @@ protected void bindNaturalIdentifier(Table table, Mapping mapping, PersistentCla Property property = persistentClass.getProperty(propertyName); property.setNaturalIdentifier(true); - if (!mutable) property.setUpdateable(false); + if (!mutable) { + property.setUpdateable(false); + } uk.addColumns(property.getColumnIterator()); } @@ -2038,8 +1969,7 @@ protected void setGeneratedUniqueName(UniqueKey uk) { MessageDigest md; try { md = MessageDigest.getInstance("MD5"); - } - catch (NoSuchAlgorithmException e) { + } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } @@ -2057,7 +1987,7 @@ protected void setGeneratedUniqueName(UniqueKey uk) { protected boolean canBindOneToOneWithSingleColumnAndForeignKey(Association currentGrailsProp) { if (currentGrailsProp.isBidirectional()) { final Association otherSide = currentGrailsProp.getInverseSide(); - if(otherSide != null) { + if (otherSide != null) { if (isHasOne(otherSide)) { return false; } @@ -2079,14 +2009,12 @@ protected boolean isIdentityProperty(Mapping gormMapping, PersistentProperty cur return false; } - String identityName = ((Identity)identityMapping).getName(); + String identityName = ((Identity) identityMapping).getName(); return identityName != null && identityName.equals(currentGrailsProp.getName()); } - protected void bindEnumType(PersistentProperty property, SimpleValue simpleValue, - String path, String sessionFactoryBeanName) { - bindEnumType(property, property.getType(), simpleValue, - getColumnNameForPropertyAndPath(property, path, null, sessionFactoryBeanName)); + protected void bindEnumType(PersistentProperty property, SimpleValue simpleValue, String path, String sessionFactoryBeanName) { + bindEnumType(property, property.getType(), simpleValue, getColumnNameForPropertyAndPath(property, path, null, sessionFactoryBeanName)); } protected void bindEnumType(PersistentProperty property, Class propertyType, SimpleValue simpleValue, String columnName) { @@ -2104,16 +2032,13 @@ protected void bindEnumType(PersistentProperty property, Class propertyType, if (isDefaultEnumType || "string".equalsIgnoreCase(enumType)) { enumProperties.put(EnumType.TYPE, String.valueOf(Types.VARCHAR)); enumProperties.put(EnumType.NAMED, Boolean.TRUE.toString()); - } - else if("identity".equals(enumType)) { + } else if ("identity".equals(enumType)) { simpleValue.setTypeName(IdentityEnumType.class.getName()); - } - else if (!"ordinal".equalsIgnoreCase(enumType)) { + } else if (!"ordinal".equalsIgnoreCase(enumType)) { simpleValue.setTypeName(enumType); } simpleValue.setTypeParameters(enumProperties); - } - else { + } else { simpleValue.setTypeName(typeName); } @@ -2126,8 +2051,7 @@ else if (!"ordinal".equalsIgnoreCase(enumType)) { Mapping mapping = getMapping(owner); if (mapping == null || mapping.getTablePerHierarchy()) { if (LOG.isDebugEnabled()) { - LOG.debug("[GrailsDomainBinder] Sub class property [" + property.getName() + - "] for column name [" + column.getName() + "] set to nullable"); + LOG.debug("[GrailsDomainBinder] Sub class property [" + property.getName() + "] for column name [" + column.getName() + "] set to nullable"); } column.setNullable(true); } else { @@ -2136,7 +2060,9 @@ else if (!"ordinal".equalsIgnoreCase(enumType)) { } column.setValue(simpleValue); column.setName(columnName); - if (t != null) t.addColumn(column); + if (t != null) { + t.addColumn(column); + } simpleValue.addColumn(column); @@ -2152,7 +2078,7 @@ protected Class getUserType(PersistentProperty currentGrailsProp) { PropertyConfig config = getPropertyConfig(currentGrailsProp); Object typeObj = config == null ? null : config.getType(); if (typeObj instanceof Class) { - userType = (Class)typeObj; + userType = (Class) typeObj; } else if (typeObj != null) { String typeName = typeObj.toString(); try { @@ -2160,7 +2086,7 @@ protected Class getUserType(PersistentProperty currentGrailsProp) { } catch (ClassNotFoundException e) { // only print a warning if the user type is in a package this excludes basic // types like string, int etc. - if (typeName.indexOf(".")>-1) { + if (typeName.indexOf(".") > -1) { if (LOG.isWarnEnabled()) { LOG.warn("UserType not found ", e); } @@ -2177,7 +2103,9 @@ protected boolean isCompositeIdProperty(Mapping gormMapping, PersistentProperty String[] propertyNames = ((CompositeIdentity) id).getPropertyNames(); String property = currentGrailsProp.getName(); for (String currentName : propertyNames) { - if(currentName != null && currentName.equals(property)) return true; + if (currentName != null && currentName.equals(property)) { + return true; + } } } } @@ -2185,20 +2113,19 @@ protected boolean isCompositeIdProperty(Mapping gormMapping, PersistentProperty } protected boolean isBidirectionalManyToOne(PersistentProperty currentGrailsProp) { - return ((currentGrailsProp instanceof org.grails.datastore.mapping.model.types.ManyToOne) && ((Association)currentGrailsProp).isBidirectional()); + return ((currentGrailsProp instanceof org.grails.datastore.mapping.model.types.ManyToOne) && ((Association) currentGrailsProp).isBidirectional()); } /** * Binds a Hibernate component type using the given GrailsDomainClassProperty instance * - * @param component The component to bind - * @param property The property - * @param isNullable Whether it is nullable or not - * @param mappings The Hibernate Mappings object - * @param sessionFactoryBeanName the session factory bean name + * @param component The component to bind + * @param property The property + * @param isNullable Whether it is nullable or not + * @param mappings The Hibernate Mappings object + * @param sessionFactoryBeanName the session factory bean name */ - protected void bindComponent(Component component, Embedded property, - boolean isNullable, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected void bindComponent(Component component, Embedded property, boolean isNullable, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { component.setEmbedded(true); Class type = property.getType(); String role = qualify(type.getName(), property.getName()); @@ -2214,67 +2141,64 @@ protected void bindComponent(Component component, Embedded property, Class propertyType = property.getOwner().getJavaClass(); for (PersistentProperty currentGrailsProp : properties) { - if (currentGrailsProp.equals(domainClass.getIdentity())) continue; - if (currentGrailsProp.getName().equals(GormProperties.VERSION)) continue; + if (currentGrailsProp.equals(domainClass.getIdentity())) { + continue; + } + if (currentGrailsProp.getName().equals(GormProperties.VERSION)) { + continue; + } if (currentGrailsProp.getType().equals(propertyType)) { component.setParentProperty(currentGrailsProp.getName()); continue; } - bindComponentProperty(component, property, currentGrailsProp, persistentClass, path, - table, mappings, sessionFactoryBeanName); + bindComponentProperty(component, property, currentGrailsProp, persistentClass, path, table, mappings, sessionFactoryBeanName); } } - protected void bindComponentProperty(Component component, PersistentProperty componentProperty, - PersistentProperty currentGrailsProp, PersistentClass persistentClass, - String path, Table table, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected void bindComponentProperty(Component component, PersistentProperty componentProperty, PersistentProperty currentGrailsProp, PersistentClass persistentClass, String path, Table table, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { Value value; // see if it's a collection type CollectionType collectionType = CT.collectionTypeForClass(currentGrailsProp.getType()); if (collectionType != null) { // create collection - Collection collection = collectionType.create((ToMany) currentGrailsProp, persistentClass, - path, mappings, sessionFactoryBeanName); + Collection collection = collectionType.create((ToMany) currentGrailsProp, persistentClass, path, mappings, sessionFactoryBeanName); mappings.addCollectionBinding(collection); value = collection; - } - // work out what type of relationship it is and bind value - else if (currentGrailsProp instanceof org.grails.datastore.mapping.model.types.ManyToOne) { - if (LOG.isDebugEnabled()) + } else if (currentGrailsProp instanceof org.grails.datastore.mapping.model.types.ManyToOne) { + // work out what type of relationship it is and bind value + if (LOG.isDebugEnabled()) { LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as ManyToOne"); + } value = new ManyToOne(metadataBuildingContext, table); bindManyToOne((Association) currentGrailsProp, (ManyToOne) value, path, mappings, sessionFactoryBeanName); } else if (currentGrailsProp instanceof org.grails.datastore.mapping.model.types.OneToOne) { - if (LOG.isDebugEnabled()) + if (LOG.isDebugEnabled()) { LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as OneToOne"); + } if (canBindOneToOneWithSingleColumnAndForeignKey((Association) currentGrailsProp)) { value = new OneToOne(metadataBuildingContext, table, persistentClass); bindOneToOne((org.grails.datastore.mapping.model.types.OneToOne) currentGrailsProp, (OneToOne) value, path, sessionFactoryBeanName); - } - else { + } else { value = new ManyToOne(metadataBuildingContext, table); bindManyToOne((Association) currentGrailsProp, (ManyToOne) value, path, mappings, sessionFactoryBeanName); } - } - else if (currentGrailsProp instanceof Embedded) { + } else if (currentGrailsProp instanceof Embedded) { value = new Component(metadataBuildingContext, persistentClass); bindComponent((Component) value, (Embedded) currentGrailsProp, true, mappings, sessionFactoryBeanName); - } - else { - if (LOG.isDebugEnabled()) + } else { + if (LOG.isDebugEnabled()) { LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as SimpleValue"); + } value = new SimpleValue(metadataBuildingContext, table); if (currentGrailsProp.getType().isEnum()) { bindEnumType(currentGrailsProp, (SimpleValue) value, path, sessionFactoryBeanName); - } - else { - bindSimpleValue(currentGrailsProp, componentProperty, (SimpleValue) value, path, - mappings, sessionFactoryBeanName); + } else { + bindSimpleValue(currentGrailsProp, componentProperty, (SimpleValue) value, path, mappings, sessionFactoryBeanName); } } @@ -2292,7 +2216,9 @@ else if (currentGrailsProp instanceof Embedded) { } protected boolean isComponentPropertyNullable(PersistentProperty componentProperty) { - if (componentProperty == null) return false; + if (componentProperty == null) { + return false; + } final PersistentEntity domainClass = componentProperty.getOwner(); final Mapping mapping = getMapping(domainClass.getJavaClass()); return !domainClass.isRoot() && (mapping == null || mapping.isTablePerHierarchy()) || componentProperty.isNullable(); @@ -2325,8 +2251,7 @@ protected void bindOneToMany(org.grails.datastore.mapping.model.types.OneToMany * */ @SuppressWarnings("unchecked") - protected void bindManyToOne(Association property, ManyToOne manyToOne, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected void bindManyToOne(Association property, ManyToOne manyToOne, String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName); @@ -2337,25 +2262,22 @@ protected void bindManyToOne(Association property, ManyToOne manyToOne, if (isComposite) { CompositeIdentity ci = (CompositeIdentity) mapping.getIdentity(); bindCompositeIdentifierToManyToOne(property, manyToOne, ci, refDomainClass, path, sessionFactoryBeanName); - } - else { + } else { if (property.isCircular() && (property instanceof ManyToMany)) { PropertyConfig pc = getPropertyConfig(property); if (pc.getColumns().isEmpty()) { mapping.getColumns().put(property.getName(), pc); } - if (!hasJoinKeyMapping(pc) ) { + if (!hasJoinKeyMapping(pc)) { JoinTable jt = new JoinTable(); final ColumnConfig columnConfig = new ColumnConfig(); - columnConfig.setName(namingStrategy.propertyToColumnName(property.getName()) + - UNDERSCORE + FOREIGN_KEY_SUFFIX); + columnConfig.setName(namingStrategy.propertyToColumnName(property.getName()) + UNDERSCORE + FOREIGN_KEY_SUFFIX); jt.setKey(columnConfig); pc.setJoinTable(jt); } bindSimpleValue(property, manyToOne, path, pc, sessionFactoryBeanName); - } - else { + } else { // bind column bindSimpleValue(property, null, manyToOne, path, mappings, sessionFactoryBeanName); } @@ -2367,16 +2289,13 @@ protected void bindManyToOne(Association property, ManyToOne manyToOne, Column c = getColumnForSimpleValue(manyToOne); if (config != null && !config.isUniqueWithinGroup()) { c.setUnique(config.isUnique()); - } - else if (property.isBidirectional() && isHasOne(property.getInverseSide())) { + } else if (property.isBidirectional() && isHasOne(property.getInverseSide())) { c.setUnique(true); } } } - protected void bindCompositeIdentifierToManyToOne(Association property, - SimpleValue value, CompositeIdentity compositeId, PersistentEntity refDomainClass, - String path, String sessionFactoryBeanName) { + protected void bindCompositeIdentifierToManyToOne(Association property, SimpleValue value, CompositeIdentity compositeId, PersistentEntity refDomainClass, String path, String sessionFactoryBeanName) { NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName); @@ -2391,25 +2310,24 @@ protected void bindCompositeIdentifierToManyToOne(Association property, for (String propertyName : propertyNames) { ColumnConfig cc; // if a column configuration exists in the mapping use it - if(j < i) { + if (j < i) { cc = columns.get(j++); - } - // otherwise create a new one to represent the composite column - else { + } else { + // otherwise create a new one to represent the composite column cc = new ColumnConfig(); } // if the name is null then configure the name by convention - if(cc.getName() == null) { + if (cc.getName() == null) { // use the referenced table name as a prefix String prefix = getTableName(refDomainClass, sessionFactoryBeanName); PersistentProperty referencedProperty = refDomainClass.getPropertyByName(propertyName); // if the referenced property is a ToOne and it has a composite id // then a column is needed for each property that forms the composite id - if(referencedProperty instanceof ToOne) { + if (referencedProperty instanceof ToOne) { ToOne toOne = (ToOne) referencedProperty; PersistentProperty[] compositeIdentity = toOne.getAssociatedEntity().getCompositeIdentity(); - if(compositeIdentity != null) { + if (compositeIdentity != null) { for (PersistentProperty cip : compositeIdentity) { // for each property of a composite id by default we use the table name and the property name as a prefix String compositeIdPrefix = addUnderscore(prefix, namingStrategy.propertyToColumnName(referencedProperty.getName())); @@ -2439,17 +2357,15 @@ private int calculateForeignKeyColumnCount(PersistentEntity refDomainClass, Stri int expectedForeignKeyColumnLength = 0; for (String propertyName : propertyNames) { PersistentProperty referencedProperty = refDomainClass.getPropertyByName(propertyName); - if(referencedProperty instanceof ToOne) { + if (referencedProperty instanceof ToOne) { ToOne toOne = (ToOne) referencedProperty; PersistentProperty[] compositeIdentity = toOne.getAssociatedEntity().getCompositeIdentity(); - if(compositeIdentity != null) { + if (compositeIdentity != null) { expectedForeignKeyColumnLength += compositeIdentity.length; - } - else { + } else { expectedForeignKeyColumnLength++; } - } - else { + } else { expectedForeignKeyColumnLength++; } } @@ -2460,22 +2376,18 @@ protected boolean hasCompositeIdentifier(Mapping mapping) { return mapping != null && (mapping.getIdentity() instanceof CompositeIdentity); } - protected void bindOneToOne(final org.grails.datastore.mapping.model.types.OneToOne property, OneToOne oneToOne, - String path, String sessionFactoryBeanName) { + protected void bindOneToOne(final org.grails.datastore.mapping.model.types.OneToOne property, OneToOne oneToOne, String path, String sessionFactoryBeanName) { PropertyConfig config = getPropertyConfig(property); final Association otherSide = property.getInverseSide(); final boolean hasOne = isHasOne(otherSide); oneToOne.setConstrained(hasOne); - oneToOne.setForeignKeyType(oneToOne.isConstrained() ? - ForeignKeyDirection.FROM_PARENT : - ForeignKeyDirection.TO_PARENT); + oneToOne.setForeignKeyType(oneToOne.isConstrained() ? ForeignKeyDirection.FROM_PARENT : ForeignKeyDirection.TO_PARENT); oneToOne.setAlternateUniqueKey(true); if (config != null && config.getFetchMode() != null) { oneToOne.setFetchMode(config.getFetchMode()); - } - else { + } else { oneToOne.setFetchMode(FetchMode.DEFAULT); } @@ -2488,8 +2400,7 @@ protected void bindOneToOne(final org.grails.datastore.mapping.model.types.OneTo if (hasOne) { PropertyConfig pc = getPropertyConfig(property); bindSimpleValue(property, oneToOne, path, pc, sessionFactoryBeanName); - } - else { + } else { oneToOne.setReferencedPropertyName(otherSide.getName()); } } @@ -2499,14 +2410,14 @@ protected void bindOneToOneInternal(org.grails.datastore.mapping.model.types.One } /** + * */ protected void bindManyToOneValues(org.grails.datastore.mapping.model.types.Association property, ManyToOne manyToOne) { PropertyConfig config = getPropertyConfig(property); if (config != null && config.getFetchMode() != null) { manyToOne.setFetchMode(config.getFetchMode()); - } - else { + } else { manyToOne.setFetchMode(FetchMode.DEFAULT); } @@ -2520,8 +2431,7 @@ protected void bindManyToOneValues(org.grails.datastore.mapping.model.types.Asso manyToOne.setReferencedEntityName(property.getAssociatedEntity().getName()); } - protected void bindVersion(PersistentProperty version, RootClass entity, - InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected void bindVersion(PersistentProperty version, RootClass entity, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { if (version != null) { @@ -2530,15 +2440,11 @@ protected void bindVersion(PersistentProperty version, RootClass entity, bindSimpleValue(version, null, val, EMPTY_PATH, mappings, sessionFactoryBeanName); if (val.isTypeSpecified()) { - if (!(val.getType() instanceof IntegerType || - val.getType() instanceof LongType || - val.getType() instanceof TimestampType)) { - LOG.warn("Invalid version class specified in " + version.getOwner().getName() + - "; must be one of [int, Integer, long, Long, Timestamp, Date]. Not mapping the version."); + if (!(val.getType() instanceof IntegerType || val.getType() instanceof LongType || val.getType() instanceof TimestampType)) { + LOG.warn("Invalid version class specified in " + version.getOwner().getName() + "; must be one of [int, Integer, long, Long, Timestamp, Date]. Not mapping the version."); return; } - } - else { + } else { val.setTypeName("version".equals(version.getName()) ? "integer" : "timestamp"); } Property prop = new Property(); @@ -2550,22 +2456,20 @@ protected void bindVersion(PersistentProperty version, RootClass entity, entity.setDeclaredVersion(prop); entity.setOptimisticLockStyle(OptimisticLockStyle.VERSION); entity.addProperty(prop); - } - else { + } else { entity.setOptimisticLockStyle(OptimisticLockStyle.NONE); } } @SuppressWarnings("unchecked") - protected void bindSimpleId(PersistentProperty identifier, RootClass entity, - InFlightMetadataCollector mappings, Identity mappedId, String sessionFactoryBeanName) { + protected void bindSimpleId(PersistentProperty identifier, RootClass entity, InFlightMetadataCollector mappings, Identity mappedId, String sessionFactoryBeanName) { Mapping mapping = getMapping(identifier.getOwner()); boolean useSequence = mapping != null && mapping.isTablePerConcreteClass(); // create the id value SimpleValue id = new SimpleValue(metadataBuildingContext, entity.getTable()); - Property idProperty = new Property(); + Property idProperty = new Property(); idProperty.setName(identifier.getName()); idProperty.setValue(id); entity.setDeclaredIdentifierProperty(idProperty); @@ -2579,13 +2483,13 @@ protected void bindSimpleId(PersistentProperty identifier, RootClass entity, id.setIdentifierGeneratorStrategy(useSequence ? "sequence-identity" : "native"); } else { String generator = mappedId.getGenerator(); - if("native".equals(generator) && useSequence) { + if ("native".equals(generator) && useSequence) { generator = "sequence-identity"; } id.setIdentifierGeneratorStrategy(generator); params.putAll(mappedId.getParams()); - if(params.containsKey(SEQUENCE_KEY)) { - params.put(SequenceStyleGenerator.SEQUENCE_PARAM, params.getProperty(SEQUENCE_KEY)); + if (params.containsKey(SEQUENCE_KEY)) { + params.put(SequenceStyleGenerator.SEQUENCE_PARAM, params.getProperty(SEQUENCE_KEY)); } if ("assigned".equals(generator)) { id.setNullValue("undefined"); @@ -2622,7 +2526,7 @@ protected void bindSimpleId(PersistentProperty identifier, RootClass entity, private String getSchemaName(InFlightMetadataCollector mappings) { Identifier schema = mappings.getDatabase().getDefaultNamespace().getName().getSchema(); - if(schema != null) { + if (schema != null) { return schema.getCanonicalName(); } return null; @@ -2630,7 +2534,7 @@ private String getSchemaName(InFlightMetadataCollector mappings) { private String getCatalogName(InFlightMetadataCollector mappings) { Identifier catalog = mappings.getDatabase().getDefaultNamespace().getName().getCatalog(); - if(catalog != null) { + if (catalog != null) { return catalog.getCanonicalName(); } return null; @@ -2654,22 +2558,18 @@ protected void bindProperty(PersistentProperty grailsProperty, Property prop, In prop.setUpdateable(getUpdateableness(grailsProperty)); } - AccessType accessType = AccessType.getAccessStrategy( - grailsProperty.getMapping().getMappedForm().getAccessType() - ); + AccessType accessType = AccessType.getAccessStrategy(grailsProperty.getMapping().getMappedForm().getAccessType()); - if(accessType == AccessType.FIELD) { + if (accessType == AccessType.FIELD) { EntityReflector.PropertyReader reader = grailsProperty.getReader(); - Method getter = reader != null ? reader.getter() : null; - if(getter != null && getter.getAnnotation(Traits.Implemented.class) != null) { + Method getter = reader != null ? reader.getter() : null; + if (getter != null && getter.getAnnotation(Traits.Implemented.class) != null) { prop.setPropertyAccessorName(TraitPropertyAccessStrategy.class.getName()); + } else { + prop.setPropertyAccessorName(accessType.getType()); } - else { - prop.setPropertyAccessorName( accessType.getType() ); - } - } - else { - prop.setPropertyAccessorName( accessType.getType() ); + } else { + prop.setPropertyAccessorName(accessType.getType()); } @@ -2680,26 +2580,24 @@ protected void bindProperty(PersistentProperty grailsProperty, Property prop, In // lazy to true final boolean isToOne = grailsProperty instanceof ToOne && !(grailsProperty instanceof Embedded); PersistentEntity propertyOwner = grailsProperty.getOwner(); - boolean isLazyable = isToOne || - !(grailsProperty instanceof Association) && !grailsProperty.equals(propertyOwner.getIdentity()); + boolean isLazyable = isToOne || !(grailsProperty instanceof Association) && !grailsProperty.equals(propertyOwner.getIdentity()); if (isLazyable) { final boolean isLazy = getLaziness(grailsProperty); prop.setLazy(isLazy); - if (isLazy && isToOne && !(PersistentAttributeInterceptable.class.isAssignableFrom(propertyOwner.getJavaClass()))) { +// if (isLazy && isToOne && !(PersistentAttributeInterceptable.class.isAssignableFrom(propertyOwner.getJavaClass()))) { // handleLazyProxy(propertyOwner, grailsProperty); - } +// } } } protected boolean getLaziness(PersistentProperty grailsProperty) { PropertyConfig config = getPropertyConfig(grailsProperty); final Boolean lazy = config.getLazy(); - if(lazy == null && grailsProperty instanceof Association) { + if (lazy == null && grailsProperty instanceof Association) { return true; - } - else if(lazy != null) { + } else if (lazy != null) { return lazy; } return false; @@ -2716,13 +2614,11 @@ protected boolean getUpdateableness(PersistentProperty grailsProperty) { } protected boolean isBidirectionalManyToOneWithListMapping(PersistentProperty grailsProperty, Property prop) { - if(grailsProperty instanceof Association) { + if (grailsProperty instanceof Association) { Association association = (Association) grailsProperty; Association otherSide = association.getInverseSide(); - return association.isBidirectional() && otherSide != null && - prop.getValue() instanceof ManyToOne && - List.class.isAssignableFrom(otherSide.getType()); + return association.isBidirectional() && otherSide != null && prop.getValue() instanceof ManyToOne && List.class.isAssignableFrom(otherSide.getType()); } return false; } @@ -2739,19 +2635,16 @@ protected void setCascadeBehaviour(PersistentProperty grailsProperty, Property p PersistentEntity referenced = association.getAssociatedEntity(); if (isHasOne(association)) { cascadeStrategy = CASCADE_ALL; - } - else if (association instanceof org.grails.datastore.mapping.model.types.OneToOne) { + } else if (association instanceof org.grails.datastore.mapping.model.types.OneToOne) { if (referenced != null && association.isOwningSide()) { cascadeStrategy = CASCADE_ALL; - } - else { + } else { cascadeStrategy = CASCADE_SAVE_UPDATE; } } else if (association instanceof org.grails.datastore.mapping.model.types.OneToMany) { if (referenced != null && association.isOwningSide()) { cascadeStrategy = CASCADE_ALL; - } - else { + } else { cascadeStrategy = CASCADE_SAVE_UPDATE; } } else if (grailsProperty instanceof ManyToMany) { @@ -2761,18 +2654,14 @@ else if (association instanceof org.grails.datastore.mapping.model.types.OneToOn } else if (grailsProperty instanceof org.grails.datastore.mapping.model.types.ManyToOne) { if (referenced != null && referenced.isOwningEntity(domainClass) && !isCircularAssociation(grailsProperty)) { cascadeStrategy = CASCADE_ALL; - } - else if(isCompositeIdProperty((Mapping) domainClass.getMapping().getMappedForm(), grailsProperty)) { + } else if (isCompositeIdProperty((Mapping) domainClass.getMapping().getMappedForm(), grailsProperty)) { cascadeStrategy = CASCADE_ALL; - } - else { + } else { cascadeStrategy = CASCADE_NONE; } - } - else if (grailsProperty instanceof Basic) { + } else if (grailsProperty instanceof Basic) { cascadeStrategy = CASCADE_ALL; - } - else if (Map.class.isAssignableFrom(grailsProperty.getType())) { + } else if (Map.class.isAssignableFrom(grailsProperty.getType())) { referenced = association.getAssociatedEntity(); if (referenced != null && referenced.isOwningEntity(domainClass)) { cascadeStrategy = CASCADE_ALL; @@ -2818,25 +2707,21 @@ protected String getAssociationDescription(Association grailsProperty) { * * @param property * @param parentProperty - * @param simpleValue The simple value to bind + * @param simpleValue The simple value to bind * @param path - * @param mappings The Hibernate mappings instance - * @param sessionFactoryBeanName the session factory bean name + * @param mappings The Hibernate mappings instance + * @param sessionFactoryBeanName the session factory bean name */ - protected void bindSimpleValue(PersistentProperty property, PersistentProperty parentProperty, - SimpleValue simpleValue, String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { + protected void bindSimpleValue(PersistentProperty property, PersistentProperty parentProperty, SimpleValue simpleValue, String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { // set type - bindSimpleValue(property,parentProperty, simpleValue, path, getPropertyConfig(property), sessionFactoryBeanName); + bindSimpleValue(property, parentProperty, simpleValue, path, getPropertyConfig(property), sessionFactoryBeanName); } - protected void bindSimpleValue(PersistentProperty grailsProp, SimpleValue simpleValue, - String path, PropertyConfig propertyConfig, String sessionFactoryBeanName) { + protected void bindSimpleValue(PersistentProperty grailsProp, SimpleValue simpleValue, String path, PropertyConfig propertyConfig, String sessionFactoryBeanName) { bindSimpleValue(grailsProp, null, simpleValue, path, propertyConfig, sessionFactoryBeanName); } - protected void bindSimpleValue(PersistentProperty grailsProp, - PersistentProperty parentProperty, SimpleValue simpleValue, - String path, PropertyConfig propertyConfig, String sessionFactoryBeanName) { + protected void bindSimpleValue(PersistentProperty grailsProp, PersistentProperty parentProperty, SimpleValue simpleValue, String path, PropertyConfig propertyConfig, String sessionFactoryBeanName) { setTypeForPropertyConfig(grailsProp, simpleValue, propertyConfig); final PropertyConfig mappedForm = (PropertyConfig) grailsProp.getMapping().getMappedForm(); if (mappedForm.isDerived() && !(grailsProp instanceof TenantId)) { @@ -2848,17 +2733,17 @@ protected void bindSimpleValue(PersistentProperty grailsProp, boolean hasConfig = propertyConfig != null; String generator = hasConfig ? propertyConfig.getGenerator() : null; - if(generator != null) { + if (generator != null) { simpleValue.setIdentifierGeneratorStrategy(generator); Properties params = propertyConfig.getTypeParams(); - if(params != null) { + if (params != null) { Properties generatorProps = new Properties(); generatorProps.putAll(params); - if(generatorProps.containsKey(SEQUENCE_KEY)) { - generatorProps.put(SequenceStyleGenerator.SEQUENCE_PARAM, generatorProps.getProperty(SEQUENCE_KEY)); + if (generatorProps.containsKey(SEQUENCE_KEY)) { + generatorProps.put(SequenceStyleGenerator.SEQUENCE_PARAM, generatorProps.getProperty(SEQUENCE_KEY)); } - simpleValue.setIdentifierGeneratorProperties( generatorProps ); + simpleValue.setIdentifierGeneratorProperties(generatorProps); } } @@ -2866,10 +2751,9 @@ protected void bindSimpleValue(PersistentProperty grailsProp, // not all custom mapped properties will have column definitions, // in which case we still need to create a Hibernate column for // this value. - List columnDefinitions = hasConfig ? propertyConfig.getColumns() - : Arrays.asList(new Object[] { null }); + List columnDefinitions = hasConfig ? propertyConfig.getColumns() : Arrays.asList(new Object[]{null}); if (columnDefinitions.isEmpty()) { - columnDefinitions = Arrays.asList(new Object[] { null }); + columnDefinitions = Arrays.asList(new Object[]{null}); } for (Object columnDefinition : columnDefinitions) { @@ -2899,7 +2783,7 @@ protected void bindSimpleValue(PersistentProperty grailsProp, if (cc.getScale() != -1) { column.setScale(cc.getScale()); } - if(!mappedForm.isUniqueWithinGroup()) { + if (!mappedForm.isUniqueWithinGroup()) { column.setUnique(cc.isUnique()); } } @@ -2919,8 +2803,7 @@ protected void setTypeForPropertyConfig(PersistentProperty grailsProp, SimpleVal final String typeName = getTypeName(grailsProp, getPropertyConfig(grailsProp), getMapping(grailsProp.getOwner())); if (typeName == null) { simpleValue.setTypeName(grailsProp.getType().getName()); - } - else { + } else { simpleValue.setTypeName(typeName); if (config != null) { simpleValue.setTypeParameters(config.getTypeParams()); @@ -2937,8 +2820,7 @@ protected void setTypeForPropertyConfig(PersistentProperty grailsProp, SimpleVal * @param columnName The property name * @param mappings The mappings */ - protected void bindSimpleValue(String type, SimpleValue simpleValue, boolean nullable, - String columnName, InFlightMetadataCollector mappings) { + protected void bindSimpleValue(String type, SimpleValue simpleValue, boolean nullable, String columnName, InFlightMetadataCollector mappings) { simpleValue.setTypeName(type); Table t = simpleValue.getTable(); @@ -2946,7 +2828,9 @@ protected void bindSimpleValue(String type, SimpleValue simpleValue, boolean nul column.setNullable(nullable); column.setValue(simpleValue); column.setName(columnName); - if (t != null) t.addColumn(column); + if (t != null) { + t.addColumn(column); + } simpleValue.addColumn(column); } @@ -2954,15 +2838,14 @@ protected void bindSimpleValue(String type, SimpleValue simpleValue, boolean nul /** * Binds a Column instance to the Hibernate meta model * - * @param property The Grails domain class property + * @param property The Grails domain class property * @param parentProperty - * @param column The column to bind + * @param column The column to bind * @param path - * @param table The table name - * @param sessionFactoryBeanName the session factory bean name + * @param table The table name + * @param sessionFactoryBeanName the session factory bean name */ - protected void bindColumn(PersistentProperty property, PersistentProperty parentProperty, - Column column, ColumnConfig cc, String path, Table table, String sessionFactoryBeanName) { + protected void bindColumn(PersistentProperty property, PersistentProperty parentProperty, Column column, ColumnConfig cc, String path, Table table, String sessionFactoryBeanName) { if (cc != null) { column.setComment(cc.getComment()); @@ -2981,23 +2864,18 @@ protected void bindColumn(PersistentProperty property, PersistentProperty parent } if (property instanceof ManyToMany) { column.setNullable(false); - } - else if (property instanceof org.grails.datastore.mapping.model.types.OneToOne && association.isBidirectional() && !association.isOwningSide()) { + } else if (property instanceof org.grails.datastore.mapping.model.types.OneToOne && association.isBidirectional() && !association.isOwningSide()) { if (isHasOne(((Association) property).getInverseSide())) { column.setNullable(false); - } - else { + } else { column.setNullable(true); } - } - else if ((property instanceof ToOne) && association.isCircular()) { + } else if ((property instanceof ToOne) && association.isCircular()) { column.setNullable(true); - } - else { + } else { column.setNullable(property.isNullable()); } - } - else { + } else { column.setName(columnName); column.setNullable(property.isNullable() || (parentProperty != null && parentProperty.isNullable())); @@ -3020,24 +2898,24 @@ else if ((property instanceof ToOne) && association.isCircular()) { if (!owner.isRoot()) { Mapping mapping = getMapping(owner); if (mapping == null || mapping.getTablePerHierarchy()) { - if (LOG.isDebugEnabled()) - LOG.debug("[GrailsDomainBinder] Sub class property [" + property.getName() + "] for column name ["+column.getName()+"] set to nullable"); + if (LOG.isDebugEnabled()) { + LOG.debug("[GrailsDomainBinder] Sub class property [" + property.getName() + "] for column name [" + column.getName() + "] set to nullable"); + } column.setNullable(true); } else { column.setNullable(property.isNullable()); } } - if (LOG.isDebugEnabled()) - LOG.debug("[GrailsDomainBinder] bound property [" + property.getName() + "] to column name ["+column.getName()+"] in table ["+table.getName()+"]"); + if (LOG.isDebugEnabled()) { + LOG.debug("[GrailsDomainBinder] bound property [" + property.getName() + "] to column name [" + column.getName() + "] in table [" + table.getName() + "]"); + } } - - protected void createKeyForProps(PersistentProperty grailsProp, String path, Table table, - String columnName, List propertyNames, String sessionFactoryBeanName) { + protected void createKeyForProps(PersistentProperty grailsProp, String path, Table table, String columnName, List propertyNames, String sessionFactoryBeanName) { List keyList = new ArrayList<>(); keyList.add(new Column(columnName)); - for (Iterator i = propertyNames.iterator(); i.hasNext();) { + for (Iterator i = propertyNames.iterator(); i.hasNext(); ) { String propertyName = (String) i.next(); PersistentProperty otherProp = grailsProp.getOwner().getPropertyByName(propertyName); if (otherProp == null) { @@ -3056,7 +2934,7 @@ protected void createUniqueKeyForColumns(Table table, String columnName, List - 1) { + if (cc != null && cc.getScale() > -1) { column.setScale(cc.getScale()); } else if (constrainedProperty.getScale() > -1) { scale = constrainedProperty.getScale(); @@ -3266,25 +3136,20 @@ protected void bindNumericColumnConstraints(Column column, PersistentProperty pr } - if( cc != null && cc.getPrecision() > -1) { + if (cc != null && cc.getPrecision() > -1) { column.setPrecision(cc.getPrecision()); - } - else { + } else { Comparable minConstraintValue = constrainedProperty.getMin(); Comparable maxConstraintValue = constrainedProperty.getMax(); int minConstraintValueLength = 0; if ((minConstraintValue != null) && (minConstraintValue instanceof Number)) { - minConstraintValueLength = Math.max( - countDigits((Number) minConstraintValue), - countDigits(((Number) minConstraintValue).longValue()) + scale); + minConstraintValueLength = Math.max(countDigits((Number) minConstraintValue), countDigits(((Number) minConstraintValue).longValue()) + scale); } int maxConstraintValueLength = 0; if ((maxConstraintValue != null) && (maxConstraintValue instanceof Number)) { - maxConstraintValueLength = Math.max( - countDigits((Number) maxConstraintValue), - countDigits(((Number) maxConstraintValue).longValue()) + scale); + maxConstraintValueLength = Math.max(countDigits((Number) maxConstraintValue), countDigits(((Number) maxConstraintValue).longValue()) + scale); } if (minConstraintValueLength > 0 && maxConstraintValueLength > 0) { @@ -3334,15 +3199,13 @@ protected void handleUniqueConstraint(PersistentProperty property, Column column if (mappedForm.isUnique()) { if (!mappedForm.isUniqueWithinGroup()) { column.setUnique(true); - } - else { + } else { createKeyForProps(property, path, table, columnName, mappedForm.getUniquenessGroup(), sessionFactoryBeanName); } } } - protected boolean isNotEmpty(String s) { return GrailsHibernateUtil.isNotEmpty(s); } @@ -3375,8 +3238,7 @@ class GrailsCollectionSecondPass implements SecondPass { protected Collection collection; protected String sessionFactoryBeanName; - public GrailsCollectionSecondPass(ToMany property, InFlightMetadataCollector mappings, - Collection coll, String sessionFactoryBeanName) { + public GrailsCollectionSecondPass(ToMany property, InFlightMetadataCollector mappings, Collection coll, String sessionFactoryBeanName) { this.property = property; this.mappings = mappings; this.collection = coll; @@ -3393,11 +3255,11 @@ protected void createCollectionKeys() { if (LOG.isDebugEnabled()) { String msg = "Mapped collection key: " + columns(collection.getKey()); - if (collection.isIndexed()) + if (collection.isIndexed()) { msg += ", index: " + columns(((IndexedCollection) collection).getIndex()); + } if (collection.isOneToMany()) { - msg += ", one-to-many: " - + ((OneToMany) collection.getElement()).getReferencedEntityName(); + msg += ", one-to-many: " + ((OneToMany) collection.getElement()).getReferencedEntityName(); } else { msg += ", element: " + columns(collection.getElement()); } @@ -3410,7 +3272,9 @@ protected String columns(Value val) { Iterator iter = val.getColumnIterator(); while (iter.hasNext()) { columns.append(((Selectable) iter.next()).getText()); - if (iter.hasNext()) columns.append(", "); + if (iter.hasNext()) { + columns.append(", "); + } } return columns.toString(); } @@ -3423,54 +3287,51 @@ public void doSecondPass(Map persistentClasses) throws MappingException { } class ListSecondPass extends GrailsCollectionSecondPass { + private static final long serialVersionUID = -3024674993774205193L; - public ListSecondPass(ToMany property, InFlightMetadataCollector mappings, - Collection coll, String sessionFactoryBeanName) { + public ListSecondPass(ToMany property, InFlightMetadataCollector mappings, Collection coll, String sessionFactoryBeanName) { super(property, mappings, coll, sessionFactoryBeanName); } @Override public void doSecondPass(Map persistentClasses, Map inheritedMetas) throws MappingException { - bindListSecondPass(property, mappings, persistentClasses, - (org.hibernate.mapping.List) collection, sessionFactoryBeanName); + bindListSecondPass(property, mappings, persistentClasses, (org.hibernate.mapping.List) collection, sessionFactoryBeanName); } @SuppressWarnings("rawtypes") @Override public void doSecondPass(Map persistentClasses) throws MappingException { - bindListSecondPass(property, mappings, persistentClasses, - (org.hibernate.mapping.List) collection, sessionFactoryBeanName); + bindListSecondPass(property, mappings, persistentClasses, (org.hibernate.mapping.List) collection, sessionFactoryBeanName); } } class MapSecondPass extends GrailsCollectionSecondPass { + private static final long serialVersionUID = -3244991685626409031L; - public MapSecondPass(ToMany property, InFlightMetadataCollector mappings, - Collection coll, String sessionFactoryBeanName) { + public MapSecondPass(ToMany property, InFlightMetadataCollector mappings, Collection coll, String sessionFactoryBeanName) { super(property, mappings, coll, sessionFactoryBeanName); } @Override public void doSecondPass(Map persistentClasses, Map inheritedMetas) throws MappingException { - bindMapSecondPass(property, mappings, persistentClasses, - (org.hibernate.mapping.Map)collection, sessionFactoryBeanName); + bindMapSecondPass(property, mappings, persistentClasses, (org.hibernate.mapping.Map) collection, sessionFactoryBeanName); } @SuppressWarnings("rawtypes") @Override public void doSecondPass(Map persistentClasses) throws MappingException { - bindMapSecondPass(property, mappings, persistentClasses, - (org.hibernate.mapping.Map) collection, sessionFactoryBeanName); + bindMapSecondPass(property, mappings, persistentClasses, (org.hibernate.mapping.Map) collection, sessionFactoryBeanName); } } + /** * A Collection type, for the moment only Set is supported * * @author Graeme */ - static abstract class CollectionType { + abstract static class CollectionType { protected final Class clazz; protected final GrailsDomainBinder binder; @@ -3484,15 +3345,14 @@ static abstract class CollectionType { protected final Map, CollectionType> INSTANCES = new HashMap<>(); - public abstract Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException; - protected CollectionType(Class clazz, GrailsDomainBinder binder) { this.clazz = clazz; this.binder = binder; this.buildingContext = binder.getMetadataBuildingContext(); } + public abstract Collection create(ToMany property, PersistentClass owner, String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException; + @Override public String toString() { return clazz.getName(); @@ -3508,8 +3368,7 @@ protected void createInstances() { SET = new CollectionType(Set.class, binder) { @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { + public Collection create(ToMany property, PersistentClass owner, String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { org.hibernate.mapping.Set coll = new org.hibernate.mapping.Set(buildingContext, owner); coll.setCollectionTable(owner.getTable()); coll.setTypeName(getTypeName(property)); @@ -3522,8 +3381,7 @@ public Collection create(ToMany property, PersistentClass owner, LIST = new CollectionType(List.class, binder) { @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { + public Collection create(ToMany property, PersistentClass owner, String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { org.hibernate.mapping.List coll = new org.hibernate.mapping.List(buildingContext, owner); coll.setCollectionTable(owner.getTable()); coll.setTypeName(getTypeName(property)); @@ -3535,8 +3393,7 @@ public Collection create(ToMany property, PersistentClass owner, BAG = new CollectionType(java.util.Collection.class, binder) { @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { + public Collection create(ToMany property, PersistentClass owner, String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { Bag coll = new Bag(buildingContext, owner); coll.setCollectionTable(owner.getTable()); coll.setTypeName(getTypeName(property)); @@ -3548,8 +3405,7 @@ public Collection create(ToMany property, PersistentClass owner, MAP = new CollectionType(Map.class, binder) { @Override - public Collection create(ToMany property, PersistentClass owner, - String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { + public Collection create(ToMany property, PersistentClass owner, String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) throws MappingException { org.hibernate.mapping.Map map = new org.hibernate.mapping.Map(buildingContext, owner); map.setTypeName(getTypeName(property)); binder.bindCollection(property, map, owner, mappings, path, sessionFactoryBeanName); diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtil.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtil.java index 421e89d9933..4f618b84108 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtil.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtil.java @@ -31,7 +31,13 @@ import org.grails.orm.hibernate.datasource.MultipleDataSourceSupport; import org.grails.orm.hibernate.proxy.HibernateProxyHandler; import org.grails.orm.hibernate.support.HibernateRuntimeUtils; -import org.hibernate.*; +import org.hibernate.Criteria; +import org.hibernate.FetchMode; +import org.hibernate.FlushMode; +import org.hibernate.Hibernate; +import org.hibernate.LockMode; +import org.hibernate.Session; +import org.hibernate.SessionFactory; import org.hibernate.criterion.Order; import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.SessionImplementor; @@ -43,7 +49,8 @@ import org.springframework.core.convert.ConversionService; import org.springframework.transaction.support.TransactionSynchronizationManager; -import java.util.*; +import java.util.List; +import java.util.Map; /** * Utility methods for configuring Hibernate inside Grails. @@ -52,7 +59,6 @@ * @since 0.4 */ public class GrailsHibernateUtil extends HibernateRuntimeUtils { - protected static final Logger LOG = LoggerFactory.getLogger(GrailsHibernateUtil.class); public static final String ARGUMENT_FETCH_SIZE = "fetchSize"; public static final String ARGUMENT_TIMEOUT = "timeout"; @@ -70,6 +76,7 @@ public class GrailsHibernateUtil extends HibernateRuntimeUtils { public static final String ARGUMENT_LOCK = "lock"; public static final Class[] EMPTY_CLASS_ARRAY = {}; + protected static final Logger LOG = LoggerFactory.getLogger(GrailsHibernateUtil.class); private static HibernateProxyHandler proxyHandler = new HibernateProxyHandler(); @@ -80,26 +87,26 @@ public static void populateArgumentsForCriteria(AbstractHibernateDatastore datas /** * Populates criteria arguments for the given target class and arguments map * - * @param datastore the GrailsApplication instance + * @param datastore the GrailsApplication instance * @param targetClass The target class - * @param c The criteria instance - * @param argMap The arguments map + * @param c The criteria instance + * @param argMap The arguments map */ @SuppressWarnings("rawtypes") public static void populateArgumentsForCriteria(AbstractHibernateDatastore datastore, Class targetClass, Criteria c, Map argMap, ConversionService conversionService, boolean useDefaultMapping) { Integer maxParam = null; Integer offsetParam = null; if (argMap.containsKey(ARGUMENT_MAX)) { - maxParam = conversionService.convert(argMap.get(ARGUMENT_MAX),Integer.class); + maxParam = conversionService.convert(argMap.get(ARGUMENT_MAX), Integer.class); } if (argMap.containsKey(ARGUMENT_OFFSET)) { - offsetParam = conversionService.convert(argMap.get(ARGUMENT_OFFSET),Integer.class); + offsetParam = conversionService.convert(argMap.get(ARGUMENT_OFFSET), Integer.class); } if (argMap.containsKey(ARGUMENT_FETCH_SIZE)) { - c.setFetchSize(conversionService.convert(argMap.get(ARGUMENT_FETCH_SIZE),Integer.class)); + c.setFetchSize(conversionService.convert(argMap.get(ARGUMENT_FETCH_SIZE), Integer.class)); } if (argMap.containsKey(ARGUMENT_TIMEOUT)) { - c.setTimeout(conversionService.convert(argMap.get(ARGUMENT_TIMEOUT),Integer.class)); + c.setTimeout(conversionService.convert(argMap.get(ARGUMENT_TIMEOUT), Integer.class)); } if (argMap.containsKey(ARGUMENT_FLUSH_MODE)) { c.setFlushMode(convertFlushMode(argMap.get(ARGUMENT_FLUSH_MODE))); @@ -107,10 +114,10 @@ public static void populateArgumentsForCriteria(AbstractHibernateDatastore datas if (argMap.containsKey(ARGUMENT_READ_ONLY)) { c.setReadOnly(ClassUtils.getBooleanFromMap(ARGUMENT_READ_ONLY, argMap)); } - String orderParam = (String)argMap.get(ARGUMENT_ORDER); + String orderParam = (String) argMap.get(ARGUMENT_ORDER); Object fetchObj = argMap.get(ARGUMENT_FETCH); if (fetchObj instanceof Map) { - Map fetch = (Map)fetchObj; + Map fetch = (Map) fetchObj; for (Object o : fetch.keySet()) { String associationName = (String) o; c.setFetchMode(associationName, getFetchMode(fetch.get(associationName))); @@ -128,8 +135,7 @@ public static void populateArgumentsForCriteria(AbstractHibernateDatastore datas if (ClassUtils.getBooleanFromMap(ARGUMENT_LOCK, argMap)) { c.setLockMode(LockMode.PESSIMISTIC_WRITE); c.setCacheable(false); - } - else { + } else { if (argMap.containsKey(ARGUMENT_CACHE)) { c.setCacheable(ClassUtils.getBooleanFromMap(ARGUMENT_CACHE, argMap)); } else { @@ -155,8 +161,7 @@ public static void populateArgumentsForCriteria(AbstractHibernateDatastore datas final String order = ORDER_DESC.equalsIgnoreCase(orderParam) ? ORDER_DESC : ORDER_ASC; addOrderPossiblyNested(datastore, c, targetClass, sort, order, ignoreCase); } - } - else if (useDefaultMapping) { + } else if (useDefaultMapping) { Mapping m = GrailsDomainBinder.getMapping(targetClass); if (m != null) { Map sortMap = m.getSort().getNamesAndDirections(); @@ -179,8 +184,8 @@ public static void setBinder(GrailsDomainBinder binder) { * Populates criteria arguments for the given target class and arguments map * * @param targetClass The target class - * @param c The criteria instance - * @param argMap The arguments map + * @param c The criteria instance + * @param argMap The arguments map * */ @Deprecated @@ -199,7 +204,7 @@ private static FlushMode convertFlushMode(Object object) { return null; } if (object instanceof FlushMode) { - return (FlushMode)object; + return (FlushMode) object; } return FlushMode.valueOf(String.valueOf(object)); } @@ -212,15 +217,15 @@ private static void addOrderPossiblyNested(AbstractHibernateDatastore datastore, if (firstDotPos == -1) { addOrder(c, sort, order, ignoreCase); } else { // nested property - String sortHead = sort.substring(0,firstDotPos); - String sortTail = sort.substring(firstDotPos+1); + String sortHead = sort.substring(0, firstDotPos); + String sortTail = sort.substring(firstDotPos + 1); PersistentProperty property = getGrailsDomainClassProperty(datastore, targetClass, sortHead); if (property instanceof Embedded) { // embedded objects cannot reference entities (at time of writing), so no more recursion needed addOrder(c, sort, order, ignoreCase); - } else if(property instanceof Association) { + } else if (property instanceof Association) { Criteria subCriteria = c.createCriteria(sortHead); - Class propertyTargetClass = ((Association)property).getAssociatedEntity().getJavaClass(); + Class propertyTargetClass = ((Association) property).getAssociatedEntity().getJavaClass(); GrailsHibernateUtil.cacheCriteriaByMapping(datastore, propertyTargetClass, subCriteria); addOrderPossiblyNested(datastore, subCriteria, propertyTargetClass, sortTail, order, ignoreCase); // Recurse on nested sort } @@ -233,8 +238,7 @@ private static void addOrderPossiblyNested(AbstractHibernateDatastore datastore, private static void addOrder(Criteria c, String sort, String order, boolean ignoreCase) { if (ORDER_DESC.equals(order)) { c.addOrder(ignoreCase ? Order.desc(sort).ignoreCase() : Order.desc(sort)); - } - else { + } else { c.addOrder(ignoreCase ? Order.asc(sort).ignoreCase() : Order.asc(sort)); } } @@ -244,9 +248,9 @@ private static void addOrder(Criteria c, String sort, String order, boolean igno * assuming targetClass corresponds to a GrailsDomainClass. */ private static PersistentProperty getGrailsDomainClassProperty(AbstractHibernateDatastore datastore, Class targetClass, String propertyName) { - PersistentEntity grailsClass = datastore != null ? datastore.getMappingContext().getPersistentEntity( targetClass.getName()) : null; + PersistentEntity grailsClass = datastore != null ? datastore.getMappingContext().getPersistentEntity(targetClass.getName()) : null; if (grailsClass == null) { - throw new IllegalArgumentException("Unexpected: class is not a domain class:"+targetClass.getName()); + throw new IllegalArgumentException("Unexpected: class is not a domain class:" + targetClass.getName()); } return grailsClass.getPropertyByName(propertyName); } @@ -255,7 +259,7 @@ private static PersistentProperty getGrailsDomainClassProperty(AbstractHibernate * Configures the criteria instance to cache based on the configured mapping. * * @param targetClass The target class - * @param criteria The criteria + * @param criteria The criteria */ public static void cacheCriteriaByMapping(Class targetClass, Criteria criteria) { Mapping m = GrailsDomainBinder.getMapping(targetClass); @@ -289,18 +293,17 @@ public static FetchMode getFetchMode(Object object) { * Sets the target object to read-only using the given SessionFactory instance. This * avoids Hibernate performing any dirty checking on the object * - * @see #setObjectToReadWrite(Object, org.hibernate.SessionFactory) - * - * @param target The target object + * @param target The target object * @param sessionFactory The SessionFactory instance + * @see #setObjectToReadWrite(Object, org.hibernate.SessionFactory) */ public static void setObjectToReadyOnly(Object target, SessionFactory sessionFactory) { Object resource = TransactionSynchronizationManager.getResource(sessionFactory); - if(resource != null) { + if (resource != null) { Session session = sessionFactory.getCurrentSession(); if (canModifyReadWriteState(session, target)) { if (target instanceof HibernateProxy) { - target = ((HibernateProxy)target).getHibernateLazyInitializer().getImplementation(); + target = ((HibernateProxy) target).getHibernateLazyInitializer().getImplementation(); } session.setReadOnly(target, true); session.setHibernateFlushMode(FlushMode.MANUAL); @@ -315,10 +318,9 @@ private static boolean canModifyReadWriteState(Session session, Object target) { /** * Sets the target object to read-write, allowing Hibernate to dirty check it and auto-flush changes. * - * @see #setObjectToReadyOnly(Object, org.hibernate.SessionFactory) - * - * @param target The target object + * @param target The target object * @param sessionFactory The SessionFactory instance + * @see #setObjectToReadyOnly(Object, org.hibernate.SessionFactory) */ public static void setObjectToReadWrite(final Object target, SessionFactory sessionFactory) { Session session = sessionFactory.getCurrentSession(); @@ -335,7 +337,7 @@ public static void setObjectToReadWrite(final Object target, SessionFactory sess Object actualTarget = target; if (target instanceof HibernateProxy) { - actualTarget = ((HibernateProxy)target).getHibernateLazyInitializer().getImplementation(); + actualTarget = ((HibernateProxy) target).getHibernateLazyInitializer().getImplementation(); } session.setReadOnly(actualTarget, false); @@ -345,11 +347,12 @@ public static void setObjectToReadWrite(final Object target, SessionFactory sess /** * Increments the entities version number in order to force an update + * * @param target The target entity */ public static void incrementVersion(Object target) { MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(target.getClass()); - if (metaClass.hasProperty(target, GormProperties.VERSION)!=null) { + if (metaClass.hasProperty(target, GormProperties.VERSION) != null) { Object version = metaClass.getProperty(target, GormProperties.VERSION); if (version instanceof Long) { Long newVersion = (Long) version + 1; @@ -361,13 +364,13 @@ public static void incrementVersion(Object target) { /** * Ensures the meta class is correct for a given class * - * @param target The GroovyObject + * @param target The GroovyObject * @param persistentClass The persistent class */ @Deprecated public static void ensureCorrectGroovyMetaClass(Object target, Class persistentClass) { if (target instanceof GroovyObject) { - GroovyObject go = ((GroovyObject)target); + GroovyObject go = ((GroovyObject) target); if (!go.getMetaClass().getTheClass().equals(persistentClass)) { go.setMetaClass(GroovySystem.getMetaClassRegistry().getMetaClass(persistentClass)); } @@ -376,6 +379,7 @@ public static void ensureCorrectGroovyMetaClass(Object target, Class persiste /** * Unwraps and initializes a HibernateProxy. + * * @param proxy The proxy * @return the unproxied instance */ @@ -386,7 +390,7 @@ public static Object unwrapProxy(HibernateProxy proxy) { /** * Returns the proxy for a given association or null if it is not proxied * - * @param obj The object + * @param obj The object * @param associationName The named assoication * @return A proxy */ @@ -397,7 +401,7 @@ public static HibernateProxy getAssociationProxy(Object obj, String associationN /** * Checks whether an associated property is initialized and returns true if it is * - * @param obj The name of the object + * @param obj The name of the object * @param associationName The name of the association * @return true if is initialized */ @@ -453,5 +457,4 @@ public static String unqualify(final String qualifiedName) { return StringHelper.unqualify(qualifiedName); } - } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsIdentifierGeneratorFactory.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsIdentifierGeneratorFactory.java index eac6c6791ec..f6c2da0412c 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsIdentifierGeneratorFactory.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsIdentifierGeneratorFactory.java @@ -18,30 +18,31 @@ */ package org.grails.orm.hibernate.cfg; -import java.lang.reflect.Field; - import org.hibernate.cfg.Configuration; import org.hibernate.id.SequenceGenerator; import org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory; import org.springframework.util.ReflectionUtils; +import java.lang.reflect.Field; + /** * Hibernate IdentifierGeneratorFactory that prefers sequence-identity generator over sequence generator - * + * * @author Lari Hotari */ public class GrailsIdentifierGeneratorFactory extends DefaultIdentifierGeneratorFactory { + private static final long serialVersionUID = 1L; @Override public Class getIdentifierGeneratorClass(String strategy) { Class generatorClass = super.getIdentifierGeneratorClass(strategy); - if("native".equals(strategy) && generatorClass == SequenceGenerator.class) { + if ("native".equals(strategy) && generatorClass == SequenceGenerator.class) { generatorClass = super.getIdentifierGeneratorClass("sequence-identity"); } return generatorClass; } - + public static void applyNewInstance(Configuration cfg) throws IllegalArgumentException, IllegalAccessException { Field field = ReflectionUtils.findField(Configuration.class, "identifierGeneratorFactory"); field.setAccessible(true); diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingBuilder.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingBuilder.groovy index 89703d55900..308aa4b9932 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingBuilder.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingBuilder.groovy @@ -19,16 +19,13 @@ package org.grails.orm.hibernate.cfg import groovy.transform.CompileStatic +import jakarta.persistence.AccessType import org.grails.datastore.mapping.config.groovy.MappingConfigurationBuilder import org.grails.datastore.mapping.model.config.GormProperties import org.grails.datastore.mapping.reflect.ClassPropertyFetcher import org.hibernate.FetchMode import org.slf4j.Logger import org.slf4j.LoggerFactory -import org.springframework.beans.MutablePropertyValues -import org.springframework.validation.DataBinder - -import jakarta.persistence.AccessType /** * Implements the ORM mapping DSL constructing a model that can be evaluated by the @@ -38,7 +35,7 @@ import jakarta.persistence.AccessType * @since 1.0 */ -class HibernateMappingBuilder implements MappingConfigurationBuilder{ +class HibernateMappingBuilder implements MappingConfigurationBuilder { private static final String INCLUDE_PARAM = 'include' private static final String EXCLUDE_PARAM = 'exclude' @@ -87,10 +84,9 @@ class HibernateMappingBuilder implements MappingConfigurationBuilderConfigures the discriminator name. Example: - * { discriminator 'foo' } - * - * @param name The name of the table - */ + *

Configures the discriminator name. Example: + * { discriminator 'foo' } + * + * @param name The name of the table + */ @CompileStatic void discriminator(String name) { mapping.discriminator(name) @@ -291,20 +288,18 @@ class HibernateMappingBuilder implements MappingConfigurationBuilderConfigures the second-level cache with the default usage of 'read-write' and the default include of 'all' if * the passed argument is true @@ -372,7 +366,7 @@ class HibernateMappingBuilder implements MappingConfigurationBuilder constraintsToImports = ClassPropertyFetcher.getStaticPropertyValuesFromInheritanceHierarchy((Class)args[0], GormProperties.CONSTRAINTS, Closure) - if(constraintsToImports) { + List constraintsToImports = ClassPropertyFetcher.getStaticPropertyValuesFromInheritanceHierarchy((Class) args[0], GormProperties.CONSTRAINTS, Closure) + if (constraintsToImports) { List originalIncludes = this.methodMissingIncludes List originalExludes = this.methodMissingExcludes try { - if(args[-1] instanceof Map) { + if (args[-1] instanceof Map) { Map argMap = (Map) args[-1] def includes = argMap.get(INCLUDE_PARAM) def excludes = argMap.get(EXCLUDE_PARAM) - if(includes instanceof List) { + if (includes instanceof List) { this.methodMissingIncludes = includes } - if(excludes instanceof List) { + if (excludes instanceof List) { this.methodMissingExcludes = excludes } } - for(Closure callable in constraintsToImports) { + for (Closure callable in constraintsToImports) { callable.setDelegate(this) callable.setResolveStrategy(Closure.DELEGATE_ONLY) callable.call() @@ -694,8 +673,7 @@ class HibernateMappingBuilder implements MappingConfigurationBuilder propertyType) { addPersistentEntities(persistentClasses); } - public HibernateMappingContext(HibernateConnectionSourceSettings settings, Class...persistentClasses) { + public HibernateMappingContext(HibernateConnectionSourceSettings settings, Class... persistentClasses) { this(settings, null, persistentClasses); } @@ -105,9 +114,9 @@ public MappingFactory getMappingFactory() { @Override protected PersistentEntity createPersistentEntity(Class javaClass) { - if(GormEntity.class.isAssignableFrom(javaClass)) { + if (GormEntity.class.isAssignableFrom(javaClass)) { Object mappingStrategy = resolveMappingStrategy(javaClass); - if(isValidMappingStrategy(javaClass, mappingStrategy)) { + if (isValidMappingStrategy(javaClass, mappingStrategy)) { return new HibernatePersistentEntity(javaClass, this); } } @@ -129,7 +138,7 @@ public static boolean isDomainClass(Class clazz) { } private static boolean doIsDomainClassCheck(Class clazz) { - if(GormEntity.class.isAssignableFrom(clazz)) { + if (GormEntity.class.isAssignableFrom(clazz)) { return true; } @@ -138,7 +147,9 @@ private static boolean doIsDomainClassCheck(Class clazz) { return false; } - if (clazz.isEnum()) return false; + if (clazz.isEnum()) { + return false; + } Annotation[] allAnnotations = clazz.getAnnotations(); for (Annotation annotation : allAnnotations) { @@ -161,11 +172,9 @@ private static boolean doIsDomainClassCheck(Class clazz) { // passes all conditions return true return true; - } - catch (SecurityException e) { + } catch (SecurityException e) { // ignore - } - catch (NoSuchFieldException e) { + } catch (NoSuchFieldException e) { // ignore } testClass = testClass.getSuperclass(); @@ -191,11 +200,14 @@ public PersistentEntity getPersistentEntity(String name) { } static class HibernateEmbeddedPersistentEntity extends EmbeddedPersistentEntity { + private final ClassMapping classMapping; + public HibernateEmbeddedPersistentEntity(Class type, MappingContext ctx) { super(type, ctx); this.classMapping = new ClassMapping() { Mapping mappedForm = (Mapping) context.getMappingFactory().createMappedForm(HibernateEmbeddedPersistentEntity.this); + @Override public PersistentEntity getEntity() { return HibernateEmbeddedPersistentEntity.this; @@ -219,7 +231,7 @@ public ClassMapping getMapping() { } } - class HibernateMappingFactory extends AbstractGormMappingFactory { + class HibernateMappingFactory extends AbstractGormMappingFactory { public HibernateMappingFactory() { } @@ -234,43 +246,38 @@ public IdentityMapping createIdentityMapping(final ClassMapping classMapping) { final Mapping mappedForm = createMappedForm(classMapping.getEntity()); final Object identity = mappedForm.getIdentity(); final ValueGenerator generator; - if(identity instanceof Identity) { + if (identity instanceof Identity) { Identity id = (Identity) identity; String generatorName = id.getGenerator(); - if(generatorName != null) { + if (generatorName != null) { ValueGenerator resolvedGenerator; try { resolvedGenerator = ValueGenerator.valueOf(generatorName.toUpperCase(java.util.Locale.ENGLISH)); } catch (IllegalArgumentException e) { - if(ClassUtils.isPresent(generatorName)) { + if (ClassUtils.isPresent(generatorName)) { resolvedGenerator = ValueGenerator.CUSTOM; - } - else { - throw new DatastoreConfigurationException("Invalid id generation strategy for entity ["+classMapping.getEntity().getName()+"]: " + generatorName); + } else { + throw new DatastoreConfigurationException("Invalid id generation strategy for entity [" + classMapping.getEntity().getName() + "]: " + generatorName); } } generator = resolvedGenerator; - } - else { + } else { generator = ValueGenerator.AUTO; } - } - else { + } else { generator = ValueGenerator.AUTO; } return new IdentityMapping() { @Override public String[] getIdentifierName() { - if(identity instanceof Identity) { + if (identity instanceof Identity) { final String name = ((Identity) identity).getName(); - if(name != null) { + if (name != null) { return new String[]{name}; - } - else { + } else { return DEFAULT_IDENTITY_MAPPING; } - } - else if(identity instanceof CompositeIdentity) { + } else if (identity instanceof CompositeIdentity) { return ((CompositeIdentity) identity).getPropertyNames(); } return DEFAULT_IDENTITY_MAPPING; diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java index a9fa201954d..a8e27cdd41d 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java @@ -16,15 +16,15 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.cfg; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Entity; +import jakarta.persistence.MappedSuperclass; import org.grails.datastore.gorm.GormEntity; import org.grails.datastore.gorm.jdbc.connections.DataSourceSettings; -import org.grails.datastore.gorm.validation.jakarta.JakartaValidatorRegistry; import org.grails.datastore.mapping.core.connections.ConnectionSource; import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.validation.ValidatorRegistry; import org.grails.orm.hibernate.EventListenerIntegrator; import org.grails.orm.hibernate.GrailsSessionContext; import org.grails.orm.hibernate.HibernateEventListeners; @@ -64,12 +64,17 @@ import org.springframework.core.type.filter.TypeFilter; import org.springframework.util.ClassUtils; -import jakarta.persistence.Embeddable; -import jakarta.persistence.Entity; -import jakarta.persistence.MappedSuperclass; import javax.sql.DataSource; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; /** * A Configuration that uses a MappingContext to configure Hibernate @@ -77,11 +82,12 @@ * @since 5.0 */ public class HibernateMappingContextConfiguration extends Configuration implements ApplicationContextAware { + private static final long serialVersionUID = -7115087342689305517L; private static final String RESOURCE_PATTERN = "/**/*.class"; - private static final TypeFilter[] ENTITY_TYPE_FILTERS = new TypeFilter[] { + private static final TypeFilter[] ENTITY_TYPE_FILTERS = new TypeFilter[]{ new AnnotationTypeFilter(Entity.class, false), new AnnotationTypeFilter(Embeddable.class, false), new AnnotationTypeFilter(MappedSuperclass.class, false)}; @@ -107,7 +113,7 @@ public void setApplicationContext(ApplicationContext applicationContext) throws String dsName = ConnectionSource.DEFAULT.equals(dataSourceName) ? "dataSource" : "dataSource_" + dataSourceName; Properties properties = getProperties(); - if(applicationContext.containsBean(dsName)) { + if (applicationContext.containsBean(dsName)) { properties.put(Environment.DATASOURCE, applicationContext.getBean(dsName)); } properties.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, currentSessionContext.getName()); @@ -134,6 +140,7 @@ public void setDataSourceConnectionSource(ConnectionSource annotatedClasses = new ArrayList<>(); for (PersistentEntity persistentEntity : hibernateMappingContext.getPersistentEntities()) { Class javaClass = persistentEntity.getJavaClass(); - if(javaClass.isAnnotationPresent(Entity.class)) { + if (javaClass.isAnnotationPresent(Entity.class)) { annotatedClasses.add(javaClass); } } - if(!additionalClasses.isEmpty()) { + if (!additionalClasses.isEmpty()) { for (Class additionalClass : additionalClasses) { - if(GormEntity.class.isAssignableFrom(additionalClass)) { + if (GormEntity.class.isAssignableFrom(additionalClass)) { hibernateMappingContext.addPersistentEntity(additionalClass); } } } - addAnnotatedClasses( annotatedClasses.toArray(new Class[annotatedClasses.size()])); + addAnnotatedClasses(annotatedClasses.toArray(new Class[annotatedClasses.size()])); ClassLoaderService classLoaderService = new ClassLoaderServiceImpl(appClassLoader) { @Override public Collection loadJavaServices(Class serviceContract) { - if(MetadataContributor.class.isAssignableFrom(serviceContract)) { - if(metadataContributor != null) { + if (MetadataContributor.class.isAssignableFrom(serviceContract)) { + if (metadataContributor != null) { return (Collection) Arrays.asList(domainBinder, metadataContributor); - } - else { + } else { return Collections.singletonList((S) domainBinder); } - } - else { + } else { return super.loadJavaServices(serviceContract); } } }; EventListenerIntegrator eventListenerIntegrator = new EventListenerIntegrator(hibernateEventListeners, eventListeners); BootstrapServiceRegistry bootstrapServiceRegistry = createBootstrapServiceRegistryBuilder() - .applyIntegrator(eventListenerIntegrator) - .applyIntegrator(new MetadataIntegrator()) - .applyClassLoaderService(classLoaderService) - .build(); + .applyIntegrator(eventListenerIntegrator) + .applyIntegrator(new MetadataIntegrator()) + .applyClassLoaderService(classLoaderService) + .build(); StrategySelector strategySelector = bootstrapServiceRegistry.getService(StrategySelector.class); strategySelector.registerStrategyImplementor( @@ -291,16 +295,19 @@ public Collection loadJavaServices(Class serviceContract) { setSessionFactoryObserver(new SessionFactoryObserver() { private static final long serialVersionUID = 1; - public void sessionFactoryCreated(SessionFactory factory) {} + + public void sessionFactoryCreated(SessionFactory factory) { + } + public void sessionFactoryClosed(SessionFactory factory) { if (serviceRegistry != null) { - ((ServiceRegistryImplementor)serviceRegistry).destroy(); + ((ServiceRegistryImplementor) serviceRegistry).destroy(); } } }); StandardServiceRegistryBuilder standardServiceRegistryBuilder = createStandardServiceRegistryBuilder(bootstrapServiceRegistry) - .applySettings(getProperties()); + .applySettings(getProperties()); StandardServiceRegistry serviceRegistry = standardServiceRegistryBuilder.build(); sessionFactory = super.buildSessionFactory(serviceRegistry); @@ -330,6 +337,7 @@ protected StandardServiceRegistryBuilder createStandardServiceRegistryBuilder(Bo /** * Default listeners. + * * @param listeners the listeners */ public void setEventListeners(Map listeners) { @@ -338,6 +346,7 @@ public void setEventListeners(Map listeners) { /** * User-specifiable extra listeners. + * * @param listeners the listeners */ public void setHibernateEventListeners(HibernateEventListeners listeners) { @@ -348,14 +357,12 @@ public ServiceRegistry getServiceRegistry() { return serviceRegistry; } - @Override protected void reset() { super.reset(); try { GrailsIdentifierGeneratorFactory.applyNewInstance(this); - } - catch (Exception e) { + } catch (Exception e) { // ignore exception } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernatePersistentEntity.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernatePersistentEntity.java index a1f5b54e093..2f9aeb5a174 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernatePersistentEntity.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernatePersistentEntity.java @@ -18,7 +18,11 @@ */ package org.grails.orm.hibernate.cfg; -import org.grails.datastore.mapping.model.*; +import org.grails.datastore.mapping.model.AbstractClassMapping; +import org.grails.datastore.mapping.model.AbstractPersistentEntity; +import org.grails.datastore.mapping.model.ClassMapping; +import org.grails.datastore.mapping.model.MappingContext; +import org.grails.datastore.mapping.model.PersistentEntity; /** * Persistent entity implementation for Hibernate @@ -27,16 +31,16 @@ * @since 5.0 */ public class HibernatePersistentEntity extends AbstractPersistentEntity { - private final AbstractClassMapping classMapping; + private final AbstractClassMapping classMapping; public HibernatePersistentEntity(Class javaClass, final MappingContext context) { super(javaClass, context); - this.classMapping = new AbstractClassMapping(this, context) { Mapping mappedForm = (Mapping) context.getMappingFactory().createMappedForm(HibernatePersistentEntity.this); + @Override public PersistentEntity getEntity() { return HibernatePersistentEntity.this; @@ -55,7 +59,6 @@ protected boolean includeIdentifiers() { return true; } - @Override public ClassMapping getMapping() { return this.classMapping; diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Identity.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Identity.groovy index 8c845acb183..d0279917820 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Identity.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Identity.groovy @@ -35,6 +35,7 @@ import org.springframework.validation.DataBinder @CompileStatic @Builder(builderStrategy = SimpleStrategy, prefix = '') class Identity extends Property { + /** * The generator to use */ diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java index c242b37f16a..fe8c22d8e4b 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java @@ -34,32 +34,35 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.*; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; /** * Hibernate Usertype that enum values by their ID. * * @author Siegfried Puchbauer * @author Graeme Rocher - * * @since 1.1 */ public class IdentityEnumType implements UserType, ParameterizedType, Serializable { + public static final String ENUM_ID_ACCESSOR = "getId"; + public static final String PARAM_ENUM_CLASS = "enumClass"; + private static final long serialVersionUID = -6625622185856547501L; private static final Logger LOG = LoggerFactory.getLogger(IdentityEnumType.class); private static TypeConfiguration typeConfiguration = new TypeConfiguration(); - public static final String ENUM_ID_ACCESSOR = "getId"; - - public static final String PARAM_ENUM_CLASS = "enumClass"; private static final Map>, BidiEnumMap> ENUM_MAPPINGS = new HashMap<>(); protected Class> enumClass; protected BidiEnumMap bidiMap; protected AbstractStandardBasicType type; - protected int[] sqlTypes; + protected int[] sqlTypes; public static BidiEnumMap getBidiEnumMap(Class> cls) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { BidiEnumMap m = ENUM_MAPPINGS.get(cls); @@ -68,8 +71,7 @@ public static BidiEnumMap getBidiEnumMap(Class> cls) throws Il if (!ENUM_MAPPINGS.containsKey(cls)) { m = new BidiEnumMap(cls); ENUM_MAPPINGS.put(cls, m); - } - else { + } else { m = ENUM_MAPPINGS.get(cls); } } @@ -77,23 +79,21 @@ public static BidiEnumMap getBidiEnumMap(Class> cls) throws Il return m; } - @SuppressWarnings("unchecked") public void setParameterValues(Properties properties) { try { - enumClass = (Class>)Thread.currentThread().getContextClassLoader().loadClass( - (String)properties.get(PARAM_ENUM_CLASS)); + enumClass = (Class>) Thread.currentThread().getContextClassLoader().loadClass( + (String) properties.get(PARAM_ENUM_CLASS)); if (LOG.isDebugEnabled()) { LOG.debug(String.format("Building ID-mapping for Enum Class %s", enumClass.getName())); } bidiMap = getBidiEnumMap(enumClass); - type = (AbstractStandardBasicType)typeConfiguration.getBasicTypeRegistry().getRegisteredType(bidiMap.keyType.getName()); + type = (AbstractStandardBasicType) typeConfiguration.getBasicTypeRegistry().getRegisteredType(bidiMap.keyType.getName()); if (LOG.isDebugEnabled()) { LOG.debug(String.format("Mapped Basic Type is %s", type)); } sqlTypes = type.sqlTypes(null); - } - catch (Exception e) { + } catch (Exception e) { throw new MappingException("Error mapping Enum Class using IdentifierEnumType", e); } } @@ -127,8 +127,7 @@ public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImp public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException { if (value == null) { st.setNull(index, sqlTypes[0]); - } - else { + } else { type.nullSafeSet(st, bidiMap.getKey(value), index, session); } } @@ -154,7 +153,7 @@ public Object replace(Object orig, Object target, Object owner) throws Hibernate } @SuppressWarnings({"rawtypes", "unchecked"}) - private static class BidiEnumMap implements Serializable { + private static final class BidiEnumMap implements Serializable { private static final long serialVersionUID = 3325751131102095834L; private final Map enumToKey; diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/InstanceProxy.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/InstanceProxy.groovy index c647c43d393..6f76b003655 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/InstanceProxy.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/InstanceProxy.groovy @@ -19,12 +19,12 @@ package org.grails.orm.hibernate.cfg import groovy.transform.CompileStatic - import org.grails.orm.hibernate.AbstractHibernateGormInstanceApi import org.grails.orm.hibernate.AbstractHibernateGormValidationApi @CompileStatic class InstanceProxy { + protected instance protected AbstractHibernateGormValidationApi validateApi protected AbstractHibernateGormInstanceApi instanceApi @@ -46,10 +46,9 @@ class InstanceProxy { def invokeMethod(String name, args) { if (validateMethods.contains(name)) { - validateApi.invokeMethod(name, prependToArray(instance, (Object[])args)) - } - else { - instanceApi.invokeMethod(name, prependToArray(instance, (Object[])args)) + validateApi.invokeMethod(name, prependToArray(instance, (Object[]) args)) + } else { + instanceApi.invokeMethod(name, prependToArray(instance, (Object[]) args)) } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/JoinTable.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/JoinTable.groovy index c4bef8eba10..c3bc008128f 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/JoinTable.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/JoinTable.groovy @@ -34,6 +34,7 @@ import groovy.transform.builder.SimpleStrategy @Builder(builderStrategy = SimpleStrategy, prefix = '') @CompileStatic class JoinTable extends Table { + /** * The foreign key column */ diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Mapping.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Mapping.groovy index d6fca255dbc..560f6f83dbc 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Mapping.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Mapping.groovy @@ -52,7 +52,7 @@ class Mapping extends Entity { return null } - return type instanceof Class ? ((Class)type).name : type.toString() + return type instanceof Class ? ((Class) type).name : type.toString() } /** @@ -193,8 +193,8 @@ class Mapping extends Entity { */ @Override Mapping id(Map identityConfig) { - if(identity instanceof Identity) { - Identity.configureExisting((Identity)identity, identityConfig) + if (identity instanceof Identity) { + Identity.configureExisting((Identity) identity, identityConfig) } return this } @@ -205,8 +205,8 @@ class Mapping extends Entity { */ @Override Mapping id(@DelegatesTo(Identity) Closure identityConfig) { - if(identity instanceof Identity) { - Identity.configureExisting((Identity)identity, identityConfig) + if (identity instanceof Identity) { + Identity.configureExisting((Identity) identity, identityConfig) } return this } @@ -228,7 +228,7 @@ class Mapping extends Entity { * @return This mapping */ Mapping cache(@DelegatesTo(CacheConfig) Closure cacheConfig) { - if(this.cache == null) { + if (this.cache == null) { this.cache = new CacheConfig() } CacheConfig.configureExisting(cache, cacheConfig) @@ -241,7 +241,7 @@ class Mapping extends Entity { * @return This mapping */ Mapping cache(Map cacheConfig) { - if(this.cache == null) { + if (this.cache == null) { this.cache = new CacheConfig() } CacheConfig.configureExisting(cache, cacheConfig) @@ -254,7 +254,7 @@ class Mapping extends Entity { * @return This mapping */ Mapping cache(String usage) { - if(this.cache == null) { + if (this.cache == null) { this.cache = new CacheConfig() } this.cache.usage = usage @@ -270,7 +270,7 @@ class Mapping extends Entity { * @return This mapping */ Mapping sort(String name, String direction) { - if(name && direction) { + if (name && direction) { this.sort.name = name this.sort.direction = direction } @@ -284,7 +284,7 @@ class Mapping extends Entity { * @return This mapping */ Mapping sort(Map nameAndDirections) { - if(nameAndDirections) { + if (nameAndDirections) { this.sort.namesAndDirections = nameAndDirections } return this @@ -296,7 +296,7 @@ class Mapping extends Entity { * @return This mapping */ Mapping discriminator(@DelegatesTo(DiscriminatorConfig) Closure discriminatorDef) { - if(discriminator == null) { + if (discriminator == null) { discriminator = new DiscriminatorConfig() } discriminatorDef.setDelegate(discriminator) @@ -311,7 +311,7 @@ class Mapping extends Entity { * @return This mapping */ Mapping discriminator(String value) { - if(discriminator == null) { + if (discriminator == null) { discriminator = new DiscriminatorConfig() } discriminator.value = value @@ -324,28 +324,27 @@ class Mapping extends Entity { * @return This mapping */ Mapping discriminator(Map args) { - if(args != null) { - if(discriminator == null) { + if (args != null) { + if (discriminator == null) { discriminator = new DiscriminatorConfig() } String value = args.remove('value')?.toString() discriminator.value = value if (args.column instanceof String) { - discriminator.column = new ColumnConfig(name:args.column.toString()) - } - else if (args.column instanceof Map) { + discriminator.column = new ColumnConfig(name: args.column.toString()) + } else if (args.column instanceof Map) { ColumnConfig config = new ColumnConfig() DataBinder dataBinder = new DataBinder(config) - dataBinder.bind(new MutablePropertyValues((Map)args.column)) + dataBinder.bind(new MutablePropertyValues((Map) args.column)) discriminator.column = config } discriminator.type(args.remove('type')) - if(args.containsKey('insert')) { - discriminator.insertable( args.remove('insert') as Boolean ) + if (args.containsKey('insert')) { + discriminator.insertable(args.remove('insert') as Boolean) } - if(args.containsKey('insertable')) { - discriminator.insertable( args.remove('insertable') as Boolean ) + if (args.containsKey('insertable')) { + discriminator.insertable(args.remove('insertable') as Boolean) } discriminator.formula(args.remove('formula')?.toString()) } @@ -357,9 +356,9 @@ class Mapping extends Entity { * @param propertyNames * @return */ - CompositeIdentity composite(String...propertyNames) { + CompositeIdentity composite(String... propertyNames) { identity = new CompositeIdentity(propertyNames: propertyNames) - return (CompositeIdentity)identity + return (CompositeIdentity) identity } /** @@ -397,7 +396,7 @@ class Mapping extends Entity { @CompileStatic Mapping version(String versionColumn) { PropertyConfig pc = getOrInitializePropertyConfig(GormProperties.VERSION) - pc.columns << new ColumnConfig(name:versionColumn) + pc.columns << new ColumnConfig(name: versionColumn) return this } @@ -436,11 +435,10 @@ class Mapping extends Entity { */ @Override PropertyConfig property(@DelegatesTo(PropertyConfig) Closure propertyConfig) { - if(columns.containsKey('*')) { + if (columns.containsKey('*')) { PropertyConfig cloned = cloneGlobalConstraint() return PropertyConfig.configureExisting(cloned, propertyConfig) - } - else { + } else { return PropertyConfig.configureNew(propertyConfig) } } @@ -462,13 +460,12 @@ class Mapping extends Entity { * @return This mapping */ @Override - PropertyConfig property( Map propertyConfig) { - if(columns.containsKey('*')) { + PropertyConfig property(Map propertyConfig) { + if (columns.containsKey('*')) { // apply global constraints constraints PropertyConfig cloned = cloneGlobalConstraint() return PropertyConfig.configureExisting(cloned, propertyConfig) - } - else { + } else { return PropertyConfig.configureNew(propertyConfig) } } @@ -512,13 +509,11 @@ class Mapping extends Entity { @Override def propertyMissing(String name, Object val) { - if(val instanceof Closure) { - property(name, (Closure)val) - } - else if(val instanceof PropertyConfig) { - columns[name] =((PropertyConfig)val) - } - else { + if (val instanceof Closure) { + property(name, (Closure) val) + } else if (val instanceof PropertyConfig) { + columns[name] = ((PropertyConfig) val) + } else { throw new MissingPropertyException(name, Mapping) } } @@ -526,30 +521,26 @@ class Mapping extends Entity { @CompileDynamic @Override def methodMissing(String name, Object args) { - if(args && args.getClass().isArray()) { - if(args[0] instanceof Closure) { - property(name, (Closure)args[0]) - } - else if(args[0] instanceof PropertyConfig) { - columns[name] = (PropertyConfig)args[0] - } - else if(args[0] instanceof Map) { + if (args && args.getClass().isArray()) { + if (args[0] instanceof Closure) { + property(name, (Closure) args[0]) + } else if (args[0] instanceof PropertyConfig) { + columns[name] = (PropertyConfig) args[0] + } else if (args[0] instanceof Map) { PropertyConfig property = getOrInitializePropertyConfig(name) Map namedArgs = (Map) args[0] - if(args[-1] instanceof Closure) { + if (args[-1] instanceof Closure) { PropertyConfig.configureExisting( property, - ((Closure)args[-1]) + ((Closure) args[-1]) ) } PropertyConfig.configureExisting(property, namedArgs) - } - else { + } else { throw new MissingMethodException(name, getClass(), args) } - } - else { + } else { throw new MissingMethodException(name, getClass(), args) } } @@ -557,17 +548,16 @@ class Mapping extends Entity { @Override protected PropertyConfig getOrInitializePropertyConfig(String name) { PropertyConfig pc = columns[name] - if(pc == null && columns.containsKey('*')) { + if (pc == null && columns.containsKey('*')) { // apply global constraints constraints PropertyConfig globalConstraints = columns.get('*') - if(globalConstraints != null) { - pc = (PropertyConfig)globalConstraints.clone() - if(pc.columns.size() == 1) { + if (globalConstraints != null) { + pc = (PropertyConfig) globalConstraints.clone() + if (pc.columns.size() == 1) { pc.firstColumnIsColumnCopy = true } } - } - else { + } else { pc = columns[name] } if (pc == null) { diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/NaturalId.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/NaturalId.groovy index 6eb401b4048..ff0d6f25d4e 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/NaturalId.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/NaturalId.groovy @@ -29,6 +29,7 @@ import groovy.transform.builder.SimpleStrategy @CompileStatic @Builder(builderStrategy = SimpleStrategy, prefix = '') class NaturalId { + /** * The property names that make up the natural id */ diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/PersistentEntityNamingStrategy.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/PersistentEntityNamingStrategy.java index 3149415a47a..d16e7dfb5ef 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/PersistentEntityNamingStrategy.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/PersistentEntityNamingStrategy.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.cfg; import org.grails.datastore.mapping.model.PersistentEntity; diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyConfig.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyConfig.groovy index 79fd0f717cb..363bd770773 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyConfig.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyConfig.groovy @@ -22,13 +22,12 @@ import groovy.transform.CompileStatic import groovy.transform.PackageScope import groovy.transform.builder.Builder import groovy.transform.builder.SimpleStrategy +import jakarta.persistence.FetchType import org.grails.datastore.mapping.config.Property import org.hibernate.FetchMode import org.springframework.beans.MutablePropertyValues import org.springframework.validation.DataBinder -import jakarta.persistence.FetchType - /** * Custom mapping for a single domain property. Note that a property * can have multiple columns via a component or a user type. @@ -67,7 +66,6 @@ class PropertyConfig extends Property { */ String sort - /** * The default sort order */ @@ -78,19 +76,18 @@ class PropertyConfig extends Property { */ Integer batchSize - /** * Whether to ignore ObjectNotFoundException */ boolean ignoreNotFound = false /** - * Whether or not this is column is insertable by hibernate + * Whether or not this is column is insertable by hibernate */ boolean insertable = true /** - * Whether or not this column is updatable by hibernate + * Whether or not this column is updatable by hibernate */ boolean updatable = true @@ -124,12 +121,11 @@ class PropertyConfig extends Property { * @return This property config */ PropertyConfig column(@DelegatesTo(ColumnConfig) Closure columnDef) { - if(columns.size() == 1 && firstColumnIsColumnCopy) { + if (columns.size() == 1 && firstColumnIsColumnCopy) { firstColumnIsColumnCopy = false ColumnConfig.configureExisting(columns[0], columnDef) - } - else { - columns.add( ColumnConfig.configureNew(columnDef) ) + } else { + columns.add(ColumnConfig.configureNew(columnDef)) } return this } @@ -139,13 +135,12 @@ class PropertyConfig extends Property { * @param columnDef The column definition * @return This property config */ - PropertyConfig column( Map columnDef ) { - if(columns.size() == 1 && firstColumnIsColumnCopy) { + PropertyConfig column(Map columnDef) { + if (columns.size() == 1 && firstColumnIsColumnCopy) { firstColumnIsColumnCopy = false ColumnConfig.configureExisting(columns[0], columnDef) - } - else { - columns.add( ColumnConfig.configureNew(columnDef) ) + } else { + columns.add(ColumnConfig.configureNew(columnDef)) } return this } @@ -155,13 +150,12 @@ class PropertyConfig extends Property { * @param columnDef The column definition * @return This property config */ - PropertyConfig column( String columnDef ) { - if(columns.size() == 1 && firstColumnIsColumnCopy) { + PropertyConfig column(String columnDef) { + if (columns.size() == 1 && firstColumnIsColumnCopy) { firstColumnIsColumnCopy = false columns[0].name = columnDef - } - else { - columns.add( ColumnConfig.configureNew(name: columnDef) ) + } else { + columns.add(ColumnConfig.configureNew(name: columnDef)) } return this } @@ -176,7 +170,7 @@ class PropertyConfig extends Property { * @return This mapping */ PropertyConfig cache(@DelegatesTo(CacheConfig) Closure cacheConfig) { - if(this.cache == null) { + if (this.cache == null) { this.cache = new CacheConfig() } CacheConfig.configureExisting(cache, cacheConfig) @@ -189,7 +183,7 @@ class PropertyConfig extends Property { * @return This mapping */ PropertyConfig cache(Map cacheConfig) { - if(this.cache == null) { + if (this.cache == null) { this.cache = new CacheConfig() } CacheConfig.configureExisting(cache, cacheConfig) @@ -220,7 +214,7 @@ class PropertyConfig extends Property { @Override void setUnique(boolean unique) { super.setUnique(unique) - if(columns.size() == 1) { + if (columns.size() == 1) { columns[0].unique = unique } } @@ -230,10 +224,10 @@ class PropertyConfig extends Property { PropertyConfig joinTable(Map joinTableDef) { DataBinder dataBinder = new DataBinder(joinTable) dataBinder.bind(new MutablePropertyValues(joinTableDef)) - if(joinTableDef.key) { + if (joinTableDef.key) { joinTable.key(joinTableDef.key.toString()) } - if(joinTableDef.column) { + if (joinTableDef.column) { joinTable.column(joinTableDef.column.toString()) } return this @@ -243,10 +237,9 @@ class PropertyConfig extends Property { * @param fetch The Hibernate {@link FetchMode} */ void setFetch(FetchMode fetch) { - if(FetchMode.JOIN.equals(fetch)) { + if (FetchMode.JOIN.equals(fetch)) { super.setFetchStrategy(FetchType.EAGER) - } - else { + } else { super.setFetchStrategy(FetchType.LAZY) } } @@ -256,7 +249,7 @@ class PropertyConfig extends Property { */ FetchMode getFetchMode() { FetchType strategy = super.getFetchStrategy() - if(strategy == null) { + if (strategy == null) { return FetchMode.DEFAULT } switch (strategy) { @@ -292,7 +285,6 @@ class PropertyConfig extends Property { return configureExisting(property, config) } - /** * Configures a new PropertyConfig instance * @@ -317,12 +309,11 @@ class PropertyConfig extends Property { ColumnConfig cc if (property.columns) { cc = property.columns[0] - } - else { + } else { cc = new ColumnConfig() property.columns.add cc } - if(config.column) { + if (config.column) { config.name = config.column } ColumnConfig.configureExisting(cc, config) @@ -349,13 +340,13 @@ class PropertyConfig extends Property { */ String getColumn() { checkHasSingleColumn() - if(columns.isEmpty()) return null + if (columns.isEmpty()) return null return columns[0].name } String getEnumType() { checkHasSingleColumn() - if(columns.isEmpty()) return "default" + if (columns.isEmpty()) return "default" return columns[0].enumType } @@ -366,7 +357,7 @@ class PropertyConfig extends Property { */ String getSqlType() { checkHasSingleColumn() - if(columns.isEmpty()) return null + if (columns.isEmpty()) return null return columns[0].sqlType } @@ -377,7 +368,7 @@ class PropertyConfig extends Property { */ String getIndexName() { checkHasSingleColumn() - if(columns.isEmpty()) return null + if (columns.isEmpty()) return null return columns[0].index?.toString() } @@ -388,11 +379,10 @@ class PropertyConfig extends Property { * column. */ boolean isUnique() { - if(columns.size()>1) { + if (columns.size() > 1) { return super.isUnique() - } - else { - if(columns.isEmpty()) return super.isUnique() + } else { + if (columns.isEmpty()) return super.isUnique() return columns[0].unique } } @@ -404,7 +394,7 @@ class PropertyConfig extends Property { */ int getLength() { checkHasSingleColumn() - if(columns.isEmpty()) return -1 + if (columns.isEmpty()) return -1 return columns[0].length } @@ -415,7 +405,7 @@ class PropertyConfig extends Property { */ int getPrecision() { checkHasSingleColumn() - if(columns.isEmpty()) return -1 + if (columns.isEmpty()) return -1 return columns[0].precision } @@ -426,7 +416,7 @@ class PropertyConfig extends Property { */ int getScale() { checkHasSingleColumn() - if(columns.isEmpty()) { + if (columns.isEmpty()) { return super.getScale() } return columns[0].scale @@ -435,10 +425,9 @@ class PropertyConfig extends Property { @Override void setScale(int scale) { checkHasSingleColumn() - if(!columns.isEmpty()) { + if (!columns.isEmpty()) { columns[0].scale = scale - } - else { + } else { super.setScale(scale) } } @@ -455,19 +444,19 @@ class PropertyConfig extends Property { @Override PropertyConfig clone() throws CloneNotSupportedException { - PropertyConfig pc = (PropertyConfig)super.clone() + PropertyConfig pc = (PropertyConfig) super.clone() pc.fetch = fetchMode - pc.indexColumn = indexColumn != null ? (PropertyConfig)indexColumn.clone() : null + pc.indexColumn = indexColumn != null ? (PropertyConfig) indexColumn.clone() : null pc.cache = cache != null ? cache.clone() : cache pc.joinTable = joinTable.clone() - if(typeParams != null) { + if (typeParams != null) { pc.typeParams = new Properties(typeParams) } List newColumns = new ArrayList(columns.size()) pc.columns = newColumns - for(c in columns) { + for (c in columns) { newColumns.add(c.clone()) } return pc diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyDefinitionDelegate.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyDefinitionDelegate.groovy index 29e538f19a7..8a23a49ee7a 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyDefinitionDelegate.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyDefinitionDelegate.groovy @@ -35,6 +35,7 @@ import org.grails.datastore.mapping.model.DatastoreConfigurationException */ @CompileStatic class PropertyDefinitionDelegate { + PropertyConfig config private int index = 0 @@ -51,11 +52,10 @@ class PropertyDefinitionDelegate { // Create a new column configuration based on the mapping for this column. ColumnConfig column - if(index < config.columns.size()) { + if (index < config.columns.size()) { // configure existing column = config.columns[0] - } - else { + } else { column = new ColumnConfig() // Append the new column configuration to the property config. config.columns << column @@ -66,7 +66,7 @@ class PropertyDefinitionDelegate { column.index = args["index"] column.unique = args["unique"] ?: false column.length = args["length"] ? args["length"] as Integer : -1 - column.precision = args["precision"] ? args["precision"] as Integer : -1 + column.precision = args["precision"] ? args["precision"] as Integer : -1 column.scale = args["scale"] ? args["scale"] as Integer : -1 index++ diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Settings.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Settings.java index cd9d5e064ba..ac3ea289b89 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Settings.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Settings.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.cfg; /** diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/SortConfig.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/SortConfig.groovy index 8a1fc87d409..37438d605da 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/SortConfig.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/SortConfig.groovy @@ -28,6 +28,7 @@ import groovy.transform.builder.SimpleStrategy @CompileStatic @Builder(builderStrategy = SimpleStrategy, prefix = '') class SortConfig { + /** * The property to sort bu */ diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Table.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Table.groovy index 70e917dbb17..36b7473c90b 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Table.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/cfg/Table.groovy @@ -33,6 +33,7 @@ import org.springframework.validation.DataBinder @Builder(builderStrategy = SimpleStrategy, prefix = '') @CompileStatic class Table { + /** * The table name */ diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/compiler/HibernateEntityTransformation.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/compiler/HibernateEntityTransformation.groovy index 572cd473c15..53eaf464ba9 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/compiler/HibernateEntityTransformation.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/compiler/HibernateEntityTransformation.groovy @@ -22,9 +22,19 @@ package org.grails.orm.hibernate.compiler import grails.gorm.dirty.checking.DirtyCheckedProperty import groovy.transform.CompilationUnitAware import groovy.transform.CompileStatic +import jakarta.persistence.Transient import org.apache.grails.common.compiler.GroovyTransformOrder import org.apache.groovy.ast.tools.AnnotatedNodeUtils -import org.codehaus.groovy.ast.* +import org.codehaus.groovy.ast.ASTNode +import org.codehaus.groovy.ast.AnnotatedNode +import org.codehaus.groovy.ast.AnnotationNode +import org.codehaus.groovy.ast.ClassCodeVisitorSupport +import org.codehaus.groovy.ast.ClassHelper +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.FieldNode +import org.codehaus.groovy.ast.InnerClassNode +import org.codehaus.groovy.ast.MethodNode +import org.codehaus.groovy.ast.Parameter import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.IfStatement import org.codehaus.groovy.ast.stmt.ReturnStatement @@ -45,10 +55,22 @@ import org.hibernate.engine.spi.ManagedEntity import org.hibernate.engine.spi.PersistentAttributeInterceptable import org.hibernate.engine.spi.PersistentAttributeInterceptor -import jakarta.persistence.Transient import java.lang.reflect.Modifier -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX +import static org.codehaus.groovy.ast.tools.GeneralUtils.equalsNullX +import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS +import static org.codehaus.groovy.ast.tools.GeneralUtils.neX +import static org.codehaus.groovy.ast.tools.GeneralUtils.param +import static org.codehaus.groovy.ast.tools.GeneralUtils.params +import static org.codehaus.groovy.ast.tools.GeneralUtils.propX +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.ternaryX +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX /** * A transformation that transforms entities that implement the {@link grails.gorm.hibernate.annotation.ManagedEntity} trait, @@ -60,6 +82,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.* @CompileStatic @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) class HibernateEntityTransformation implements ASTTransformation, CompilationUnitAware, TransformWithPriority { + private static final ClassNode MY_TYPE = new ClassNode(grails.gorm.hibernate.annotation.ManagedEntity.class); private static final Object APPLIED_MARKER = new Object(); @@ -97,12 +120,12 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni def mapWith = AstUtils.getPropertyFromHierarchy(classNode, GormProperties.MAPPING_STRATEGY) String mapWithValue = mapWith?.initialExpression?.text - if(mapWithValue != null && (mapWithValue != ('hibernate') || mapWithValue != GormProperties.DEFAULT_MAPPING_STRATEGY)) { + if (mapWithValue != null && (mapWithValue != ('hibernate') || mapWithValue != GormProperties.DEFAULT_MAPPING_STRATEGY)) { return } new GormEntityTransformation(compilationUnit: compilationUnit).visit(classNode, sourceUnit) - + ClassNode managedEntityClassNode = ClassHelper.make(ManagedEntity) ClassNode attributeInterceptableClassNode = ClassHelper.make(PersistentAttributeInterceptable) ClassNode entityEntryClassNode = ClassHelper.make(EntityEntry) @@ -120,21 +143,19 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni AnnotationNode transientAnnotationNode = new AnnotationNode(ClassHelper.make(Transient.class)) FieldNode entityEntryHolderField = classNode.addField(entryHolderFieldName, Modifier.PRIVATE | Modifier.TRANSIENT, entityEntryClassNode, null) entityEntryHolderField - .addAnnotation(transientAnnotationNode) + .addAnnotation(transientAnnotationNode) FieldNode previousManagedEntityField = classNode.addField(previousManagedEntityFieldName, Modifier.PRIVATE | Modifier.TRANSIENT, managedEntityClassNode, null) previousManagedEntityField - .addAnnotation(transientAnnotationNode) + .addAnnotation(transientAnnotationNode) FieldNode nextManagedEntityField = classNode.addField(nextManagedEntityFieldName, Modifier.PRIVATE | Modifier.TRANSIENT, managedEntityClassNode, null) nextManagedEntityField - .addAnnotation(transientAnnotationNode) + .addAnnotation(transientAnnotationNode) FieldNode interceptorField = classNode.addField(interceptorFieldName, Modifier.PRIVATE | Modifier.TRANSIENT, persistentAttributeInterceptorClassNode, null) interceptorField - .addAnnotation(transientAnnotationNode) - - + .addAnnotation(transientAnnotationNode) // add method: PersistentAttributeInterceptor $$_hibernate_getInterceptor() def getInterceptorMethod = new MethodNode( @@ -157,7 +178,7 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni ClassHelper.VOID_TYPE, params(p1), null, - assignS( varX(interceptorField), varX(p1) ) + assignS(varX(interceptorField), varX(p1)) ) classNode.addMethod(setInterceptorMethod) AnnotatedNodeUtils.markAsGenerated(classNode, setInterceptorMethod) @@ -176,7 +197,6 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni AnnotatedNodeUtils.markAsGenerated(classNode, getEntityInstanceMethod) staticCompilationVisitor.visitMethod(getEntityInstanceMethod) - // add method: EntityEntry $$_hibernate_getEntityEntry() def getEntityEntryMethod = new MethodNode( '$$_hibernate_getEntityEntry', @@ -198,7 +218,7 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni ClassHelper.VOID_TYPE, params(entityEntryParam), null, - assignS( varX(entityEntryHolderField), varX(entityEntryParam) ) + assignS(varX(entityEntryHolderField), varX(entityEntryParam)) ) classNode.addMethod(setEntityEntryMethod) AnnotatedNodeUtils.markAsGenerated(classNode, setEntityEntryMethod) @@ -238,7 +258,7 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni ClassHelper.VOID_TYPE, params(previousParam), null, - assignS( varX(previousManagedEntityField), varX(previousParam) ) + assignS(varX(previousManagedEntityField), varX(previousParam)) ) classNode.addMethod(setPreviousManagedEntityMethod) AnnotatedNodeUtils.markAsGenerated(classNode, setPreviousManagedEntityMethod) @@ -252,17 +272,18 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni ClassHelper.VOID_TYPE, params(nextParam), null, - assignS( varX(nextManagedEntityField), varX(nextParam) ) + assignS(varX(nextManagedEntityField), varX(nextParam)) ) classNode.addMethod(setNextManagedEntityMethod) AnnotatedNodeUtils.markAsGenerated(classNode, setNextManagedEntityMethod) staticCompilationVisitor.visitMethod(setNextManagedEntityMethod) List allMethods = classNode.getMethods() - for(MethodNode methodNode in allMethods) { - if(methodNode.getAnnotations(ClassHelper.make(DirtyCheckedProperty))) { - if(AstUtils.isGetter(methodNode)) { + for (MethodNode methodNode in allMethods) { + if (methodNode.getAnnotations(ClassHelper.make(DirtyCheckedProperty))) { + if (AstUtils.isGetter(methodNode)) { def codeVisitor = new ClassCodeVisitorSupport() { + @Override protected SourceUnit getSourceUnit() { return sourceUnit @@ -270,7 +291,7 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni @Override void visitReturnStatement(ReturnStatement statement) { - ReturnStatement rs = (ReturnStatement)statement + ReturnStatement rs = (ReturnStatement) statement def i = varX(interceptorField) def propertyName = NameUtils.getPropertyNameForGetterOrSetter(methodNode.getName()) @@ -289,24 +310,23 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni } } codeVisitor.visitMethod(methodNode) - } - else { + } else { Statement code = methodNode.code - if(code instanceof BlockStatement) { - BlockStatement bs = (BlockStatement)code + if (code instanceof BlockStatement) { + BlockStatement bs = (BlockStatement) code Parameter parameter = methodNode.getParameters()[0] ClassNode parameterType = parameter.type final boolean isPrimitive = ClassHelper.isPrimitiveType(parameterType) String writeMethodName = isPrimitive ? "write${NameUtils.capitalize(parameterType.getName())}" : "writeObject" String propertyName = NameUtils.getPropertyNameForGetterOrSetter(methodNode.getName()) def interceptorFieldExpr = fieldX(interceptorField) - def ifStatement = ifS( neX(interceptorFieldExpr, constX(null) ), - assignS( - varX(parameter), - callX( interceptorFieldExpr, writeMethodName, args( varX("this"), constX(propertyName), propX(varX("this"), propertyName), varX(parameter))) - ) + def ifStatement = ifS(neX(interceptorFieldExpr, constX(null)), + assignS( + varX(parameter), + callX(interceptorFieldExpr, writeMethodName, args(varX("this"), constX(propertyName), propX(varX("this"), propertyName), varX(parameter))) + ) ) - staticCompilationVisitor.visitIfElse((IfStatement)ifStatement) + staticCompilationVisitor.visitIfElse((IfStatement) ifStatement) bs.getStatements().add(0, ifStatement) } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/AbstractHibernateConnectionSourceFactory.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/AbstractHibernateConnectionSourceFactory.java index 3aab65a879b..4999b149e4d 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/AbstractHibernateConnectionSourceFactory.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/AbstractHibernateConnectionSourceFactory.java @@ -16,15 +16,16 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.connections; import org.grails.datastore.gorm.jdbc.connections.CachedDataSourceConnectionSourceFactory; -import org.grails.datastore.mapping.core.connections.*; -import org.grails.orm.hibernate.cfg.Settings; import org.grails.datastore.gorm.jdbc.connections.DataSourceConnectionSourceFactory; import org.grails.datastore.gorm.jdbc.connections.DataSourceSettings; import org.grails.datastore.gorm.jdbc.connections.DataSourceSettingsBuilder; +import org.grails.datastore.mapping.core.connections.AbstractConnectionSourceFactory; +import org.grails.datastore.mapping.core.connections.ConnectionSource; +import org.grails.datastore.mapping.core.connections.ConnectionSourceSettings; +import org.grails.orm.hibernate.cfg.Settings; import org.hibernate.SessionFactory; import org.springframework.core.env.PropertyResolver; @@ -58,7 +59,6 @@ public ConnectionSource creat return create(name, dataSourceConnectionSource, settings); } - @Override public Serializable getConnectionSourcesConfigurationKey() { return Settings.SETTING_DATASOURCES; @@ -72,36 +72,34 @@ public HibernateConnectionSourceSettings bu /** * Creates a ConnectionSource for the given DataSource * - * @param name The name + * @param name The name * @param dataSourceConnectionSource The data source connection source - * @param settings The settings + * @param settings The settings * @return The ConnectionSource */ - public abstract ConnectionSource create(String name, ConnectionSource dataSourceConnectionSource, HibernateConnectionSourceSettings settings); + public abstract ConnectionSource create(String name, ConnectionSource dataSourceConnectionSource, HibernateConnectionSourceSettings settings); protected HibernateConnectionSourceSettings buildSettings(String name, PropertyResolver configuration, F fallbackSettings, boolean isDefaultDataSource) { HibernateConnectionSourceSettingsBuilder builder; HibernateConnectionSourceSettings settings; - if(isDefaultDataSource) { + if (isDefaultDataSource) { String qualified = Settings.SETTING_DATASOURCES + '.' + Settings.SETTING_DATASOURCE; builder = new HibernateConnectionSourceSettingsBuilder(configuration, "", fallbackSettings); Map config = configuration.getProperty(qualified, Map.class, Collections.emptyMap()); settings = builder.build(); - if(!config.isEmpty()) { + if (!config.isEmpty()) { DataSourceSettings dsfallbackSettings = null; - if(fallbackSettings instanceof HibernateConnectionSourceSettings) { - dsfallbackSettings = ((HibernateConnectionSourceSettings)fallbackSettings).getDataSource(); - } - else if(fallbackSettings instanceof DataSourceSettings) { + if (fallbackSettings instanceof HibernateConnectionSourceSettings) { + dsfallbackSettings = ((HibernateConnectionSourceSettings) fallbackSettings).getDataSource(); + } else if (fallbackSettings instanceof DataSourceSettings) { dsfallbackSettings = (DataSourceSettings) fallbackSettings; } DataSourceSettingsBuilder dataSourceSettingsBuilder = new DataSourceSettingsBuilder(configuration, qualified, dsfallbackSettings); DataSourceSettings dataSourceSettings = dataSourceSettingsBuilder.build(); settings.setDataSource(dataSourceSettings); } - } - else { + } else { String prefix = Settings.SETTING_DATASOURCES + "." + name; settings = buildSettingsWithPrefix(configuration, fallbackSettings, prefix); } @@ -114,22 +112,20 @@ private HibernateConnectionSourceSettings b builder = new HibernateConnectionSourceSettingsBuilder(configuration, prefix, fallbackSettings); DataSourceSettings dsfallbackSettings = null; - if(fallbackSettings instanceof HibernateConnectionSourceSettings) { - dsfallbackSettings = ((HibernateConnectionSourceSettings)fallbackSettings).getDataSource(); - } - else if(fallbackSettings instanceof DataSourceSettings) { + if (fallbackSettings instanceof HibernateConnectionSourceSettings) { + dsfallbackSettings = ((HibernateConnectionSourceSettings) fallbackSettings).getDataSource(); + } else if (fallbackSettings instanceof DataSourceSettings) { dsfallbackSettings = (DataSourceSettings) fallbackSettings; } settings = builder.build(); - if(prefix.length() == 0) { + if (prefix.length() == 0) { // if the prefix is zero length then this is a datasource added at runtime using ConnectionSources.addConnectionSource DataSourceSettingsBuilder dataSourceSettingsBuilder = new DataSourceSettingsBuilder(configuration, prefix, dsfallbackSettings); DataSourceSettings dataSourceSettings = dataSourceSettingsBuilder.build(); settings.setDataSource(dataSourceSettings); - } - else { - if(configuration.getProperty(prefix + ".dataSource", Map.class, Collections.emptyMap()).isEmpty()) { + } else { + if (configuration.getProperty(prefix + ".dataSource", Map.class, Collections.emptyMap()).isEmpty()) { DataSourceSettingsBuilder dataSourceSettingsBuilder = new DataSourceSettingsBuilder(configuration, prefix, dsfallbackSettings); DataSourceSettings dataSourceSettings = dataSourceSettingsBuilder.build(); settings.setDataSource(dataSourceSettings); diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSource.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSource.java index 72da82de170..306318a33ad 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSource.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSource.java @@ -16,12 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.connections; +import org.grails.datastore.gorm.jdbc.connections.DataSourceSettings; import org.grails.datastore.mapping.core.connections.ConnectionSource; import org.grails.datastore.mapping.core.connections.DefaultConnectionSource; -import org.grails.datastore.gorm.jdbc.connections.DataSourceSettings; import org.hibernate.SessionFactory; import javax.sql.DataSource; @@ -36,7 +35,7 @@ */ public class HibernateConnectionSource extends DefaultConnectionSource { - protected final ConnectionSource dataSource; + protected final ConnectionSource dataSource; public HibernateConnectionSource(String name, SessionFactory sessionFactory, ConnectionSource dataSourceConnectionSource, HibernateConnectionSourceSettings settings) { super(name, sessionFactory, settings); @@ -50,7 +49,7 @@ public void close() throws IOException { SessionFactory sessionFactory = getSource(); sessionFactory.close(); } finally { - if(dataSource != null) { + if (dataSource != null) { dataSource.close(); } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactory.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactory.java index 155ac461bce..65ead411059 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactory.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactory.java @@ -16,9 +16,10 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.connections; +import org.grails.datastore.gorm.jdbc.connections.DataSourceSettings; +import org.grails.datastore.gorm.jdbc.connections.SpringDataSourceConnectionSourceFactory; import org.grails.datastore.gorm.validation.jakarta.JakartaValidatorRegistry; import org.grails.datastore.mapping.core.connections.ConnectionSource; import org.grails.datastore.mapping.core.exceptions.ConfigurationException; @@ -28,7 +29,6 @@ import org.grails.orm.hibernate.cfg.GrailsDomainBinder; import org.grails.orm.hibernate.cfg.HibernateMappingContext; import org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration; -import org.grails.datastore.gorm.jdbc.connections.*; import org.grails.orm.hibernate.support.AbstractClosureEventTriggeringInterceptor; import org.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor; import org.hibernate.Interceptor; @@ -66,13 +66,13 @@ public class HibernateConnectionSourceFactory extends AbstractHibernateConnectio protected HibernateMappingContext mappingContext; protected Class[] persistentClasses = new Class[0]; - private ApplicationContext applicationContext; protected HibernateEventListeners hibernateEventListeners; protected Interceptor interceptor; protected MetadataContributor metadataContributor; protected MessageSource messageSource = new StaticMessageSource(); + private ApplicationContext applicationContext; - public HibernateConnectionSourceFactory(Class...classes) { + public HibernateConnectionSourceFactory(Class... classes) { this.persistentClasses = classes; } @@ -109,7 +109,7 @@ public ConnectionSource creat public HibernateMappingContextConfiguration buildConfiguration(String name, ConnectionSource dataSourceConnectionSource, HibernateConnectionSourceSettings settings) { boolean isDefault = ConnectionSource.DEFAULT.equals(name); - if(mappingContext == null) { + if (mappingContext == null) { mappingContext = new HibernateMappingContext(settings, applicationContext, persistentClasses); } @@ -117,28 +117,25 @@ public HibernateMappingContextConfiguration buildConfiguration(String name, Conn Class configClass = hibernateSettings.getConfigClass(); HibernateMappingContextConfiguration configuration; - if(configClass != null) { - if( !HibernateMappingContextConfiguration.class.isAssignableFrom(configClass) ) { + if (configClass != null) { + if (!HibernateMappingContextConfiguration.class.isAssignableFrom(configClass)) { throw new ConfigurationException("The configClass setting must be a subclass for [HibernateMappingContextConfiguration]"); - } - else { + } else { configuration = (HibernateMappingContextConfiguration) BeanUtils.instantiateClass(configClass); } - } - else { + } else { configuration = new HibernateMappingContextConfiguration(); } - if(JakartaValidatorRegistry.isAvailable() && messageSource != null) { - ValidatorRegistry registry = new JakartaValidatorRegistry(mappingContext,dataSourceConnectionSource.getSettings(), messageSource ); + if (JakartaValidatorRegistry.isAvailable() && messageSource != null) { + ValidatorRegistry registry = new JakartaValidatorRegistry(mappingContext, dataSourceConnectionSource.getSettings(), messageSource); mappingContext.setValidatorRegistry(registry); configuration.getProperties().put("jakarta.persistence.validation.factory", registry); } - if(applicationContext != null && applicationContext.containsBean(dataSourceConnectionSource.getName())) { + if (applicationContext != null && applicationContext.containsBean(dataSourceConnectionSource.getName())) { configuration.setApplicationContext(this.applicationContext); - } - else { + } else { configuration.setDataSourceConnectionSource(dataSourceConnectionSource); } @@ -234,10 +231,9 @@ public HibernateMappingContextConfiguration buildConfiguration(String name, Conn AbstractClosureEventTriggeringInterceptor eventTriggeringInterceptor; - if(closureEventTriggeringInterceptorClass == null) { + if (closureEventTriggeringInterceptorClass == null) { eventTriggeringInterceptor = new ClosureEventTriggeringInterceptor(); - } - else { + } else { eventTriggeringInterceptor = BeanUtils.instantiateClass(closureEventTriggeringInterceptorClass); } @@ -245,7 +241,7 @@ public HibernateMappingContextConfiguration buildConfiguration(String name, Conn try { Class namingStrategy = hibernateSettings.getNaming_strategy(); - if(namingStrategy != null) { + if (namingStrategy != null) { GrailsDomainBinder.configureNamingStrategy(name, namingStrategy); } } catch (Throwable e) { @@ -254,7 +250,7 @@ public HibernateMappingContextConfiguration buildConfiguration(String name, Conn configuration.setEventListeners(hibernateSettings.toHibernateEventListeners(eventTriggeringInterceptor)); HibernateEventListeners hibernateEventListeners = hibernateSettings.getHibernateEventListeners(); - configuration.setHibernateEventListeners(this.hibernateEventListeners != null ? this.hibernateEventListeners : hibernateEventListeners); + configuration.setHibernateEventListeners(this.hibernateEventListeners != null ? this.hibernateEventListeners : hibernateEventListeners); configuration.setHibernateMappingContext(mappingContext); configuration.setDataSourceName(name); configuration.setSessionFactoryBeanName(isDefault ? "sessionFactory" : "sessionFactory_" + name); @@ -265,10 +261,10 @@ public HibernateMappingContextConfiguration buildConfiguration(String name, Conn @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - if(applicationContext != null) { + if (applicationContext != null) { this.applicationContext = applicationContext; this.messageSource = applicationContext; - if (!GrailsVersion.isAtLeastMajorMinor(3,3)) { + if (!GrailsVersion.isAtLeastMajorMinor(3, 3)) { SpringDataSourceConnectionSourceFactory springDataSourceConnectionSourceFactory = new SpringDataSourceConnectionSourceFactory(); springDataSourceConnectionSourceFactory.setApplicationContext(applicationContext); this.dataSourceConnectionSourceFactory = springDataSourceConnectionSourceFactory; diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettings.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettings.groovy index 89f198bfaeb..d21d003b670 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettings.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettings.groovy @@ -23,9 +23,9 @@ import groovy.transform.AutoClone import groovy.transform.CompileStatic import groovy.transform.builder.Builder import groovy.transform.builder.SimpleStrategy +import org.grails.datastore.gorm.jdbc.connections.DataSourceSettings import org.grails.datastore.mapping.core.connections.ConnectionSourceSettings import org.grails.orm.hibernate.HibernateEventListeners -import org.grails.datastore.gorm.jdbc.connections.DataSourceSettings import org.grails.orm.hibernate.dirty.GrailsEntityDirtinessStrategy import org.grails.orm.hibernate.support.AbstractClosureEventTriggeringInterceptor import org.hibernate.CustomEntityDirtinessStrategy @@ -66,12 +66,11 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings { */ Properties toProperties() { Properties properties = new Properties() - properties.putAll( dataSource.toHibernateProperties() ) - properties.putAll( hibernate.toProperties() ) + properties.putAll(dataSource.toHibernateProperties()) + properties.putAll(hibernate.toProperties()) return properties } - @Builder(builderStrategy = SimpleStrategy, prefix = '') @AutoClone static class HibernateSettings extends LinkedHashMap { @@ -99,7 +98,6 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings { */ FlushSettings flush = new FlushSettings() - /** * The configuration class */ @@ -206,19 +204,19 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings { @CompileStatic Map toHibernateEventListeners(AbstractClosureEventTriggeringInterceptor eventTriggeringInterceptor) { - if(eventTriggeringInterceptor != null) { + if (eventTriggeringInterceptor != null) { return [ - 'save': eventTriggeringInterceptor, - 'save-update': eventTriggeringInterceptor, - 'pre-load': eventTriggeringInterceptor, - 'post-load': eventTriggeringInterceptor, - 'pre-insert': eventTriggeringInterceptor, - 'post-insert': eventTriggeringInterceptor, - 'pre-update': eventTriggeringInterceptor, - 'post-update': eventTriggeringInterceptor, - 'pre-delete': eventTriggeringInterceptor, - 'post-delete': eventTriggeringInterceptor - ] as Map + 'save' : eventTriggeringInterceptor, + 'save-update': eventTriggeringInterceptor, + 'pre-load' : eventTriggeringInterceptor, + 'post-load' : eventTriggeringInterceptor, + 'pre-insert' : eventTriggeringInterceptor, + 'post-insert': eventTriggeringInterceptor, + 'pre-update' : eventTriggeringInterceptor, + 'post-update': eventTriggeringInterceptor, + 'pre-delete' : eventTriggeringInterceptor, + 'post-delete': eventTriggeringInterceptor + ] as Map } return Collections.emptyMap() } @@ -231,10 +229,10 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings { @CompileStatic Properties toProperties() { Properties props = new Properties() - if(naming_strategy != null) { + if (naming_strategy != null) { props.put("hibernate.naming_strategy".toString(), naming_strategy.name) } - if(configClass != null) { + if (configClass != null) { props.put("hibernate.config_class".toString(), configClass.name) } props.put('hibernate.use_query_cache', String.valueOf(cache.queries)) @@ -261,8 +259,8 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings { } String prefix = "hibernate" - props.putAll( additionalProperties ) - populateProperties(props, this,prefix) + props.putAll(additionalProperties) + populateProperties(props, this, prefix) return props } @@ -270,10 +268,9 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings { protected void populateProperties(Properties props, Map current, String prefix) { for (key in current.keySet()) { def value = current.get(key) - if(value instanceof Map) { - populateProperties(props, (Map)value, "${prefix}.$key") - } - else { + if (value instanceof Map) { + populateProperties(props, (Map) value, "${prefix}.$key") + } else { props.put("$prefix.$key".toString(), value) } } @@ -302,6 +299,7 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings { * @see org.hibernate.FlushMode */ static enum FlushMode { + MANUAL(0), COMMIT(5), AUTO(10), @@ -336,6 +334,5 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings { boolean enabled = true } - } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsBuilder.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsBuilder.groovy index 74b33bca46b..1624075101e 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsBuilder.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsBuilder.groovy @@ -32,31 +32,32 @@ import org.springframework.core.env.PropertyResolver */ @CompileStatic class HibernateConnectionSourceSettingsBuilder extends ConfigurationBuilder { + HibernateConnectionSourceSettings fallBackHibernateSettings HibernateConnectionSourceSettingsBuilder(PropertyResolver propertyResolver, String configurationPrefix = "", ConnectionSourceSettings fallBackConfiguration = null) { super(propertyResolver, configurationPrefix, fallBackConfiguration) - if(fallBackConfiguration instanceof HibernateConnectionSourceSettings) { - fallBackHibernateSettings = (HibernateConnectionSourceSettings)fallBackConfiguration + if (fallBackConfiguration instanceof HibernateConnectionSourceSettings) { + fallBackHibernateSettings = (HibernateConnectionSourceSettings) fallBackConfiguration } } @Override protected HibernateConnectionSourceSettings createBuilder() { def settings = new HibernateConnectionSourceSettings() - if(fallBackHibernateSettings != null) { - settings.getHibernate().putAll( fallBackHibernateSettings.getHibernate() ) + if (fallBackHibernateSettings != null) { + settings.getHibernate().putAll(fallBackHibernateSettings.getHibernate()) } return settings } @Override HibernateConnectionSourceSettings build() { - HibernateConnectionSourceSettings finalSettings = (HibernateConnectionSourceSettings)super.build() + HibernateConnectionSourceSettings finalSettings = (HibernateConnectionSourceSettings) super.build() Map orgHibernateProperties = propertyResolver.getProperty("org.hibernate", Map.class, Collections.emptyMap()) Properties additionalProperties = finalSettings.getHibernate().getAdditionalProperties() - for(key in orgHibernateProperties.keySet()) { + for (key in orgHibernateProperties.keySet()) { additionalProperties.put("org.hibernate.$key".toString(), orgHibernateProperties.get(key)) } return finalSettings diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/datasource/MultipleDataSourceSupport.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/datasource/MultipleDataSourceSupport.java index 71823e05bf3..c0bae0c5621 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/datasource/MultipleDataSourceSupport.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/datasource/MultipleDataSourceSupport.java @@ -30,6 +30,7 @@ * @since 5.0.2 */ public class MultipleDataSourceSupport { + /** * If a domain class uses more than one datasource, we need to know which one to use * when calling a method without a namespace qualifier. diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/dirty/GrailsEntityDirtinessStrategy.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/dirty/GrailsEntityDirtinessStrategy.groovy index 7d938fb513f..2ca0169e1c4 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/dirty/GrailsEntityDirtinessStrategy.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/dirty/GrailsEntityDirtinessStrategy.groovy @@ -93,47 +93,42 @@ class GrailsEntityDirtinessStrategy implements CustomEntityDirtinessStrategy { @Override void findDirty(Object entity, EntityPersister persister, Session session, CustomEntityDirtinessStrategy.DirtyCheckContext dirtyCheckContext) { Status status = getStatus(session, entity) - if(entity instanceof DirtyCheckable) { + if (entity instanceof DirtyCheckable) { dirtyCheckContext.doDirtyChecking( new CustomEntityDirtinessStrategy.AttributeChecker() { + @Override boolean isDirty(CustomEntityDirtinessStrategy.AttributeInformation attributeInformation) { String propertyName = attributeInformation.name - if(status != null) { - if(status == Status.MANAGED) { + if (status != null) { + if (status == Status.MANAGED) { // perform dirty check DirtyCheckable dirtyCheckable = cast(entity) - if(GormProperties.LAST_UPDATED == propertyName) { + if (GormProperties.LAST_UPDATED == propertyName) { return dirtyCheckable.hasChanged() - } - else { - if(dirtyCheckable.hasChanged(propertyName)) { + } else { + if (dirtyCheckable.hasChanged(propertyName)) { return true - } - else { + } else { PersistentEntity gormEntity = GormEnhancer.findEntity(Hibernate.getClass(entity)) PersistentProperty prop = gormEntity.getPropertyByName(attributeInformation.name) - if(prop instanceof Embedded) { + if (prop instanceof Embedded) { def val = prop.reader.read(entity) - if( val instanceof DirtyCheckable ) { - return ((DirtyCheckable)val).hasChanged() - } - else { + if (val instanceof DirtyCheckable) { + return ((DirtyCheckable) val).hasChanged() + } else { return false } - } - else { + } else { return false } } } - } - else { + } else { // either deleted or in a state that cannot be regarded as dirty return false } - } - else { + } else { // a new object not within the session return true } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/event/listener/AbstractHibernateEventListener.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/event/listener/AbstractHibernateEventListener.java index d08b0fc8788..e2f979f530e 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/event/listener/AbstractHibernateEventListener.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/event/listener/AbstractHibernateEventListener.java @@ -53,8 +53,9 @@ protected AbstractHibernateEventListener(AbstractHibernateDatastore datastore) { /** * {@inheritDoc} + * * @see org.springframework.context.event.SmartApplicationListener#supportsEventType( - * java.lang.Class) + *java.lang.Class) */ public boolean supportsEventType(Class eventType) { return AbstractPersistenceEvent.class.isAssignableFrom(eventType); diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/event/listener/HibernateEventListener.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/event/listener/HibernateEventListener.java index 9b9b364b161..22d463e79cc 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/event/listener/HibernateEventListener.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/event/listener/HibernateEventListener.java @@ -30,7 +30,16 @@ import org.hibernate.Hibernate; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.event.spi.*; +import org.hibernate.event.spi.EventSource; +import org.hibernate.event.spi.PostDeleteEvent; +import org.hibernate.event.spi.PostInsertEvent; +import org.hibernate.event.spi.PostLoadEvent; +import org.hibernate.event.spi.PostUpdateEvent; +import org.hibernate.event.spi.PreDeleteEvent; +import org.hibernate.event.spi.PreInsertEvent; +import org.hibernate.event.spi.PreLoadEvent; +import org.hibernate.event.spi.PreUpdateEvent; +import org.hibernate.event.spi.SaveOrUpdateEvent; import org.springframework.context.ApplicationEvent; import java.util.concurrent.ConcurrentHashMap; @@ -49,7 +58,6 @@ public class HibernateEventListener extends AbstractHibernateEventListener { protected transient ConcurrentMap>, ClosureEventListener> eventListeners = new ConcurrentHashMap<>(); - public HibernateEventListener(AbstractHibernateDatastore datastore) { super(datastore); } @@ -58,40 +66,40 @@ public HibernateEventListener(AbstractHibernateDatastore datastore) { protected void onPersistenceEvent(final AbstractPersistenceEvent event) { switch (event.getEventType()) { case PreInsert: - if (onPreInsert((PreInsertEvent)event.getNativeEvent())) { + if (onPreInsert((PreInsertEvent) event.getNativeEvent())) { event.cancel(); } break; case PostInsert: - onPostInsert((PostInsertEvent)event.getNativeEvent()); + onPostInsert((PostInsertEvent) event.getNativeEvent()); break; case PreUpdate: - if (onPreUpdate((PreUpdateEvent)event.getNativeEvent())) { + if (onPreUpdate((PreUpdateEvent) event.getNativeEvent())) { event.cancel(); } break; case PostUpdate: - onPostUpdate((PostUpdateEvent)event.getNativeEvent()); + onPostUpdate((PostUpdateEvent) event.getNativeEvent()); break; case PreDelete: - if (onPreDelete((PreDeleteEvent)event.getNativeEvent())) { + if (onPreDelete((PreDeleteEvent) event.getNativeEvent())) { event.cancel(); } break; case PostDelete: - onPostDelete((PostDeleteEvent)event.getNativeEvent()); + onPostDelete((PostDeleteEvent) event.getNativeEvent()); break; case PreLoad: - onPreLoad((PreLoadEvent)event.getNativeEvent()); + onPreLoad((PreLoadEvent) event.getNativeEvent()); break; case PostLoad: - onPostLoad((PostLoadEvent)event.getNativeEvent()); + onPostLoad((PostLoadEvent) event.getNativeEvent()); break; case SaveOrUpdate: - onSaveOrUpdate((SaveOrUpdateEvent)event.getNativeEvent()); + onSaveOrUpdate((SaveOrUpdateEvent) event.getNativeEvent()); break; case Validation: - onValidate((ValidationEvent)event); + onValidate((ValidationEvent) event); break; default: throw new IllegalStateException("Unexpected EventType: " + event.getEventType()); @@ -100,7 +108,7 @@ protected void onPersistenceEvent(final AbstractPersistenceEvent event) { public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException { Object entity = event.getObject(); - if(entity != null) { + if (entity != null) { ClosureEventListener eventListener; EventSource session = event.getSession(); eventListener = findEventListener(entity, (SessionFactoryImplementor) session.getSessionFactory()); @@ -181,7 +189,9 @@ public void onValidate(ValidationEvent event) { } protected ClosureEventListener findEventListener(Object entity, SessionFactoryImplementor factory) { - if (entity == null) return null; + if (entity == null) { + return null; + } Class clazz = Hibernate.getClass(entity); SoftKey> key = new SoftKey>(clazz); @@ -192,7 +202,7 @@ protected ClosureEventListener findEventListener(Object entity, SessionFactoryIm Boolean shouldTrigger = cachedShouldTrigger.get(key); if (shouldTrigger == null || shouldTrigger) { - synchronized(cachedShouldTrigger) { + synchronized (cachedShouldTrigger) { eventListener = eventListeners.get(key); if (eventListener == null) { AbstractHibernateDatastore datastore = getDatastore(); @@ -215,6 +225,7 @@ protected ClosureEventListener findEventListener(Object entity, SessionFactoryIm /** * {@inheritDoc} + * * @see org.springframework.context.event.SmartApplicationListener#supportsEventType(java.lang.Class) */ public boolean supportsEventType(Class eventType) { diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/CouldNotDetermineHibernateDialectException.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/CouldNotDetermineHibernateDialectException.java index 5333dd30f5b..814e41d9b5c 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/CouldNotDetermineHibernateDialectException.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/CouldNotDetermineHibernateDialectException.java @@ -34,5 +34,4 @@ public CouldNotDetermineHibernateDialectException(String message) { public CouldNotDetermineHibernateDialectException(String message, Throwable cause) { super(message, cause); } - -} \ No newline at end of file +} diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/GrailsHibernateConfigurationException.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/GrailsHibernateConfigurationException.java index 44cccf611ec..95b514074ae 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/GrailsHibernateConfigurationException.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/GrailsHibernateConfigurationException.java @@ -24,7 +24,7 @@ * @author Graeme Rocher * @since 1.1 */ -public class GrailsHibernateConfigurationException extends GrailsHibernateException{ +public class GrailsHibernateConfigurationException extends GrailsHibernateException { private static final long serialVersionUID = 5212907914995954558L; diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/GrailsHibernateException.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/GrailsHibernateException.java index 1febb6e6750..8139d47142e 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/GrailsHibernateException.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/GrailsHibernateException.java @@ -30,7 +30,6 @@ public abstract class GrailsHibernateException extends DatastoreException { private static final long serialVersionUID = -6019220941440364736L; - public GrailsHibernateException(String message) { super(message); } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/GrailsQueryException.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/GrailsQueryException.java index 71cf1ff86c4..ca576919f81 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/GrailsQueryException.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/exceptions/GrailsQueryException.java @@ -30,7 +30,6 @@ public class GrailsQueryException extends DatastoreException { private static final long serialVersionUID = 775603608315415077L; - public GrailsQueryException(String message, Throwable cause) { super(message, cause); } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/multitenancy/MultiTenantEventListener.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/multitenancy/MultiTenantEventListener.java index c36e88fa54f..be8da7682af 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/multitenancy/MultiTenantEventListener.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/multitenancy/MultiTenantEventListener.java @@ -16,21 +16,23 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.multitenancy; import grails.gorm.multitenancy.Tenants; import org.grails.datastore.gorm.GormEnhancer; import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.connections.ConnectionSource; -import org.grails.datastore.mapping.engine.event.*; +import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; +import org.grails.datastore.mapping.engine.event.PersistenceEventListener; +import org.grails.datastore.mapping.engine.event.PreInsertEvent; +import org.grails.datastore.mapping.engine.event.PreUpdateEvent; +import org.grails.datastore.mapping.engine.event.ValidationEvent; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.types.TenantId; import org.grails.datastore.mapping.multitenancy.MultiTenantCapableDatastore; import org.grails.datastore.mapping.multitenancy.exceptions.TenantException; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.event.PreQueryEvent; -import org.grails.datastore.mapping.reflect.EntityReflector; import org.grails.orm.hibernate.AbstractHibernateDatastore; import org.springframework.context.ApplicationEvent; @@ -43,6 +45,7 @@ * @since 6.0 */ public class MultiTenantEventListener implements PersistenceEventListener { + @Override public boolean supportsEventType(Class eventType) { return org.grails.datastore.gorm.multitenancy.MultiTenantEventListener.SUPPORTED_EVENTS.contains(eventType); @@ -55,47 +58,45 @@ public boolean supportsSourceType(Class sourceType) { @Override public void onApplicationEvent(ApplicationEvent event) { - if(supportsEventType(event.getClass())) { + if (supportsEventType(event.getClass())) { Datastore hibernateDatastore = (Datastore) event.getSource(); - if(event instanceof PreQueryEvent) { + if (event instanceof PreQueryEvent) { PreQueryEvent preQueryEvent = (PreQueryEvent) event; Query query = preQueryEvent.getQuery(); PersistentEntity entity = query.getEntity(); - if(entity.isMultiTenant()) { - if(hibernateDatastore == null) { + if (entity.isMultiTenant()) { + if (hibernateDatastore == null) { hibernateDatastore = GormEnhancer.findDatastore(entity.getJavaClass()); } - if(supportsSourceType(hibernateDatastore.getClass())) { - ((AbstractHibernateDatastore)hibernateDatastore).enableMultiTenancyFilter(); + if (supportsSourceType(hibernateDatastore.getClass())) { + ((AbstractHibernateDatastore) hibernateDatastore).enableMultiTenancyFilter(); } } - } - else if((event instanceof ValidationEvent) || (event instanceof PreInsertEvent) || (event instanceof PreUpdateEvent)) { + } else if ((event instanceof ValidationEvent) || (event instanceof PreInsertEvent) || (event instanceof PreUpdateEvent)) { AbstractPersistenceEvent preInsertEvent = (AbstractPersistenceEvent) event; PersistentEntity entity = preInsertEvent.getEntity(); - if(entity.isMultiTenant()) { + if (entity.isMultiTenant()) { TenantId tenantId = entity.getTenantId(); - if(hibernateDatastore == null) { + if (hibernateDatastore == null) { hibernateDatastore = GormEnhancer.findDatastore(entity.getJavaClass()); } - if(supportsSourceType(hibernateDatastore.getClass())) { + if (supportsSourceType(hibernateDatastore.getClass())) { Serializable currentId; - if(hibernateDatastore instanceof MultiTenantCapableDatastore) { + if (hibernateDatastore instanceof MultiTenantCapableDatastore) { currentId = Tenants.currentId((MultiTenantCapableDatastore) hibernateDatastore); - } - else { + } else { currentId = Tenants.currentId(hibernateDatastore.getClass()); } - if(currentId != null) { + if (currentId != null) { try { - if(currentId == ConnectionSource.DEFAULT) { + if (currentId == ConnectionSource.DEFAULT) { currentId = (Serializable) preInsertEvent.getEntityAccess().getProperty(tenantId.getName()); } preInsertEvent.getEntityAccess().setProperty(tenantId.getName(), currentId); } catch (Exception e) { - throw new TenantException("Could not assigned tenant id ["+currentId+"] to property ["+tenantId+"], probably due to a type mismatch. You should return a type from the tenant resolver that matches the property type of the tenant id!: " + e.getMessage(), e); + throw new TenantException("Could not assigned tenant id [" + currentId + "] to property [" + tenantId + "], probably due to a type mismatch. You should return a type from the tenant resolver that matches the property type of the tenant id!: " + e.getMessage(), e); } } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java index 43dd52c9852..aa786b5e6f8 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java @@ -18,11 +18,8 @@ */ package org.grails.orm.hibernate.proxy; -import java.io.Serializable; -import org.grails.datastore.gorm.GormEnhancer; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.engine.AssociationQueryExecutor; -import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.proxy.ProxyFactory; import org.grails.datastore.mapping.proxy.ProxyHandler; import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; @@ -31,6 +28,8 @@ import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxyHelper; +import java.io.Serializable; + /** * Implementation of the ProxyHandler interface for Hibernate using org.hibernate.Hibernate * and HibernateProxyHelper where possible. @@ -58,8 +57,7 @@ public boolean isInitialized(Object obj, String associationName) { try { Object proxy = ClassPropertyFetcher.getInstancePropertyValue(obj, associationName); return isInitialized(proxy); - } - catch (RuntimeException e) { + } catch (RuntimeException e) { return false; } } @@ -68,6 +66,7 @@ public boolean isInitialized(Object obj, String associationName) { * Unproxies a HibernateProxy. If the proxy is uninitialized, it automatically triggers an initialization. * In case the supplied object is null or not a proxy, the object will be returned as-is. * {@inheritDoc} + * * @see Hibernate#unproxy */ @Override @@ -81,14 +80,14 @@ public Object unwrap(Object object) { /** * {@inheritDoc} + * * @see org.hibernate.proxy.AbstractLazyInitializer#getIdentifier */ @Override public Serializable getIdentifier(Object o) { if (o instanceof HibernateProxy) { - return ((HibernateProxy)o).getHibernateLazyInitializer().getIdentifier(); - } - else { + return ((HibernateProxy) o).getHibernateLazyInitializer().getIdentifier(); + } else { //TODO seems we can get the id here if its has normal getId // PersistentEntity persistentEntity = GormEnhancer.findStaticApi(o.getClass()).getGormPersistentEntity(); // return persistentEntity.getMappingContext().getEntityReflector(persistentEntity).getIdentifier(o); @@ -98,6 +97,7 @@ public Serializable getIdentifier(Object o) { /** * {@inheritDoc} + * * @see HibernateProxyHelper#getClassWithoutInitializingProxy */ @Override @@ -107,6 +107,7 @@ public Class getProxiedClass(Object o) { /** * calls unwrap which calls unproxy + * * @see #unwrap(Object) * @deprecated use unwrap */ @@ -120,7 +121,7 @@ public Object unwrapIfProxy(Object instance) { */ @Override public boolean isProxy(Object o) { - return (o instanceof HibernateProxy) || (o instanceof PersistentCollection); + return (o instanceof HibernateProxy) || (o instanceof PersistentCollection); } /** @@ -161,8 +162,7 @@ public HibernateProxy getAssociationProxy(Object obj, String associationName) { return (HibernateProxy) proxy; } return null; - } - catch (RuntimeException e) { + } catch (RuntimeException e) { return null; } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/proxy/SimpleHibernateProxyHandler.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/proxy/SimpleHibernateProxyHandler.java index 6deb4816ce8..8715e476e3b 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/proxy/SimpleHibernateProxyHandler.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/proxy/SimpleHibernateProxyHandler.java @@ -27,7 +27,6 @@ import org.grails.datastore.mapping.proxy.ProxyFactory; import org.grails.datastore.mapping.proxy.ProxyHandler; import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.hibernate.Hibernate; import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxyHelper; @@ -50,11 +49,9 @@ public class SimpleHibernateProxyHandler extends JavassistProxyFactory implement public boolean isInitialized(Object o) { if (o instanceof HibernateProxy) { return !((HibernateProxy) o).getHibernateLazyInitializer().isUninitialized(); - } - else if (o instanceof PersistentCollection) { + } else if (o instanceof PersistentCollection) { return ((PersistentCollection) o).wasInitialized(); - } - else { + } else { return super.isInitialized(o); } } @@ -63,8 +60,7 @@ public boolean isInitialized(Object obj, String associationName) { try { Object proxy = ClassPropertyFetcher.getInstancePropertyValue(obj, associationName); return isInitialized(proxy); - } - catch (RuntimeException e) { + } catch (RuntimeException e) { return false; } } @@ -81,10 +77,9 @@ public Serializable getIdentifier(Object obj) { public Object unwrapIfProxy(Object instance) { if (instance instanceof HibernateProxy) { - final HibernateProxy proxy = (HibernateProxy)instance; + final HibernateProxy proxy = (HibernateProxy) instance; return unwrapProxy(proxy); - } - else { + } else { return super.unwrap(instance); } } @@ -104,19 +99,18 @@ public Object unwrapProxy(final HibernateProxy proxy) { /** * Ensures the meta class is correct for a given class * - * @param target The GroovyObject + * @param target The GroovyObject * @param persistentClass The persistent class */ private static void ensureCorrectGroovyMetaClass(Object target, Class persistentClass) { if (target instanceof GroovyObject) { - GroovyObject go = ((GroovyObject)target); + GroovyObject go = ((GroovyObject) target); if (!go.getMetaClass().getTheClass().equals(persistentClass)) { go.setMetaClass(GroovySystem.getMetaClassRegistry().getMetaClass(persistentClass)); } } } - public HibernateProxy getAssociationProxy(Object obj, String associationName) { try { Object proxy = ClassPropertyFetcher.getInstancePropertyValue(obj, associationName); @@ -124,8 +118,7 @@ public HibernateProxy getAssociationProxy(Object obj, String associationName) { return (HibernateProxy) proxy; } return null; - } - catch (RuntimeException e) { + } catch (RuntimeException e) { return null; } } @@ -136,28 +129,26 @@ public boolean isProxy(Object o) { public void initialize(Object o) { if (o instanceof HibernateProxy) { - final LazyInitializer hibernateLazyInitializer = ((HibernateProxy)o).getHibernateLazyInitializer(); + final LazyInitializer hibernateLazyInitializer = ((HibernateProxy) o).getHibernateLazyInitializer(); if (hibernateLazyInitializer.isUninitialized()) { hibernateLazyInitializer.initialize(); } - } - else { + } else { super.initialize(o); } } public Object getProxyIdentifier(Object o) { if (o instanceof HibernateProxy) { - return ((HibernateProxy)o).getHibernateLazyInitializer().getIdentifier(); + return ((HibernateProxy) o).getHibernateLazyInitializer().getIdentifier(); } return super.getIdentifier(o); } public Class getProxiedClass(Object o) { - if(o instanceof HibernateProxy) { + if (o instanceof HibernateProxy) { return HibernateProxyHelper.getClassWithoutInitializingProxy(o); - } - else { + } else { return super.getProxiedClass(o); } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index 1537a350f64..9b00bc3e82d 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java @@ -16,32 +16,58 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.query; import grails.gorm.MultiTenant; -import groovy.lang.*; +import groovy.lang.Closure; +import groovy.lang.DelegatesTo; +import groovy.lang.GroovyObjectSupport; +import groovy.lang.MetaClass; +import groovy.lang.MetaMethod; +import groovy.lang.MissingMethodException; +import jakarta.persistence.criteria.JoinType; +import jakarta.persistence.metamodel.Attribute; +import jakarta.persistence.metamodel.EntityType; import org.grails.datastore.mapping.multitenancy.MultiTenancySettings; import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.*; +import org.grails.datastore.mapping.query.api.BuildableCriteria; +import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.datastore.mapping.reflect.NameUtils; import org.grails.orm.hibernate.AbstractHibernateDatastore; -import org.hibernate.*; import org.hibernate.Criteria; -import org.hibernate.criterion.*; +import org.hibernate.FetchMode; +import org.hibernate.LockMode; +import org.hibernate.Metamodel; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.TypeHelper; +import org.hibernate.criterion.AggregateProjection; +import org.hibernate.criterion.CountProjection; +import org.hibernate.criterion.CriteriaSpecification; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.IdentifierProjection; +import org.hibernate.criterion.Junction; +import org.hibernate.criterion.Order; +import org.hibernate.criterion.Projection; import org.hibernate.criterion.ProjectionList; import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Property; +import org.hibernate.criterion.PropertyProjection; import org.hibernate.criterion.Restrictions; +import org.hibernate.criterion.SimpleExpression; +import org.hibernate.criterion.Subqueries; import org.hibernate.transform.ResultTransformer; import org.hibernate.type.Type; import org.springframework.beans.BeanUtils; import org.springframework.core.convert.ConversionService; -import jakarta.persistence.criteria.JoinType; -import jakarta.persistence.metamodel.Attribute; -import jakarta.persistence.metamodel.EntityType; import java.beans.PropertyDescriptor; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Abstract super class for sharing code between Hibernate 3 and 4 implementations of HibernateCriteriaBuilder @@ -49,33 +75,33 @@ * @author Graeme Rocher * @since 3.0.7 */ -public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSupport implements org.grails.datastore.mapping.query.api.BuildableCriteria, org.grails.datastore.mapping.query.api.ProjectionList { +public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSupport implements org.grails.datastore.mapping.query.api.BuildableCriteria, org.grails.datastore.mapping.query.api.ProjectionList { public static final String AND = "and"; // builder public static final String IS_NULL = "isNull"; // builder public static final String IS_NOT_NULL = "isNotNull"; // builder - public static final String NOT = "not";// builder + public static final String NOT = "not"; // builder public static final String OR = "or"; // builder public static final String ID_EQUALS = "idEq"; // builder public static final String IS_EMPTY = "isEmpty"; //builder public static final String IS_NOT_EMPTY = "isNotEmpty"; //builder - public static final String RLIKE = "rlike";//method - public static final String BETWEEN = "between";//method - public static final String EQUALS = "eq";//method - public static final String EQUALS_PROPERTY = "eqProperty";//method - public static final String GREATER_THAN = "gt";//method - public static final String GREATER_THAN_PROPERTY = "gtProperty";//method - public static final String GREATER_THAN_OR_EQUAL = "ge";//method - public static final String GREATER_THAN_OR_EQUAL_PROPERTY = "geProperty";//method - public static final String ILIKE = "ilike";//method - public static final String IN = "in";//method + public static final String RLIKE = "rlike"; //method + public static final String BETWEEN = "between"; //method + public static final String EQUALS = "eq"; //method + public static final String EQUALS_PROPERTY = "eqProperty"; //method + public static final String GREATER_THAN = "gt"; //method + public static final String GREATER_THAN_PROPERTY = "gtProperty"; //method + public static final String GREATER_THAN_OR_EQUAL = "ge"; //method + public static final String GREATER_THAN_OR_EQUAL_PROPERTY = "geProperty"; //method + public static final String ILIKE = "ilike"; //method + public static final String IN = "in"; //method public static final String LESS_THAN = "lt"; //method - public static final String LESS_THAN_PROPERTY = "ltProperty";//method - public static final String LESS_THAN_OR_EQUAL = "le";//method - public static final String LESS_THAN_OR_EQUAL_PROPERTY = "leProperty";//method - public static final String LIKE = "like";//method - public static final String NOT_EQUAL = "ne";//method - public static final String NOT_EQUAL_PROPERTY = "neProperty";//method + public static final String LESS_THAN_PROPERTY = "ltProperty"; //method + public static final String LESS_THAN_OR_EQUAL = "le"; //method + public static final String LESS_THAN_OR_EQUAL_PROPERTY = "leProperty"; //method + public static final String LIKE = "like"; //method + public static final String NOT_EQUAL = "ne"; //method + public static final String NOT_EQUAL_PROPERTY = "neProperty"; //method public static final String SIZE_EQUALS = "sizeEq"; //method public static final String ORDER_DESCENDING = "desc"; public static final String ORDER_ASCENDING = "asc"; @@ -88,7 +114,7 @@ public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSuppo protected static final String SCROLL_CALL = "scroll"; protected static final String SET_RESULT_TRANSFORMER_CALL = "setResultTransformer"; protected static final String PROJECTIONS = "projections"; - + protected static final String ALIAS = "_alias"; protected SessionFactory sessionFactory; protected Session hibernateSession; @@ -105,7 +131,6 @@ public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSuppo protected List aliasStack = new ArrayList(); protected List aliasInstanceStack = new ArrayList(); protected Map aliasMap = new HashMap(); - protected static final String ALIAS = "_alias"; protected ResultTransformer resultTransformer; protected int aliasCount; protected boolean paginationEnabledList = false; @@ -129,7 +154,7 @@ public AbstractHibernateCriteriaBuilder(Class targetClass, SessionFactory sessio public void setDatastore(AbstractHibernateDatastore datastore) { this.datastore = datastore; - if(MultiTenant.class.isAssignableFrom(targetClass) && datastore.getMultiTenancyMode() == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR ) { + if (MultiTenant.class.isAssignableFrom(targetClass) && datastore.getMultiTenancyMode() == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) { datastore.enableMultiTenancyFilter(); } } @@ -140,6 +165,7 @@ public void setConversionService(ConversionService conversionService) { /** * A projection that selects a property name + * * @param propertyName The name of the property */ public org.grails.datastore.mapping.query.api.ProjectionList property(String propertyName) { @@ -148,8 +174,9 @@ public org.grails.datastore.mapping.query.api.ProjectionList property(String pro /** * A projection that selects a property name + * * @param propertyName The name of the property - * @param alias The alias to use + * @param alias The alias to use */ public org.grails.datastore.mapping.query.api.ProjectionList property(String propertyName, String alias) { final PropertyProjection propertyProjection = Projections.property(calculatePropertyName(propertyName)); @@ -161,13 +188,12 @@ public org.grails.datastore.mapping.query.api.ProjectionList property(String pro * Adds a projection to the projectList for the given alias * * @param propertyProjection The projection - * @param alias The alias + * @param alias The alias */ protected void addProjectionToList(Projection propertyProjection, String alias) { if (alias != null) { - projectionList.add(propertyProjection,alias); - } - else { + projectionList.add(propertyProjection, alias); + } else { projectionList.add(propertyProjection); } } @@ -175,9 +201,9 @@ protected void addProjectionToList(Projection propertyProjection, String alias) /** * Adds a sql projection to the criteria * - * @param sql SQL projecting a single value + * @param sql SQL projecting a single value * @param columnAlias column alias for the projected value - * @param type the type of the projected value + * @param type the type of the projected value */ protected void sqlProjection(String sql, String columnAlias, Type type) { sqlProjection(sql, Collections.singletonList(columnAlias), Collections.singletonList(type)); @@ -186,9 +212,9 @@ protected void sqlProjection(String sql, String columnAlias, Type type) { /** * Adds a sql projection to the criteria * - * @param sql SQL projecting + * @param sql SQL projecting * @param columnAliases List of column aliases for the projected values - * @param types List of types for the projected values + * @param types List of types for the projected values */ protected void sqlProjection(String sql, List columnAliases, List types) { projectionList.add(Projections.sqlProjection(sql, columnAliases.toArray(new String[columnAliases.size()]), types.toArray(new Type[types.size()]))); @@ -197,10 +223,10 @@ protected void sqlProjection(String sql, List columnAliases, List /** * Adds a sql projection to the criteria * - * @param sql SQL projecting - * @param groupBy group by clause + * @param sql SQL projecting + * @param groupBy group by clause * @param columnAliases List of column aliases for the projected values - * @param types List of types for the projected values + * @param types List of types for the projected values */ protected void sqlGroupProjection(String sql, String groupBy, List columnAliases, List types) { projectionList.add(Projections.sqlGroupProjection(sql, groupBy, columnAliases.toArray(new String[columnAliases.size()]), types.toArray(new Type[types.size()]))); @@ -208,6 +234,7 @@ protected void sqlGroupProjection(String sql, String groupBy, List colum /** * A projection that selects a distince property name + * * @param propertyName The property name */ public org.grails.datastore.mapping.query.api.ProjectionList distinct(String propertyName) { @@ -217,12 +244,13 @@ public org.grails.datastore.mapping.query.api.ProjectionList distinct(String pro /** * A projection that selects a distince property name + * * @param propertyName The property name - * @param alias The alias to use + * @param alias The alias to use */ public org.grails.datastore.mapping.query.api.ProjectionList distinct(String propertyName, String alias) { final Projection proj = Projections.distinct(Projections.property(calculatePropertyName(propertyName))); - addProjectionToList(proj,alias); + addProjectionToList(proj, alias); return this; } @@ -240,7 +268,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList distinct(Collection * A distinct projection that takes a list * * @param propertyNames The list of distince property names - * @param alias The alias to use + * @param alias The alias to use */ @SuppressWarnings("rawtypes") public org.grails.datastore.mapping.query.api.ProjectionList distinct(Collection propertyNames, String alias) { @@ -266,7 +294,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList avg(String property * Adds a projection that allows the criteria to return the property average value * * @param propertyName The name of the property - * @param alias The alias to use + * @param alias The alias to use */ public org.grails.datastore.mapping.query.api.ProjectionList avg(String propertyName, String alias) { final AggregateProjection aggregateProjection = Projections.avg(calculatePropertyName(propertyName)); @@ -289,7 +317,6 @@ public BuildableCriteria join(String property, JoinType joinType) { return this; } - /** * Whether a pessimistic lock should be obtained. * @@ -301,16 +328,13 @@ public void lock(boolean shouldLock) { if (shouldLock) { if (lastAlias != null) { criteria.setLockMode(lastAlias, LockMode.PESSIMISTIC_WRITE); - } - else { + } else { criteria.setLockMode(LockMode.PESSIMISTIC_WRITE); } - } - else { + } else { if (lastAlias != null) { criteria.setLockMode(lastAlias, LockMode.NONE); - } - else { + } else { criteria.setLockMode(LockMode.NONE); } } @@ -328,6 +352,7 @@ public BuildableCriteria select(String associationPath) { /** * Whether to use the query cache + * * @param shouldCache True if the query should be cached */ public BuildableCriteria cache(boolean shouldCache) { @@ -337,6 +362,7 @@ public BuildableCriteria cache(boolean shouldCache) { /** * Whether to check for changes on the objects loaded + * * @param readOnly True to disable dirty checking */ public BuildableCriteria readOnly(boolean readOnly) { @@ -353,7 +379,7 @@ public BuildableCriteria readOnly(boolean readOnly) { protected String calculatePropertyName(String propertyName) { String lastAlias = getLastAlias(); if (lastAlias != null) { - return lastAlias +'.'+propertyName; + return lastAlias + '.' + propertyName; } return propertyName; @@ -376,15 +402,14 @@ public Class getTargetClass() { * @param propertyValue The property value * @return The calculated property value */ - @SuppressWarnings({ "rawtypes", "unchecked" }) + @SuppressWarnings({"rawtypes", "unchecked"}) protected Object calculatePropertyValue(Object propertyValue) { if (propertyValue instanceof CharSequence) { return propertyValue.toString(); } if (propertyValue instanceof QueryableCriteria) { propertyValue = convertToHibernateCriteria((QueryableCriteria) propertyValue); - } - else if (propertyValue instanceof Closure) { + } else if (propertyValue instanceof Closure) { propertyValue = convertToHibernateCriteria( new grails.gorm.DetachedCriteria(targetClass).build((Closure) propertyValue)); } @@ -406,7 +431,7 @@ public void count(String propertyName) { * Adds a projection that allows the criteria to return the property count * * @param propertyName The name of the property - * @param alias The alias to use + * @param alias The alias to use */ public void count(String propertyName, String alias) { final CountProjection proj = Projections.count(calculatePropertyName(propertyName)); @@ -451,7 +476,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList distinct() { * Adds a projection that allows the criteria to return the distinct property count * * @param propertyName The name of the property - * @param alias The alias to use + * @param alias The alias to use */ public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(String propertyName, String alias) { final CountProjection proj = Projections.countDistinct(calculatePropertyName(propertyName)); @@ -459,12 +484,11 @@ public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(Strin return this; } - /** * Adds a projection that allows the criteria's result to be grouped by a property * * @param propertyName The name of the property - * @param alias The alias to use + * @param alias The alias to use */ public org.grails.datastore.mapping.query.api.ProjectionList groupProperty(String propertyName, String alias) { final PropertyProjection proj = Projections.groupProperty(calculatePropertyName(propertyName)); @@ -485,7 +509,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList max(String property * Adds a projection that allows the criteria to retrieve a maximum property value * * @param propertyName The name of the property - * @param alias The alias to use + * @param alias The alias to use */ public org.grails.datastore.mapping.query.api.ProjectionList max(String propertyName, String alias) { final AggregateProjection proj = Projections.max(calculatePropertyName(propertyName)); @@ -545,7 +569,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList sum(String property * Adds a projection that allows the criteria to retrieve the sum of the results of a property * * @param propertyName The name of the property - * @param alias The alias to use + * @param alias The alias to use */ public org.grails.datastore.mapping.query.api.ProjectionList sum(String propertyName, String alias) { final AggregateProjection proj = Projections.sum(calculatePropertyName(propertyName)); @@ -557,7 +581,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList sum(String property * Sets the fetch mode of an associated path * * @param associationPath The name of the associated path - * @param fetchMode The fetch mode to set + * @param fetchMode The fetch mode to set */ public void fetchMode(String associationPath, FetchMode fetchMode) { if (criteria != null) { @@ -567,6 +591,7 @@ public void fetchMode(String associationPath, FetchMode fetchMode) { /** * Sets the resultTransformer. + * * @param transformer The result transformer to use. */ public void resultTransformer(ResultTransformer transformer) { @@ -578,25 +603,24 @@ public void resultTransformer(ResultTransformer transformer) { /** * Join an association, assigning an alias to the joined association. - * + *

* Functionally equivalent to createAlias(String, String, int) using * CriteriaSpecificationINNER_JOIN for the joinType. * * @param associationPath A dot-seperated property path - * @param alias The alias to assign to the joined association (for later reference). - * + * @param alias The alias to assign to the joined association (for later reference). * @return this (for method chaining) * #see {@link #createAlias(String, String, int)} - * @throws HibernateException Indicates a problem creating the sub criteria + * @throws org.hibernate.HibernateException Indicates a problem creating the sub criteria */ public Criteria createAlias(String associationPath, String alias) { return criteria.createAlias(associationPath, alias); } - /** * Creates a Criterion that compares to class properties for equality - * @param propertyName The first property name + * + * @param propertyName The first property name * @param otherPropertyName The second property name * @return A Criterion instance */ @@ -614,7 +638,8 @@ public org.grails.datastore.mapping.query.api.Criteria eqProperty(String propert /** * Creates a Criterion that compares to class properties for !equality - * @param propertyName The first property name + * + * @param propertyName The first property name * @param otherPropertyName The second property name * @return A Criterion instance */ @@ -632,7 +657,8 @@ public org.grails.datastore.mapping.query.api.Criteria neProperty(String propert /** * Creates a Criterion that tests if the first property is greater than the second property - * @param propertyName The first property name + * + * @param propertyName The first property name * @param otherPropertyName The second property name * @return A Criterion instance */ @@ -650,7 +676,8 @@ public org.grails.datastore.mapping.query.api.Criteria gtProperty(String propert /** * Creates a Criterion that tests if the first property is greater than or equal to the second property - * @param propertyName The first property name + * + * @param propertyName The first property name * @param otherPropertyName The second property name * @return A Criterion instance */ @@ -668,7 +695,8 @@ public org.grails.datastore.mapping.query.api.Criteria geProperty(String propert /** * Creates a Criterion that tests if the first property is less than the second property - * @param propertyName The first property name + * + * @param propertyName The first property name * @param otherPropertyName The second property name * @return A Criterion instance */ @@ -686,7 +714,8 @@ public org.grails.datastore.mapping.query.api.Criteria ltProperty(String propert /** * Creates a Criterion that tests if the first property is less than or equal to the second property - * @param propertyName The first property name + * + * @param propertyName The first property name * @param otherPropertyName The second property name * @return A Criterion instance */ @@ -704,7 +733,7 @@ public org.grails.datastore.mapping.query.api.Criteria leProperty(String propert @Override public org.grails.datastore.mapping.query.api.Criteria allEq(Map propertyValues) { - addToCriteria( Restrictions.allEq(propertyValues) ); + addToCriteria(Restrictions.allEq(propertyValues)); return this; } @@ -716,7 +745,7 @@ public org.grails.datastore.mapping.query.api.Criteria allEq(Map * @param propertyValue The property value * @return A Criterion instance */ - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) public org.grails.datastore.mapping.query.api.Criteria eqAll(String propertyName, Closure propertyValue) { return eqAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @@ -729,7 +758,7 @@ public org.grails.datastore.mapping.query.api.Criteria eqAll(String propertyName * @param propertyValue The property value * @return A Criterion instance */ - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) public org.grails.datastore.mapping.query.api.Criteria gtAll(String propertyName, Closure propertyValue) { return gtAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @@ -741,7 +770,7 @@ public org.grails.datastore.mapping.query.api.Criteria gtAll(String propertyName * @param propertyValue The property value * @return A Criterion instance */ - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) public org.grails.datastore.mapping.query.api.Criteria ltAll(String propertyName, Closure propertyValue) { return ltAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @@ -753,7 +782,7 @@ public org.grails.datastore.mapping.query.api.Criteria ltAll(String propertyName * @param propertyValue The property value * @return A Criterion instance */ - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) public org.grails.datastore.mapping.query.api.Criteria geAll(String propertyName, Closure propertyValue) { return geAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @@ -765,7 +794,7 @@ public org.grails.datastore.mapping.query.api.Criteria geAll(String propertyName * @param propertyValue The property value * @return A Criterion instance */ - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) public org.grails.datastore.mapping.query.api.Criteria leAll(String propertyName, Closure propertyValue) { return leAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @@ -916,7 +945,8 @@ public org.grails.datastore.mapping.query.api.Criteria leAll(String propertyName /** * Creates a "greater than" Criterion based on the specified property name and value - * @param propertyName The property name + * + * @param propertyName The property name * @param propertyValue The property value * @return A Criterion instance */ @@ -931,9 +961,8 @@ public org.grails.datastore.mapping.query.api.Criteria gt(String propertyName, O Criterion gt; if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - gt = Property.forName(propertyName).gt((org.hibernate.criterion.DetachedCriteria)propertyValue); - } - else { + gt = Property.forName(propertyName).gt((org.hibernate.criterion.DetachedCriteria) propertyValue); + } else { gt = Restrictions.gt(propertyName, propertyValue); } addToCriteria(gt); @@ -941,12 +970,13 @@ public org.grails.datastore.mapping.query.api.Criteria gt(String propertyName, O } public org.grails.datastore.mapping.query.api.Criteria lte(String s, Object o) { - return le(s,o); + return le(s, o); } /** * Creates a "greater than or equal to" Criterion based on the specified property name and value - * @param propertyName The property name + * + * @param propertyName The property name * @param propertyValue The property value * @return A Criterion instance */ @@ -962,8 +992,7 @@ public org.grails.datastore.mapping.query.api.Criteria ge(String propertyName, O Criterion ge; if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { ge = Property.forName(propertyName).ge((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { + } else { ge = Restrictions.ge(propertyName, propertyValue); } addToCriteria(ge); @@ -972,7 +1001,8 @@ public org.grails.datastore.mapping.query.api.Criteria ge(String propertyName, O /** * Creates a "less than" Criterion based on the specified property name and value - * @param propertyName The property name + * + * @param propertyName The property name * @param propertyValue The property value * @return A Criterion instance */ @@ -987,8 +1017,7 @@ public org.grails.datastore.mapping.query.api.Criteria lt(String propertyName, O Criterion lt; if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { lt = Property.forName(propertyName).lt((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { + } else { lt = Restrictions.lt(propertyName, propertyValue); } addToCriteria(lt); @@ -997,7 +1026,8 @@ public org.grails.datastore.mapping.query.api.Criteria lt(String propertyName, O /** * Creates a "less than or equal to" Criterion based on the specified property name and value - * @param propertyName The property name + * + * @param propertyName The property name * @param propertyValue The property value * @return A Criterion instance */ @@ -1012,8 +1042,7 @@ public org.grails.datastore.mapping.query.api.Criteria le(String propertyName, O Criterion le; if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { le = Property.forName(propertyName).le((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { + } else { le = Restrictions.le(propertyName, propertyValue); } addToCriteria(le); @@ -1080,9 +1109,10 @@ protected org.grails.datastore.mapping.query.api.Criteria executeLogicalExpressi try { invokeClosureNode(callable); } finally { - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); - if(logicalExpression != null) + LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size() - 1); + if (logicalExpression != null) { addToCriteria(logicalExpression.toCriterion()); + } } return this; @@ -1090,9 +1120,9 @@ protected org.grails.datastore.mapping.query.api.Criteria executeLogicalExpressi /** * Creates an "equals" Criterion based on the specified property name and value. Case-sensitive. - * @param propertyName The property name - * @param propertyValue The property value * + * @param propertyName The property name + * @param propertyValue The property value * @return A Criterion instance */ public org.grails.datastore.mapping.query.api.Criteria eq(String propertyName, Object propertyValue) { @@ -1106,7 +1136,8 @@ public org.grails.datastore.mapping.query.api.Criteria idEq(Object o) { /** * Groovy moves the map to the first parameter if using the idiomatic form, e.g. * eq 'firstName', 'Fred', ignoreCase: true. - * @param params optional map with customization parameters; currently only 'ignoreCase' is supported. + * + * @param params optional map with customization parameters; currently only 'ignoreCase' is supported. * @param propertyName * @param propertyValue * @return A Criterion instance @@ -1120,10 +1151,10 @@ public org.grails.datastore.mapping.query.api.Criteria eq(Map params, String pro * Creates an "equals" Criterion based on the specified property name and value. * Supports case-insensitive search if the params map contains true * under the 'ignoreCase' key. - * @param propertyName The property name - * @param propertyValue The property value - * @param params optional map with customization parameters; currently only 'ignoreCase' is supported. * + * @param propertyName The property name + * @param propertyValue The property value + * @param params optional map with customization parameters; currently only 'ignoreCase' is supported. * @return A Criterion instance */ @SuppressWarnings("rawtypes") @@ -1138,14 +1169,13 @@ public org.grails.datastore.mapping.query.api.Criteria eq(String propertyName, O Criterion eq; if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { eq = Property.forName(propertyName).eq((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { - eq = Restrictions.eq(propertyName, propertyValue); + } else { + eq = Restrictions.eq(propertyName, propertyValue); } if (params != null && (eq instanceof SimpleExpression)) { Object ignoreCase = params.get("ignoreCase"); - if (ignoreCase instanceof Boolean && (Boolean)ignoreCase) { - eq = ((SimpleExpression)eq).ignoreCase(); + if (ignoreCase instanceof Boolean && (Boolean) ignoreCase) { + eq = ((SimpleExpression) eq).ignoreCase(); } } addToCriteria(eq); @@ -1170,7 +1200,7 @@ public org.grails.datastore.mapping.query.api.Criteria sqlRestriction(String sql * Applies a sql restriction to the results to allow something like: * * @param sqlRestriction the sql restriction - * @param values jdbc parameters + * @param values jdbc parameters * @return a Criteria instance */ public org.grails.datastore.mapping.query.api.Criteria sqlRestriction(String sqlRestriction, List values) { @@ -1187,7 +1217,7 @@ public org.grails.datastore.mapping.query.api.Criteria sqlRestriction(String sql final TypeHelper typeHelper = sessionFactory.getTypeHelper(); for (int i = 0; i < typesArray.length; i++) { final Object value = values.get(i); - typesArray[i] = typeHelper.basic(value.getClass()); + typesArray[i] = typeHelper.basic(value.getClass()); valuesArray[i] = value; } } @@ -1197,9 +1227,9 @@ public org.grails.datastore.mapping.query.api.Criteria sqlRestriction(String sql /** * Creates a Criterion with from the specified property name and "like" expression - * @param propertyName The property name - * @param propertyValue The like value * + * @param propertyName The property name + * @param propertyValue The like value * @return A Criterion instance */ public org.grails.datastore.mapping.query.api.Criteria like(String propertyName, Object propertyValue) { @@ -1216,18 +1246,18 @@ public org.grails.datastore.mapping.query.api.Criteria like(String propertyName, /** * Creates a Criterion with from the specified property name and "rlike" (a regular expression version of "like") expression - * @param propertyName The property name - * @param propertyValue The ilike value * + * @param propertyName The property name + * @param propertyValue The ilike value * @return A Criterion instance */ public abstract org.grails.datastore.mapping.query.api.Criteria rlike(String propertyName, Object propertyValue); /** * Creates a Criterion with from the specified property name and "ilike" (a case sensitive version of "like") expression - * @param propertyName The property name - * @param propertyValue The ilike value * + * @param propertyName The property name + * @param propertyValue The ilike value * @return A Criterion instance */ public org.grails.datastore.mapping.query.api.Criteria ilike(String propertyName, Object propertyValue) { @@ -1244,9 +1274,9 @@ public org.grails.datastore.mapping.query.api.Criteria ilike(String propertyName /** * Applys a "in" contrain on the specified property - * @param propertyName The property name - * @param values A collection of values * + * @param propertyName The property name + * @param values A collection of values * @return A Criterion instance */ @SuppressWarnings("rawtypes") @@ -1258,24 +1288,25 @@ public org.grails.datastore.mapping.query.api.Criteria in(String propertyName, C propertyName = calculatePropertyName(propertyName); - if(values instanceof List) { - values = convertArgumentList((List)values); + if (values instanceof List) { + values = convertArgumentList((List) values); } addToCriteria(Restrictions.in(propertyName, values == null ? Collections.EMPTY_LIST : values)); return this; } - @SuppressWarnings({ "rawtypes", "unchecked" }) + @SuppressWarnings({"rawtypes", "unchecked"}) protected List convertArgumentList(List argList) { List convertedList = new ArrayList(argList.size()); for (Object item : argList) { - if(item instanceof CharSequence) { + if (item instanceof CharSequence) { item = item.toString(); } convertedList.add(item); } return convertedList; } + /** * Delegates to in as in is a Groovy keyword */ @@ -1293,9 +1324,9 @@ public org.grails.datastore.mapping.query.api.Criteria inList(String propertyNam /** * Applys a "in" contrain on the specified property - * @param propertyName The property name - * @param values A collection of values * + * @param propertyName The property name + * @param values A collection of values * @return A Criterion instance */ public org.grails.datastore.mapping.query.api.Criteria in(String propertyName, Object[] values) { @@ -1344,8 +1375,7 @@ private void addOrderInternal(Criteria criteria, Order o) { } if (paginationEnabledList) { orderEntries.add(o); - } - else { + } else { criteria.addOrder(o); } } @@ -1361,16 +1391,15 @@ public org.grails.datastore.mapping.query.api.Criteria order(Query.Order o) { private void addOrderInternal(Criteria criteria, Query.Order o, String property) { final int i = property.indexOf('.'); - if(i == -1) { + if (i == -1) { Order order = convertOrder(o, property); addOrderInternal(criteria, order); - } - else { - String sortHead = property.substring(0,i); - String sortTail = property.substring(i+1); + } else { + String sortHead = property.substring(0, i); + String sortTail = property.substring(i + 1); createAliasIfNeccessary(sortHead, sortHead, org.hibernate.sql.JoinType.INNER_JOIN.getJoinTypeValue()); - final Criteria sub = aliasInstanceStack.get(aliasInstanceStack.size()-1); + final Criteria sub = aliasInstanceStack.get(aliasInstanceStack.size() - 1); addOrderInternal(sub, o, sortTail); } } @@ -1379,13 +1408,13 @@ protected Order convertOrder(Query.Order o, String property) { Order order; switch (o.getDirection()) { case DESC: - order = Order.desc(property); + order = Order.desc(property); break; default: order = Order.asc(property); break; } - if(o.isIgnoreCase()) { + if (o.isIgnoreCase()) { order.ignoreCase(); } return order; @@ -1395,8 +1424,7 @@ protected Order convertOrder(Query.Order o, String property) { * Orders by the specified property name and direction * * @param propertyName The property name to order by - * @param direction Either "asc" for ascending or "desc" for descending - * + * @param direction Either "asc" for ascending or "desc" for descending * @return A Order instance */ public org.grails.datastore.mapping.query.api.Criteria order(String propertyName, String direction) { @@ -1408,14 +1436,12 @@ public org.grails.datastore.mapping.query.api.Criteria order(String propertyName Order o; if (direction.equals(ORDER_DESCENDING)) { o = Order.desc(propertyName); - } - else { + } else { o = Order.asc(propertyName); } if (paginationEnabledList) { orderEntries.add(o); - } - else { + } else { criteria.addOrder(o); } return this; @@ -1425,8 +1451,7 @@ public org.grails.datastore.mapping.query.api.Criteria order(String propertyName * Creates a Criterion that contrains a collection property by size * * @param propertyName The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return A Criterion instance */ public org.grails.datastore.mapping.query.api.Criteria sizeEq(String propertyName, int size) { @@ -1444,8 +1469,7 @@ public org.grails.datastore.mapping.query.api.Criteria sizeEq(String propertyNam * Creates a Criterion that contrains a collection property to be greater than the given size * * @param propertyName The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return A Criterion instance */ public org.grails.datastore.mapping.query.api.Criteria sizeGt(String propertyName, int size) { @@ -1463,8 +1487,7 @@ public org.grails.datastore.mapping.query.api.Criteria sizeGt(String propertyNam * Creates a Criterion that contrains a collection property to be greater than or equal to the given size * * @param propertyName The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return A Criterion instance */ public org.grails.datastore.mapping.query.api.Criteria sizeGe(String propertyName, int size) { @@ -1482,8 +1505,7 @@ public org.grails.datastore.mapping.query.api.Criteria sizeGe(String propertyNam * Creates a Criterion that contrains a collection property to be less than or equal to the given size * * @param propertyName The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return A Criterion instance */ public org.grails.datastore.mapping.query.api.Criteria sizeLe(String propertyName, int size) { @@ -1501,8 +1523,7 @@ public org.grails.datastore.mapping.query.api.Criteria sizeLe(String propertyNam * Creates a Criterion that contrains a collection property to be less than to the given size * * @param propertyName The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return A Criterion instance */ public org.grails.datastore.mapping.query.api.Criteria sizeLt(String propertyName, int size) { @@ -1520,8 +1541,7 @@ public org.grails.datastore.mapping.query.api.Criteria sizeLt(String propertyNam * Creates a Criterion that contrains a collection property to be not equal to the given size * * @param propertyName The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return A Criterion instance */ public org.grails.datastore.mapping.query.api.Criteria sizeNe(String propertyName, int size) { @@ -1537,7 +1557,8 @@ public org.grails.datastore.mapping.query.api.Criteria sizeNe(String propertyNam /** * Creates a "not equal" Criterion based on the specified property name and value - * @param propertyName The property name + * + * @param propertyName The property name * @param propertyValue The property value * @return The criterion object */ @@ -1559,9 +1580,10 @@ public org.grails.datastore.mapping.query.api.Criteria notEqual(String propertyN /** * Creates a "between" Criterion based on the property name and specified lo and hi values + * * @param propertyName The property name - * @param lo The low value - * @param hi The high value + * @param lo The low value + * @param hi The high value * @return A Criterion instance */ public org.grails.datastore.mapping.query.api.Criteria between(String propertyName, Object lo, Object hi) { @@ -1592,7 +1614,7 @@ public Object list(@DelegatesTo(Criteria.class) Closure c) { public Object list(Map params, @DelegatesTo(Criteria.class) Closure c) { return invokeMethod(LIST_CALL, new Object[]{params, c}); } - + @Override public Object listDistinct(@DelegatesTo(Criteria.class) Closure c) { return invokeMethod(LIST_DISTINCT_CALL, new Object[]{c}); @@ -1602,16 +1624,16 @@ public Object listDistinct(@DelegatesTo(Criteria.class) Closure c) { public Object get(@DelegatesTo(Criteria.class) Closure c) { return invokeMethod(GET_CALL, new Object[]{c}); } - + @Override public Object scroll(@DelegatesTo(Criteria.class) Closure c) { return invokeMethod(SCROLL_CALL, new Object[]{c}); } - + @SuppressWarnings("rawtypes") @Override public Object invokeMethod(String name, Object obj) { - Object[] args = obj.getClass().isArray() ? (Object[])obj : new Object[]{obj}; + Object[] args = obj.getClass().isArray() ? (Object[]) obj : new Object[]{obj}; if (paginationEnabledList && SET_RESULT_TRANSFORMER_CALL.equals(name) && args.length == 1 && args[0] instanceof ResultTransformer) { @@ -1626,14 +1648,11 @@ public Object invokeMethod(String name, Object obj) { if (name.equals(GET_CALL)) { uniqueResult = true; - } - else if (name.equals(SCROLL_CALL)) { + } else if (name.equals(SCROLL_CALL)) { scroll = true; - } - else if (name.equals(COUNT_CALL)) { + } else if (name.equals(COUNT_CALL)) { count = true; - } - else if (name.equals(LIST_DISTINCT_CALL)) { + } else if (name.equals(LIST_DISTINCT_CALL)) { resultTransformer = CriteriaSpecification.DISTINCT_ROOT_ENTITY; } @@ -1644,8 +1663,7 @@ else if (name.equals(LIST_DISTINCT_CALL)) { paginationEnabledList = true; orderEntries = new ArrayList<>(); invokeClosureNode(args[1]); - } - else { + } else { invokeClosureNode(args[0]); } @@ -1656,12 +1674,10 @@ else if (name.equals(LIST_DISTINCT_CALL)) { if (!uniqueResult) { if (scroll) { result = criteria.scroll(); - } - else if (count) { + } else if (count) { criteria.setProjection(Projections.rowCount()); result = criteria.uniqueResult(); - } - else if (paginationEnabledList) { + } else if (paginationEnabledList) { // Calculate how many results there are in total. This has been // moved to before the 'list()' invocation to avoid any "ORDER // BY" clause added by 'populateArgumentsForCriteria()', otherwise @@ -1679,17 +1695,16 @@ else if (paginationEnabledList) { } if (resultTransformer == null) { // GRAILS-9644 - Use projection transformer - criteria.setResultTransformer( isProjection ? - CriteriaSpecification.PROJECTION : - CriteriaSpecification.ROOT_ENTITY + criteria.setResultTransformer(isProjection ? + CriteriaSpecification.PROJECTION : + CriteriaSpecification.ROOT_ENTITY ); - } - else if (paginationEnabledList) { + } else if (paginationEnabledList) { // relevant to GRAILS-5692 criteria.setResultTransformer(resultTransformer); } // GRAILS-7324 look if we already have association to sort by - Map argMap = (Map)args[0]; + Map argMap = (Map) args[0]; final String sort = (String) argMap.get(HibernateQueryConstants.ARGUMENT_SORT); if (sort != null) { boolean ignoreCase = true; @@ -1712,12 +1727,10 @@ else if (paginationEnabledList) { } } result = createPagedResultList(argMap); - } - else { + } else { result = criteria.list(); } - } - else { + } else { result = executeUniqueResultWithProxyUnwrap(); } if (!participate) { @@ -1726,7 +1739,9 @@ else if (paginationEnabledList) { return result; } - if (criteria == null) createCriteriaInstance(); + if (criteria == null) { + createCriteriaInstance(); + } MetaMethod metaMethod = getMetaClass().getMetaMethod(name, args); if (metaMethod != null) { @@ -1745,7 +1760,7 @@ else if (paginationEnabledList) { if (isAssociationQueryMethod(args) || isAssociationQueryWithJoinSpecificationMethod(args)) { final boolean hasMoreThanOneArg = args.length > 1; Object callable = hasMoreThanOneArg ? args[1] : args[0]; - int joinType = hasMoreThanOneArg ? (Integer)args[0] : org.hibernate.sql.JoinType.INNER_JOIN.getJoinTypeValue(); + int joinType = hasMoreThanOneArg ? (Integer) args[0] : org.hibernate.sql.JoinType.INNER_JOIN.getJoinTypeValue(); if (name.equals(AND) || name.equals(OR) || name.equals(NOT)) { if (criteria == null) { @@ -1755,7 +1770,7 @@ else if (paginationEnabledList) { logicalExpressionStack.add(new LogicalExpression(name)); invokeClosureNode(callable); - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); + LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size() - 1); addToCriteria(logicalExpression.toCriterion()); return name; @@ -1790,7 +1805,7 @@ else if (paginationEnabledList) { } associationStack.add(name); final String associationPath = getAssociationPath(); - createAliasIfNeccessary(name, associationPath,joinType); + createAliasIfNeccessary(name, associationPath, joinType); // the criteria within an association node are grouped with an implicit AND logicalExpressionStack.add(new LogicalExpression(AND)); invokeClosureNode(callable); @@ -1798,11 +1813,11 @@ else if (paginationEnabledList) { if (!aliasInstanceStack.isEmpty()) { aliasInstanceStack.remove(aliasInstanceStack.size() - 1); } - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); + LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size() - 1); if (!logicalExpression.args.isEmpty()) { addToCriteria(logicalExpression.toCriterion()); } - associationStack.remove(associationStack.size()-1); + associationStack.remove(associationStack.size() - 1); targetClass = oldTargetClass; return name; @@ -1814,16 +1829,15 @@ else if (paginationEnabledList) { targetClass = pd.getPropertyType(); invokeClosureNode(callable); targetClass = oldTargetClass; - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); + LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size() - 1); if (!logicalExpression.args.isEmpty()) { addToCriteria(logicalExpression.toCriterion()); } - associationStack.remove(associationStack.size()-1); + associationStack.remove(associationStack.size() - 1); return name; } } - } - else if (args.length == 1 && args[0] != null) { + } else if (args.length == 1 && args[0] != null) { if (criteria == null) { throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); } @@ -1842,17 +1856,14 @@ else if (args.length == 1 && args[0] != null) { throwRuntimeException(new IllegalArgumentException("call to [" + name + "] with value [" + value + "] requires a String value.")); } - String propertyName = calculatePropertyName((String)value); + String propertyName = calculatePropertyName((String) value); if (name.equals(IS_NULL)) { c = Restrictions.isNull(propertyName); - } - else if (name.equals(IS_NOT_NULL)) { + } else if (name.equals(IS_NOT_NULL)) { c = Restrictions.isNotNull(propertyName); - } - else if (name.equals(IS_EMPTY)) { + } else if (name.equals(IS_EMPTY)) { c = Restrictions.isEmpty(propertyName); - } - else if (name.equals(IS_NOT_EMPTY)) { + } else if (name.equals(IS_NOT_EMPTY)) { c = Restrictions.isNotEmpty(propertyName); } } @@ -1869,7 +1880,6 @@ else if (name.equals(IS_NOT_EMPTY)) { protected abstract List createPagedResultList(Map args); - private boolean isAssociationQueryMethod(Object[] args) { return args.length == 1 && args[0] instanceof Closure; } @@ -1878,13 +1888,11 @@ private boolean isAssociationQueryWithJoinSpecificationMethod(Object[] args) { return args.length == 2 && (args[0] instanceof Number) && (args[1] instanceof Closure); } - private void createAliasIfNeccessary(String associationName, String associationPath, int joinType) { String newAlias; if (aliasMap.containsKey(associationPath)) { newAlias = aliasMap.get(associationPath); - } - else { + } else { aliasCount++; newAlias = associationName + ALIAS + aliasCount; aliasMap.put(associationPath, newAlias); @@ -1897,7 +1905,9 @@ private String getAssociationPath() { StringBuilder fullPath = new StringBuilder(); for (Object anAssociationStack : associationStack) { String propertyName = (String) anAssociationStack; - if (fullPath.length() > 0) fullPath.append("."); + if (fullPath.length() > 0) { + fullPath.append("."); + } fullPath.append(propertyName); } return fullPath.toString(); @@ -1921,20 +1931,17 @@ public Criteria buildCriteria(Closure criteriaClosure) { return criteria; } - protected abstract void createCriteriaInstance(); protected abstract void cacheCriteriaMapping(); - private void invokeClosureNode(Object args) { - Closure callable = (Closure)args; + Closure callable = (Closure) args; callable.setDelegate(this); callable.setResolveStrategy(Closure.DELEGATE_FIRST); callable.call(); } - /** * adds and returns the given criterion to the currently active criteria set. * this might be either the root criteria or a currently open @@ -1943,28 +1950,26 @@ private void invokeClosureNode(Object args) { protected Criterion addToCriteria(Criterion c) { if (!logicalExpressionStack.isEmpty()) { logicalExpressionStack.get(logicalExpressionStack.size() - 1).args.add(c); - } - else { + } else { criteria.add(c); } return c; } - - /** * Add order directly to criteria. */ private static void addOrder(Criteria c, String sort, String order, boolean ignoreCase) { if (HibernateQueryConstants.ORDER_DESC.equals(order)) { - c.addOrder( ignoreCase ? Order.desc(sort).ignoreCase() : Order.desc(sort)); - } - else { - c.addOrder( ignoreCase ? Order.asc(sort).ignoreCase() : Order.asc(sort) ); + c.addOrder(ignoreCase ? Order.desc(sort).ignoreCase() : Order.desc(sort)); + } else { + c.addOrder(ignoreCase ? Order.asc(sort).ignoreCase() : Order.asc(sort)); } } + /** * Returns the criteria instance + * * @return The criteria instance */ public Criteria getInstance() { @@ -1973,6 +1978,7 @@ public Criteria getInstance() { /** * Set whether a unique result should be returned + * * @param uniqueResult True if a unique result should be returned */ public void setUniqueResult(boolean uniqueResult) { @@ -1987,9 +1993,8 @@ public void setUniqueResult(boolean uniqueResult) { * CriteriaSpecificationFULL_JOIN, or CriteriaSpecificationLEFT_JOIN. * * @param associationPath A dot-seperated property path - * @param alias The alias to assign to the joined association (for later reference). - * @param joinType The type of join to use. - * + * @param alias The alias to assign to the joined association (for later reference). + * @param joinType The type of join to use. * @return this (for method chaining) * @throws org.hibernate.HibernateException Indicates a problem creating the sub criteria */ @@ -1997,14 +2002,46 @@ public void setUniqueResult(boolean uniqueResult) { protected abstract Class getClassForAssociationType(Attribute type); + /** + * Throws a runtime exception where necessary to ensure the session gets closed + */ + protected void throwRuntimeException(RuntimeException t) { + closeSessionFollowingException(); + throw t; + } + + private void closeSessionFollowingException() { + closeSession(); + criteria = null; + } + + /** + * Closes the session if it is copen + */ + protected void closeSession() { + if (hibernateSession != null && hibernateSession.isOpen() && !participate) { + hibernateSession.close(); + } + } + + public int getDefaultFlushMode() { + return defaultFlushMode; + } + + public void setDefaultFlushMode(int defaultFlushMode) { + this.defaultFlushMode = defaultFlushMode; + } /** * instances of this class are pushed onto the logicalExpressionStack * to represent all the unfinished "and", "or", and "not" expressions. */ protected class LogicalExpression { + + //CHECKSTYLE:OFF public final Object name; public final List args = new ArrayList(); + //CHECKSTYLE:ON public LogicalExpression(Object name) { this.name = name; @@ -2047,33 +2084,4 @@ public Junction buildJunction(Junction junction, List criterions) { return junction; } } - /** - * Throws a runtime exception where necessary to ensure the session gets closed - */ - protected void throwRuntimeException(RuntimeException t) { - closeSessionFollowingException(); - throw t; - } - - private void closeSessionFollowingException() { - closeSession(); - criteria = null; - } - - /** - * Closes the session if it is copen - */ - protected void closeSession() { - if (hibernateSession != null && hibernateSession.isOpen() && !participate) { - hibernateSession.close(); - } - } - - public int getDefaultFlushMode() { - return defaultFlushMode; - } - - public void setDefaultFlushMode(int defaultFlushMode) { - this.defaultFlushMode = defaultFlushMode; - } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriterionAdapter.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriterionAdapter.java index 118206d3835..0bdca13a4ae 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriterionAdapter.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriterionAdapter.java @@ -25,7 +25,14 @@ import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.datastore.mapping.query.criteria.FunctionCallingCriterion; -import org.hibernate.criterion.*; +import org.hibernate.criterion.Conjunction; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.DetachedCriteria; +import org.hibernate.criterion.Disjunction; +import org.hibernate.criterion.Junction; +import org.hibernate.criterion.Property; +import org.hibernate.criterion.Restrictions; +import org.hibernate.criterion.Subqueries; import java.util.HashMap; import java.util.List; @@ -38,7 +45,8 @@ * @since 2.0 */ public abstract class AbstractHibernateCriterionAdapter { - protected static final Map, CriterionAdaptor> criterionAdaptors = new HashMap, CriterionAdaptor>(); + + protected static final Map, CriterionAdaptor> CRITERION_ADAPTORS = new HashMap, CriterionAdaptor>(); protected static boolean initialized; protected static final String ALIAS = "_alias"; @@ -51,7 +59,7 @@ protected void initialize() { return; } - synchronized (criterionAdaptors) { + synchronized (CRITERION_ADAPTORS) { // add simple property criterions (idEq, eq, ne, gt, lt, ge, le) addSimplePropertyCriterionAdapters(); @@ -74,7 +82,6 @@ protected void initialize() { // add subquery adapters (gtAll, geAll, gtSome, ltAll, leAll) addSubqueryCriterionAdapters(); - // add junctions (conjunction, disjunction, negation) addJunctionCriterionAdapters(); @@ -82,12 +89,11 @@ protected void initialize() { addAssociationQueryCriterionAdapters(); } - initialized = true; } protected void addSubqueryCriterionAdapters() { - criterionAdaptors.put(Query.GreaterThanAll.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.GreaterThanAll.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanAll criterion, String alias) { QueryableCriteria subQuery = criterion.getValue(); @@ -97,66 +103,66 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que } }); - criterionAdaptors.put(Query.GreaterThanEqualsAll.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.GreaterThanEqualsAll.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanEqualsAll criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); + DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery, criterion.getValue()); return Property.forName(getPropertyName(criterion, alias)).geAll(detachedCriteria); } }); - criterionAdaptors.put(Query.LessThanAll.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.LessThanAll.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanAll criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); + DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery, criterion.getValue()); return Property.forName(getPropertyName(criterion, alias)).ltAll(detachedCriteria); } }); - criterionAdaptors.put(Query.LessThanEqualsAll.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.LessThanEqualsAll.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanEqualsAll criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); + DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery, criterion.getValue()); return Property.forName(getPropertyName(criterion, alias)).leAll(detachedCriteria); } }); - criterionAdaptors.put(Query.GreaterThanSome.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.GreaterThanSome.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanSome criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); + DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery, criterion.getValue()); return Property.forName(getPropertyName(criterion, alias)).gtSome(detachedCriteria); } }); - criterionAdaptors.put(Query.GreaterThanEqualsSome.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.GreaterThanEqualsSome.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanEqualsSome criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); + DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery, criterion.getValue()); return Property.forName(getPropertyName(criterion, alias)).geSome(detachedCriteria); } }); - criterionAdaptors.put(Query.LessThanSome.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.LessThanSome.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanSome criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); + DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery, criterion.getValue()); return Property.forName(getPropertyName(criterion, alias)).ltSome(detachedCriteria); } }); - criterionAdaptors.put(Query.LessThanEqualsSome.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.LessThanEqualsSome.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanEqualsSome criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); + DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery, criterion.getValue()); return Property.forName(getPropertyName(criterion, alias)).leSome(detachedCriteria); } }); - criterionAdaptors.put(Query.NotIn.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.NotIn.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.NotIn criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getSubquery()); + DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery, criterion.getSubquery()); return Property.forName(getPropertyName(criterion, alias)).notIn(detachedCriteria); } }); - criterionAdaptors.put(Query.Exists.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.Exists.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Exists criterion, String alias) { final QueryableCriteria subquery = criterion.getSubquery(); @@ -164,29 +170,28 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que if (subquery.getAlias() == null) { subqueryAlias = criterion.getSubquery().getPersistentEntity().getJavaClass().getSimpleName() + ALIAS; } - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,subquery, subqueryAlias); + DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery, subquery, subqueryAlias); return Subqueries.exists(detachedCriteria); } }); - criterionAdaptors.put(Query.NotExists.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.NotExists.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.NotExists criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getSubquery()); + DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery, criterion.getSubquery()); return Subqueries.notExists(detachedCriteria); } }); } protected void addAssociationQueryCriterionAdapters() { - criterionAdaptors.put(DetachedAssociationCriteria.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(DetachedAssociationCriteria.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { DetachedAssociationCriteria existing = (DetachedAssociationCriteria) criterion; - if(existing.getAlias() == null) { + if (existing.getAlias() == null) { alias = hibernateQuery.handleAssociationQuery(existing.getAssociation(), existing.getCriteria()); - } - else{ + } else { alias = hibernateQuery.handleAssociationQuery(existing.getAssociation(), existing.getCriteria(), existing.getAlias()); } Association association = existing.getAssociation(); @@ -200,7 +205,7 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que } } }); - criterionAdaptors.put(AssociationQuery.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(AssociationQuery.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { AssociationQuery existing = (AssociationQuery) criterion; @@ -208,8 +213,7 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que String newAlias = hibernateQuery.handleAssociationQuery(existing.getAssociation(), existing.getCriteria().getCriteria()); if (alias == null) { alias = newAlias; - } - else { + } else { alias += '.' + newAlias; } applySubCriteriaToJunction(existing.getAssociation().getAssociatedEntity(), hibernateQuery, existing.getCriteria().getCriteria(), conjunction, alias); @@ -219,7 +223,7 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que } protected void addJunctionCriterionAdapters() { - criterionAdaptors.put(Query.Conjunction.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.Conjunction.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Conjunction criterion, String alias) { Conjunction conjunction = Restrictions.conjunction(); @@ -227,7 +231,7 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que return conjunction; } }); - criterionAdaptors.put(Query.Disjunction.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.Disjunction.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Disjunction criterion, String alias) { Disjunction disjunction = Restrictions.disjunction(); @@ -235,17 +239,17 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que return disjunction; } }); - criterionAdaptors.put(Query.Negation.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.Negation.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Negation criterion, String alias) { - CriterionAdaptor adapter = (CriterionAdaptor)criterionAdaptors.get(Query.Disjunction.class); + CriterionAdaptor adapter = (CriterionAdaptor) CRITERION_ADAPTORS.get(Query.Disjunction.class); return Restrictions.not(adapter.toHibernateCriterion(hibernateQuery, new Query.Disjunction(criterion.getCriteria()), alias)); } }); } protected void addRangeQueryCriterionAdapters() { - criterionAdaptors.put(Query.Between.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.Between.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { Query.Between btwCriterion = (Query.Between) criterion; @@ -253,16 +257,14 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que } }); - - criterionAdaptors.put(Query.In.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.In.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { Query.In inListQuery = (Query.In) criterion; QueryableCriteria subquery = inListQuery.getSubquery(); - if(subquery != null) { - return Property.forName(getPropertyName(criterion,alias)).in( toHibernateDetachedCriteria(hibernateQuery, subquery) ); - } - else { + if (subquery != null) { + return Property.forName(getPropertyName(criterion, alias)).in(toHibernateDetachedCriteria(hibernateQuery, subquery)); + } else { return Restrictions.in(getPropertyName(criterion, alias), inListQuery.getValues()); } } @@ -270,13 +272,13 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que } protected void addLikeCriterionAdapters() { - criterionAdaptors.put(Query.RLike.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.RLike.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { return createRlikeExpression(getPropertyName(criterion, alias), ((Query.RLike) criterion).getPattern()); } }); - criterionAdaptors.put(Query.Like.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.Like.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Like criterion, String alias) { String propertyName = getPropertyName(criterion, alias); @@ -284,7 +286,7 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que return Restrictions.like(propertyName, value); } }); - criterionAdaptors.put(Query.ILike.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.ILike.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.ILike criterion, String alias) { String propertyName = getPropertyName(criterion, alias); @@ -295,42 +297,42 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que } protected void addPropertyComparisonCriterionAdapters() { - criterionAdaptors.put(Query.EqualsProperty.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.EqualsProperty.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.EqualsProperty criterion, String alias) { String propertyName = getPropertyName(criterion, alias); return Restrictions.eqProperty(propertyName, criterion.getOtherProperty()); } }); - criterionAdaptors.put(Query.GreaterThanProperty.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.GreaterThanProperty.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanProperty criterion, String alias) { String propertyName = getPropertyName(criterion, alias); return Restrictions.gtProperty(propertyName, criterion.getOtherProperty()); } }); - criterionAdaptors.put(Query.GreaterThanEqualsProperty.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.GreaterThanEqualsProperty.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanEqualsProperty criterion, String alias) { String propertyName = getPropertyName(criterion, alias); return Restrictions.geProperty(propertyName, criterion.getOtherProperty()); } }); - criterionAdaptors.put(Query.LessThanProperty.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.LessThanProperty.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanProperty criterion, String alias) { String propertyName = getPropertyName(criterion, alias); return Restrictions.ltProperty(propertyName, criterion.getOtherProperty()); } }); - criterionAdaptors.put(Query.LessThanEqualsProperty.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.LessThanEqualsProperty.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanEqualsProperty criterion, String alias) { String propertyName = getPropertyName(criterion, alias); return Restrictions.leProperty(propertyName, criterion.getOtherProperty()); } }); - criterionAdaptors.put(Query.NotEqualsProperty.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.NotEqualsProperty.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.NotEqualsProperty criterion, String alias) { String propertyName = getPropertyName(criterion, alias); @@ -340,28 +342,28 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que } protected void addSimpleCriterionAdapters() { - criterionAdaptors.put(Query.IsNull.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.IsNull.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.IsNull criterion, String alias) { String propertyName = getPropertyName(criterion, alias); return Restrictions.isNull(propertyName); } }); - criterionAdaptors.put(Query.IsNotNull.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.IsNotNull.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.IsNotNull criterion, String alias) { String propertyName = getPropertyName(criterion, alias); return Restrictions.isNotNull(propertyName); } }); - criterionAdaptors.put(Query.IsEmpty.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.IsEmpty.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.IsEmpty criterion, String alias) { String propertyName = getPropertyName(criterion, alias); return Restrictions.isEmpty(propertyName); } }); - criterionAdaptors.put(Query.IsNotEmpty.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.IsNotEmpty.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.IsNotEmpty criterion, String alias) { String propertyName = getPropertyName(criterion, alias); @@ -371,76 +373,76 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que } protected void addSizeComparisonCriterionAdapters() { - criterionAdaptors.put(Query.SizeEquals.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.SizeEquals.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.SizeEquals criterion, String alias) { String propertyName = getPropertyName(criterion, alias); Object value = criterion.getValue(); - int size = value instanceof Number ? ((Number)value).intValue() : Integer.parseInt(value.toString()); + int size = value instanceof Number ? ((Number) value).intValue() : Integer.parseInt(value.toString()); return Restrictions.sizeEq(propertyName, size); } }); - criterionAdaptors.put(Query.SizeGreaterThan.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.SizeGreaterThan.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.SizeGreaterThan criterion, String alias) { String propertyName = getPropertyName(criterion, alias); Object value = criterion.getValue(); - int size = value instanceof Number ? ((Number)value).intValue() : Integer.parseInt(value.toString()); + int size = value instanceof Number ? ((Number) value).intValue() : Integer.parseInt(value.toString()); return Restrictions.sizeGt(propertyName, size); } }); - criterionAdaptors.put(Query.SizeGreaterThanEquals.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.SizeGreaterThanEquals.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.SizeGreaterThanEquals criterion, String alias) { String propertyName = getPropertyName(criterion, alias); Object value = criterion.getValue(); - int size = value instanceof Number ? ((Number)value).intValue() : Integer.parseInt(value.toString()); + int size = value instanceof Number ? ((Number) value).intValue() : Integer.parseInt(value.toString()); return Restrictions.sizeGe(propertyName, size); } }); - criterionAdaptors.put(Query.SizeLessThan.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.SizeLessThan.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.SizeLessThan criterion, String alias) { String propertyName = getPropertyName(criterion, alias); Object value = criterion.getValue(); - int size = value instanceof Number ? ((Number)value).intValue() : Integer.parseInt(value.toString()); + int size = value instanceof Number ? ((Number) value).intValue() : Integer.parseInt(value.toString()); return Restrictions.sizeLt(propertyName, size); } }); - criterionAdaptors.put(Query.SizeLessThanEquals.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.SizeLessThanEquals.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.SizeLessThanEquals criterion, String alias) { String propertyName = getPropertyName(criterion, alias); Object value = criterion.getValue(); - int size = value instanceof Number ? ((Number)value).intValue() : Integer.parseInt(value.toString()); + int size = value instanceof Number ? ((Number) value).intValue() : Integer.parseInt(value.toString()); return Restrictions.sizeLe(propertyName, size); } }); } protected void addSimplePropertyCriterionAdapters() { - criterionAdaptors.put(Query.IdEquals.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.IdEquals.class, new CriterionAdaptor() { @Override public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { return Restrictions.idEq(((Query.IdEquals) criterion).getValue()); } }); - criterionAdaptors.put(Query.Equals.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.Equals.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Equals criterion, String alias) { String propertyName = getPropertyName(criterion, alias); Object value = criterion.getValue(); - if(value instanceof DetachedCriteria) { + if (value instanceof DetachedCriteria) { return Property.forName(propertyName).eq((DetachedCriteria) value); } return Restrictions.eq(propertyName, value); } }); - criterionAdaptors.put(Query.NotEquals.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.NotEquals.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.NotEquals criterion, String alias) { String propertyName = getPropertyName(criterion, alias); @@ -451,7 +453,7 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que return Restrictions.ne(propertyName, value); } }); - criterionAdaptors.put(Query.GreaterThan.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.GreaterThan.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThan criterion, String alias) { String propertyName = getPropertyName(criterion, alias); @@ -462,18 +464,18 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que return Restrictions.gt(propertyName, value); } }); - criterionAdaptors.put(Query.GreaterThanEquals.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.GreaterThanEquals.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanEquals criterion, String alias) { String propertyName = getPropertyName(criterion, alias); Object value = criterion.getValue(); - if(value instanceof DetachedCriteria) { + if (value instanceof DetachedCriteria) { return Property.forName(propertyName).ge((DetachedCriteria) value); } return Restrictions.ge(propertyName, value); } }); - criterionAdaptors.put(Query.LessThan.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.LessThan.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThan criterion, String alias) { String propertyName = getPropertyName(criterion, alias); @@ -484,7 +486,7 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que return Restrictions.lt(propertyName, value); } }); - criterionAdaptors.put(Query.LessThanEquals.class, new CriterionAdaptor() { + CRITERION_ADAPTORS.put(Query.LessThanEquals.class, new CriterionAdaptor() { @Override public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanEquals criterion, String alias) { String propertyName = getPropertyName(criterion, alias); @@ -497,10 +499,11 @@ public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Que }); } - /** utility methods to group and clean up the initialization of the Criterion Adapters**/ + /** + * utility methods to group and clean up the initialization of the Criterion Adapters + **/ protected abstract Criterion createRlikeExpression(String propertyName, String pattern); - protected String getPropertyName(Query.Criterion criterion, String alias) { return calculatePropertyName(((Query.PropertyNameCriterion) criterion).getProperty(), alias); } @@ -513,50 +516,48 @@ protected String calculatePropertyName(String property, String alias) { } protected void applySubCriteriaToJunction(PersistentEntity entity, AbstractHibernateQuery hibernateCriteria, List existing, - Junction conjunction, String alias) { + Junction conjunction, String alias) { for (Query.Criterion subCriterion : existing) { if (subCriterion instanceof Query.PropertyCriterion) { Query.PropertyCriterion pc = (Query.PropertyCriterion) subCriterion; if (pc.getValue() instanceof QueryableCriteria) { pc.setValue(toHibernateDetachedCriteria(hibernateCriteria, (QueryableCriteria) pc.getValue())); - } - else { + } else { AbstractHibernateQuery.doTypeConversionIfNeccessary(entity, pc); } } - CriterionAdaptor criterionAdaptor = criterionAdaptors.get(subCriterion.getClass()); + CriterionAdaptor criterionAdaptor = CRITERION_ADAPTORS.get(subCriterion.getClass()); if (criterionAdaptor != null) { Criterion c = criterionAdaptor.toHibernateCriterion(hibernateCriteria, subCriterion, alias); - if (c != null) + if (c != null) { conjunction.add(c); - } - else if (subCriterion instanceof FunctionCallingCriterion) { + } + } else if (subCriterion instanceof FunctionCallingCriterion) { Criterion sqlRestriction = hibernateCriteria.getRestrictionForFunctionCall((FunctionCallingCriterion) subCriterion, entity); if (sqlRestriction != null) { - conjunction.add(sqlRestriction); + conjunction.add(sqlRestriction); } } } } - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - final CriterionAdaptor criterionAdaptor = criterionAdaptors.get(criterion.getClass()); + final CriterionAdaptor criterionAdaptor = CRITERION_ADAPTORS.get(criterion.getClass()); if (criterionAdaptor != null) { return criterionAdaptor.toHibernateCriterion(hibernateQuery, criterion, alias); } return null; } - protected abstract org.hibernate.criterion.DetachedCriteria toHibernateDetachedCriteria(AbstractHibernateQuery query, QueryableCriteria queryableCriteria); protected org.hibernate.criterion.DetachedCriteria toHibernateDetachedCriteria(AbstractHibernateQuery query, QueryableCriteria queryableCriteria, String alias) { return toHibernateDetachedCriteria(query, queryableCriteria); } - public static abstract class CriterionAdaptor { + public abstract static class CriterionAdaptor { + public abstract org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, T criterion, String alias); protected Object convertStringValue(Object o) { diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 9e8beae4967..57ca7f3b38c 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -18,34 +18,37 @@ */ package org.grails.orm.hibernate.query; -import java.lang.reflect.Field; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - import jakarta.persistence.FetchType; import jakarta.persistence.criteria.JoinType; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.proxy.ProxyHandler; -import org.grails.datastore.mapping.query.event.PostQueryEvent; -import org.grails.datastore.mapping.query.event.PreQueryEvent; -import org.grails.orm.hibernate.AbstractHibernateSession; -import org.grails.orm.hibernate.IHibernateTemplate; -import org.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder; -import org.grails.orm.hibernate.cfg.Mapping; -import org.grails.orm.hibernate.proxy.HibernateProxyHandler; import org.grails.datastore.gorm.finders.DynamicFinder; import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; +import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.types.Association; import org.grails.datastore.mapping.model.types.Embedded; +import org.grails.datastore.mapping.proxy.ProxyHandler; import org.grails.datastore.mapping.query.AssociationQuery; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.datastore.mapping.query.criteria.FunctionCallingCriterion; -import org.hibernate.*; -import org.hibernate.criterion.*; +import org.grails.datastore.mapping.query.event.PostQueryEvent; +import org.grails.datastore.mapping.query.event.PreQueryEvent; +import org.grails.orm.hibernate.AbstractHibernateSession; +import org.grails.orm.hibernate.IHibernateTemplate; +import org.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder; +import org.grails.orm.hibernate.cfg.Mapping; +import org.grails.orm.hibernate.proxy.HibernateProxyHandler; +import org.hibernate.Criteria; +import org.hibernate.FetchMode; +import org.hibernate.LockMode; +import org.hibernate.NonUniqueResultException; +import org.hibernate.SessionFactory; +import org.hibernate.criterion.CriteriaSpecification; +import org.hibernate.criterion.DetachedCriteria; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Restrictions; +import org.hibernate.criterion.SimpleExpression; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.function.SQLFunction; import org.hibernate.persister.entity.PropertyMapping; @@ -58,6 +61,15 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException; import org.springframework.util.ReflectionUtils; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + /** * Bridges the Query API with the Hibernate Criteria API * @@ -73,6 +85,7 @@ public abstract class AbstractHibernateQuery extends Query { protected static ConversionService conversionService = new DefaultConversionService(); protected static Field opField = ReflectionUtils.findField(SimpleExpression.class, "op"); private static final Map JOIN_STATUS_CACHE = new ConcurrentHashMap(); + static { ReflectionUtils.makeAccessible(opField); } @@ -87,14 +100,14 @@ public abstract class AbstractHibernateQuery extends Query { protected LinkedList entityStack = new LinkedList(); protected LinkedList associationStack = new LinkedList(); protected LinkedList aliasInstanceStack = new LinkedList(); - private boolean hasJoins = false; protected ProxyHandler proxyHandler = new HibernateProxyHandler(); protected final AbstractHibernateCriterionAdapter abstractHibernateCriterionAdapter; + private boolean hasJoins = false; protected AbstractHibernateQuery(Criteria criteria, AbstractHibernateSession session, PersistentEntity entity) { super(session, entity); this.criteria = criteria; - if(entity != null) { + if (entity != null) { initializeJoinStatus(); } this.abstractHibernateCriterionAdapter = createHibernateCriterionAdapter(); @@ -104,11 +117,16 @@ protected AbstractHibernateQuery(DetachedCriteria criteria, PersistentEntity ent super(null, entity); this.detachedCriteria = criteria; this.abstractHibernateCriterionAdapter = createHibernateCriterionAdapter(); - if(entity != null) { + if (entity != null) { initializeJoinStatus(); } } + protected AbstractHibernateQuery(Criteria subCriteria, AbstractHibernateSession session, PersistentEntity associatedEntity, String newAlias) { + this(subCriteria, session, associatedEntity); + alias = newAlias; + } + @Override protected Object resolveIdIfEntity(Object value) { // for Hibernate queries, the object itself is used in queries, not the id @@ -117,19 +135,17 @@ protected Object resolveIdIfEntity(Object value) { protected void initializeJoinStatus() { Boolean cachedStatus = JOIN_STATUS_CACHE.get(entity.getName()); - if(cachedStatus != null) hasJoins = cachedStatus; - else { - for(Association a : entity.getAssociations()) { - if( a.getFetchStrategy() == FetchType.EAGER ) hasJoins = true; + if (cachedStatus != null) { + hasJoins = cachedStatus; + } else { + for (Association a : entity.getAssociations()) { + if (a.getFetchStrategy() == FetchType.EAGER) { + hasJoins = true; + } } } } - protected AbstractHibernateQuery(Criteria subCriteria, AbstractHibernateSession session, PersistentEntity associatedEntity, String newAlias) { - this(subCriteria, session, associatedEntity); - alias = newAlias; - } - @Override public Query isEmpty(String property) { org.hibernate.criterion.Criterion criterion = Restrictions.isEmpty(calculatePropertyName(property)); @@ -162,8 +178,7 @@ public void add(Criterion criterion) { if (sqlRestriction != null) { addToCriteria(sqlRestriction); } - } - else if (criterion instanceof PropertyCriterion) { + } else if (criterion instanceof PropertyCriterion) { PropertyCriterion pc = (PropertyCriterion) criterion; Object value = pc.getValue(); if (value instanceof QueryableCriteria) { @@ -180,7 +195,7 @@ else if (criterion instanceof PropertyCriterion) { Association association = associationCriteria.getAssociation(); List criteria = associationCriteria.getCriteria(); - if(association instanceof Embedded) { + if (association instanceof Embedded) { String associationName = association.getName(); if (getCurrentAlias() != null) { associationName = getCurrentAlias() + '.' + associationName; @@ -191,15 +206,13 @@ else if (criterion instanceof PropertyCriterion) { addToCriteria(hibernateCriterion); } } - } - else { + } else { CriteriaAndAlias criteriaAndAlias = getCriteriaAndAlias(associationCriteria); - if(criteriaAndAlias.criteria != null) { + if (criteriaAndAlias.criteria != null) { aliasInstanceStack.add(criteriaAndAlias.criteria); - } - else if(criteriaAndAlias.detachedCriteria != null) { + } else if (criteriaAndAlias.detachedCriteria != null) { aliasInstanceStack.add(criteriaAndAlias.detachedCriteria); } aliasStack.add(criteriaAndAlias.alias); @@ -212,8 +225,7 @@ else if(criteriaAndAlias.detachedCriteria != null) { for (Criterion c : associationCriteriaList) { add(c); } - } - finally { + } finally { aliasInstanceStack.removeLast(); aliasStack.removeLast(); entityStack.removeLast(); @@ -221,8 +233,7 @@ else if(criteriaAndAlias.detachedCriteria != null) { } } - } - else { + } else { final org.hibernate.criterion.Criterion hibernateCriterion = getHibernateCriterionAdapter().toHibernateCriterion(this, criterion, getCurrentAlias()); if (hibernateCriterion != null) { @@ -231,7 +242,6 @@ else if(criteriaAndAlias.detachedCriteria != null) { } } - @Override public PersistentEntity getEntity() { if (!entityStack.isEmpty()) { @@ -241,10 +251,9 @@ public PersistentEntity getEntity() { } protected String getAssociationPath(String propertyName) { - if(propertyName.indexOf('.') > -1) { + if (propertyName.indexOf('.') > -1) { return propertyName; - } - else { + } else { StringBuilder fullPath = new StringBuilder(); for (Association association : associationStack) { @@ -286,14 +295,16 @@ static void doTypeConversionIfNeccessary(PersistentEntity entity, PropertyCriter org.hibernate.criterion.Criterion getRestrictionForFunctionCall(FunctionCallingCriterion criterion, PersistentEntity entity) { org.hibernate.criterion.Criterion sqlRestriction; - SessionFactory sessionFactory = ((IHibernateTemplate)session.getNativeInterface()).getSessionFactory(); + SessionFactory sessionFactory = ((IHibernateTemplate) session.getNativeInterface()).getSessionFactory(); String property = criterion.getProperty(); Criterion datastoreCriterion = criterion.getPropertyCriterion(); PersistentProperty pp = entity.getPropertyByName(property); - if (pp == null) throw new InvalidDataAccessResourceUsageException( - "Cannot execute function defined in query [" + criterion.getFunctionName() + - "] on non-existent property [" + property + "] of [" + entity.getJavaClass() + "]"); + if (pp == null) { + throw new InvalidDataAccessResourceUsageException( + "Cannot execute function defined in query [" + criterion.getFunctionName() + + "] on non-existent property [" + property + "] of [" + entity.getJavaClass() + "]"); + } String functionName = criterion.getFunctionName(); @@ -305,7 +316,7 @@ org.hibernate.criterion.Criterion getRestrictionForFunctionCall(FunctionCallingC if (basic != null && datastoreCriterion instanceof PropertyCriterion) { PropertyCriterion pc = (PropertyCriterion) datastoreCriterion; - final org.hibernate.criterion.Criterion hibernateCriterion = getHibernateCriterionAdapter().toHibernateCriterion(this, datastoreCriterion,alias); + final org.hibernate.criterion.Criterion hibernateCriterion = getHibernateCriterionAdapter().toHibernateCriterion(this, datastoreCriterion, alias); if (hibernateCriterion instanceof SimpleExpression) { SimpleExpression expr = (SimpleExpression) hibernateCriterion; Object op = ReflectionUtils.getField(opField, expr); @@ -313,29 +324,24 @@ org.hibernate.criterion.Criterion getRestrictionForFunctionCall(FunctionCallingC String[] columns; if (alias != null) { columns = mapping.toColumns(alias, property); - } - else { + } else { columns = mapping.toColumns(property); } String root = render(basic, Arrays.asList(columns), sessionFactory, sqlFunction); Object value = pc.getValue(); if (value != null) { sqlRestriction = Restrictions.sqlRestriction(root + op + "?", value, typeResolver.basic(value.getClass().getName())); - } - else { + } else { sqlRestriction = Restrictions.sqlRestriction(root + op + "?", value, basic); } + } else { + throw new InvalidDataAccessResourceUsageException("Unsupported function [" + functionName + "] defined in query for property [" + property + "] with type [" + pp.getType() + "]"); } - else { - throw new InvalidDataAccessResourceUsageException("Unsupported function ["+functionName+"] defined in query for property ["+property+"] with type ["+pp.getType()+"]"); - } - } - else { - throw new InvalidDataAccessResourceUsageException("Unsupported function ["+functionName+"] defined in query for property ["+property+"] with type ["+pp.getType()+"]"); + } else { + throw new InvalidDataAccessResourceUsageException("Unsupported function [" + functionName + "] defined in query for property [" + property + "] with type [" + pp.getType() + "]"); } - } - else { - throw new InvalidDataAccessResourceUsageException("Unsupported function defined in query ["+functionName+"]"); + } else { + throw new InvalidDataAccessResourceUsageException("Unsupported function defined in query [" + functionName + "]"); } return sqlRestriction; } @@ -468,10 +474,9 @@ public AssociationQuery createQuery(String associationName) { CriteriaAndAlias subCriteria = getOrCreateAlias(associationName, alias); Association association = (Association) property; - if(subCriteria.criteria != null) { + if (subCriteria.criteria != null) { return new HibernateAssociationQuery(subCriteria.criteria, (AbstractHibernateSession) getSession(), association.getAssociatedEntity(), association, alias); - } - else if(subCriteria.detachedCriteria != null) { + } else if (subCriteria.detachedCriteria != null) { return new HibernateAssociationQuery(subCriteria.detachedCriteria, (AbstractHibernateSession) getSession(), association.getAssociatedEntity(), association, alias); } } @@ -482,7 +487,7 @@ protected CriteriaAndAlias getCriteriaAndAlias(DetachedAssociationCriteria assoc String associationPath = associationCriteria.getAssociationPath(); String alias = associationCriteria.getAlias(); - if(associationPath == null) { + if (associationPath == null) { associationPath = associationCriteria.getAssociation().getName(); } return getOrCreateAlias(associationPath, alias); @@ -492,14 +497,13 @@ protected CriteriaAndAlias getOrCreateAlias(String associationName, String alias CriteriaAndAlias subCriteria = null; String associationPath = getAssociationPath(associationName); Criteria parentCriteria = criteria; - if(alias == null) { + if (alias == null) { alias = generateAlias(associationName); - } - else { + } else { CriteriaAndAlias criteriaAndAlias = createdAssociationPaths.get(alias); - if(criteriaAndAlias != null) { + if (criteriaAndAlias != null) { parentCriteria = criteriaAndAlias.criteria; - if(parentCriteria != null) { + if (parentCriteria != null) { alias = associationName + '_' + alias; associationPath = criteriaAndAlias.associationPath + '.' + associationPath; @@ -508,28 +512,26 @@ protected CriteriaAndAlias getOrCreateAlias(String associationName, String alias } if (createdAssociationPaths.containsKey(associationName)) { subCriteria = createdAssociationPaths.get(associationName); - } - else { + } else { JoinType joinType = joinTypes.get(associationName); - if(parentCriteria != null) { + if (parentCriteria != null) { Criteria sc = parentCriteria.createAlias(associationPath, alias, resolveJoinType(joinType)); subCriteria = new CriteriaAndAlias(sc, alias, associationPath); - } - else if(detachedCriteria != null) { + } else if (detachedCriteria != null) { DetachedCriteria sc = detachedCriteria.createAlias(associationPath, alias, resolveJoinType(joinType)); subCriteria = new CriteriaAndAlias(sc, alias, associationPath); } - if(subCriteria != null) { + if (subCriteria != null) { - createdAssociationPaths.put(associationPath,subCriteria); - createdAssociationPaths.put(alias,subCriteria); + createdAssociationPaths.put(associationPath, subCriteria); + createdAssociationPaths.put(alias, subCriteria); } } return subCriteria; } private org.hibernate.sql.JoinType resolveJoinType(JoinType joinType) { - if(joinType == null) { + if (joinType == null) { return org.hibernate.sql.JoinType.INNER_JOIN; } switch (joinType) { @@ -552,22 +554,25 @@ public ProjectionList projections() { @Override public Query max(int max) { - if(criteria != null) + if (criteria != null) { criteria.setMaxResults(max); + } return this; } @Override public Query maxResults(int max) { - if(criteria != null) + if (criteria != null) { criteria.setMaxResults(max); + } return this; } @Override public Query offset(int offset) { - if(criteria != null) + if (criteria != null) { criteria.setFirstResult(offset); + } return this; } @@ -598,12 +603,12 @@ public Query order(Order order) { String property = order.getProperty(); int i = property.indexOf('.'); - if(i > -1) { + if (i > -1) { - String sortHead = property.substring(0,i); + String sortHead = property.substring(0, i); String sortTail = property.substring(i + 1); - if(createdAssociationPaths.containsKey(sortHead)) { + if (createdAssociationPaths.containsKey(sortHead)) { CriteriaAndAlias criteriaAndAlias = createdAssociationPaths.get(sortHead); Criteria criteria = criteriaAndAlias.criteria; org.hibernate.criterion.Order hibernateOrder = order.getDirection() == Order.Direction.ASC ? @@ -611,22 +616,19 @@ public Query order(Order order) { org.hibernate.criterion.Order.desc(property); criteria.addOrder(order.isIgnoreCase() ? hibernateOrder.ignoreCase() : hibernateOrder); - } - else { + } else { PersistentProperty persistentProperty = entity.getPropertyByName(sortHead); - if(persistentProperty instanceof Association) { + if (persistentProperty instanceof Association) { Association a = (Association) persistentProperty; - if(persistentProperty instanceof Embedded) { + if (persistentProperty instanceof Embedded) { addSimpleOrder(order, property); - } - else { - if(criteria != null) { + } else { + if (criteria != null) { Criteria subCriteria = criteria.createCriteria(sortHead); addOrderToCriteria(subCriteria, sortTail, order); - } - else if(detachedCriteria != null) { + } else if (detachedCriteria != null) { DetachedCriteria subDetachedCriteria = detachedCriteria.createCriteria(sortHead); addOrderToDetachedCriteria(subDetachedCriteria, sortTail, order); } @@ -635,8 +637,7 @@ else if(detachedCriteria != null) { } - } - else { + } else { addSimpleOrder(order, property); } @@ -645,16 +646,16 @@ else if(detachedCriteria != null) { private void addSimpleOrder(Order order, String property) { Criteria c = criteria; - if(c != null) { + if (c != null) { addOrderToCriteria(c, property, order); - }else { + } else { DetachedCriteria dc = detachedCriteria; addOrderToDetachedCriteria(dc, property, order); } } private void addOrderToDetachedCriteria(DetachedCriteria dc, String property, Order order) { - if(dc != null) { + if (dc != null) { org.hibernate.criterion.Order hibernateOrder = order.getDirection() == Order.Direction.ASC ? org.hibernate.criterion.Order.asc(calculatePropertyName(property)) : org.hibernate.criterion.Order.desc(calculatePropertyName(property)); @@ -674,32 +675,36 @@ private void addOrderToCriteria(Criteria c, String property, Order order) { @Override public Query join(String property) { this.hasJoins = true; - if(criteria != null) + if (criteria != null) { criteria.setFetchMode(property, FetchMode.JOIN); - else if(detachedCriteria != null) + } else if (detachedCriteria != null) { detachedCriteria.setFetchMode(property, FetchMode.JOIN); + } return this; } @Override public Query select(String property) { this.hasJoins = true; - if(criteria != null) + if (criteria != null) { criteria.setFetchMode(property, FetchMode.SELECT); - else if(detachedCriteria != null) + } else if (detachedCriteria != null) { detachedCriteria.setFetchMode(property, FetchMode.SELECT); + } return this; } @Override public List list() { - if(criteria == null) throw new IllegalStateException("Cannot execute query using a detached criteria instance"); + if (criteria == null) { + throw new IllegalStateException("Cannot execute query using a detached criteria instance"); + } int projectionLength = 0; if (hibernateProjectionList != null) { org.hibernate.criterion.ProjectionList projectionList = hibernateProjectionList.getHibernateProjectionList(); projectionLength = projectionList.getLength(); - if(projectionLength > 0) { + if (projectionLength > 0) { criteria.setProjection(projectionList); } } @@ -717,25 +722,27 @@ public List list() { public List listForCriteria() { Datastore datastore = session.getDatastore(); ApplicationEventPublisher publisher = datastore.getApplicationEventPublisher(); - if(publisher != null) { + if (publisher != null) { publisher.publishEvent(new PreQueryEvent(datastore, this)); } List results = criteria.list(); - if(publisher != null) { + if (publisher != null) { publisher.publishEvent(new PostQueryEvent(datastore, this, results)); } return results; } protected void applyDefaultSortOrderAndCaching() { - if(this.orderBy.isEmpty() && entity != null) { + if (this.orderBy.isEmpty() && entity != null) { // don't apply default sorting, if projections present - if(hibernateProjectionList != null && !hibernateProjectionList.isEmpty()) return; + if (hibernateProjectionList != null && !hibernateProjectionList.isEmpty()) { + return; + } Mapping mapping = AbstractGrailsDomainBinder.getMapping(entity.getJavaClass()); - if(mapping != null) { - if(queryCache == null && mapping.getCache() != null && mapping.getCache().isEnabled()) { + if (mapping != null) { + if (queryCache == null && mapping.getCache() != null && mapping.getCache().isEnabled()) { criteria.setCacheable(true); } @@ -748,18 +755,23 @@ protected void applyDefaultSortOrderAndCaching() { protected void applyFetchStrategies() { for (Map.Entry entry : fetchStrategies.entrySet()) { - switch(entry.getValue()) { + switch (entry.getValue()) { case EAGER: - if(criteria != null) + if (criteria != null) { criteria.setFetchMode(entry.getKey(), FetchMode.JOIN); - else if(detachedCriteria != null) + } else if (detachedCriteria != null) { detachedCriteria.setFetchMode(entry.getKey(), FetchMode.JOIN); + } break; case LAZY: - if(criteria != null) + if (criteria != null) { criteria.setFetchMode(entry.getKey(), FetchMode.SELECT); - else if(detachedCriteria != null) + } else if (detachedCriteria != null) { detachedCriteria.setFetchMode(entry.getKey(), FetchMode.SELECT); + } + break; + default: + // do nothing break; } } @@ -772,7 +784,9 @@ protected void flushBeforeQuery() { @Override public Object singleResult() { - if(criteria == null) throw new IllegalStateException("Cannot execute query using a detached criteria instance"); + if (criteria == null) { + throw new IllegalStateException("Cannot execute query using a detached criteria instance"); + } if (hibernateProjectionList != null) { criteria.setProjection(hibernateProjectionList.getHibernateProjectionList()); @@ -783,22 +797,21 @@ public Object singleResult() { Datastore datastore = session.getDatastore(); ApplicationEventPublisher publisher = datastore.getApplicationEventPublisher(); - if(publisher != null) { + if (publisher != null) { publisher.publishEvent(new PreQueryEvent(datastore, this)); } Object result; - if(hasJoins) { + if (hasJoins) { try { - result = proxyHandler.unwrap(criteria.uniqueResult());; + result = proxyHandler.unwrap(criteria.uniqueResult()); } catch (NonUniqueResultException e) { result = singleResultViaListCall(); } - } - else { + } else { result = singleResultViaListCall(); } - if(publisher != null) { + if (publisher != null) { publisher.publishEvent(new PostQueryEvent(datastore, this, Collections.singletonList(result))); } return result; @@ -806,17 +819,16 @@ public Object singleResult() { private Object singleResultViaListCall() { criteria.setMaxResults(1); - if(hibernateProjectionList != null && hibernateProjectionList.isRowCount()) { + if (hibernateProjectionList != null && hibernateProjectionList.isRowCount()) { criteria.setFirstResult(0); } List results = criteria.list(); - if(results.size()>0) { + if (results.size() > 0) { return proxyHandler.unwrap(results.get(0)); } return null; } - @Override protected List executeQuery(PersistentEntity entity, Junction criteria) { return list(); @@ -843,20 +855,18 @@ protected void addToCriteria(org.hibernate.criterion.Criterion criterion) { } if (aliasInstanceStack.isEmpty()) { - if(criteria != null) { + if (criteria != null) { criteria.add(criterion); - } - else if(detachedCriteria != null) { + } else if (detachedCriteria != null) { detachedCriteria.add(criterion); } - } - else { + } else { Object criteriaObject = aliasInstanceStack.getLast(); - if(criteriaObject instanceof Criteria) - ((Criteria)criteriaObject).add(criterion); - else if(criteriaObject instanceof DetachedCriteria) { - ((DetachedCriteria)criteriaObject).add(criterion); + if (criteriaObject instanceof Criteria) { + ((Criteria) criteriaObject).add(criterion); + } else if (criteriaObject instanceof DetachedCriteria) { + ((DetachedCriteria) criteriaObject).add(criterion); } } } @@ -900,8 +910,7 @@ public Junction add(Criterion c) { if (sqlRestriction != null) { hibernateJunction.add(sqlRestriction); } - } - else { + } else { AbstractHibernateCriterionAdapter adapter = getHibernateCriterionAdapter(); org.hibernate.criterion.Criterion criterion = adapter.toHibernateCriterion(AbstractHibernateQuery.this, c, alias); if (criterion != null) { @@ -931,7 +940,6 @@ public boolean isEmpty() { return projectionList.getLength() == 0; } - @Override public ProjectionList add(Projection p) { projectionList.add(new HibernateProjectionAdapter(p).toHibernateProjection()); @@ -1002,10 +1010,11 @@ public ProjectionList avg(String name) { @Override public ProjectionList distinct() { - if(criteria != null) + if (criteria != null) { criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - else if(detachedCriteria != null) + } else if (detachedCriteria != null) { detachedCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); + } return this; } } @@ -1033,11 +1042,14 @@ public HibernateAssociationQuery(DetachedCriteria criteria, AbstractHibernateSes public Query order(Order order) { Order.Direction direction = order.getDirection(); - switch(direction) { + switch (direction) { case ASC: assocationCriteria.addOrder(org.hibernate.criterion.Order.asc(order.getProperty())); case DESC: assocationCriteria.addOrder(org.hibernate.criterion.Order.desc(order.getProperty())); + default: + // do nothing + break; } return super.order(order); } @@ -1050,15 +1062,13 @@ public Query isEmpty(String property) { } protected void addToCriteria(org.hibernate.criterion.Criterion criterion) { - if (hibernateJunction != null) { - hibernateJunction.add(criterion); - } - else if(assocationCriteria != null) { - assocationCriteria.add(criterion); - } - else if(detachedAssocationCriteria != null) { - detachedAssocationCriteria.add(criterion); - } + if (hibernateJunction != null) { + hibernateJunction.add(criterion); + } else if (assocationCriteria != null) { + assocationCriteria.add(criterion); + } else if (detachedAssocationCriteria != null) { + detachedAssocationCriteria.add(criterion); + } } @Override @@ -1201,6 +1211,7 @@ public Query rlike(String property, String expr) { } protected class CriteriaAndAlias { + protected DetachedCriteria detachedCriteria; protected Criteria criteria; protected String alias; diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java index 8a12def8605..f2a2236d156 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java @@ -16,18 +16,24 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.query; -import org.grails.datastore.mapping.config.Property; -import org.grails.datastore.mapping.reflect.ClassUtils; -import org.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder; -import org.grails.orm.hibernate.cfg.Mapping; +import jakarta.persistence.LockModeType; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Expression; +import jakarta.persistence.criteria.From; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Root; import org.grails.datastore.gorm.finders.DynamicFinder; +import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.types.Association; import org.grails.datastore.mapping.model.types.Embedded; +import org.grails.datastore.mapping.reflect.ClassUtils; +import org.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder; +import org.grails.orm.hibernate.cfg.Mapping; import org.hibernate.Criteria; import org.hibernate.FetchMode; import org.hibernate.FlushMode; @@ -36,11 +42,8 @@ import org.hibernate.query.Query; import org.springframework.core.convert.ConversionService; -import jakarta.persistence.LockModeType; -import jakarta.persistence.criteria.*; import java.util.Map; - /** * Utility methods for configuring Hibernate queries * @@ -179,12 +182,12 @@ public static void populateArgumentsForCriteria( Map sortMap = (Map) sortObj; for (Object sort : sortMap.keySet()) { final String order = DynamicFinder.ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? DynamicFinder.ORDER_DESC : DynamicFinder.ORDER_ASC; - addOrderPossiblyNested(query,queryRoot, criteriaBuilder, entity, (String) sort, order, ignoreCase); + addOrderPossiblyNested(query, queryRoot, criteriaBuilder, entity, (String) sort, order, ignoreCase); } } else { final String sort = (String) sortObj; final String order = DynamicFinder.ORDER_DESC.equalsIgnoreCase(orderParam) ? DynamicFinder.ORDER_DESC : DynamicFinder.ORDER_ASC; - addOrderPossiblyNested(query, queryRoot, criteriaBuilder,entity, sort, order, ignoreCase); + addOrderPossiblyNested(query, queryRoot, criteriaBuilder, entity, sort, order, ignoreCase); } } else if (useDefaultMapping) { Mapping m = AbstractGrailsDomainBinder.getMapping(entity.getJavaClass()); @@ -192,7 +195,7 @@ public static void populateArgumentsForCriteria( Map sortMap = m.getSort().getNamesAndDirections(); for (Object sort : sortMap.keySet()) { final String order = DynamicFinder.ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? DynamicFinder.ORDER_DESC : DynamicFinder.ORDER_ASC; - addOrderPossiblyNested(query,queryRoot, criteriaBuilder, entity, (String) sort, order, true); + addOrderPossiblyNested(query, queryRoot, criteriaBuilder, entity, (String) sort, order, true); } } } @@ -279,7 +282,6 @@ private static void addOrderPossiblyNested(Criteria c, PersistentEntity entity, } } - /** * Add order to criteria, creating necessary subCriteria if nested sort property (ie. sort:'nested.property'). */ diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateCriterionAdapter.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateCriterionAdapter.java index c5e779ea4cf..cb85a364898 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateCriterionAdapter.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateCriterionAdapter.java @@ -20,9 +20,6 @@ import grails.orm.HibernateCriteriaBuilder; import grails.orm.RlikeExpression; - -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.DetachedCriteria; diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java index e0a5f41914a..d7c003bc57e 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.query; import org.grails.datastore.mapping.core.Datastore; @@ -36,6 +35,7 @@ * @since 6.0 */ public class HibernateHqlQuery extends Query { + private final org.hibernate.query.Query query; public HibernateHqlQuery(Session session, PersistentEntity entity, org.hibernate.query.Query query) { @@ -55,13 +55,12 @@ protected List executeQuery(PersistentEntity entity, Junction criteria) { PreQueryEvent preQueryEvent = new PreQueryEvent(datastore, this); applicationEventPublisher.publishEvent(preQueryEvent); - if(uniqueResult) { + if (uniqueResult) { query.setMaxResults(1); List results = query.list(); applicationEventPublisher.publishEvent(new PostQueryEvent(datastore, this, results)); return results; - } - else { + } else { List results = query.list(); applicationEventPublisher.publishEvent(new PostQueryEvent(datastore, this, results)); diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateProjectionAdapter.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateProjectionAdapter.java index 971dba57ff0..380d761b732 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateProjectionAdapter.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateProjectionAdapter.java @@ -18,13 +18,13 @@ */ package org.grails.orm.hibernate.query; -import java.util.HashMap; -import java.util.Map; - import org.grails.datastore.mapping.query.Query; import org.hibernate.criterion.Projection; import org.hibernate.criterion.Projections; +import java.util.HashMap; +import java.util.Map; + /** * Adapts Grails datastore API to Hibernate projections. * @@ -32,41 +32,42 @@ * @since 2.0 */ public class HibernateProjectionAdapter { + + private static final Map, ProjectionAdapter> ADAPTER_MAP = new HashMap<>(); private Query.Projection projection; - private static Map, ProjectionAdapter> adapterMap = new HashMap<>(); static { - adapterMap.put(Query.AvgProjection.class, gormProjection -> { + ADAPTER_MAP.put(Query.AvgProjection.class, gormProjection -> { Query.AvgProjection avg = (Query.AvgProjection) gormProjection; return Projections.avg(avg.getPropertyName()); }); - adapterMap.put(Query.IdProjection.class, gormProjection -> Projections.id()); - adapterMap.put(Query.SumProjection.class, gormProjection -> { + ADAPTER_MAP.put(Query.IdProjection.class, gormProjection -> Projections.id()); + ADAPTER_MAP.put(Query.SumProjection.class, gormProjection -> { Query.SumProjection avg = (Query.SumProjection) gormProjection; return Projections.sum(avg.getPropertyName()); }); - adapterMap.put(Query.DistinctPropertyProjection.class, gormProjection -> { + ADAPTER_MAP.put(Query.DistinctPropertyProjection.class, gormProjection -> { Query.DistinctPropertyProjection avg = (Query.DistinctPropertyProjection) gormProjection; return Projections.distinct(Projections.property(avg.getPropertyName())); }); - adapterMap.put(Query.PropertyProjection.class, gormProjection -> { + ADAPTER_MAP.put(Query.PropertyProjection.class, gormProjection -> { Query.PropertyProjection avg = (Query.PropertyProjection) gormProjection; return Projections.property(avg.getPropertyName()); }); - adapterMap.put(Query.CountProjection.class, gormProjection -> Projections.rowCount()); - adapterMap.put(Query.CountDistinctProjection.class, gormProjection -> { + ADAPTER_MAP.put(Query.CountProjection.class, gormProjection -> Projections.rowCount()); + ADAPTER_MAP.put(Query.CountDistinctProjection.class, gormProjection -> { Query.CountDistinctProjection cd = (Query.CountDistinctProjection) gormProjection; return Projections.countDistinct(cd.getPropertyName()); }); - adapterMap.put(Query.GroupPropertyProjection.class, gormProjection -> { + ADAPTER_MAP.put(Query.GroupPropertyProjection.class, gormProjection -> { Query.GroupPropertyProjection cd = (Query.GroupPropertyProjection) gormProjection; return Projections.groupProperty(cd.getPropertyName()); }); - adapterMap.put(Query.MaxProjection.class, gormProjection -> { + ADAPTER_MAP.put(Query.MaxProjection.class, gormProjection -> { Query.MaxProjection cd = (Query.MaxProjection) gormProjection; return Projections.max(cd.getPropertyName()); }); - adapterMap.put(Query.MinProjection.class, gormProjection -> { + ADAPTER_MAP.put(Query.MinProjection.class, gormProjection -> { Query.MinProjection cd = (Query.MinProjection) gormProjection; return Projections.min(cd.getPropertyName()); }); @@ -77,12 +78,15 @@ public HibernateProjectionAdapter(Query.Projection projection) { } public Projection toHibernateProjection() { - ProjectionAdapter projectionAdapter = adapterMap.get(projection.getClass()); - if(projectionAdapter == null) throw new UnsupportedOperationException("Unsupported projection used: " + projection.getClass().getName()); + ProjectionAdapter projectionAdapter = ADAPTER_MAP.get(projection.getClass()); + if (projectionAdapter == null) { + throw new UnsupportedOperationException("Unsupported projection used: " + projection.getClass().getName()); + } return projectionAdapter.toHibernateProjection(projection); } private interface ProjectionAdapter { + Projection toHibernateProjection(Query.Projection gormProjection); } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java index 2bf3b138830..642ee203505 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java @@ -20,19 +20,12 @@ import grails.orm.HibernateCriteriaBuilder; import grails.orm.RlikeExpression; - -import java.sql.SQLException; -import java.util.Iterator; -import java.util.List; - +import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.orm.hibernate.AbstractHibernateSession; import org.grails.orm.hibernate.GrailsHibernateTemplate; import org.grails.orm.hibernate.HibernateSession; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.dialect.Dialect; @@ -43,6 +36,9 @@ import org.hibernate.type.BasicType; import org.hibernate.type.TypeResolver; +import java.util.Iterator; +import java.util.List; + /** * Bridges the Query API with the Hibernate Criteria API * diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQueryConstants.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQueryConstants.java index 0f85cd090ed..4d0b2e9c7fa 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQueryConstants.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQueryConstants.java @@ -16,14 +16,13 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.query; /** * Constants used for query arguments etc. * - * @since 3.0.7 * @author Graeme Rocher + * @since 3.0.7 */ public interface HibernateQueryConstants { diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/PagedResultList.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/PagedResultList.java index 5ae8f7dc4e6..eb96372d042 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/PagedResultList.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/query/PagedResultList.java @@ -18,15 +18,15 @@ */ package org.grails.orm.hibernate.query; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.orm.hibernate.GrailsHibernateTemplate; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.query.Query; -import jakarta.persistence.criteria.CriteriaBuilder; -import jakarta.persistence.criteria.CriteriaQuery; -import jakarta.persistence.criteria.Root; import java.sql.SQLException; public class PagedResultList extends grails.gorm.PagedResultList { @@ -64,7 +64,7 @@ public Integer doInHibernate(Session session) throws HibernateException, SQLExce final CriteriaQuery finalQuery = criteriaQuery.select(criteriaBuilder.count(queryRoot)).distinct(true).orderBy(); final Query query = session.createQuery(finalQuery); hibernateTemplate.applySettings(query); - return ((Number)query.uniqueResult()).intValue(); + return ((Number) query.uniqueResult()).intValue(); } }); } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/AbstractClosureEventTriggeringInterceptor.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/AbstractClosureEventTriggeringInterceptor.java index 9379b11fd98..e8cd24ef2ec 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/AbstractClosureEventTriggeringInterceptor.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/AbstractClosureEventTriggeringInterceptor.java @@ -16,11 +16,17 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.support; import org.hibernate.event.internal.DefaultSaveOrUpdateEventListener; -import org.hibernate.event.spi.*; +import org.hibernate.event.spi.PostDeleteEventListener; +import org.hibernate.event.spi.PostInsertEventListener; +import org.hibernate.event.spi.PostLoadEventListener; +import org.hibernate.event.spi.PostUpdateEventListener; +import org.hibernate.event.spi.PreDeleteEventListener; +import org.hibernate.event.spi.PreInsertEventListener; +import org.hibernate.event.spi.PreLoadEventListener; +import org.hibernate.event.spi.PreUpdateEventListener; import org.springframework.context.ApplicationContextAware; /** @@ -39,4 +45,5 @@ public abstract class AbstractClosureEventTriggeringInterceptor extends DefaultS PreDeleteEventListener, PreUpdateEventListener, PreInsertEventListener { + } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventListener.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventListener.java index c3e694a7c45..1748c810e58 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventListener.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventListener.java @@ -39,7 +39,25 @@ import org.hibernate.action.internal.EntityUpdateAction; import org.hibernate.engine.spi.ActionQueue; import org.hibernate.engine.spi.ExecutableList; -import org.hibernate.event.spi.*; +import org.hibernate.event.spi.AbstractEvent; +import org.hibernate.event.spi.AbstractPreDatabaseOperationEvent; +import org.hibernate.event.spi.PostDeleteEvent; +import org.hibernate.event.spi.PostDeleteEventListener; +import org.hibernate.event.spi.PostInsertEvent; +import org.hibernate.event.spi.PostInsertEventListener; +import org.hibernate.event.spi.PostLoadEvent; +import org.hibernate.event.spi.PostLoadEventListener; +import org.hibernate.event.spi.PostUpdateEvent; +import org.hibernate.event.spi.PostUpdateEventListener; +import org.hibernate.event.spi.PreDeleteEvent; +import org.hibernate.event.spi.PreDeleteEventListener; +import org.hibernate.event.spi.PreInsertEvent; +import org.hibernate.event.spi.PreLoadEvent; +import org.hibernate.event.spi.PreLoadEventListener; +import org.hibernate.event.spi.PreUpdateEvent; +import org.hibernate.event.spi.PreUpdateEventListener; +import org.hibernate.event.spi.SaveOrUpdateEvent; +import org.hibernate.event.spi.SaveOrUpdateEventListener; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.tuple.entity.EntityMetamodel; import org.slf4j.Logger; @@ -71,8 +89,8 @@ public class ClosureEventListener implements SaveOrUpdateEventListener, PreDeleteEventListener, PreUpdateEventListener { - private static final long serialVersionUID = 1; protected static final Logger LOG = LoggerFactory.getLogger(ClosureEventListener.class); + private static final long serialVersionUID = 1; private final EventTriggerCaller saveOrUpdateCaller; private final EventTriggerCaller beforeInsertCaller; @@ -101,10 +119,9 @@ public ClosureEventListener(PersistentEntity persistentEntity, boolean failOnErr saveOrUpdateCaller = buildCaller(AbstractPersistenceEvent.ONLOAD_SAVE, domainClazz); beforeInsertCaller = buildCaller(AbstractPersistenceEvent.BEFORE_INSERT_EVENT, domainClazz); EventTriggerCaller preLoadEventCaller = buildCaller(AbstractPersistenceEvent.ONLOAD_EVENT, domainClazz); - if (preLoadEventCaller == null) { + if (preLoadEventCaller == null) { this.preLoadEventCaller = buildCaller(AbstractPersistenceEvent.BEFORE_LOAD_EVENT, domainClazz); - } - else { + } else { this.preLoadEventCaller = preLoadEventCaller; } @@ -127,16 +144,15 @@ public ClosureEventListener(PersistentEntity persistentEntity, boolean failOnErr validateParams.put(AbstractHibernateGormValidationApi.ARGUMENT_DEEP_VALIDATE, Boolean.FALSE); try { - actionQueueUpdatesField=ReflectionUtils.findField(ActionQueue.class, "updates"); + actionQueueUpdatesField = ReflectionUtils.findField(ActionQueue.class, "updates"); actionQueueUpdatesField.setAccessible(true); - entityUpdateActionStateField=ReflectionUtils.findField(EntityUpdateAction.class, "state"); + entityUpdateActionStateField = ReflectionUtils.findField(EntityUpdateAction.class, "state"); entityUpdateActionStateField.setAccessible(true); } catch (Exception e) { // ignore } } - public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException { // no-op, merely a hook for plugins to override } @@ -282,7 +298,7 @@ public void onValidate(ValidationEvent event) { protected boolean doValidate(Object entity) { boolean evict = false; GormValidateable validateable = (GormValidateable) entity; - if ( !validateable.shouldSkipValidation() + if (!validateable.shouldSkipValidation() && !validateable.validate(validateParams)) { evict = true; if (failOnErrorEnabled) { @@ -306,25 +322,27 @@ private void synchronizePersisterState(AbstractPreDatabaseOperationEvent event, private void synchronizePersisterState(AbstractPreDatabaseOperationEvent event, Object[] state, EntityPersister persister, String[] propertyNames) { Object entity = event.getEntity(); EntityReflector reflector = persistentEntity.getReflector(); - HashMap changedState= new HashMap<>(); + HashMap changedState = new HashMap<>(); EntityMetamodel entityMetamodel = persister.getEntityMetamodel(); for (int i = 0; i < propertyNames.length; i++) { String p = propertyNames[i]; Integer index = entityMetamodel.getPropertyIndexOrNull(p); - if(index == null) continue; - + if (index == null) { + continue; + } + PersistentProperty property = persistentEntity.getPropertyByName(p); if (property == null) { continue; } String propertyName = property.getName(); - if(GormProperties.VERSION.equals(propertyName)) { + if (GormProperties.VERSION.equals(propertyName)) { continue; } Object value = reflector.getProperty(entity, propertyName); - if(state[index] != value) { + if (state[index] != value) { changedState.put(i, value); } state[index] = value; @@ -335,23 +353,22 @@ private void synchronizePersisterState(AbstractPreDatabaseOperationEvent event, private void synchronizeEntityUpdateActionState(AbstractPreDatabaseOperationEvent event, Object entity, HashMap changedState) { - if(actionQueueUpdatesField != null && event instanceof PreInsertEvent && changedState.size() > 0) { + if (actionQueueUpdatesField != null && event instanceof PreInsertEvent && changedState.size() > 0) { try { - ExecutableList updates = (ExecutableList)actionQueueUpdatesField.get(event.getSession().getActionQueue()); - if(updates != null) { + ExecutableList updates = (ExecutableList) actionQueueUpdatesField.get(event.getSession().getActionQueue()); + if (updates != null) { for (EntityUpdateAction updateAction : updates) { - if(updateAction.getInstance() == entity) { - Object[] updateState = (Object[])entityUpdateActionStateField.get(updateAction); + if (updateAction.getInstance() == entity) { + Object[] updateState = (Object[]) entityUpdateActionStateField.get(updateAction); if (updateState != null) { - for(Map.Entry entry : changedState.entrySet()) { + for (Map.Entry entry : changedState.entrySet()) { updateState[entry.getKey()] = entry.getValue(); } } } } } - } - catch (Exception e) { + } catch (Exception e) { LOG.warn("Error synchronizing object state with Hibernate: " + e.getMessage(), e); } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java index b5f03c11157..8782929d495 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java @@ -81,7 +81,7 @@ public void setEventPublisher(ConfigurableApplicationEventPublisher eventPublish @Override public void onSaveOrUpdate(SaveOrUpdateEvent hibernateEvent) throws HibernateException { Object entity = getEntity(hibernateEvent); - if(entity != null && proxyHandler.isInitialized(entity)) { + if (entity != null && proxyHandler.isInitialized(entity)) { activateDirtyChecking(entity); org.grails.datastore.mapping.engine.event.SaveOrUpdateEvent grailsEvent = new org.grails.datastore.mapping.engine.event.SaveOrUpdateEvent( this.datastore, entity); @@ -92,10 +92,9 @@ public void onSaveOrUpdate(SaveOrUpdateEvent hibernateEvent) throws HibernateExc protected Object getEntity(SaveOrUpdateEvent hibernateEvent) { Object object = hibernateEvent.getObject(); - if(object != null) { + if (object != null) { return object; - } - else { + } else { return hibernateEvent.getEntity(); } } @@ -119,18 +118,17 @@ public boolean onPreInsert(PreInsertEvent hibernateEvent) { PersistentEntity persistentEntity = mappingContext.getPersistentEntity(type.getName()); AbstractPersistenceEvent grailsEvent; ModificationTrackingEntityAccess entityAccess = null; - if(persistentEntity != null) { + if (persistentEntity != null) { entityAccess = new ModificationTrackingEntityAccess(mappingContext.createEntityAccess(persistentEntity, entity)); grailsEvent = new org.grails.datastore.mapping.engine.event.PreInsertEvent(this.datastore, persistentEntity, entityAccess); - } - else { + } else { grailsEvent = new org.grails.datastore.mapping.engine.event.PreInsertEvent(this.datastore, entity); } publishEvent(hibernateEvent, grailsEvent); boolean cancelled = grailsEvent.isCancelled(); - if(!cancelled && entityAccess != null) { + if (!cancelled && entityAccess != null) { synchronizeHibernateState(hibernateEvent, entityAccess); } return cancelled; @@ -138,7 +136,7 @@ public boolean onPreInsert(PreInsertEvent hibernateEvent) { private void synchronizeHibernateState(PreInsertEvent hibernateEvent, ModificationTrackingEntityAccess entityAccess) { Map modifiedProperties = entityAccess.getModifiedProperties(); - if(!modifiedProperties.isEmpty()) { + if (!modifiedProperties.isEmpty()) { Object[] state = hibernateEvent.getState(); EntityPersister persister = hibernateEvent.getPersister(); synchronizeHibernateState(persister, state, modifiedProperties); @@ -175,9 +173,9 @@ private void updateModifiedPropertiesWithAutoTimestamp(Map modif private void synchronizeHibernateState(EntityPersister persister, Object[] state, Map modifiedProperties) { EntityMetamodel entityMetamodel = persister.getEntityMetamodel(); - for(Map.Entry entry : modifiedProperties.entrySet()) { + for (Map.Entry entry : modifiedProperties.entrySet()) { Integer index = entityMetamodel.getPropertyIndexOrNull(entry.getKey()); - if(index != null) { + if (index != null) { state[index] = entry.getValue(); } } @@ -198,17 +196,16 @@ public boolean onPreUpdate(PreUpdateEvent hibernateEvent) { PersistentEntity persistentEntity = mappingContext.getPersistentEntity(type.getName()); AbstractPersistenceEvent grailsEvent; ModificationTrackingEntityAccess entityAccess = null; - if(persistentEntity != null) { + if (persistentEntity != null) { entityAccess = new ModificationTrackingEntityAccess(mappingContext.createEntityAccess(persistentEntity, entity)); grailsEvent = new org.grails.datastore.mapping.engine.event.PreUpdateEvent(this.datastore, persistentEntity, entityAccess); - } - else { + } else { grailsEvent = new org.grails.datastore.mapping.engine.event.PreUpdateEvent(this.datastore, entity); } publishEvent(hibernateEvent, grailsEvent); boolean cancelled = grailsEvent.isCancelled(); - if(!cancelled && entityAccess != null) { + if (!cancelled && entityAccess != null) { boolean autoTimestamp = persistentEntity.getMapping().getMappedForm().isAutoTimestamp(); synchronizeHibernateState(hibernateEvent, entityAccess, autoTimestamp); } @@ -238,7 +235,7 @@ public void onPostDelete(PostDeleteEvent hibernateEvent) { private void publishEvent(AbstractEvent hibernateEvent, AbstractPersistenceEvent mappingEvent) { mappingEvent.setNativeEvent(hibernateEvent); - if(eventPublisher != null) { + if (eventPublisher != null) { eventPublisher.publishEvent(mappingEvent); } } @@ -248,29 +245,28 @@ public boolean requiresPostCommitHanding(EntityPersister persister) { return false; } - @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - if(applicationContext instanceof ConfigurableApplicationContext) { + if (applicationContext instanceof ConfigurableApplicationContext) { this.eventPublisher = new ConfigurableApplicationContextEventPublisher((ConfigurableApplicationContext) applicationContext); } } private void activateDirtyChecking(Object entity) { - if(entity instanceof DirtyCheckable && proxyHandler.isInitialized(entity)) { + if (entity instanceof DirtyCheckable && proxyHandler.isInitialized(entity)) { PersistentEntity persistentEntity = mappingContext.getPersistentEntity(Hibernate.getClass(entity).getName()); entity = proxyHandler.unwrap(entity); DirtyCheckable dirtyCheckable = (DirtyCheckable) entity; Map dirtyCheckingState = persistentEntity.getReflector().getDirtyCheckingState(entity); - if(dirtyCheckingState == null) { + if (dirtyCheckingState == null) { dirtyCheckable.trackChanges(); for (Embedded association : persistentEntity.getEmbedded()) { - if(DirtyCheckable.class.isAssignableFrom(association.getType())) { + if (DirtyCheckable.class.isAssignableFrom(association.getType())) { Object embedded = association.getReader().read(entity); - if(embedded != null) { + if (embedded != null) { DirtyCheckable embeddedCheck = (DirtyCheckable) embedded; - if(embeddedCheck.listDirtyPropertyNames().isEmpty()) { + if (embeddedCheck.listDirtyPropertyNames().isEmpty()) { embeddedCheck.trackChanges(); } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/DataSourceFactoryBean.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/DataSourceFactoryBean.groovy index 3859372de45..cd77639fabf 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/DataSourceFactoryBean.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/DataSourceFactoryBean.groovy @@ -22,8 +22,6 @@ package org.grails.orm.hibernate.support import org.grails.orm.hibernate.AbstractHibernateDatastore import org.grails.orm.hibernate.connections.HibernateConnectionSource import org.springframework.beans.factory.FactoryBean -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.beans.factory.annotation.Qualifier import javax.sql.DataSource @@ -44,7 +42,7 @@ class DataSourceFactoryBean implements FactoryBean { @Override DataSource getObject() throws Exception { - ((HibernateConnectionSource)datastore.connectionSources.getConnectionSource(connectionName)).dataSource + ((HibernateConnectionSource) datastore.connectionSources.getConnectionSource(connectionName)).dataSource } @Override diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreConnectionSourcesRegistrar.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreConnectionSourcesRegistrar.groovy index 1e39988a84d..d2e28ee0d8a 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreConnectionSourcesRegistrar.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreConnectionSourcesRegistrar.groovy @@ -54,12 +54,12 @@ class HibernateDatastoreConnectionSourcesRegistrar implements BeanDefinitionRegi @Override void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { - for(String dataSourceName in dataSourceNames) { + for (String dataSourceName in dataSourceNames) { boolean isDefault = dataSourceName == ConnectionSource.DEFAULT || dataSourceName == Settings.SETTING_DATASOURCE - boolean shouldConfigureDataSourceBean = GrailsVersion.isAtLeastMajorMinor(3,3) + boolean shouldConfigureDataSourceBean = GrailsVersion.isAtLeastMajorMinor(3, 3) String dataSourceBeanName = isDefault ? Settings.SETTING_DATASOURCE : "${Settings.SETTING_DATASOURCE}_$dataSourceName" - if(!registry.containsBeanDefinition(dataSourceBeanName) && shouldConfigureDataSourceBean) { + if (!registry.containsBeanDefinition(dataSourceBeanName) && shouldConfigureDataSourceBean) { def dataSourceBean = new RootBeanDefinition() dataSourceBean.setTargetType(DataSource) dataSourceBean.setBeanClass(InstanceFactoryBean) @@ -72,7 +72,7 @@ class HibernateDatastoreConnectionSourcesRegistrar implements BeanDefinitionRegi registry.registerBeanDefinition(dataSourceBeanName, dataSourceBean) } - if(!isDefault) { + if (!isDefault) { String suffix = '_' + dataSourceName String sessionFactoryName = "sessionFactory$suffix" String transactionManagerBeanName = "transactionManager$suffix" diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreFactoryBean.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreFactoryBean.groovy index ec72c5de213..f414cb6a673 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreFactoryBean.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreFactoryBean.groovy @@ -28,6 +28,7 @@ import org.springframework.beans.factory.FactoryBean import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContextAware import org.springframework.core.env.PropertyResolver + /** * Helper for constructing the datastore * @@ -62,7 +63,7 @@ public class HibernateDatastoreFactoryBean AbstractHibernateDatastore datastore = objectType.newInstance(mappingContext, sessionFactory, configuration, dataSourceName) - if(applicationContext != null) { + if (applicationContext != null) { datastore.setApplicationContext(applicationContext) } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java index 50ce661f036..a4401c39889 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java @@ -18,12 +18,6 @@ */ package org.grails.orm.hibernate.support; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.Properties; - -import javax.sql.DataSource; - import org.grails.orm.hibernate.exceptions.CouldNotDetermineHibernateDialectException; import org.hibernate.HibernateException; import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; @@ -32,7 +26,11 @@ import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl; import org.hibernate.engine.jdbc.dialect.internal.StandardDialectResolver; -import org.hibernate.engine.jdbc.dialect.spi.*; +import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter; +import org.hibernate.engine.jdbc.dialect.spi.DialectFactory; +import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; +import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource; +import org.hibernate.engine.jdbc.dialect.spi.DialectResolver; import org.hibernate.service.Service; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.spi.ServiceBinding; @@ -45,6 +43,11 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Properties; + /** * @author Steven Devijver * @author Graeme Rocher @@ -88,7 +91,7 @@ public void afterPropertiesSet() throws MetaDataAccessException { Connection connection = null; - String dbName = (String)JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductName"); + String dbName = (String) JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductName"); try { connection = DataSourceUtils.getConnection(dataSource); @@ -113,12 +116,12 @@ public DialectResolutionInfo getDialectResolutionInfo() { hibernateDialectClassName = vendorNameDialectMappings.getProperty(dbName); } - if (!StringUtils.hasText(hibernateDialectClassName)) { + if (!StringUtils.hasText(hibernateDialectClassName)) { throw new CouldNotDetermineHibernateDialectException( "Could not determine Hibernate dialect for database name [" + dbName + "]!"); - } + } } finally { - DataSourceUtils.releaseConnection(connection,dataSource); + DataSourceUtils.releaseConnection(connection, dataSource); } } diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy index ee03ca5f337..46bcc950be0 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy @@ -20,15 +20,15 @@ package org.grails.orm.hibernate.support import groovy.transform.CompileStatic +import org.codehaus.groovy.runtime.StringGroovyMethods import org.grails.datastore.gorm.GormValidateable +import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.model.config.GormProperties +import org.grails.datastore.mapping.model.types.Association +import org.grails.datastore.mapping.model.types.OneToOne import org.grails.datastore.mapping.proxy.ProxyHandler import org.grails.datastore.mapping.validation.ValidationErrors import org.grails.orm.hibernate.proxy.HibernateProxyHandler -import org.codehaus.groovy.runtime.StringGroovyMethods -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.model.types.Association -import org.grails.datastore.mapping.model.types.OneToOne import org.hibernate.Session import org.hibernate.SessionFactory import org.springframework.core.convert.ConversionService @@ -43,6 +43,7 @@ import org.springframework.validation.FieldError */ @CompileStatic class HibernateRuntimeUtils { + private static ProxyHandler proxyHandler = new HibernateProxyHandler(); private static final String DYNAMIC_FILTER_ENABLER = "dynamicFilterEnabler"; @@ -71,9 +72,9 @@ class HibernateRuntimeUtils { MetaClass mc = isGormValidateable ? null : GroovySystem.metaClassRegistry.getMetaClass(target.getClass()) def errors = new ValidationErrors(target) - Errors originalErrors = isGormValidateable ? ((GormValidateable)target).getErrors() : (Errors) mc.getProperty(target, GormProperties.ERRORS) + Errors originalErrors = isGormValidateable ? ((GormValidateable) target).getErrors() : (Errors) mc.getProperty(target, GormProperties.ERRORS) for (Object o in originalErrors.fieldErrors) { - FieldError fe = (FieldError)o + FieldError fe = (FieldError) o if (fe.isBindingFailure()) { errors.addError(new FieldError(fe.getObjectName(), fe.field, @@ -85,10 +86,9 @@ class HibernateRuntimeUtils { } } - if(isGormValidateable) { - ((GormValidateable)target).setErrors(errors) - } - else { + if (isGormValidateable) { + ((GormValidateable) target).setErrors(errors) + } else { mc.setProperty(target, GormProperties.ERRORS, errors); } return errors; @@ -96,7 +96,7 @@ class HibernateRuntimeUtils { public static void autoAssociateBidirectionalOneToOnes(PersistentEntity entity, Object target) { def mappingContext = entity.mappingContext - for (Association association : entity.associations) { + for (Association association : entity.associations) { if (!(association instanceof OneToOne) || !association.bidirectional || !association.owningSide) { continue } @@ -112,7 +112,6 @@ class HibernateRuntimeUtils { continue } - def entityReflector = mappingContext.getEntityReflector(entity) Object inverseObject = entityReflector.getProperty(target, propertyName) if (inverseObject == null) { @@ -135,23 +134,23 @@ class HibernateRuntimeUtils { static Object convertValueToType(Object passedValue, Class targetType, ConversionService conversionService) { // workaround for GROOVY-6127, do not assign directly in parameters before it's fixed Object value = passedValue - if(targetType != null && value != null && !(value in targetType)) { + if (targetType != null && value != null && !(value in targetType)) { if (value instanceof CharSequence) { value = value.toString() - if(value in targetType) { + if (value in targetType) { return value } } try { - if (value instanceof Number && (targetType==Long || targetType==Integer)) { - if(targetType == Long) { - value = ((Number)value).toLong() + if (value instanceof Number && (targetType == Long || targetType == Integer)) { + if (targetType == Long) { + value = ((Number) value).toLong() } else { - value = ((Number)value).toInteger() + value = ((Number) value).toInteger() } } else if (value instanceof String && targetType in Number) { String strValue = value.trim() - if(targetType == Long) { + if (targetType == Long) { value = Long.parseLong(strValue) } else if (targetType == Integer) { value = Integer.parseInt(strValue) diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateVersionSupport.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateVersionSupport.java index 64e62a35dc7..498775db1ad 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateVersionSupport.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateVersionSupport.java @@ -19,12 +19,10 @@ package org.grails.orm.hibernate.support; import org.grails.datastore.mapping.core.grailsversion.GrailsVersion; -import org.grails.datastore.mapping.reflect.ClassUtils; -import org.hibernate.*; -import org.springframework.util.Assert; -import org.springframework.util.ReflectionUtils; - -import java.lang.reflect.Method; +import org.hibernate.FlushMode; +import org.hibernate.Hibernate; +import org.hibernate.Query; +import org.hibernate.Session; /** * @@ -32,15 +30,14 @@ * * @author Graeme Rocher * @author Juergen Hoeller - * * @since 6.0 * */ public class HibernateVersionSupport { - /** * Get the native Hibernate FlushMode, adapting between Hibernate 5.0/5.1 and 5.2+. + * * @param session the Hibernate Session to get the flush mode from * @return the FlushMode (never {@code null}) * @since 4.3 @@ -53,6 +50,7 @@ public static FlushMode getFlushMode(Session session) { /** * Set the native Hibernate FlushMode, adapting between Hibernate 5.0/5.1 and 5.2+. + * * @param session the Hibernate Session to get the flush mode from * @since 4.3 * @deprecated Previously used for Hibernate backwards, will be removed in a future release. @@ -64,6 +62,7 @@ public static void setFlushMode(Session session, FlushMode flushMode) { /** * Check the current hibernate version + * * @param required The required version * @return True if it is at least the given version */ @@ -80,7 +79,7 @@ public static boolean isAtLeastVersion(String required) { * Creates a query * * @param session The session - * @param query The query + * @param query The query * @return The created query * @deprecated Previously used for Hibernate backwards, will be removed in a future release. */ diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/SoftKey.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/SoftKey.java index faec3a90045..635bebc7110 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/SoftKey.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/support/SoftKey.java @@ -26,6 +26,7 @@ * @author Lari Hotari */ public class SoftKey extends SoftReference { + final int hash; public SoftKey(T referent) { @@ -50,7 +51,7 @@ public boolean equals(Object obj) { return false; } @SuppressWarnings("unchecked") - SoftKey other = (SoftKey)obj; + SoftKey other = (SoftKey) obj; if (hash != other.hash) { return false; } @@ -60,8 +61,7 @@ public boolean equals(Object obj) { if (otherReferent != null) { return false; } - } - else if (!referent.equals(otherReferent)) { + } else if (!referent.equals(otherReferent)) { return false; } return true; diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/transaction/HibernateJtaTransactionManagerAdapter.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/transaction/HibernateJtaTransactionManagerAdapter.java index eee227bbfc9..c69b246ecf5 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/transaction/HibernateJtaTransactionManagerAdapter.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/transaction/HibernateJtaTransactionManagerAdapter.java @@ -16,13 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.transaction; -import jakarta.transaction.*; -import javax.transaction.xa.XAResource; - -import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; +import jakarta.transaction.RollbackException; +import jakarta.transaction.Status; +import jakarta.transaction.Synchronization; +import jakarta.transaction.SystemException; +import jakarta.transaction.Transaction; +import jakarta.transaction.TransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; @@ -30,31 +31,34 @@ import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; +import javax.transaction.xa.XAResource; + /** * Adapter for adding transaction controlling hooks for supporting * Hibernate's org.hibernate.engine.transaction.Isolater class's interaction with transactions - * + *

* This is required when there is no real JTA transaction manager in use and Spring's - * {@link TransactionAwareDataSourceProxy} is used. - * + * {@link org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy} is used. + *

* Without this solution, using Hibernate's TableGenerator identity strategies will fail to support transactions. * The id generator will commit the current transaction and break transactional behaviour. - * + *

* The javadoc of Hibernate's {@code TableHiLoGenerator} states this. However this isn't mentioned in the javadocs of other TableGenerators. - * + * * @author Lari Hotari */ public class HibernateJtaTransactionManagerAdapter implements TransactionManager { + PlatformTransactionManager springTransactionManager; - ThreadLocal currentTransactionHolder= new ThreadLocal<>(); - + ThreadLocal currentTransactionHolder = new ThreadLocal<>(); + public HibernateJtaTransactionManagerAdapter(PlatformTransactionManager springTransactionManager) { this.springTransactionManager = springTransactionManager; } - + @Override public void begin() { - TransactionDefinition definition=new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW); + TransactionDefinition definition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW); currentTransactionHolder.set(springTransactionManager.getTransaction(definition)); } @@ -68,21 +72,21 @@ public void commit() throws public void rollback() throws IllegalStateException, SecurityException { springTransactionManager.rollback(getAndRemoveStatus()); } - + @Override public void setRollbackOnly() throws IllegalStateException { currentTransactionHolder.get().setRollbackOnly(); } - + protected TransactionStatus getAndRemoveStatus() { - TransactionStatus status=currentTransactionHolder.get(); + TransactionStatus status = currentTransactionHolder.get(); currentTransactionHolder.remove(); return status; } @Override public int getStatus() { - TransactionStatus status=currentTransactionHolder.get(); + TransactionStatus status = currentTransactionHolder.get(); return convertToJtaStatus(status); } @@ -95,7 +99,7 @@ protected static int convertToJtaStatus(TransactionStatus status) { } else { return Status.STATUS_ACTIVE; } - } else { + } else { return Status.STATUS_NO_TRANSACTION; } } @@ -107,7 +111,7 @@ public Transaction getTransaction() { @Override public void resume(Transaction tobj) throws IllegalStateException { - TransactionAdapter transaction = (TransactionAdapter)tobj; + TransactionAdapter transaction = (TransactionAdapter) tobj; // commit the PROPAGATION_NOT_SUPPORTED transaction returned in suspend springTransactionManager.commit(transaction.transactionStatus); } @@ -117,23 +121,24 @@ public Transaction suspend() { currentTransactionHolder.set(springTransactionManager.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_NOT_SUPPORTED))); return new TransactionAdapter(springTransactionManager, currentTransactionHolder); } - + @Override public void setTransactionTimeout(int seconds) { - + } private static class TransactionAdapter implements Transaction { + PlatformTransactionManager springTransactionManager; TransactionStatus transactionStatus; ThreadLocal currentTransactionHolder; - + TransactionAdapter(PlatformTransactionManager springTransactionManager, ThreadLocal currentTransactionHolder) { this.springTransactionManager = springTransactionManager; this.currentTransactionHolder = currentTransactionHolder; this.transactionStatus = currentTransactionHolder.get(); } - + @Override public void commit() throws SecurityException, IllegalStateException { @@ -165,7 +170,7 @@ public void registerSynchronization(final Synchronization sync) throws RollbackE public void beforeCompletion() { sync.beforeCompletion(); } - + @Override public void afterCompletion(int status) { int jtaStatus; @@ -178,35 +183,44 @@ public void afterCompletion(int status) { } sync.afterCompletion(jtaStatus); } - - public void suspend() { } - public void resume() { } - public void flush() { } - public void beforeCommit(boolean readOnly) { } - public void afterCommit() { } + + public void suspend() { + } + + public void resume() { + } + + public void flush() { + } + + public void beforeCommit(boolean readOnly) { + } + + public void afterCommit() { + } }); } @Override public void rollback() throws IllegalStateException, SystemException { springTransactionManager.rollback(transactionStatus); - currentTransactionHolder.remove(); + currentTransactionHolder.remove(); } @Override public void setRollbackOnly() throws IllegalStateException, SystemException { transactionStatus.setRollbackOnly(); } - + @Override public boolean equals(Object obj) { - if(obj == this) { + if (obj == this) { return true; } else if (obj == null) { return false; } else if (obj.getClass() == TransactionAdapter.class) { - TransactionAdapter other = (TransactionAdapter)obj; - if(other.transactionStatus == this.transactionStatus) { + TransactionAdapter other = (TransactionAdapter) obj; + if (other.transactionStatus == this.transactionStatus) { return true; } else if (other.transactionStatus != null) { return other.transactionStatus.equals(this.transactionStatus); @@ -217,7 +231,7 @@ public boolean equals(Object obj) { return false; } } - + @Override public int hashCode() { return transactionStatus != null ? transactionStatus.hashCode() : System.identityHashCode(this); diff --git a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/transaction/PlatformTransactionManagerProxy.java b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/transaction/PlatformTransactionManagerProxy.java index 8e90d0d345c..e22b304cdf3 100644 --- a/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/transaction/PlatformTransactionManagerProxy.java +++ b/grails-data-hibernate5/core/src/main/groovy/org/grails/orm/hibernate/transaction/PlatformTransactionManagerProxy.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.orm.hibernate.transaction; import org.springframework.transaction.PlatformTransactionManager; @@ -31,6 +30,7 @@ * @author Burt Beckwith */ public class PlatformTransactionManagerProxy implements PlatformTransactionManager { + private PlatformTransactionManager targetTransactionManager; public PlatformTransactionManagerProxy() { @@ -56,4 +56,4 @@ public PlatformTransactionManager getTargetTransactionManager() { public void setTargetTransactionManager(PlatformTransactionManager targetTransactionManager) { this.targetTransactionManager = targetTransactionManager; } -} \ No newline at end of file +} diff --git a/grails-data-hibernate5/dbmigration/build.gradle b/grails-data-hibernate5/dbmigration/build.gradle index 9fd197a1fd0..25f2f4e900c 100644 --- a/grails-data-hibernate5/dbmigration/build.gradle +++ b/grails-data-hibernate5/dbmigration/build.gradle @@ -110,4 +110,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/grails-extension-gradle-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-data-hibernate5/dbmigration/grails-app/conf/logback.groovy b/grails-data-hibernate5/dbmigration/grails-app/conf/logback.groovy index f9f0967baec..e5f8ee3ac63 100644 --- a/grails-data-hibernate5/dbmigration/grails-app/conf/logback.groovy +++ b/grails-data-hibernate5/dbmigration/grails-app/conf/logback.groovy @@ -27,7 +27,7 @@ import java.nio.charset.StandardCharsets conversionRule 'clr', ColorConverter conversionRule 'wex', WhitespaceThrowableProxyConverter -// See http://logback.qos.ch/manual/groovy.html for details on configuration +// See https://logback.qos.ch/manual/groovy.html for details on configuration appender('STDOUT', ConsoleAppender) { encoder(PatternLayoutEncoder) { charset = StandardCharsets.UTF_8 diff --git a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/DatabaseMigrationGrailsPlugin.groovy b/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/DatabaseMigrationGrailsPlugin.groovy index 771ed86765b..26160dd408a 100644 --- a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/DatabaseMigrationGrailsPlugin.groovy +++ b/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/DatabaseMigrationGrailsPlugin.groovy @@ -40,11 +40,10 @@ class DatabaseMigrationGrailsPlugin extends Plugin { def title = "Grails Database Migration Plugin" // Headline display name of the plugin def author = "Kazuki YAMAMOTO" - def authorEmail = "" def description = 'Grails Database Migration Plugin' - def documentation = "http://grails.org/plugin/database-migration" + def documentation = "https://docs.grails.org" def license = "APACHE" - def scm = [url: "https://github.com/grails-plugins/grails-database-migration"] + def scm = [url: "https://github.com/apache/grails-core"] @Override Closure doWithSpring() { diff --git a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommand.groovy b/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommand.groovy index 3b0afc70f7e..c41228b269f 100644 --- a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommand.groovy +++ b/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommand.groovy @@ -39,7 +39,6 @@ import liquibase.command.core.DiffCommandStep import liquibase.command.core.GenerateChangelogCommandStep import liquibase.command.core.helpers.AbstractChangelogCommandStep import liquibase.command.core.helpers.DbUrlConnectionArgumentsCommandStep -import liquibase.command.core.helpers.DbUrlConnectionCommandStep import liquibase.command.core.helpers.DiffOutputControlCommandStep import liquibase.command.core.helpers.PreCompareCommandStep import liquibase.command.core.helpers.ReferenceDbUrlConnectionCommandStep @@ -265,7 +264,6 @@ trait DatabaseMigrationCommand { .addArgumentValue(GenerateChangelogCommandStep.RUN_ON_CHANGE_TYPES_ARG, AbstractChangelogCommandStep.RUN_ON_CHANGE_TYPES_ARG.getDefaultValue()) .addArgumentValue(GenerateChangelogCommandStep.REPLACE_IF_EXISTS_TYPES_ARG, AbstractChangelogCommandStep.REPLACE_IF_EXISTS_TYPES_ARG.getDefaultValue()); - if(diffOutputControl.isReplaceIfExistsSet()) { command.addArgumentValue(GenerateChangelogCommandStep.USE_OR_REPLACE_OPTION, true) } diff --git a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyDiffToChangeLogCommandStep.groovy b/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyDiffToChangeLogCommandStep.groovy index 94771e3b3b5..ce297ce6327 100644 --- a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyDiffToChangeLogCommandStep.groovy +++ b/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyDiffToChangeLogCommandStep.groovy @@ -18,6 +18,7 @@ */ package org.grails.plugins.databasemigration.liquibase +import grails.util.GrailsStringUtils import groovy.transform.CompileStatic import liquibase.command.CommandResultsBuilder import liquibase.command.CommandScope @@ -31,7 +32,6 @@ import liquibase.database.ObjectQuotingStrategy import liquibase.diff.DiffResult import liquibase.diff.output.DiffOutputControl import liquibase.serializer.ChangeLogSerializerFactory -import grails.util.GrailsStringUtils @CompileStatic class GroovyDiffToChangeLogCommandStep extends DiffChangelogCommandStep { diff --git a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyGenerateChangeLogCommandStep.groovy b/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyGenerateChangeLogCommandStep.groovy index f9430191d48..e03fbc05b06 100644 --- a/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyGenerateChangeLogCommandStep.groovy +++ b/grails-data-hibernate5/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyGenerateChangeLogCommandStep.groovy @@ -18,6 +18,7 @@ */ package org.grails.plugins.databasemigration.liquibase +import grails.util.GrailsStringUtils import groovy.transform.CompileStatic import liquibase.Scope import liquibase.command.CommandResultsBuilder @@ -33,7 +34,6 @@ import liquibase.diff.DiffResult import liquibase.diff.output.DiffOutputControl import liquibase.diff.output.changelog.DiffToChangeLog import liquibase.serializer.ChangeLogSerializerFactory -import grails.util.GrailsStringUtils @CompileStatic class GroovyGenerateChangeLogCommandStep extends GenerateChangelogCommandStep { diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/configuration.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/configuration.adoc index 6c022e4a321..7c2f097fb9f 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/configuration.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/configuration.adoc @@ -27,14 +27,14 @@ There are a few configuration options for the plugin. All configurations are pre |changelogLocation |`grails-app/migrations` |the folder containing the main changelog file (which can include one or more other files) |changelogFileName |`changelog.groovy` |the name of the main changelog file |changelogProperties |none |a map of properties to use for property substitution in Groovy DSL changelogs -|contexts |none |A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run +|contexts |none |A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run |dbDocLocation |`target/dbdoc` |the directory where the output from the <> script is written |dbDocController.enabled |`true` in dev mode |whether the /dbdoc/ url is accessible at runtime |dropOnStart |`false` |if `true` then drops all tables before auto-running migrations (if updateOnStart is true) |updateOnStart |`false` |if `true` then changesets from the specified list of names will be run at startup |updateOnStartFileName |none |the file name (relative to `changelogLocation`) to run at startup if `updateOnStart` is `true` |updateOnStartDefaultSchema |none |the default schema to use when running auto-migrate on start -|updateOnStartContexts |none |A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run +|updateOnStartContexts |none |A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run |updateAllOnStart |false |if `true` then changesets from the specified list of names will be run at startup for all dataSources. Useful for Grails Multitenancy with Multiple Databases (same db schema) |autoMigrateScripts |['RunApp'] |the scripts when running auto-migrate. Useful to run auto-migrate during test phase with: ['RunApp', 'TestApp'] |excludeObjects |none |A comma-delimited list of database object names to ignore while performing a dbm-gorm-diff or dbm-generate-gorm-changelog diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/groovyChanges.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/groovyChanges.adoc index 63cef1ea114..ad3b0a1cd98 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/groovyChanges.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/groovyChanges.adoc @@ -19,7 +19,7 @@ under the License. === Groovy Changes -In addition to the built-in Liquibase changes (see http://www.liquibase.org/manual/home[the documentation] for what's available) you can also make database changes using Groovy code (as long as you're using the Groovy DSL file format). These changes use the `grailsChange` tag name and are contained in a `changeSet` tag like standard built-in tags. +In addition to the built-in Liquibase changes (see https://www.liquibase.org/manual/home[the documentation] for what's available) you can also make database changes using Groovy code (as long as you're using the Groovy DSL file format). These changes use the `grailsChange` tag name and are contained in a `changeSet` tag like standard built-in tags. There are four supported inner tags and two callable methods (to override the default confirmation message and checksum value). diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/groovyPreconditions.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/groovyPreconditions.adoc index b1cf087f24d..197c8a53db9 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/groovyPreconditions.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/groovyPreconditions.adoc @@ -19,7 +19,7 @@ under the License. === Groovy Preconditions -In addition to the built-in Liquibase preconditions (see http://www.liquibase.org/manual/preconditions[the documentation] for what's available) you can also specify preconditions using Groovy code (as long as you're using the Groovy DSL file format). These changes use the `grailsPrecondition` tag name and are contained in the `databaseChangeLog` tag or in a `changeSet` tag like standard built-in tags. +In addition to the built-in Liquibase preconditions (see https://www.liquibase.org/manual/preconditions[the documentation] for what's available) you can also specify preconditions using Groovy code (as long as you're using the Groovy DSL file format). These changes use the `grailsPrecondition` tag name and are contained in the `databaseChangeLog` tag or in a `changeSet` tag like standard built-in tags. ==== General format diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/introduction.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/introduction.adoc index 86020cd09db..c34d4e78d2c 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/introduction.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/introduction.adoc @@ -19,7 +19,7 @@ under the License. === Introduction -The Database Migration plugin helps you manage database changes while developing Grails applications. The plugin uses the http://www.liquibase.org/[Liquibase] library. +The Database Migration plugin helps you manage database changes while developing Grails applications. The plugin uses the https://www.liquibase.org/[Liquibase] library. Using this plugin (and Liquibase in general) adds some structure and process to managing database changes. It will help avoid inconsistencies, communication issues, and other problems with ad-hoc approaches. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Documentation Scripts/dbm-db-doc.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Documentation Scripts/dbm-db-doc.adoc index 70432449ff1..519016e839a 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Documentation Scripts/dbm-db-doc.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Documentation Scripts/dbm-db-doc.adoc @@ -38,7 +38,7 @@ Required arguments: _none_ . Optional arguments: * `destination` - The path to write to -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. NOTE: Note that the `contexts` and `dataSource` parameter name and value must be quoted if executed in Windows, e.g. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-changelog-sync-sql.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-changelog-sync-sql.adoc index b420bb0ea1e..eff35d72cb4 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-changelog-sync-sql.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-changelog-sync-sql.adoc @@ -38,7 +38,7 @@ Required arguments: __none__. Optional arguments: * `filename` - The path to the output file to write to. If not specified output is written to the console -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-changelog-sync.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-changelog-sync.adoc index d01ac50af15..09747f8ff86 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-changelog-sync.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-changelog-sync.adoc @@ -37,7 +37,7 @@ Required arguments: __none__. Optional arguments: -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included * `defaultSchema` - The default schema name to use * `dataSource` - If provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-mark-next-changeset-ran.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-mark-next-changeset-ran.adoc index 92c9e5e9240..330c23e333a 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-mark-next-changeset-ran.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-mark-next-changeset-ran.adoc @@ -38,7 +38,7 @@ Required arguments: __none__. Optional arguments: * `filename` - The path to the output file to write to -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-status.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-status.adoc index ea161d69c21..2e6b1bbbc81 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-status.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Maintenance Scripts/dbm-status.adoc @@ -37,7 +37,7 @@ Optional arguments: * `filename` - The path to the output file to write to. If not specified output is written to the console * `verbose` - If `true` (the default) the changesets are listed; if `false` only the count is displayed -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-future-rollback-sql.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-future-rollback-sql.adoc index f8cad410955..1f2b4af1faa 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-future-rollback-sql.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-future-rollback-sql.adoc @@ -36,7 +36,7 @@ Required arguments: _none_ . Optional arguments: * `filename` - The path to the output file to write to. If not specified output is written to the console -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-generate-changelog.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-generate-changelog.adoc index fad29777c5e..713df5144b9 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-generate-changelog.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-generate-changelog.adoc @@ -42,7 +42,7 @@ Required arguments: _none_ . Optional arguments: * `filename` - The path to the output file to write to. If not specified output is written to the console -* `diffTypes` - A comma-delimited list of change types to include - see http://www.liquibase.org/manual/diff#controlling_checks_since_1.8[the documentation] for what types are available +* `diffTypes` - A comma-delimited list of change types to include - see https://www.liquibase.org/manual/diff#controlling_checks_since_1.8[the documentation] for what types are available * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. * `add` - if specified add an include in the root changelog file referencing the new file diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-count-sql.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-count-sql.adoc index a43305cc85e..f922cc0382b 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-count-sql.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-count-sql.adoc @@ -39,7 +39,7 @@ Required arguments: Optional arguments: * `filename` - The path to the output file to write to. If not specified output is written to the console -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-count.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-count.adoc index 2dcf1ef35b0..034962620f2 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-count.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-count.adoc @@ -38,7 +38,7 @@ Required arguments: Optional arguments: -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-sql.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-sql.adoc index 80fd0e1ab7a..c8fb392c529 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-sql.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-sql.adoc @@ -40,7 +40,7 @@ Required arguments: Optional arguments: * `filename` - The path to the output file to write to. If not specified output is written to the console -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-to-date-sql.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-to-date-sql.adoc index ba498f2f1e0..3083d8d33a9 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-to-date-sql.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-to-date-sql.adoc @@ -41,7 +41,7 @@ Optional arguments: * `time` - The rollback time * `filename` - The path to the output file to write to. If not specified output is written to the console -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-to-date.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-to-date.adoc index b115237bfd2..1860a3538b1 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-to-date.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback-to-date.adoc @@ -40,7 +40,7 @@ Required arguments: Optional arguments: * `time` - The rollback time -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be included * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback.adoc index 07869dcbe8b..b134cdaa125 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Rollback Scripts/dbm-rollback.adoc @@ -39,7 +39,7 @@ Required arguments: Optional arguments: -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-previous-changeset-sql.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-previous-changeset-sql.adoc index 03d506d08f7..f1f7d040722 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-previous-changeset-sql.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-previous-changeset-sql.adoc @@ -41,7 +41,7 @@ Optional arguments: * `filename` - The path to the output file to write to. If not specified output is written to the console * `skip` - The number of changesets to skip if you want to exclude recent ones -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run * `defaultSchema` - The default schema name to use NOTE: Note that the `contexts` and `defaultSchema` parameter name and value must be quoted if executed in Windows, e.g. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update-count-sql.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update-count-sql.adoc index 32b82237cc7..b3fdd0ac3a2 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update-count-sql.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update-count-sql.adoc @@ -42,7 +42,7 @@ Required arguments: Optional arguments: * `filename` - The path to the output file to write to. If not specified output is written to the console -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update-count.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update-count.adoc index d8b039ab0ba..ba26395c0e0 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update-count.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update-count.adoc @@ -39,7 +39,7 @@ Required arguments: Optional arguments: -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update-sql.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update-sql.adoc index bd528ca8189..cdfb2280db6 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update-sql.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update-sql.adoc @@ -40,7 +40,7 @@ Required arguments: _none_ . Optional arguments: * `filename` - The path to the output file to write to. If not specified output is written to the console -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update.adoc b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update.adoc index d2a9fb5dfe7..4ee55feefcc 100644 --- a/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update.adoc +++ b/grails-data-hibernate5/docs/src/docs/asciidoc/databaseMigration/ref/Update Scripts/dbm-update.adoc @@ -37,7 +37,7 @@ Required arguments: _none_ . Optional arguments: -* `contexts` - A comma-delimited list of http://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run +* `contexts` - A comma-delimited list of https://www.liquibase.org/manual/contexts[context] names. If specified, only changesets tagged with one of the context names will be run * `defaultSchema` - The default schema name to use * `dataSource` - if provided will run the script for the specified dataSource. Not needed for the default dataSource. diff --git a/grails-data-hibernate5/grails-plugin/build.gradle b/grails-data-hibernate5/grails-plugin/build.gradle index d9a30d22ae2..29dee27599f 100644 --- a/grails-data-hibernate5/grails-plugin/build.gradle +++ b/grails-data-hibernate5/grails-plugin/build.gradle @@ -89,4 +89,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/grails-extension-gradle-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy index 14f1748e563..da6c0df35c0 100644 --- a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy +++ b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy @@ -46,6 +46,7 @@ import javax.sql.DataSource */ @Slf4j class HibernateDatastoreSpringInitializer extends AbstractDatastoreInitializer { + public static final String SESSION_FACTORY_BEAN_NAME = "sessionFactory" public static final String DEFAULT_DATA_SOURCE_NAME = Settings.SETTING_DATASOURCE public static final String DATA_SOURCES = Settings.SETTING_DATASOURCES; @@ -88,18 +89,17 @@ class HibernateDatastoreSpringInitializer extends AbstractDatastoreInitializer { Set dataSourceNames = new HashSet() - if(config == null) { + if (config == null) { dataSourceNames = [defaultDataSourceBeanName] as Set - } - else { + } else { Map dataSources = config.getProperty(DATA_SOURCES, Map.class, Collections.emptyMap()) if (dataSources != null && !dataSources.isEmpty()) { - dataSourceNames.addAll( AbstractConnectionSources.toValidConnectionSourceNames(dataSources) ) + dataSourceNames.addAll(AbstractConnectionSources.toValidConnectionSourceNames(dataSources)) } - Map dataSource = (Map)config.getProperty(DEFAULT_DATA_SOURCE_NAME, Map.class, Collections.emptyMap()) + Map dataSource = (Map) config.getProperty(DEFAULT_DATA_SOURCE_NAME, Map.class, Collections.emptyMap()) if (dataSource != null && !dataSource.isEmpty()) { - dataSourceNames.add( ConnectionSource.DEFAULT ) + dataSourceNames.add(ConnectionSource.DEFAULT) } } this.dataSources = dataSourceNames @@ -151,23 +151,23 @@ class HibernateDatastoreSpringInitializer extends AbstractDatastoreInitializer { bean.autowire = true dataSourceConnectionSourceFactory = ref('dataSourceConnectionSourceFactory') } - hibernateDatastore(HibernateDatastore, config, hibernateConnectionSourceFactory, eventPublisher) { bean-> + hibernateDatastore(HibernateDatastore, config, hibernateConnectionSourceFactory, eventPublisher) { bean -> bean.primary = true } - sessionFactory(hibernateDatastore:'getSessionFactory') { bean-> + sessionFactory(hibernateDatastore: 'getSessionFactory') { bean -> bean.primary = true } - transactionManager(hibernateDatastore:"getTransactionManager") { bean-> + transactionManager(hibernateDatastore: "getTransactionManager") { bean -> bean.primary = true } - autoTimestampEventListener(hibernateDatastore:"getAutoTimestampEventListener") + autoTimestampEventListener(hibernateDatastore: "getAutoTimestampEventListener") getBeanDefinition("transactionManager").beanClass = PlatformTransactionManager hibernateDatastoreConnectionSourcesRegistrar(HibernateDatastoreConnectionSourcesRegistrar, dataSources) // domain model mapping context, used for configuration - grailsDomainClassMappingContext(hibernateDatastore:"getMappingContext") + grailsDomainClassMappingContext(hibernateDatastore: "getMappingContext") loadDataServices(null) - .each {serviceName, serviceClass-> + .each { serviceName, serviceClass -> "$serviceName"(DatastoreServiceMethodInvokingFactoryBean, serviceClass) { targetObject = ref("hibernateDatastore") targetMethod = 'getService' @@ -175,8 +175,8 @@ class HibernateDatastoreSpringInitializer extends AbstractDatastoreInitializer { } } - if(isGrailsPresent) { - if(ClassUtils.isPresent("org.grails.plugin.hibernate.support.AggregatePersistenceContextInterceptor")) { + if (isGrailsPresent) { + if (ClassUtils.isPresent("org.grails.plugin.hibernate.support.AggregatePersistenceContextInterceptor")) { ClassLoader cl = ClassUtils.getClassLoader() persistenceInterceptor(cl.loadClass("org.grails.plugin.hibernate.support.AggregatePersistenceContextInterceptor"), ref("hibernateDatastore")) proxyHandler(cl.loadClass("org.grails.datastore.gorm.proxy.ProxyHandlerAdapter"), ref('hibernateProxyHandler')) diff --git a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy index 902df434989..1a5fa1e8725 100644 --- a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy +++ b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy @@ -64,36 +64,39 @@ class HibernateGrailsPlugin extends Plugin { Set dataSourceNames - Closure doWithSpring() {{-> - ConfigurableApplicationContext applicationContext = (ConfigurableApplicationContext) applicationContext - - GrailsApplication grailsApplication = grailsApplication - Config config = grailsApplication.config - if(config instanceof PropertySourcesConfig) { - ConfigurableConversionService conversionService = applicationContext.getEnvironment().getConversionService() - conversionService.addConverter(new Converter() { - @Override - Class convert(String source) { - Class.forName(source) - } - }) - ((PropertySourcesConfig)config).setConversionService(conversionService) + Closure doWithSpring() { + { -> + ConfigurableApplicationContext applicationContext = (ConfigurableApplicationContext) applicationContext + + GrailsApplication grailsApplication = grailsApplication + Config config = grailsApplication.config + if (config instanceof PropertySourcesConfig) { + ConfigurableConversionService conversionService = applicationContext.getEnvironment().getConversionService() + conversionService.addConverter(new Converter() { + + @Override + Class convert(String source) { + Class.forName(source) + } + }) + ((PropertySourcesConfig) config).setConversionService(conversionService) + } + + + def domainClasses = grailsApplication.getArtefacts(DomainClassArtefactHandler.TYPE) + .collect() { GrailsClass cls -> cls.clazz } + + def springInitializer = new HibernateDatastoreSpringInitializer((PropertyResolver) config, domainClasses) + springInitializer.enableReload = Environment.isDevelopmentMode() + springInitializer.registerApplicationIfNotPresent = false + springInitializer.grailsPlugin = true + dataSourceNames = springInitializer.dataSources + def beans = springInitializer.getBeanDefinitions((BeanDefinitionRegistry) applicationContext) + + beans.delegate = delegate + beans.call() } - - - def domainClasses = grailsApplication.getArtefacts(DomainClassArtefactHandler.TYPE) - .collect() { GrailsClass cls -> cls.clazz } - - def springInitializer = new HibernateDatastoreSpringInitializer((PropertyResolver)config, domainClasses) - springInitializer.enableReload = Environment.isDevelopmentMode() - springInitializer.registerApplicationIfNotPresent = false - springInitializer.grailsPlugin = true - dataSourceNames = springInitializer.dataSources - def beans = springInitializer.getBeanDefinitions((BeanDefinitionRegistry)applicationContext) - - beans.delegate = delegate - beans.call() - }} + } @Override diff --git a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/commands/SchemaExportCommand.groovy b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/commands/SchemaExportCommand.groovy index 9f4b1cc6bb8..91e4f1d6d2f 100644 --- a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/commands/SchemaExportCommand.groovy +++ b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/commands/SchemaExportCommand.groovy @@ -25,16 +25,10 @@ import groovy.transform.CompileStatic import org.grails.build.parsing.CommandLine import org.grails.datastore.mapping.core.connections.ConnectionSource import org.grails.orm.hibernate.HibernateDatastore -import org.grails.orm.hibernate.HibernateMappingContextSessionFactoryBean -import org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration -import org.hibernate.boot.MetadataBuilder -import org.hibernate.boot.MetadataSources -import org.hibernate.boot.spi.MetadataImplementor import org.hibernate.engine.spi.SessionFactoryImplementor -import org.hibernate.service.ServiceRegistry -import org.hibernate.service.spi.ServiceRegistryImplementor import org.hibernate.tool.hbm2ddl.SchemaExport as HibernateSchemaExport import org.hibernate.tool.schema.TargetType + /** * Adds a schema-export command * @@ -56,11 +50,11 @@ class SchemaExportCommand implements ApplicationCommand { boolean stdout = false for (arg in commandLine.remainingArgs) { - switch(arg) { - case 'export': export = true; break + switch (arg) { + case 'export': export = true; break case 'generate': export = false; break - case 'stdout': stdout = true; break - default: filename = arg + case 'stdout': stdout = true; break + default: filename = arg } } @@ -73,8 +67,8 @@ class SchemaExportCommand implements ApplicationCommand { HibernateDatastore hibernateDatastore = applicationContext.getBean("hibernateDatastore", HibernateDatastore) hibernateDatastore = hibernateDatastore.getDatastoreForConnection(dataSourceName) - def serviceRegistry = ((SessionFactoryImplementor)hibernateDatastore.sessionFactory).getServiceRegistry() - .getParentServiceRegistry() + def serviceRegistry = ((SessionFactoryImplementor) hibernateDatastore.sessionFactory).getServiceRegistry() + .getParentServiceRegistry() def metadata = hibernateDatastore.metadata def schemaExport = new HibernateSchemaExport() @@ -82,23 +76,21 @@ class SchemaExportCommand implements ApplicationCommand { .setOutputFile(file.path) .setDelimiter(';') - String action = export ? "Exporting" : "Generating script to ${file.path}" String ds = argsMap.datasource ? "for DataSource '$argsMap.datasource'" : "for the default DataSource" println "$action in environment '${Environment.current.name}' $ds" EnumSet targetTypes - if(stdout) { + if (stdout) { targetTypes = EnumSet.of(TargetType.SCRIPT, TargetType.STDOUT) - } - else { + } else { targetTypes = EnumSet.of(TargetType.SCRIPT) } schemaExport.execute(targetTypes, HibernateSchemaExport.Action.CREATE, metadata, serviceRegistry) if (schemaExport.exceptions) { - def e = (Exception)schemaExport.exceptions[0] + def e = (Exception) schemaExport.exceptions[0] e.printStackTrace() return false } diff --git a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/test/hibernate/HibernateSpec.groovy b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/test/hibernate/HibernateSpec.groovy index 9d3c4acb2ac..d53fa387d77 100644 --- a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/test/hibernate/HibernateSpec.groovy +++ b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/test/hibernate/HibernateSpec.groovy @@ -51,8 +51,11 @@ import spock.lang.Specification @CompileStatic abstract class HibernateSpec extends Specification { - @Shared @AutoCleanup HibernateDatastore hibernateDatastore - @Shared PlatformTransactionManager transactionManager + @Shared + @AutoCleanup + HibernateDatastore hibernateDatastore + @Shared + PlatformTransactionManager transactionManager void setupSpec() { @@ -71,7 +74,7 @@ abstract class HibernateSpec extends Specification { propertySources.addLast(it) } } - propertySources.addFirst(new MapPropertySource("defaults", getConfiguration())) + propertySources.addFirst(new MapPropertySource("defaults", getConfiguration() as Map)) Config config = new PropertySourcesConfig(propertySources) List domainClasses = getDomainClasses() String packageName = getPackageToScan(config) @@ -156,8 +159,8 @@ abstract class HibernateSpec extends Specification { private boolean canLoadFileExtension(PropertySourceLoader loader, String name) { return Arrays - .stream(loader.fileExtensions) - .map { String extension -> extension.toLowerCase() } - .anyMatch { String extension -> name.toLowerCase().endsWith(extension) } + .stream(loader.fileExtensions) + .map { String extension -> extension.toLowerCase() } + .anyMatch { String extension -> name.toLowerCase().endsWith(extension) } } } diff --git a/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.java b/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.java index 92564870738..3a03bb23a13 100644 --- a/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.java +++ b/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.java @@ -36,8 +36,6 @@ */ public abstract class AbstractMultipleDataSourceAggregatePersistenceContextInterceptor implements PersistenceContextInterceptor { - - protected final List interceptors = new ArrayList(); protected final AbstractHibernateDatastore hibernateDatastore; @@ -117,4 +115,4 @@ public void setReadWrite() { protected abstract SessionFactoryAwarePersistenceContextInterceptor createPersistenceContextInterceptor(String dataSourceName); -} \ No newline at end of file +} diff --git a/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/AggregatePersistenceContextInterceptor.java b/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/AggregatePersistenceContextInterceptor.java index 060681f57dc..450fa4a1446 100644 --- a/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/AggregatePersistenceContextInterceptor.java +++ b/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/AggregatePersistenceContextInterceptor.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.plugin.hibernate.support; import org.grails.orm.hibernate.AbstractHibernateDatastore; diff --git a/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/GrailsOpenSessionInViewInterceptor.java b/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/GrailsOpenSessionInViewInterceptor.java index 5a556b20dfa..5d88899605a 100644 --- a/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/GrailsOpenSessionInViewInterceptor.java +++ b/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/GrailsOpenSessionInViewInterceptor.java @@ -54,20 +54,19 @@ protected void applyFlushMode(Session session) { @Override public void postHandle(WebRequest request, ModelMap model) throws DataAccessException { - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(getSessionFactory()); + SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory()); Session session = sessionHolder != null ? sessionHolder.getSession() : null; try { super.postHandle(request, model); FlushMode flushMode = session != null ? session.getHibernateFlushMode() : null; boolean isNotManual = flushMode != FlushMode.MANUAL && flushMode != FlushMode.COMMIT; if (session != null && isNotManual) { - if(logger.isDebugEnabled()) { + if (logger.isDebugEnabled()) { logger.debug("Eagerly flushing Hibernate session"); } session.flush(); } - } - finally { + } finally { if (session != null) { session.setHibernateFlushMode(FlushMode.MANUAL); } @@ -76,10 +75,9 @@ public void postHandle(WebRequest request, ModelMap model) throws DataAccessExce public void setHibernateDatastore(AbstractHibernateDatastore hibernateDatastore) { String defaultFlushModeName = hibernateDatastore.getDefaultFlushModeName(); - if(hibernateDatastore.isOsivReadOnly()) { + if (hibernateDatastore.isOsivReadOnly()) { this.hibernateFlushMode = FlushMode.MANUAL; - } - else { + } else { this.hibernateFlushMode = FlushMode.valueOf(defaultFlushModeName); } setSessionFactory(hibernateDatastore.getSessionFactory()); diff --git a/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/HibernatePersistenceContextInterceptor.java b/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/HibernatePersistenceContextInterceptor.java index aed44815d69..27ae3525eb2 100644 --- a/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/HibernatePersistenceContextInterceptor.java +++ b/grails-data-hibernate5/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/HibernatePersistenceContextInterceptor.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.plugin.hibernate.support; import grails.persistence.support.PersistenceContextInterceptor; @@ -47,20 +46,16 @@ public class HibernatePersistenceContextInterceptor implements PersistenceContextInterceptor, SessionFactoryAwarePersistenceContextInterceptor { private static final Logger LOG = LoggerFactory.getLogger(HibernatePersistenceContextInterceptor.class); - private AbstractHibernateDatastore hibernateDatastore; - - - private static ThreadLocal> participate = ThreadLocal.withInitial(HashMap::new); - - private static ThreadLocal> nestingCount = ThreadLocal.withInitial(HashMap::new); - + private static final ThreadLocal> PARTICIPATE = ThreadLocal.withInitial(HashMap::new); + private static final ThreadLocal> NESTING_COUNT = ThreadLocal.withInitial(HashMap::new); + private AbstractHibernateDatastore hibernateDatastore; private String dataSourceName; static { ShutdownOperations.addOperation(() -> { - participate.remove(); - nestingCount.remove(); + PARTICIPATE.remove(); + NESTING_COUNT.remove(); }); } @@ -84,7 +79,7 @@ public HibernatePersistenceContextInterceptor(String dataSourceName) { */ public void destroy() { DeferredBindingActions.clear(); - if(!disconnected.isEmpty()) { + if (!disconnected.isEmpty()) { disconnected.pop(); } if (getSessionFactory() == null || decNestingCount() > 0 || getParticipate()) { @@ -97,72 +92,82 @@ public void destroy() { try { disconnected.clear(); SessionFactoryUtils.closeSession(holder.getSession()); - } - catch (RuntimeException ex) { + } catch (RuntimeException ex) { LOG.error("Unexpected exception on closing Hibernate Session", ex); } } public void disconnect() { - if (getSessionFactory() == null) return; + if (getSessionFactory() == null) { + return; + } try { disconnected.add( getSession(false).disconnect() ); - } - catch (Exception e) { + } catch (Exception e) { // no session ignore } } public void reconnect() { - if (getSessionFactory() == null) return; + if (getSessionFactory() == null) { + return; + } Session session = getSession(); - if(!session.isConnected() && !disconnected.isEmpty()) { + if (!session.isConnected() && !disconnected.isEmpty()) { try { Connection connection = disconnected.peekLast(); getSession().reconnect(connection); } catch (IllegalStateException e) { // cannot reconnect on different exception. ignore - LOG.debug(e.getMessage(),e); + LOG.debug(e.getMessage(), e); } } } public void flush() { - if (getSessionFactory() == null) return; - if(!getParticipate()) { - if(!transactionRequired) { + if (getSessionFactory() == null) { + return; + } + if (!getParticipate()) { + if (!transactionRequired) { getSession().flush(); - } - else if(TransactionSynchronizationManager.isSynchronizationActive()) { + } else if (TransactionSynchronizationManager.isSynchronizationActive()) { getSession().flush(); } } } public void clear() { - if (getSessionFactory() == null) return; + if (getSessionFactory() == null) { + return; + } getSession().clear(); } public void setReadOnly() { - if (getSessionFactory() == null) return; + if (getSessionFactory() == null) { + return; + } getSession().setHibernateFlushMode(FlushMode.MANUAL); } public void setReadWrite() { - if (getSessionFactory() == null) return; + if (getSessionFactory() == null) { + return; + } getSession().setHibernateFlushMode(FlushMode.AUTO); } public boolean isOpen() { - if (getSessionFactory() == null) return false; + if (getSessionFactory() == null) { + return false; + } try { return getSession(false).isOpen(); - } - catch (Exception e) { + } catch (Exception e) { return false; } } @@ -181,8 +186,7 @@ public void init() { if (TransactionSynchronizationManager.hasResource(sf)) { // Do not modify the Session: just set the participate flag. setParticipate(true); - } - else { + } else { setParticipate(false); LOG.debug("Opening single Hibernate session in HibernatePersistenceContextInterceptor"); Session session = getSession(); @@ -231,7 +235,7 @@ public void setSessionFactory(SessionFactory sessionFactory) { } private int incNestingCount() { - Map map = nestingCount.get(); + Map map = NESTING_COUNT.get(); Integer current = map.get(dataSourceName); int value = (current != null) ? current + 1 : 1; map.put(dataSourceName, value); @@ -239,7 +243,7 @@ private int incNestingCount() { } private int decNestingCount() { - Map map = nestingCount.get(); + Map map = NESTING_COUNT.get(); Integer current = map.get(dataSourceName); int value = (current != null) ? current - 1 : 0; if (value < 0) { @@ -250,12 +254,12 @@ private int decNestingCount() { } private void setParticipate(boolean flag) { - Map map = participate.get(); + Map map = PARTICIPATE.get(); map.put(dataSourceName, flag); } private boolean getParticipate() { - Map map = participate.get(); + Map map = PARTICIPATE.get(); Boolean ret = map.get(dataSourceName); return (ret != null) ? ret : false; } diff --git a/grails-data-mongodb/boot-plugin/build.gradle b/grails-data-mongodb/boot-plugin/build.gradle index 11b97e45c48..3d050aec144 100644 --- a/grails-data-mongodb/boot-plugin/build.gradle +++ b/grails-data-mongodb/boot-plugin/build.gradle @@ -107,4 +107,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/mongodb-test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-data-mongodb/boot-plugin/src/main/groovy/org/grails/datastore/gorm/mongodb/boot/autoconfigure/MongoDbGormAutoConfiguration.groovy b/grails-data-mongodb/boot-plugin/src/main/groovy/org/grails/datastore/gorm/mongodb/boot/autoconfigure/MongoDbGormAutoConfiguration.groovy index d54c4e4d21c..c5cf73b0430 100644 --- a/grails-data-mongodb/boot-plugin/src/main/groovy/org/grails/datastore/gorm/mongodb/boot/autoconfigure/MongoDbGormAutoConfiguration.groovy +++ b/grails-data-mongodb/boot-plugin/src/main/groovy/org/grails/datastore/gorm/mongodb/boot/autoconfigure/MongoDbGormAutoConfiguration.groovy @@ -51,7 +51,7 @@ import java.beans.Introspector @Configuration @ConditionalOnMissingBean(MongoDatastore) @AutoConfigureAfter(MongoAutoConfiguration) -class MongoDbGormAutoConfiguration implements ApplicationContextAware{ +class MongoDbGormAutoConfiguration implements ApplicationContextAware { @Autowired(required = false) private MongoProperties mongoProperties @@ -67,15 +67,15 @@ class MongoDbGormAutoConfiguration implements ApplicationContextAware{ @Bean MongoDatastore mongoDatastore() { ConfigurableApplicationContext context = applicationContext - if(!(context instanceof ConfigurableApplicationContext)) { + if (!(context instanceof ConfigurableApplicationContext)) { throw new IllegalArgumentException("MongoDbGormAutoConfiguration requires an instance of ConfigurableApplicationContext") } ConfigurableListableBeanFactory beanFactory = context.beanFactory List packageNames = AutoConfigurationPackages.get(beanFactory) List packages = [] - for(name in packageNames) { + for (name in packageNames) { Package pkg = Package.getPackage(name) - if(pkg != null) { + if (pkg != null) { packages.add(pkg) } } @@ -83,25 +83,23 @@ class MongoDbGormAutoConfiguration implements ApplicationContextAware{ MongoDatastore datastore ConfigurableEnvironment environment = context.environment ConfigurableApplicationContextEventPublisher eventPublisher = new ConfigurableApplicationContextEventPublisher(context) - if(mongo != null) { - datastore = new MongoDatastore(mongo, environment,eventPublisher, packages as Package[]) - } - else if(mongoProperties != null) { + if (mongo != null) { + datastore = new MongoDatastore(mongo, environment, eventPublisher, packages as Package[]) + } else if (mongoProperties != null) { this.mongo = MongoClients.create(mongoOptions) - datastore = new MongoDatastore(mongo, environment,eventPublisher, packages as Package[]) - } - else { + datastore = new MongoDatastore(mongo, environment, eventPublisher, packages as Package[]) + } else { datastore = new MongoDatastore(environment, eventPublisher, packages as Package[]) } - for(Service service in datastore.getServices()) { + for (Service service in datastore.getServices()) { Class serviceClass = service.getClass() grails.gorm.services.Service ann = serviceClass.getAnnotation(grails.gorm.services.Service) String serviceName = ann?.name() - if(serviceName == null) { + if (serviceName == null) { serviceName = Introspector.decapitalize(serviceClass.simpleName) } - if(!context.containsBean(serviceName)) { + if (!context.containsBean(serviceName)) { context.beanFactory.registerSingleton( serviceName, service @@ -118,10 +116,10 @@ class MongoDbGormAutoConfiguration implements ApplicationContextAware{ @Override void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - if(!(applicationContext instanceof ConfigurableApplicationContext)) { + if (!(applicationContext instanceof ConfigurableApplicationContext)) { throw new IllegalArgumentException("MongoDbGormAutoConfiguration requires an instance of ConfigurableApplicationContext") } - this.applicationContext = (ConfigurableApplicationContext)applicationContext + this.applicationContext = (ConfigurableApplicationContext) applicationContext } } diff --git a/grails-data-mongodb/bson/build.gradle b/grails-data-mongodb/bson/build.gradle index 646d1fe3186..0b010c5e1c4 100644 --- a/grails-data-mongodb/bson/build.gradle +++ b/grails-data-mongodb/bson/build.gradle @@ -101,4 +101,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/mongodb-test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/BigDecimalCodec.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/BigDecimalCodec.groovy index 532d2560d03..84edf9ac86e 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/BigDecimalCodec.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/BigDecimalCodec.groovy @@ -35,6 +35,7 @@ import org.bson.types.Decimal128 */ @CompileStatic class BigDecimalCodec implements Codec { + @Override BigDecimal decode(BsonReader reader, DecoderContext decoderContext) { return reader.readDecimal128().bigDecimalValue() diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/BigIntegerCodec.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/BigIntegerCodec.groovy index d93241d5331..0732e5012d9 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/BigIntegerCodec.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/BigIntegerCodec.groovy @@ -35,6 +35,7 @@ import org.bson.types.Decimal128 */ @CompileStatic class BigIntegerCodec implements Codec { + @Override BigInteger decode(BsonReader reader, DecoderContext decoderContext) { return reader.readDecimal128().bigDecimalValue().toBigInteger() diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/BsonPersistentEntityCodec.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/BsonPersistentEntityCodec.groovy index 48ba03a2e99..c89d0cb2c66 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/BsonPersistentEntityCodec.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/BsonPersistentEntityCodec.groovy @@ -20,15 +20,32 @@ package org.grails.datastore.bson.codecs import groovy.transform.CompileStatic -import org.bson.* +import org.bson.BsonDocument +import org.bson.BsonDocumentWriter +import org.bson.BsonReader +import org.bson.BsonType +import org.bson.BsonValue +import org.bson.BsonWriter import org.bson.codecs.BsonValueCodecProvider import org.bson.codecs.Codec import org.bson.codecs.DecoderContext import org.bson.codecs.EncoderContext import org.bson.codecs.configuration.CodecRegistry import org.bson.conversions.Bson -import org.grails.datastore.bson.codecs.decoders.* -import org.grails.datastore.bson.codecs.encoders.* +import org.grails.datastore.bson.codecs.decoders.BasicCollectionTypeDecoder +import org.grails.datastore.bson.codecs.decoders.CustomTypeDecoder +import org.grails.datastore.bson.codecs.decoders.EmbeddedCollectionDecoder +import org.grails.datastore.bson.codecs.decoders.EmbeddedDecoder +import org.grails.datastore.bson.codecs.decoders.IdentityDecoder +import org.grails.datastore.bson.codecs.decoders.SimpleDecoder +import org.grails.datastore.bson.codecs.decoders.TenantIdDecoder +import org.grails.datastore.bson.codecs.encoders.BasicCollectionTypeEncoder +import org.grails.datastore.bson.codecs.encoders.CustomTypeEncoder +import org.grails.datastore.bson.codecs.encoders.EmbeddedCollectionEncoder +import org.grails.datastore.bson.codecs.encoders.EmbeddedEncoder +import org.grails.datastore.bson.codecs.encoders.IdentityEncoder +import org.grails.datastore.bson.codecs.encoders.SimpleEncoder +import org.grails.datastore.bson.codecs.encoders.TenantIdEncoder import org.grails.datastore.gorm.schemaless.DynamicAttributes import org.grails.datastore.mapping.dirty.checking.DirtyCheckable import org.grails.datastore.mapping.engine.EntityAccess @@ -37,7 +54,14 @@ import org.grails.datastore.mapping.model.MappingContext import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.mapping.model.config.GormProperties -import org.grails.datastore.mapping.model.types.* +import org.grails.datastore.mapping.model.types.Basic +import org.grails.datastore.mapping.model.types.Custom +import org.grails.datastore.mapping.model.types.Embedded +import org.grails.datastore.mapping.model.types.EmbeddedCollection +import org.grails.datastore.mapping.model.types.Identity +import org.grails.datastore.mapping.model.types.Simple +import org.grails.datastore.mapping.model.types.TenantId + /** * Encodes and decodes {@link org.grails.datastore.mapping.model.PersistentEntity} objects from a BSON stream * @@ -46,6 +70,7 @@ import org.grails.datastore.mapping.model.types.* */ @CompileStatic class BsonPersistentEntityCodec implements Codec { + public static final EncoderContext DEFAULT_ENCODER_CONTEXT = EncoderContext.builder().build() public static final DecoderContext DEFAULT_DECODER_CONTEXT = DecoderContext.builder().build() private static final Map, PropertyEncoder> ENCODERS = [:] @@ -98,61 +123,55 @@ class BsonPersistentEntityCodec implements Codec { boolean abortReading = false final boolean hasDynamicAttributes = instance instanceof DynamicAttributes - while(bsonType != BsonType.END_OF_DOCUMENT) { + while (bsonType != BsonType.END_OF_DOCUMENT) { def name = bsonReader.readName() - if(!abortReading) { + if (!abortReading) { - if(isDiscriminatorProperty(name)) { + if (isDiscriminatorProperty(name)) { def childEntity = mappingContext .getChildEntityByDiscriminator(persistentEntity.rootEntity, bsonReader.readString()) - if(childEntity != null) { + if (childEntity != null) { persistentEntity = childEntity instance = childEntity .newInstance() def newAccess = createEntityAccess(childEntity, instance) - newAccess.setIdentifierNoConversion( access.identifier ) + newAccess.setIdentifierNoConversion(access.identifier) access = newAccess } bsonType = bsonReader.readBsonType() continue } - if(isIdentifierProperty(name)) { - getPropertyDecoder(Identity).decode( bsonReader, (Identity)persistentEntity.identity, access, decoderContext, codecRegistry) + if (isIdentifierProperty(name)) { + getPropertyDecoder(Identity).decode(bsonReader, (Identity) persistentEntity.identity, access, decoderContext, codecRegistry) Object cachedInstance = retrieveCachedInstance(access) - if(cachedInstance != null) { + if (cachedInstance != null) { instance = cachedInstance abortReading = true } - } - else { + } else { PersistentProperty property = persistentEntity.getPropertyByName(name) - if(property && bsonType != BsonType.NULL) { + if (property && bsonType != BsonType.NULL) { def propKind = property.getClass().superclass - if(CharSequence.isAssignableFrom(property.type) && bsonType == BsonType.STRING) { + if (CharSequence.isAssignableFrom(property.type) && bsonType == BsonType.STRING) { access.setPropertyNoConversion(property.name, bsonReader.readString()) - } - else { - getPropertyDecoder((Class)propKind)?.decode(bsonReader, property, access, decoderContext, codecRegistry) + } else { + getPropertyDecoder((Class) propKind)?.decode(bsonReader, property, access, decoderContext, codecRegistry) } - } - else if(!abortReading && hasDynamicAttributes) { - readSchemaless(bsonReader, ((DynamicAttributes)instance), name, decoderContext) - } - else { + } else if (!abortReading && hasDynamicAttributes) { + readSchemaless(bsonReader, ((DynamicAttributes) instance), name, decoderContext) + } else { bsonReader.skipValue() } } - } - else if(!abortReading){ - readSchemaless(bsonReader, ((DynamicAttributes)instance), name, decoderContext) - } - else { + } else if (!abortReading) { + readSchemaless(bsonReader, ((DynamicAttributes) instance), name, decoderContext) + } else { bsonReader.skipValue() } bsonType = bsonReader.readBsonType() @@ -161,11 +180,9 @@ class BsonPersistentEntityCodec implements Codec { readingComplete(access) - return instance } - void encode(BsonWriter writer, Object value, EncoderContext encoderContext = DEFAULT_ENCODER_CONTEXT) { encode(writer, value, encoderContext, true) } @@ -175,7 +192,7 @@ class BsonPersistentEntityCodec implements Codec { def access = createEntityAccess(value) def entity = access.persistentEntity - if(!entity.isRoot()) { + if (!entity.isRoot()) { def discriminatorName = getDiscriminatorAttributeName() def discriminator = entity.discriminator writer.writeName(discriminatorName) @@ -184,8 +201,8 @@ class BsonPersistentEntityCodec implements Codec { if (includeIdentifier) { def id = access.getIdentifier() - if(id != null) { - getPropertyEncoder(Identity).encode writer, (Identity)entity.identity, id, access, encoderContext, codecRegistry + if (id != null) { + getPropertyEncoder(Identity).encode writer, (Identity) entity.identity, id, access, encoderContext, codecRegistry } } @@ -193,17 +210,17 @@ class BsonPersistentEntityCodec implements Codec { def propKind = prop.getClass().superclass Object v = access.getProperty(prop.name) if (v != null) { - PropertyEncoder encoder = getPropertyEncoder((Class)propKind) + PropertyEncoder encoder = getPropertyEncoder((Class) propKind) encoder?.encode(writer, (PersistentProperty) prop, v, access, encoderContext, codecRegistry) } } - if(value instanceof DynamicAttributes) { + if (value instanceof DynamicAttributes) { def attributes = ((DynamicAttributes) value).attributes() writeAttributes(attributes, writer, encoderContext) } - beforeFinishDocument(writer,access) + beforeFinishDocument(writer, access) writer.writeEndDocument() writer.flush() writingComplete(access) @@ -219,77 +236,72 @@ class BsonPersistentEntityCodec implements Codec { def entity = access.persistentEntity def proxyFactory = mappingContext.proxyFactory - if( proxyFactory.isProxy(value) ) { + if (proxyFactory.isProxy(value)) { value = proxyFactory.unwrap(value) } - if(value instanceof DirtyCheckable) { + if (value instanceof DirtyCheckable) { BsonWriter writer = new BsonDocumentWriter(update) writer.writeStartDocument() - DirtyCheckable dirty = (DirtyCheckable)value + DirtyCheckable dirty = (DirtyCheckable) value Set processed = [] def dirtyProperties = new ArrayList(dirty.listDirtyPropertyNames()) boolean isNew = dirtyProperties.isEmpty() && dirty.hasChanged() def isVersioned = entity.isVersioned() - if(isNew) { + if (isNew) { // if it is new it can only be an embedded entity that has now been updated // so we get all properties dirtyProperties = entity.persistentPropertyNames - if(isVersioned) { + if (isVersioned) { EntityPersister.incrementEntityVersion(access) } - } - else { + } else { // schedule lastUpdated if necessary - if( entity.getPropertyByName(GormProperties.LAST_UPDATED) != null) { + if (entity.getPropertyByName(GormProperties.LAST_UPDATED) != null) { dirtyProperties.add(GormProperties.LAST_UPDATED) } } - for(propertyName in dirtyProperties) { + for (propertyName in dirtyProperties) { def prop = entity.getPropertyByName(propertyName) - if(prop != null) { + if (prop != null) { processed << propertyName Object v = access.getProperty(prop.name) if (v != null) { - if(prop instanceof Embedded) { + if (prop instanceof Embedded) { writer.writeName(prop.name) - encodeUpdate(v, createEntityAccess(((Embedded)prop).associatedEntity, v), encoderContext, true) - } - else if(prop instanceof EmbeddedCollection) { + encodeUpdate(v, createEntityAccess(((Embedded) prop).associatedEntity, v), encoderContext, true) + } else if (prop instanceof EmbeddedCollection) { // TODO: embedded collections - } - else { + } else { def propKind = prop.getClass().superclass if (prop instanceof PersistentProperty) { - PropertyEncoder propertyEncoder = getPropertyEncoder((Class)propKind) + PropertyEncoder propertyEncoder = getPropertyEncoder((Class) propKind) propertyEncoder?.encode(writer, prop, v, access, encoderContext, codecRegistry) } } - } - else if(embedded || !isNew) { + } else if (embedded || !isNew) { writer.writeName(propertyName) writer.writeNull() } } } - if(value instanceof DynamicAttributes) { + if (value instanceof DynamicAttributes) { Map attributes = ((DynamicAttributes) value).attributes() - for(attr in attributes.keySet()) { + for (attr in attributes.keySet()) { Object v = attributes.get(attr) - if(v == null) { + if (v == null) { writer.writeName(attr) writer.writeNull() - } - else { + } else { writer.writeName(attr) - Codec codec = (Codec)codecRegistry.get(v.getClass()) + Codec codec = (Codec) codecRegistry.get(v.getClass()) codec.encode(writer, v, encoderContext) } } @@ -316,7 +328,7 @@ class BsonPersistentEntityCodec implements Codec { for (name in attributes.keySet()) { writer.writeName name Object v = attributes.get(name) - Codec codec = (Codec)codecRegistry.get(v.getClass()) + Codec codec = (Codec) codecRegistry.get(v.getClass()) codec.encode(writer, v, encoderContext) } } @@ -384,13 +396,13 @@ class BsonPersistentEntityCodec implements Codec { def codec = codecRegistry.get(targetClass) - BsonValue bsonValue = (BsonValue)codec.decode(bsonReader, decoderContext) - if(bsonValue != null) { + BsonValue bsonValue = (BsonValue) codec.decode(bsonReader, decoderContext) + if (bsonValue != null) { def converter = CodecExtensions.getBsonConverter(bsonValue.getClass()) dynamicAttributes.putAt( name, - converter != null ? converter.convert( bsonValue ) : bsonValue + converter != null ? converter.convert(bsonValue) : bsonValue ) } } @@ -416,7 +428,6 @@ class BsonPersistentEntityCodec implements Codec { return discriminatorName != null && name.equals(discriminatorName) } - /** * Obtains the property encoder for the given property type * diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecCustomTypeMarshaller.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecCustomTypeMarshaller.groovy index b2b6584fe4b..3fae9e2c068 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecCustomTypeMarshaller.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecCustomTypeMarshaller.groovy @@ -20,14 +20,9 @@ package org.grails.datastore.bson.codecs import groovy.transform.CompileStatic -import org.bson.BsonDocument -import org.bson.BsonDocumentWriter -import org.bson.BsonWriter import org.bson.Document import org.bson.codecs.Codec -import org.bson.codecs.EncoderContext import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.engine.internal.MappingUtils import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller import org.grails.datastore.mapping.model.MappingContext import org.grails.datastore.mapping.model.PersistentProperty @@ -41,6 +36,7 @@ import org.grails.datastore.mapping.query.Query */ @CompileStatic class CodecCustomTypeMarshaller implements CustomTypeMarshaller { + final Codec codec final MappingContext mappingContext diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecExtensions.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecExtensions.groovy index aecf152e983..eee8228851a 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecExtensions.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecExtensions.groovy @@ -66,21 +66,22 @@ import java.util.regex.Pattern */ @CompileStatic class CodecExtensions implements CodecProvider { + private static final Map ADDITIONAL_CODECS = [:] private static final Map, List> BSON_VALUE_CONVERTERS = new LinkedHashMap, List>().withDefault { Class cls -> new ArrayList() as List } private static final Map> BSON_TYPE_CODECS = [ - (BsonType.ARRAY) : new ListCodec(), + (BsonType.ARRAY) : new ListCodec(), (BsonType.DOCUMENT) : new DocumentCodec(), - (BsonType.BINARY) : new ByteArrayCodec(), - (BsonType.BOOLEAN) : new BooleanCodec(), - (BsonType.DATE_TIME) : new DateCodec(), - (BsonType.DOUBLE) : new DoubleCodec(), - (BsonType.INT32) : new IntegerCodec(), - (BsonType.INT64) : new LongCodec(), - (BsonType.STRING) : new StringCodec(), - (BsonType.OBJECT_ID) : new ObjectIdCodec() + (BsonType.BINARY) : new ByteArrayCodec(), + (BsonType.BOOLEAN) : new BooleanCodec(), + (BsonType.DATE_TIME): new DateCodec(), + (BsonType.DOUBLE) : new DoubleCodec(), + (BsonType.INT32) : new IntegerCodec(), + (BsonType.INT64) : new LongCodec(), + (BsonType.STRING) : new StringCodec(), + (BsonType.OBJECT_ID): new ObjectIdCodec() ] static { @@ -95,99 +96,113 @@ class CodecExtensions implements CodecProvider { ADDITIONAL_CODECS[HashMap] = new MapCodec() ADDITIONAL_CODECS[ArrayList] = new ListCodec() BSON_VALUE_CONVERTERS[BsonBinary] << new Converter() { + @Override byte[] convert(BsonBinary source) { return source.data } } BSON_VALUE_CONVERTERS[BsonObjectId] << new Converter() { + @Override ObjectId convert(BsonObjectId source) { source.value } } BSON_VALUE_CONVERTERS[BsonTimestamp] << new Converter() { + @Override Date convert(BsonTimestamp source) { new Date(source.time * 1000) } } BSON_VALUE_CONVERTERS[BsonDateTime] << new Converter() { + @Override Date convert(BsonDateTime source) { new Date(source.value) } } BSON_VALUE_CONVERTERS[BsonString] << new Converter() { + @Override CharSequence convert(BsonString source) { source.value } } BSON_VALUE_CONVERTERS[BsonString] << new Converter() { + @Override String convert(BsonString source) { source.value } } BSON_VALUE_CONVERTERS[BsonRegularExpression] << new Converter() { + @Override Pattern convert(BsonRegularExpression source) { Pattern.compile(source.pattern) } } BSON_VALUE_CONVERTERS[BsonBoolean] << new Converter() { + @Override Boolean convert(BsonBoolean source) { source.value } } BSON_VALUE_CONVERTERS[BsonNull] << new Converter() { + @Override Object convert(BsonNull source) { return null } } BSON_VALUE_CONVERTERS[BsonDouble] << new Converter() { + @Override Double convert(BsonDouble source) { source.doubleValue() } } BSON_VALUE_CONVERTERS[BsonDouble] << new Converter() { + @Override Float convert(BsonDouble source) { source.doubleValue().floatValue() } } BSON_VALUE_CONVERTERS[BsonInt32] << new Converter() { + @Override Integer convert(BsonInt32 source) { return source.intValue() } } BSON_VALUE_CONVERTERS[BsonInt32] << new Converter() { + @Override Short convert(BsonInt32 source) { source.intValue().shortValue() } } BSON_VALUE_CONVERTERS[BsonInt64] << new Converter() { + @Override Long convert(BsonInt64 source) { source.longValue() } } BSON_VALUE_CONVERTERS[BsonArray] << new Converter() { + @Override List convert(BsonArray source) { List list = [] - for(BsonValue v in source) { - if(v != null) { + for (BsonValue v in source) { + if (v != null) { def converter = BSON_VALUE_CONVERTERS[v.getClass()]?.first() list << (converter ? converter.convert(v) : v) - } - else { + } else { list << v } } @@ -195,16 +210,16 @@ class CodecExtensions implements CodecProvider { } } BSON_VALUE_CONVERTERS[BsonArray] << new Converter() { + @Override Object[] convert(BsonArray source) { Object[] array = new Object[source.size()] int i = 0 - for(BsonValue v in source) { - if(v != null) { + for (BsonValue v in source) { + if (v != null) { def converter = BSON_VALUE_CONVERTERS[v.getClass()]?.first() array[i++] = (converter ? converter.convert(v) : v) - } - else { + } else { array[i++] = v } } @@ -212,17 +227,17 @@ class CodecExtensions implements CodecProvider { } } BSON_VALUE_CONVERTERS[BsonDocument] << new Converter>() { + @Override Map convert(BsonDocument source) { Map map = [:] - for(key in source.keySet()) { + for (key in source.keySet()) { def v = source[key] - if(v != null) { + if (v != null) { def converter = BSON_VALUE_CONVERTERS[v.getClass()]?.first() map[key] = (converter ? converter.convert(v) : v) - } - else { + } else { map[key] = v } @@ -232,6 +247,7 @@ class CodecExtensions implements CodecProvider { } BSON_VALUE_CONVERTERS[BsonDecimal128] << new Converter() { + @Override BigDecimal convert(BsonDecimal128 source) { return source.decimal128Value().bigDecimalValue() @@ -240,12 +256,12 @@ class CodecExtensions implements CodecProvider { } static Collection getBsonConverters() { - return (Collection)BSON_VALUE_CONVERTERS.values().flatten() + return (Collection) BSON_VALUE_CONVERTERS.values().flatten() } static Converter getBsonConverter(Class type) { def converters = BSON_VALUE_CONVERTERS.get(type) - if(!converters.isEmpty()) { + if (!converters.isEmpty()) { return converters.first() } return null @@ -254,8 +270,8 @@ class CodecExtensions implements CodecProvider { static Codec getCodecForBsonType(BsonType bsonType, CodecRegistry registry) { def codec = BSON_TYPE_CODECS.get(bsonType) - if(codec != null) { - if(codec instanceof CodecRegistryAware) { + if (codec != null) { + if (codec instanceof CodecRegistryAware) { codec.codecRegistry = registry } return codec @@ -266,8 +282,8 @@ class CodecExtensions implements CodecProvider { @Override def Codec get(Class clazz, CodecRegistry registry) { def codec = ADDITIONAL_CODECS.get(clazz) - if(codec != null) { - if(codec instanceof CodecRegistryAware) { + if (codec != null) { + if (codec instanceof CodecRegistryAware) { codec.codecRegistry = registry } return codec @@ -276,6 +292,7 @@ class CodecExtensions implements CodecProvider { } static class MapCodec implements Codec>, CodecRegistryAware { + CodecRegistry codecRegistry @Override @@ -284,11 +301,11 @@ class CodecExtensions implements CodecProvider { Map map = [:] reader.readStartDocument() BsonType bsonType = reader.readBsonType() - while(bsonType != BsonType.END_OF_DOCUMENT) { + while (bsonType != BsonType.END_OF_DOCUMENT) { def key = reader.readName() BsonValue bsonValue = readValue(reader, decoderContext) Object value = null - if(bsonValue != null) { + if (bsonValue != null) { def converter = BSON_VALUE_CONVERTERS.get(bsonValue.getClass())?.first() value = converter ? converter.convert(bsonValue) : bsonValue } @@ -302,14 +319,13 @@ class CodecExtensions implements CodecProvider { @Override void encode(BsonWriter writer, Map values, EncoderContext encoderContext) { writer.writeStartDocument() - for(entry in values) { + for (entry in values) { def v = entry.value writer.writeName(entry.key) - if(v == null) { + if (v == null) { writer.writeNull() - } - else { - Codec c = (Codec)codecRegistry.get( v.getClass() ) + } else { + Codec c = (Codec) codecRegistry.get(v.getClass()) c.encode(writer, v, encoderContext) } } @@ -325,7 +341,9 @@ class CodecExtensions implements CodecProvider { return codecRegistry.get(BsonValueCodecProvider.getClassForBsonType(reader.getCurrentBsonType())).decode(reader, decoderContext); } } + static class ListCodec implements Codec, CodecRegistryAware { + CodecRegistry codecRegistry @Override @@ -333,11 +351,11 @@ class CodecExtensions implements CodecProvider { List list = new ArrayList() reader.readStartArray() BsonType bsonType = reader.readBsonType() - while(bsonType != BsonType.END_OF_DOCUMENT) { + while (bsonType != BsonType.END_OF_DOCUMENT) { BsonValue bsonValue = readValue(reader, decoderContext) Object value = null - if(bsonValue != null) { + if (bsonValue != null) { def converters = BSON_VALUE_CONVERTERS.get(bsonValue.getClass()) Converter converter = !converters.isEmpty() ? converters?.first() : null value = converter != null ? converter.convert(bsonValue) : bsonValue @@ -352,12 +370,11 @@ class CodecExtensions implements CodecProvider { @Override void encode(BsonWriter writer, List values, EncoderContext encoderContext) { writer.writeStartArray() - for(v in values) { - if(v == null) { + for (v in values) { + if (v == null) { writer.writeNull() - } - else { - Codec c = (Codec)codecRegistry.get( v.getClass() ) + } else { + Codec c = (Codec) codecRegistry.get(v.getClass()) c.encode(writer, v, encoderContext) } } @@ -378,13 +395,13 @@ class CodecExtensions implements CodecProvider { } } - static class IntRangeCodec implements Codec{ + static class IntRangeCodec implements Codec { @Override void encode(BsonWriter writer, IntRange value, EncoderContext encoderContext) { - Integer from = (Integer)value.from - Integer to = (Integer)value.to + Integer from = (Integer) value.from + Integer to = (Integer) value.to writer.writeStartArray() writer.writeInt32(from) @@ -411,7 +428,7 @@ class CodecExtensions implements CodecProvider { @Override Locale decode(BsonReader reader, DecoderContext decoderContext) { - new Locale( reader.readString() ) + new Locale(reader.readString()) } @Override @@ -429,7 +446,7 @@ class CodecExtensions implements CodecProvider { @Override Currency decode(BsonReader reader, DecoderContext decoderContext) { - Currency.getInstance( reader.readString() ) + Currency.getInstance(reader.readString()) } @Override diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecRegistryAware.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecRegistryAware.groovy index b5150a1b6ec..1d94e3c06e4 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecRegistryAware.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecRegistryAware.groovy @@ -28,5 +28,6 @@ import org.bson.codecs.configuration.CodecRegistry * @since 4.1 */ interface CodecRegistryAware { + void setCodecRegistry(CodecRegistry codecRegistry) } \ No newline at end of file diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecRegistryProvider.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecRegistryProvider.groovy index e60ef1ffdb0..4ea9297925d 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecRegistryProvider.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/CodecRegistryProvider.groovy @@ -28,5 +28,6 @@ import org.bson.codecs.configuration.CodecRegistry * @since 6.0 */ interface CodecRegistryProvider { + CodecRegistry getCodecRegistry() } \ No newline at end of file diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/BasicCollectionTypeDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/BasicCollectionTypeDecoder.groovy index 197ce133d89..319ecabdd1e 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/BasicCollectionTypeDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/BasicCollectionTypeDecoder.groovy @@ -44,42 +44,39 @@ class BasicCollectionTypeDecoder implements PropertyDecoder { void decode(BsonReader reader, Basic property, EntityAccess entityAccess, DecoderContext decoderContext, CodecRegistry codecRegistry) { CustomTypeMarshaller marshaller = property.customTypeMarshaller - if(marshaller) { + if (marshaller) { CustomTypeDecoder.decode(codecRegistry, reader, decoderContext, marshaller, property, entityAccess) - } - else { + } else { def conversionService = entityAccess.persistentEntity.mappingContext.conversionService def componentType = property.componentType def collectionType = property.type Codec codec - if(Set.isAssignableFrom(collectionType)) { + if (Set.isAssignableFrom(collectionType)) { codec = codecRegistry.get(List) - } - else { + } else { codec = codecRegistry.get(collectionType) } def value = codec.decode(reader, decoderContext) def entity = entityAccess.entity - if(value instanceof Collection) { + if (value instanceof Collection) { def converted = value.collect() { conversionService.convert(it, componentType) } - if(entity instanceof DirtyCheckable) { + if (entity instanceof DirtyCheckable) { converted = DirtyCheckingSupport.wrap(converted, (DirtyCheckable) entity, property.name) } - entityAccess.setProperty( property.name, converted ) - } - else if(value instanceof Map) { + entityAccess.setProperty(property.name, converted) + } else if (value instanceof Map) { def converted = value.collectEntries() { Map.Entry entry -> def v = entry.value entry.value = conversionService.convert(v, componentType) return entry } - if(entity instanceof DirtyCheckable) { + if (entity instanceof DirtyCheckable) { converted = new DirtyCheckingMap(converted, (DirtyCheckable) entity, property.name) } - entityAccess.setProperty( property.name, converted) + entityAccess.setProperty(property.name, converted) } } } diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/CustomTypeDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/CustomTypeDecoder.groovy index c9c7f3d89bc..6a3e6f3e1d8 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/CustomTypeDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/CustomTypeDecoder.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.bson.codecs.decoders -import groovy.transform.PackageScope import org.bson.BsonReader import org.bson.Document import org.bson.codecs.Codec @@ -34,7 +33,6 @@ import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.mapping.model.types.Custom - /** * A {@PropertyDecoder} capable of decoding {@Custom} types */ @@ -47,21 +45,19 @@ class CustomTypeDecoder implements PropertyDecoder { decode(codecRegistry, reader, decoderContext, marshaller, property, entityAccess) } - protected static void decode(CodecRegistry codecRegistry, BsonReader reader, DecoderContext decoderContext, CustomTypeMarshaller marshaller, PersistentProperty property, EntityAccess entityAccess) { def bsonType = reader.currentBsonType - if(marshaller instanceof CodecCustomTypeMarshaller) { + if (marshaller instanceof CodecCustomTypeMarshaller) { Codec codec = marshaller.codec def value = codec.decode(reader, decoderContext) if (value != null) { entityAccess.setPropertyNoConversion(property.name, value) } - } - else { + } else { def codec = CodecExtensions.getCodecForBsonType(bsonType, codecRegistry) - if(codec != null) { + if (codec != null) { def decoded = codec.decode(reader, decoderContext) def value = marshaller.read(property, new Document( MappingUtils.getTargetKey(property), @@ -70,8 +66,7 @@ class CustomTypeDecoder implements PropertyDecoder { if (value != null) { entityAccess.setProperty(property.name, value) } - } - else { + } else { reader.skipValue() } } diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/EmbeddedCollectionDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/EmbeddedCollectionDecoder.groovy index 0986fa8bb99..c782fad9a35 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/EmbeddedCollectionDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/EmbeddedCollectionDecoder.groovy @@ -51,13 +51,13 @@ class EmbeddedCollectionDecoder implements PropertyDecoder { EntityReflector associationReflector = property.getAssociatedEntity().getReflector() def owningEntity = entityAccess.entity - if(Collection.isAssignableFrom(property.type)) { + if (Collection.isAssignableFrom(property.type)) { reader.readStartArray() def bsonType = reader.readBsonType() def collection = MappingUtils.createConcreteCollection(property.type) - while(bsonType != BsonType.END_OF_DOCUMENT) { + while (bsonType != BsonType.END_OF_DOCUMENT) { def decoded = associationCodec.decode(reader, decoderContext) - if(isBidirectional) { + if (isBidirectional) { associationReflector.setProperty( decoded, inverseSide.name, @@ -72,15 +72,14 @@ class EmbeddedCollectionDecoder implements PropertyDecoder { property.name, DirtyCheckingSupport.wrap(collection, (DirtyCheckable) owningEntity, property.name) ) - } - else if(Map.isAssignableFrom(property.type)) { + } else if (Map.isAssignableFrom(property.type)) { reader.readStartDocument() def bsonType = reader.readBsonType() def map = [:] - while(bsonType != BsonType.END_OF_DOCUMENT) { + while (bsonType != BsonType.END_OF_DOCUMENT) { def key = reader.readName() def decoded = associationCodec.decode(reader, decoderContext) - if(isBidirectional) { + if (isBidirectional) { associationReflector.setProperty( decoded, inverseSide.name, @@ -95,8 +94,7 @@ class EmbeddedCollectionDecoder implements PropertyDecoder { property.name, new DirtyCheckingMap(map, (DirtyCheckable) owningEntity, property.name) ) - } - else { + } else { reader.skipValue() } } diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/EmbeddedDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/EmbeddedDecoder.groovy index b18c3d251c2..2429ef29fd6 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/EmbeddedDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/EmbeddedDecoder.groovy @@ -44,11 +44,11 @@ class EmbeddedDecoder implements PropertyDecoder { BsonPersistentEntityCodec codec = createEmbeddedEntityCodec(codecRegistry, associatedEntity) def decoded = codec.decode(reader, decoderContext) - if(decoded instanceof DirtyCheckable) { + if (decoded instanceof DirtyCheckable) { decoded.trackChanges() } - if(property.isBidirectional()) { + if (property.isBidirectional()) { Association inverseSide = property.getInverseSide() EntityReflector associationReflector = property.getAssociatedEntity().getReflector() associationReflector.setProperty( diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/IdentityDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/IdentityDecoder.groovy index 01c381847ee..9ecd4edd04c 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/IdentityDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/IdentityDecoder.groovy @@ -50,7 +50,7 @@ class IdentityDecoder implements PropertyDecoder { @Override void decode(BsonReader bsonReader, Identity property, EntityAccess access) { - access.setIdentifierNoConversion( bsonReader.readObjectId() ) + access.setIdentifierNoConversion(bsonReader.readObjectId()) } } IDENTITY_DECODERS[Long] = new IdentityTypeDecoder() { @@ -62,7 +62,7 @@ class IdentityDecoder implements PropertyDecoder { @Override void decode(BsonReader bsonReader, Identity property, EntityAccess access) { - access.setIdentifierNoConversion( bsonReader.readInt64() ) + access.setIdentifierNoConversion(bsonReader.readInt64()) } } @@ -75,7 +75,7 @@ class IdentityDecoder implements PropertyDecoder { @Override void decode(BsonReader bsonReader, Identity property, EntityAccess access) { - access.setIdentifierNoConversion( bsonReader.readInt32() ) + access.setIdentifierNoConversion(bsonReader.readInt32()) } } @@ -147,13 +147,13 @@ class IdentityDecoder implements PropertyDecoder { void decode(BsonReader bsonReader, Identity property, EntityAccess access, DecoderContext decoderContext, CodecRegistry codecRegistry) { BsonType bsonType = bsonReader.currentBsonType IdentityTypeDecoder decoder = IDENTITY_DECODERS.get(property.type) - if(decoder == null) { + if (decoder == null) { throw new IllegalStateException("Invalid identity type [$property.type}] for entity ${property.owner.name}") } - if(bsonType != decoder.bsonType()) { + if (bsonType != decoder.bsonType()) { decoder = DEFAULT_DECODERS.get(bsonType) - if(decoder == null) { + if (decoder == null) { throw new DataIntegrityViolationException("Invalid underlying identifier type [$bsonType] reading entity ${property.owner.name}. Please verify the integrity of your data.") } } @@ -162,6 +162,7 @@ class IdentityDecoder implements PropertyDecoder { } interface IdentityTypeDecoder { + BsonType bsonType() void decode(BsonReader bsonReader, Identity property, EntityAccess access) diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/InstantDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/InstantDecoder.groovy index 5c0bf06f33e..fddf52c68cc 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/InstantDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/InstantDecoder.groovy @@ -21,9 +21,9 @@ package org.grails.datastore.bson.codecs.decoders import groovy.transform.CompileStatic import org.bson.BsonReader +import org.grails.datastore.bson.codecs.temporal.InstantBsonConverter import org.grails.datastore.mapping.engine.EntityAccess import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.bson.codecs.temporal.InstantBsonConverter import static org.grails.datastore.bson.codecs.decoders.SimpleDecoder.TypeDecoder diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/LocalDateDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/LocalDateDecoder.groovy index 6ed6b91b883..68981b7eefd 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/LocalDateDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/LocalDateDecoder.groovy @@ -21,9 +21,9 @@ package org.grails.datastore.bson.codecs.decoders import groovy.transform.CompileStatic import org.bson.BsonReader +import org.grails.datastore.bson.codecs.temporal.LocalDateBsonConverter import org.grails.datastore.mapping.engine.EntityAccess import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.bson.codecs.temporal.LocalDateBsonConverter import static org.grails.datastore.bson.codecs.decoders.SimpleDecoder.TypeDecoder diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/LocalDateTimeDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/LocalDateTimeDecoder.groovy index f6eefc8da1f..cb4d92c38de 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/LocalDateTimeDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/LocalDateTimeDecoder.groovy @@ -21,9 +21,9 @@ package org.grails.datastore.bson.codecs.decoders import groovy.transform.CompileStatic import org.bson.BsonReader +import org.grails.datastore.bson.codecs.temporal.LocalDateTimeBsonConverter import org.grails.datastore.mapping.engine.EntityAccess import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.bson.codecs.temporal.LocalDateTimeBsonConverter import static org.grails.datastore.bson.codecs.decoders.SimpleDecoder.TypeDecoder diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/LocalTimeDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/LocalTimeDecoder.groovy index fbe5aff5158..bf2cf07d454 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/LocalTimeDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/LocalTimeDecoder.groovy @@ -21,9 +21,9 @@ package org.grails.datastore.bson.codecs.decoders import groovy.transform.CompileStatic import org.bson.BsonReader +import org.grails.datastore.bson.codecs.temporal.LocalTimeBsonConverter import org.grails.datastore.mapping.engine.EntityAccess import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.bson.codecs.temporal.LocalTimeBsonConverter import static org.grails.datastore.bson.codecs.decoders.SimpleDecoder.TypeDecoder diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/OffsetDateTimeDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/OffsetDateTimeDecoder.groovy index 805128b5c57..73a5d7dc801 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/OffsetDateTimeDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/OffsetDateTimeDecoder.groovy @@ -21,9 +21,9 @@ package org.grails.datastore.bson.codecs.decoders import groovy.transform.CompileStatic import org.bson.BsonReader +import org.grails.datastore.bson.codecs.temporal.OffsetDateTimeBsonConverter import org.grails.datastore.mapping.engine.EntityAccess import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.bson.codecs.temporal.OffsetDateTimeBsonConverter import static org.grails.datastore.bson.codecs.decoders.SimpleDecoder.TypeDecoder diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/OffsetTimeDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/OffsetTimeDecoder.groovy index aa430a20072..0f2d930e287 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/OffsetTimeDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/OffsetTimeDecoder.groovy @@ -21,9 +21,9 @@ package org.grails.datastore.bson.codecs.decoders import groovy.transform.CompileStatic import org.bson.BsonReader +import org.grails.datastore.bson.codecs.temporal.OffsetTimeBsonConverter import org.grails.datastore.mapping.engine.EntityAccess import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.bson.codecs.temporal.OffsetTimeBsonConverter import static org.grails.datastore.bson.codecs.decoders.SimpleDecoder.TypeDecoder diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/PeriodDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/PeriodDecoder.groovy index 52d3ce135c5..2e362446349 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/PeriodDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/PeriodDecoder.groovy @@ -21,9 +21,9 @@ package org.grails.datastore.bson.codecs.decoders import groovy.transform.CompileStatic import org.bson.BsonReader +import org.grails.datastore.bson.codecs.temporal.PeriodBsonConverter import org.grails.datastore.mapping.engine.EntityAccess import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.bson.codecs.temporal.PeriodBsonConverter import static org.grails.datastore.bson.codecs.decoders.SimpleDecoder.TypeDecoder diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/SimpleDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/SimpleDecoder.groovy index 40a85afbd48..6cbf396e19c 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/SimpleDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/SimpleDecoder.groovy @@ -29,14 +29,6 @@ import org.bson.types.Binary import org.bson.types.Decimal128 import org.bson.types.ObjectId import org.grails.datastore.bson.codecs.PropertyDecoder -import org.grails.datastore.bson.codecs.encoders.InstantEncoder -import org.grails.datastore.bson.codecs.encoders.LocalDateEncoder -import org.grails.datastore.bson.codecs.encoders.LocalDateTimeEncoder -import org.grails.datastore.bson.codecs.encoders.LocalTimeEncoder -import org.grails.datastore.bson.codecs.encoders.OffsetDateTimeEncoder -import org.grails.datastore.bson.codecs.encoders.OffsetTimeEncoder -import org.grails.datastore.bson.codecs.encoders.PeriodEncoder -import org.grails.datastore.bson.codecs.encoders.ZonedDateTimeEncoder import org.grails.datastore.mapping.engine.EntityAccess import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.mapping.model.types.Simple @@ -55,8 +47,10 @@ import java.time.ZonedDateTime */ @CompileStatic class SimpleDecoder implements PropertyDecoder { + public static final Map SIMPLE_TYPE_DECODERS public static final TypeDecoder DEFAULT_DECODER = new TypeDecoder() { + @Override BsonType bsonType() { BsonType.STRING @@ -64,7 +58,7 @@ class SimpleDecoder implements PropertyDecoder { @Override void decode(BsonReader reader, PersistentProperty property, EntityAccess entityAccess) { - entityAccess.setProperty( property.name, reader.readString()) + entityAccess.setProperty(property.name, reader.readString()) } } public static final Map DEFAULT_DECODERS = new HashMap().withDefault { Class -> @@ -84,6 +78,7 @@ class SimpleDecoder implements PropertyDecoder { } DEFAULT_DECODERS.put(BsonType.REGULAR_EXPRESSION, new TypeDecoder() { + @Override BsonType bsonType() { BsonType.REGULAR_EXPRESSION @@ -93,11 +88,12 @@ class SimpleDecoder implements PropertyDecoder { void decode(BsonReader reader, PersistentProperty property, EntityAccess entityAccess) { BsonRegularExpression regularExpression = reader.readRegularExpression() - entityAccess.setProperty( property.name, regularExpression.pattern ) + entityAccess.setProperty(property.name, regularExpression.pattern) } }) DEFAULT_DECODERS.put(BsonType.DECIMAL128, new TypeDecoder() { + @Override BsonType bsonType() { BsonType.DECIMAL128 @@ -106,13 +102,14 @@ class SimpleDecoder implements PropertyDecoder { @Override void decode(BsonReader reader, PersistentProperty property, EntityAccess entityAccess) { Decimal128 dec = reader.readDecimal128() - entityAccess.setProperty( property.name, dec ) + entityAccess.setProperty(property.name, dec) } }) - def convertingIntReader = new TypeDecoder() { + def convertingIntReader = new TypeDecoder() { + @Override void decode(BsonReader reader, PersistentProperty property, EntityAccess entityAccess) { - entityAccess.setProperty( property.name, reader.readInt32() ) + entityAccess.setProperty(property.name, reader.readInt32()) } @Override @@ -128,11 +125,11 @@ class SimpleDecoder implements PropertyDecoder { SIMPLE_TYPE_DECODERS[Byte] = convertingIntReader SIMPLE_TYPE_DECODERS[byte.class] = convertingIntReader - def intDecoder = new TypeDecoder() { + @Override void decode(BsonReader reader, PersistentProperty property, EntityAccess entityAccess) { - entityAccess.setPropertyNoConversion( property.name, reader.readInt32() ) + entityAccess.setPropertyNoConversion(property.name, reader.readInt32()) } @Override @@ -145,9 +142,10 @@ class SimpleDecoder implements PropertyDecoder { SIMPLE_TYPE_DECODERS[int.class] = intDecoder def longDecoder = new TypeDecoder() { + @Override void decode(BsonReader reader, PersistentProperty property, EntityAccess entityAccess) { - entityAccess.setPropertyNoConversion( property.name, reader.readInt64() ) + entityAccess.setPropertyNoConversion(property.name, reader.readInt64()) } @Override @@ -157,9 +155,10 @@ class SimpleDecoder implements PropertyDecoder { } def convertingLongDecoder = new TypeDecoder() { + @Override void decode(BsonReader reader, PersistentProperty property, EntityAccess entityAccess) { - entityAccess.setProperty( property.name, reader.readInt64() ) + entityAccess.setProperty(property.name, reader.readInt64()) } @Override @@ -174,9 +173,10 @@ class SimpleDecoder implements PropertyDecoder { SIMPLE_TYPE_DECODERS[long.class] = longDecoder def doubleDecoder = new TypeDecoder() { + @Override void decode(BsonReader reader, PersistentProperty property, EntityAccess entityAccess) { - entityAccess.setPropertyNoConversion( property.name, reader.readDouble() ) + entityAccess.setPropertyNoConversion(property.name, reader.readDouble()) } @Override @@ -186,9 +186,10 @@ class SimpleDecoder implements PropertyDecoder { } def convertingDoubleDecoder = new TypeDecoder() { + @Override void decode(BsonReader reader, PersistentProperty property, EntityAccess entityAccess) { - entityAccess.setPropertyNoConversion( property.name, reader.readDouble() ) + entityAccess.setPropertyNoConversion(property.name, reader.readDouble()) } @Override @@ -203,9 +204,10 @@ class SimpleDecoder implements PropertyDecoder { SIMPLE_TYPE_DECODERS[double.class] = doubleDecoder def booleanDecoder = new TypeDecoder() { + @Override void decode(BsonReader reader, PersistentProperty property, EntityAccess entityAccess) { - entityAccess.setPropertyNoConversion( property.name, reader.readBoolean() ) + entityAccess.setPropertyNoConversion(property.name, reader.readBoolean()) } @Override @@ -218,8 +220,8 @@ class SimpleDecoder implements PropertyDecoder { SIMPLE_TYPE_DECODERS[Boolean] = booleanDecoder SIMPLE_TYPE_DECODERS[boolean.class] = booleanDecoder - def binaryDecoder = new TypeDecoder() { + @Override void decode(BsonReader reader, PersistentProperty property, EntityAccess entityAccess) { def binary = reader.readBinaryData() @@ -236,10 +238,11 @@ class SimpleDecoder implements PropertyDecoder { SIMPLE_TYPE_DECODERS[([] as byte[]).getClass()] = binaryDecoder SIMPLE_TYPE_DECODERS[Date] = new TypeDecoder() { + @Override void decode(BsonReader reader, PersistentProperty property, EntityAccess entityAccess) { def time = reader.readDateTime() - entityAccess.setPropertyNoConversion( property.name, new Date(time)) + entityAccess.setPropertyNoConversion(property.name, new Date(time)) } @Override @@ -249,6 +252,7 @@ class SimpleDecoder implements PropertyDecoder { } SIMPLE_TYPE_DECODERS[Calendar] = new TypeDecoder() { + @Override BsonType bsonType() { BsonType.DATE_TIME @@ -259,7 +263,7 @@ class SimpleDecoder implements PropertyDecoder { def time = reader.readDateTime() def calendar = new GregorianCalendar() calendar.setTimeInMillis(time) - entityAccess.setPropertyNoConversion( property.name, calendar) + entityAccess.setPropertyNoConversion(property.name, calendar) } } @@ -273,6 +277,7 @@ class SimpleDecoder implements PropertyDecoder { SIMPLE_TYPE_DECODERS[Instant] = new InstantDecoder() SIMPLE_TYPE_DECODERS[Binary] = new TypeDecoder() { + @Override void decode(BsonReader reader, PersistentProperty property, EntityAccess entityAccess) { @@ -289,6 +294,7 @@ class SimpleDecoder implements PropertyDecoder { } SIMPLE_TYPE_DECODERS[ObjectId] = new TypeDecoder() { + @Override BsonType bsonType() { BsonType.OBJECT_ID @@ -302,11 +308,11 @@ class SimpleDecoder implements PropertyDecoder { reader.readObjectId() ) - } } SIMPLE_TYPE_DECODERS[BigDecimal] = new TypeDecoder() { + @Override BsonType bsonType() { BsonType.DECIMAL128 @@ -329,22 +335,19 @@ class SimpleDecoder implements PropertyDecoder { TypeDecoder decoder = SIMPLE_TYPE_DECODERS[type] - if(type.isArray()) { - if(!decoder.is(DEFAULT_DECODER)) { + if (type.isArray()) { + if (!decoder.is(DEFAULT_DECODER)) { decoder.decode reader, property, entityAccess - } - else { + } else { def arrayDecoder = codecRegistry.get(List) def bsonArray = arrayDecoder.decode(reader, decoderContext) entityAccess.setProperty(property.name, bsonArray) } - } - else { + } else { BsonType bsonType = reader.currentBsonType - if(bsonType != decoder.bsonType()) { + if (bsonType != decoder.bsonType()) { DEFAULT_DECODERS.get(bsonType).decode(reader, property, entityAccess) - } - else { + } else { decoder.decode reader, property, entityAccess } } diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/TenantIdDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/TenantIdDecoder.groovy index 4694d2a3a9a..81b3bd0cc80 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/TenantIdDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/TenantIdDecoder.groovy @@ -36,14 +36,14 @@ import org.grails.datastore.mapping.model.types.TenantId */ @CompileStatic class TenantIdDecoder implements PropertyDecoder { + @Override void decode(BsonReader reader, TenantId property, EntityAccess entityAccess, DecoderContext decoderContext, CodecRegistry codecRegistry) { BsonType bsonType = reader.currentBsonType def decoder = SimpleDecoder.SIMPLE_TYPE_DECODERS.get(property.type) - if(bsonType != decoder.bsonType()) { + if (bsonType != decoder.bsonType()) { SimpleDecoder.DEFAULT_DECODERS.get(bsonType).decode(reader, property, entityAccess) - } - else { + } else { decoder.decode reader, property, entityAccess } } diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/ZonedDateTimeDecoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/ZonedDateTimeDecoder.groovy index 8e15924a4a3..8039dc30c0a 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/ZonedDateTimeDecoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/decoders/ZonedDateTimeDecoder.groovy @@ -21,9 +21,9 @@ package org.grails.datastore.bson.codecs.decoders import groovy.transform.CompileStatic import org.bson.BsonReader +import org.grails.datastore.bson.codecs.temporal.ZonedDateTimeBsonConverter import org.grails.datastore.mapping.engine.EntityAccess import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.bson.codecs.temporal.ZonedDateTimeBsonConverter import static org.grails.datastore.bson.codecs.decoders.SimpleDecoder.TypeDecoder diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/BasicCollectionTypeEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/BasicCollectionTypeEncoder.groovy index 9edc29ec1f5..07e87068b23 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/BasicCollectionTypeEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/BasicCollectionTypeEncoder.groovy @@ -42,34 +42,31 @@ class BasicCollectionTypeEncoder implements PropertyEncoder { @Override void encode(BsonWriter writer, Basic property, Object value, EntityAccess parentAccess, EncoderContext encoderContext, CodecRegistry codecRegistry) { def marshaller = property.customTypeMarshaller - if(marshaller) { + if (marshaller) { CustomTypeEncoder.encode(codecRegistry, encoderContext, writer, property, marshaller, value) - } - else { - writer.writeName( MappingUtils.getTargetKey(property) ) + } else { + writer.writeName(MappingUtils.getTargetKey(property)) def collectionType = property.type Codec codec final boolean isSet = Set.isAssignableFrom(collectionType) - if(isSet) { - codec = (Codec)codecRegistry.get(List) - } - else { - codec = (Codec)codecRegistry.get(collectionType) + if (isSet) { + codec = (Codec) codecRegistry.get(List) + } else { + codec = (Codec) codecRegistry.get(collectionType) } - codec.encode(writer, isSet ? value as List : value, encoderContext) + codec.encode(writer, isSet ? value as List : value, encoderContext) def parent = parentAccess.entity - if(parent instanceof DirtyCheckable) { - if(value instanceof Collection) { + if (parent instanceof DirtyCheckable) { + if (value instanceof Collection) { def propertyName = property.name parentAccess.setPropertyNoConversion( propertyName, DirtyCheckingSupport.wrap(value, parent, propertyName) ) - } - else if(value instanceof Map && !(value instanceof Bson)) { + } else if (value instanceof Map && !(value instanceof Bson)) { def propertyName = property.name parentAccess.setPropertyNoConversion( propertyName, diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/CustomTypeEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/CustomTypeEncoder.groovy index 27a3db74a51..27291c6a4b6 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/CustomTypeEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/CustomTypeEncoder.groovy @@ -48,17 +48,16 @@ class CustomTypeEncoder implements PropertyEncoder { protected static void encode(CodecRegistry codecRegistry, EncoderContext encoderContext, BsonWriter writer, PersistentProperty property, CustomTypeMarshaller marshaller, value) { String targetName = MappingUtils.getTargetKey(property) - if(marshaller instanceof CodecCustomTypeMarshaller) { + if (marshaller instanceof CodecCustomTypeMarshaller) { writer.writeName(targetName) Codec codec = marshaller.codec - codec.encode(writer,value, encoderContext) - } - else { + codec.encode(writer, value, encoderContext) + } else { def document = new Document() marshaller.write(property, value, document) Object converted = document.get(targetName) - if(converted != null) { + if (converted != null) { Codec codec = (Codec) codecRegistry.get(converted.getClass()) if (codec) { writer.writeName(targetName) diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/EmbeddedCollectionEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/EmbeddedCollectionEncoder.groovy index 92db34380f2..25738a6a86f 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/EmbeddedCollectionEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/EmbeddedCollectionEncoder.groovy @@ -55,32 +55,31 @@ class EmbeddedCollectionEncoder implements PropertyEncoder { def isToOne = inverseSide instanceof ToOne def mappingContext = parentAccess.persistentEntity.mappingContext - if(Collection.isInstance(value)) { + if (Collection.isInstance(value)) { writer.writeStartArray() - for(v in value) { - if(v != null) { + for (v in value) { + if (v != null) { BsonPersistentEntityCodec codec = associatedCodec PersistentEntity entity = associatedEntity def cls = v.getClass() - if(cls != associatedEntity.javaClass) { + if (cls != associatedEntity.javaClass) { // try subclass def childEntity = mappingContext.getPersistentEntity(cls.name) - if(childEntity != null) { + if (childEntity != null) { entity = childEntity - codec = (BsonPersistentEntityCodec)codecRegistry.get(cls) - } - else { + codec = (BsonPersistentEntityCodec) codecRegistry.get(cls) + } else { continue } } def ea = mappingContext.getEntityReflector(entity) def id = ea.getIdentifier(v) - if(isBidirectional) { - if(isToOne) { + if (isBidirectional) { + if (isToOne) { ea.setProperty(v, inverseProperty, parentAccess.entity) } } @@ -89,12 +88,11 @@ class EmbeddedCollectionEncoder implements PropertyEncoder { } } writer.writeEndArray() - } - else if(Map.isInstance(value)) { + } else if (Map.isInstance(value)) { writer.writeStartDocument() - for(e in value) { - Map.Entry entry = (Map.Entry)e + for (e in value) { + Map.Entry entry = (Map.Entry) e writer.writeName entry.key diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/EmbeddedEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/EmbeddedEncoder.groovy index a4a436373a4..aa8491eeef0 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/EmbeddedEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/EmbeddedEncoder.groovy @@ -38,11 +38,11 @@ class EmbeddedEncoder implements PropertyEncoder { @Override void encode(BsonWriter writer, Embedded property, Object value, EntityAccess parentAccess, EncoderContext encoderContext, CodecRegistry codecRegistry) { - if(value != null) { + if (value != null) { def mappingContext = parentAccess.persistentEntity.mappingContext PersistentEntity associatedEntity = mappingContext.getPersistentEntity(value.getClass().name) - if(associatedEntity == null) { + if (associatedEntity == null) { associatedEntity = property.associatedEntity } diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/IdentityEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/IdentityEncoder.groovy index 2f5abb4f65c..dbfde80eb92 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/IdentityEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/IdentityEncoder.groovy @@ -51,10 +51,9 @@ class IdentityEncoder implements PropertyEncoder { protected String getIdentifierName(Identity property) { String[] identifierName = property.getOwner().mapping.identifier?.identifierName - if(identifierName != null) { + if (identifierName != null) { return identifierName[0] - } - else { + } else { return GormProperties.IDENTITY } } diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/InstantEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/InstantEncoder.groovy index 68f93c4cdf8..6f1ec808de4 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/InstantEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/InstantEncoder.groovy @@ -21,8 +21,8 @@ package org.grails.datastore.bson.codecs.encoders import groovy.transform.CompileStatic import org.bson.BsonWriter -import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.bson.codecs.temporal.InstantBsonConverter +import org.grails.datastore.mapping.model.PersistentProperty import java.time.Instant @@ -38,6 +38,6 @@ class InstantEncoder implements TypeEncoder, InstantBsonConverter { @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - write(writer, (Instant)value) + write(writer, (Instant) value) } } \ No newline at end of file diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/LocalDateEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/LocalDateEncoder.groovy index ac7ef927104..ca5de72281f 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/LocalDateEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/LocalDateEncoder.groovy @@ -21,8 +21,8 @@ package org.grails.datastore.bson.codecs.encoders import groovy.transform.CompileStatic import org.bson.BsonWriter -import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.bson.codecs.temporal.LocalDateBsonConverter +import org.grails.datastore.mapping.model.PersistentProperty import java.time.LocalDate @@ -38,6 +38,6 @@ class LocalDateEncoder implements TypeEncoder, LocalDateBsonConverter { @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - write(writer, (LocalDate)value) + write(writer, (LocalDate) value) } } diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/LocalDateTimeEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/LocalDateTimeEncoder.groovy index 5a23bef942f..02cc0366710 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/LocalDateTimeEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/LocalDateTimeEncoder.groovy @@ -21,8 +21,8 @@ package org.grails.datastore.bson.codecs.encoders import groovy.transform.CompileStatic import org.bson.BsonWriter -import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.bson.codecs.temporal.LocalDateTimeBsonConverter +import org.grails.datastore.mapping.model.PersistentProperty import java.time.LocalDateTime @@ -38,6 +38,6 @@ class LocalDateTimeEncoder implements TypeEncoder, LocalDateTimeBsonConverter { @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - write(writer, (LocalDateTime)value) + write(writer, (LocalDateTime) value) } } \ No newline at end of file diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/LocalTimeEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/LocalTimeEncoder.groovy index f4dc35dd93b..66efab6f8a2 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/LocalTimeEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/LocalTimeEncoder.groovy @@ -21,8 +21,8 @@ package org.grails.datastore.bson.codecs.encoders import groovy.transform.CompileStatic import org.bson.BsonWriter -import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.bson.codecs.temporal.LocalTimeBsonConverter +import org.grails.datastore.mapping.model.PersistentProperty import java.time.LocalTime @@ -38,6 +38,6 @@ class LocalTimeEncoder implements TypeEncoder, LocalTimeBsonConverter { @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - write(writer, (LocalTime)value) + write(writer, (LocalTime) value) } } \ No newline at end of file diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/OffsetDateTimeEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/OffsetDateTimeEncoder.groovy index e8f5b56d057..99ba8eea14b 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/OffsetDateTimeEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/OffsetDateTimeEncoder.groovy @@ -21,8 +21,8 @@ package org.grails.datastore.bson.codecs.encoders import groovy.transform.CompileStatic import org.bson.BsonWriter -import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.bson.codecs.temporal.OffsetDateTimeBsonConverter +import org.grails.datastore.mapping.model.PersistentProperty import java.time.OffsetDateTime @@ -38,6 +38,6 @@ class OffsetDateTimeEncoder implements TypeEncoder, OffsetDateTimeBsonConverter @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - write(writer, (OffsetDateTime)value) + write(writer, (OffsetDateTime) value) } } \ No newline at end of file diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/OffsetTimeEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/OffsetTimeEncoder.groovy index 80ef0944e71..669ba1141e2 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/OffsetTimeEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/OffsetTimeEncoder.groovy @@ -21,8 +21,8 @@ package org.grails.datastore.bson.codecs.encoders import groovy.transform.CompileStatic import org.bson.BsonWriter -import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.bson.codecs.temporal.OffsetTimeBsonConverter +import org.grails.datastore.mapping.model.PersistentProperty import java.time.OffsetTime @@ -38,6 +38,6 @@ class OffsetTimeEncoder implements TypeEncoder, OffsetTimeBsonConverter { @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - write(writer, (OffsetTime)value) + write(writer, (OffsetTime) value) } } \ No newline at end of file diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/PeriodEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/PeriodEncoder.groovy index b033b3cc9dc..b40fd0a8350 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/PeriodEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/PeriodEncoder.groovy @@ -21,8 +21,8 @@ package org.grails.datastore.bson.codecs.encoders import groovy.transform.CompileStatic import org.bson.BsonWriter -import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.bson.codecs.temporal.PeriodBsonConverter +import org.grails.datastore.mapping.model.PersistentProperty import java.time.Period @@ -38,6 +38,6 @@ class PeriodEncoder implements TypeEncoder, PeriodBsonConverter { @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - write(writer, (Period)value) + write(writer, (Period) value) } } \ No newline at end of file diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/SimpleEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/SimpleEncoder.groovy index 2fbc85bcb24..e77c165c2e4 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/SimpleEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/SimpleEncoder.groovy @@ -52,14 +52,16 @@ import java.time.ZonedDateTime class SimpleEncoder implements PropertyEncoder { static interface TypeEncoder { + void encode(BsonWriter writer, PersistentProperty property, Object value) } public static final Map SIMPLE_TYPE_ENCODERS public static final TypeEncoder DEFAULT_ENCODER = new TypeEncoder() { + @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - writer.writeString( value.toString() ) + writer.writeString(value.toString()) } } @@ -71,9 +73,10 @@ class SimpleEncoder implements PropertyEncoder { } TypeEncoder smallNumberEncoder = new TypeEncoder() { + @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - writer.writeInt32( ((Number)value).intValue() ) + writer.writeInt32(((Number) value).intValue()) } } SIMPLE_TYPE_ENCODERS[CharSequence] = DEFAULT_ENCODER @@ -87,45 +90,51 @@ class SimpleEncoder implements PropertyEncoder { SIMPLE_TYPE_ENCODERS[Short] = smallNumberEncoder SIMPLE_TYPE_ENCODERS[short.class] = smallNumberEncoder TypeEncoder doubleEncoder = new TypeEncoder() { + @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - writer.writeDouble( (Double)value ) + writer.writeDouble((Double) value) } } SIMPLE_TYPE_ENCODERS[Double] = doubleEncoder SIMPLE_TYPE_ENCODERS[double.class] = doubleEncoder TypeEncoder longEncoder = new TypeEncoder() { + @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - writer.writeInt64( (Long)value ) + writer.writeInt64((Long) value) } } SIMPLE_TYPE_ENCODERS[Long] = longEncoder SIMPLE_TYPE_ENCODERS[long.class] = longEncoder TypeEncoder booleanEncoder = new TypeEncoder() { + @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - writer.writeBoolean( (Boolean)value ) + writer.writeBoolean((Boolean) value) } } SIMPLE_TYPE_ENCODERS[Boolean] = booleanEncoder SIMPLE_TYPE_ENCODERS[boolean.class] = booleanEncoder SIMPLE_TYPE_ENCODERS[Calendar] = new TypeEncoder() { + @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - writer.writeDateTime( ((Calendar)value).timeInMillis ) + writer.writeDateTime(((Calendar) value).timeInMillis) } } SIMPLE_TYPE_ENCODERS[Date] = new TypeEncoder() { + @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - writer.writeDateTime( ((Date)value).time ) + writer.writeDateTime(((Date) value).time) } } SIMPLE_TYPE_ENCODERS[TimeZone] = new TypeEncoder() { + @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - writer.writeString( ((TimeZone)value).ID ) + writer.writeString(((TimeZone) value).ID) } } @@ -139,21 +148,24 @@ class SimpleEncoder implements PropertyEncoder { SIMPLE_TYPE_ENCODERS[Instant] = new InstantEncoder() SIMPLE_TYPE_ENCODERS[([] as byte[]).getClass()] = new TypeEncoder() { + @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - writer.writeBinaryData( new BsonBinary((byte[])value)) + writer.writeBinaryData(new BsonBinary((byte[]) value)) } } SIMPLE_TYPE_ENCODERS[Binary] = new TypeEncoder() { + @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - writer.writeBinaryData( new BsonBinary(((Binary)value).data)) + writer.writeBinaryData(new BsonBinary(((Binary) value).data)) } } SIMPLE_TYPE_ENCODERS[ObjectId] = new TypeEncoder() { + @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - writer.writeObjectId((ObjectId)value) + writer.writeObjectId((ObjectId) value) } } } @@ -163,21 +175,19 @@ class SimpleEncoder implements PropertyEncoder { void encode(BsonWriter writer, Simple property, Object value, EntityAccess parentAccess, EncoderContext encoderContext, CodecRegistry codecRegistry) { def type = property.type def encoder = SIMPLE_TYPE_ENCODERS[type] - writer.writeName( MappingUtils.getTargetKey(property) ) - if(type.isArray()) { - if(!encoder.is(DEFAULT_ENCODER)) { + writer.writeName(MappingUtils.getTargetKey(property)) + if (type.isArray()) { + if (!encoder.is(DEFAULT_ENCODER)) { encoder.encode(writer, property, value) - } - else { + } else { writer.writeStartArray() - for( o in value ) { + for (o in value) { encoder = SIMPLE_TYPE_ENCODERS[type.componentType] encoder.encode(writer, property, o) } writer.writeEndArray() } - } - else { + } else { encoder.encode(writer, property, value) } } @@ -187,12 +197,14 @@ class SimpleEncoder implements PropertyEncoder { */ static void enableBigDecimalEncoding() { SIMPLE_TYPE_ENCODERS[BigInteger] = new TypeEncoder() { + @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { writer.writeDecimal128(new Decimal128(((BigInteger) value).toBigDecimal())) } } SIMPLE_TYPE_ENCODERS[BigDecimal] = new TypeEncoder() { + @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { writer.writeDecimal128(new Decimal128((BigDecimal) value)) diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/TenantIdEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/TenantIdEncoder.groovy index b6e4fbc8678..3152d5f9517 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/TenantIdEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/TenantIdEncoder.groovy @@ -23,12 +23,9 @@ import groovy.transform.CompileStatic import org.bson.BsonWriter import org.bson.codecs.EncoderContext import org.bson.codecs.configuration.CodecRegistry -import org.bson.types.ObjectId import org.grails.datastore.bson.codecs.PropertyEncoder import org.grails.datastore.mapping.engine.EntityAccess import org.grails.datastore.mapping.engine.internal.MappingUtils -import org.grails.datastore.mapping.model.config.GormProperties -import org.grails.datastore.mapping.model.types.Identity import org.grails.datastore.mapping.model.types.TenantId /** @@ -42,7 +39,7 @@ class TenantIdEncoder implements PropertyEncoder { @Override void encode(BsonWriter writer, TenantId property, Object id, EntityAccess parentAccess, EncoderContext encoderContext, CodecRegistry codecRegistry) { - writer.writeName( MappingUtils.getTargetKey(property) ) + writer.writeName(MappingUtils.getTargetKey(property)) SimpleEncoder.SIMPLE_TYPE_ENCODERS.get(property.type).encode(writer, property, id) } diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/ZonedDateTimeEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/ZonedDateTimeEncoder.groovy index 590d719799d..00c8bc4ddd9 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/ZonedDateTimeEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/encoders/ZonedDateTimeEncoder.groovy @@ -21,8 +21,8 @@ package org.grails.datastore.bson.codecs.encoders import groovy.transform.CompileStatic import org.bson.BsonWriter -import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.bson.codecs.temporal.ZonedDateTimeBsonConverter +import org.grails.datastore.mapping.model.PersistentProperty import java.time.ZonedDateTime @@ -36,6 +36,6 @@ class ZonedDateTimeEncoder implements SimpleEncoder.TypeEncoder, ZonedDateTimeBs @Override void encode(BsonWriter writer, PersistentProperty property, Object value) { - write(writer, (ZonedDateTime)value) + write(writer, (ZonedDateTime) value) } } \ No newline at end of file diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/InstantBsonConverter.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/InstantBsonConverter.groovy index 7d348ffeac8..aa452dbb025 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/InstantBsonConverter.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/InstantBsonConverter.groovy @@ -19,11 +19,11 @@ package org.grails.datastore.bson.codecs.temporal +import grails.gorm.time.InstantConverter import groovy.transform.CompileStatic import org.bson.BsonReader import org.bson.BsonType import org.bson.BsonWriter -import grails.gorm.time.InstantConverter import java.time.Instant diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/LocalDateBsonConverter.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/LocalDateBsonConverter.groovy index f23479ef5e8..957a1df2d5b 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/LocalDateBsonConverter.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/LocalDateBsonConverter.groovy @@ -19,11 +19,11 @@ package org.grails.datastore.bson.codecs.temporal +import grails.gorm.time.LocalDateConverter import groovy.transform.CompileStatic import org.bson.BsonReader import org.bson.BsonType import org.bson.BsonWriter -import grails.gorm.time.LocalDateConverter import java.time.LocalDate diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/LocalDateTimeBsonConverter.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/LocalDateTimeBsonConverter.groovy index 11b28d70336..a1ced8f6bff 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/LocalDateTimeBsonConverter.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/LocalDateTimeBsonConverter.groovy @@ -19,11 +19,11 @@ package org.grails.datastore.bson.codecs.temporal +import grails.gorm.time.LocalDateTimeConverter import groovy.transform.CompileStatic import org.bson.BsonReader import org.bson.BsonType import org.bson.BsonWriter -import grails.gorm.time.LocalDateTimeConverter import java.time.LocalDateTime diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/LocalTimeBsonConverter.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/LocalTimeBsonConverter.groovy index b4f8ce1c262..a0252a66a6e 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/LocalTimeBsonConverter.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/LocalTimeBsonConverter.groovy @@ -19,11 +19,11 @@ package org.grails.datastore.bson.codecs.temporal +import grails.gorm.time.LocalTimeConverter import groovy.transform.CompileStatic import org.bson.BsonReader import org.bson.BsonType import org.bson.BsonWriter -import grails.gorm.time.LocalTimeConverter import java.time.LocalTime diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/OffsetDateTimeBsonConverter.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/OffsetDateTimeBsonConverter.groovy index 06a1f0ccb90..ffd9d37defc 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/OffsetDateTimeBsonConverter.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/OffsetDateTimeBsonConverter.groovy @@ -19,11 +19,11 @@ package org.grails.datastore.bson.codecs.temporal +import grails.gorm.time.OffsetDateTimeConverter import groovy.transform.CompileStatic import org.bson.BsonReader import org.bson.BsonType import org.bson.BsonWriter -import grails.gorm.time.OffsetDateTimeConverter import java.time.OffsetDateTime diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/OffsetTimeBsonConverter.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/OffsetTimeBsonConverter.groovy index cb66e629778..a2fe41a8605 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/OffsetTimeBsonConverter.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/codecs/temporal/OffsetTimeBsonConverter.groovy @@ -19,11 +19,11 @@ package org.grails.datastore.bson.codecs.temporal +import grails.gorm.time.OffsetTimeConverter import groovy.transform.CompileStatic import org.bson.BsonReader import org.bson.BsonType import org.bson.BsonWriter -import grails.gorm.time.OffsetTimeConverter import java.time.OffsetTime diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/json/JsonReader.java b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/json/JsonReader.java index c4c072eb07b..e131cbdbfdb 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/json/JsonReader.java +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/json/JsonReader.java @@ -15,7 +15,15 @@ */ package org.grails.datastore.bson.json; -import org.bson.*; +import org.bson.AbstractBsonReader; +import org.bson.BsonBinary; +import org.bson.BsonContextType; +import org.bson.BsonDbPointer; +import org.bson.BsonInvalidOperationException; +import org.bson.BsonReaderMark; +import org.bson.BsonRegularExpression; +import org.bson.BsonTimestamp; +import org.bson.BsonType; import org.bson.json.JsonParseException; import org.bson.types.Decimal128; import org.bson.types.ObjectId; @@ -221,7 +229,6 @@ protected void doReadEndArray() { } } - @Override protected void doReadEndDocument() { setContext(getContext().getParentContext()); diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/json/JsonScanner.java b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/json/JsonScanner.java index a7bfb411762..152f9ddb378 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/json/JsonScanner.java +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/json/JsonScanner.java @@ -35,7 +35,6 @@ class JsonScanner { final PushbackReader reader; int position; - /** * Constructs a a new {@code JSONScanner} that produces values scanned from specified {@code JSONBuffer}. * @@ -45,7 +44,6 @@ public JsonScanner(final Reader reader) { this.reader = new PushbackReader(reader); } - /** * Finds and returns the next complete token from this scanner. If scanner reached the end of the source, it will return a token with * {@code JSONTokenType.END_OF_FILE} type. @@ -89,7 +87,7 @@ public JsonToken nextToken() throws IOException { if (c == JsonToken.MINUS || Character.isDigit(c)) { return scanNumber((char) c); } else if (c == '$' || c == '_' || Character.isLetter(c)) { - return scanUnquotedString((char)c); + return scanUnquotedString((char) c); } else { reader.unread(c); throw new JsonParseException("Invalid JSON input. Position: %d. Character: '%c'.", position, c); @@ -129,17 +127,17 @@ private JsonToken scanRegularExpression() throws IOException { break; case JsonToken.BACK_SLASH: state = JsonScanner.RegularExpressionState.IN_ESCAPE_SEQUENCE; - regexBuilder.append((char)c); + regexBuilder.append((char) c); break; default: state = JsonScanner.RegularExpressionState.IN_PATTERN; - regexBuilder.append((char)c); + regexBuilder.append((char) c); break; } break; case IN_ESCAPE_SEQUENCE: state = RegularExpressionState.IN_PATTERN; - regexBuilder.append((char)c); + regexBuilder.append((char) c); break; case IN_OPTIONS: switch (c) { @@ -148,7 +146,7 @@ private JsonToken scanRegularExpression() throws IOException { case 'x': case 's': state = JsonScanner.RegularExpressionState.IN_OPTIONS; - optionsBuilder.append((char)c); + optionsBuilder.append((char) c); break; case JsonToken.COMMA: case JsonToken.CLOSE_BRACE: @@ -185,15 +183,15 @@ private JsonToken scanRegularExpression() throws IOException { /** * Reads {@code StringToken} from source. * - * @return The string token. * @param startChar + * @return The string token. */ private JsonToken scanUnquotedString(char startChar) throws IOException { StringBuilder builder = new StringBuilder(); builder.append(startChar); int c = readCharacter(); while (c == '$' || c == '_' || Character.isLetterOrDigit(c)) { - builder.append((char)c); + builder.append((char) c); c = readCharacter(); } reader.unread(c); @@ -250,15 +248,15 @@ private JsonToken scanNumber(final char firstChar) throws IOException { case SAW_LEADING_MINUS: switch (c) { case '0': - numberBuilder.append((char)c); + numberBuilder.append((char) c); state = JsonScanner.NumberState.SAW_LEADING_ZERO; break; case 'I': - numberBuilder.append((char)c); + numberBuilder.append((char) c); state = JsonScanner.NumberState.SAW_MINUS_I; break; default: - numberBuilder.append((char)c); + numberBuilder.append((char) c); if (Character.isDigit(c)) { state = JsonScanner.NumberState.SAW_INTEGER_DIGITS; } else { @@ -271,12 +269,12 @@ private JsonToken scanNumber(final char firstChar) throws IOException { case SAW_INTEGER_DIGITS: switch (c) { case '.': - numberBuilder.append((char)c); + numberBuilder.append((char) c); state = JsonScanner.NumberState.SAW_DECIMAL_POINT; break; case 'e': case 'E': - numberBuilder.append((char)c); + numberBuilder.append((char) c); state = JsonScanner.NumberState.SAW_EXPONENT_LETTER; break; case JsonToken.COMMA: @@ -288,7 +286,7 @@ private JsonToken scanNumber(final char firstChar) throws IOException { break; default: if (Character.isDigit(c)) { - numberBuilder.append((char)c); + numberBuilder.append((char) c); state = JsonScanner.NumberState.SAW_INTEGER_DIGITS; } else if (Character.isWhitespace(c)) { state = JsonScanner.NumberState.DONE; @@ -301,7 +299,7 @@ private JsonToken scanNumber(final char firstChar) throws IOException { case SAW_DECIMAL_POINT: type = JsonTokenType.DOUBLE; if (Character.isDigit(c)) { - numberBuilder.append((char)c); + numberBuilder.append((char) c); state = JsonScanner.NumberState.SAW_FRACTION_DIGITS; } else { state = JsonScanner.NumberState.INVALID; @@ -311,7 +309,7 @@ private JsonToken scanNumber(final char firstChar) throws IOException { switch (c) { case 'e': case 'E': - numberBuilder.append((char)c); + numberBuilder.append((char) c); state = JsonScanner.NumberState.SAW_EXPONENT_LETTER; break; case JsonToken.COMMA: @@ -323,7 +321,7 @@ private JsonToken scanNumber(final char firstChar) throws IOException { break; default: if (Character.isDigit(c)) { - numberBuilder.append((char)c); + numberBuilder.append((char) c); state = JsonScanner.NumberState.SAW_FRACTION_DIGITS; } else if (Character.isWhitespace(c)) { state = JsonScanner.NumberState.DONE; @@ -338,12 +336,12 @@ private JsonToken scanNumber(final char firstChar) throws IOException { switch (c) { case '+': case '-': - numberBuilder.append((char)c); + numberBuilder.append((char) c); state = JsonScanner.NumberState.SAW_EXPONENT_SIGN; break; default: if (Character.isDigit(c)) { - numberBuilder.append((char)c); + numberBuilder.append((char) c); state = JsonScanner.NumberState.SAW_EXPONENT_DIGITS; } else { state = JsonScanner.NumberState.INVALID; @@ -353,7 +351,7 @@ private JsonToken scanNumber(final char firstChar) throws IOException { break; case SAW_EXPONENT_SIGN: if (Character.isDigit(c)) { - numberBuilder.append((char)c); + numberBuilder.append((char) c); state = JsonScanner.NumberState.SAW_EXPONENT_DIGITS; } else { state = JsonScanner.NumberState.INVALID; @@ -369,7 +367,7 @@ private JsonToken scanNumber(final char firstChar) throws IOException { break; default: if (Character.isDigit(c)) { - numberBuilder.append((char)c); + numberBuilder.append((char) c); state = JsonScanner.NumberState.SAW_EXPONENT_DIGITS; } else if (Character.isWhitespace(c)) { state = JsonScanner.NumberState.DONE; @@ -381,14 +379,14 @@ private JsonToken scanNumber(final char firstChar) throws IOException { break; case SAW_MINUS_I: boolean sawMinusInfinity = true; - numberBuilder.append((char)c); + numberBuilder.append((char) c); for (int i = 0; i < NFINITY.length; i++) { if (c != NFINITY[i]) { sawMinusInfinity = false; break; } c = readCharacter(); - numberBuilder.append((char)c); + numberBuilder.append((char) c); } if (sawMinusInfinity) { type = JsonTokenType.DOUBLE; diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/json/JsonWriter.java b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/json/JsonWriter.java index 94d8c3b5da4..baa5d2d13b6 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/json/JsonWriter.java +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/json/JsonWriter.java @@ -13,10 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.grails.datastore.bson.json; -import org.bson.*; +import org.bson.AbstractBsonWriter; +import org.bson.BSONException; +import org.bson.BsonBinary; +import org.bson.BsonContextType; +import org.bson.BsonDbPointer; +import org.bson.BsonRegularExpression; +import org.bson.BsonTimestamp; import org.bson.json.JsonWriterSettings; import org.bson.types.Decimal128; import org.bson.types.ObjectId; @@ -95,6 +100,7 @@ protected void doWriteStartArray() { } } + @Override protected void doWriteEndArray() { try { @@ -137,7 +143,7 @@ protected void doWriteDateTime(long value) { writeNameHelper(getName()); writer.write(JsonToken.QUOTE); Date date = new Date(value); - writer.write( df.format(date) ); + writer.write(df.format(date)); writer.write(JsonToken.QUOTE); setState(getNextState()); } catch (IOException e) { @@ -178,8 +184,7 @@ protected void doWriteInt64(long value) { writeNameHelper(getName()); if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) { writer.write(Long.toString(value)); - } - else { + } else { writer.write(JsonToken.QUOTE); writer.write(Long.toString(value)); writer.write(JsonToken.QUOTE); @@ -260,7 +265,7 @@ protected void doWriteRegularExpression(BsonRegularExpression regularExpression) writer.write(escaped); writer.write(JsonToken.FORWARD_SLASH); writer.write(regularExpression.getOptions()); - break; + break; } } catch (IOException e) { throwBsonException(e); @@ -414,6 +419,7 @@ private void writeStringHelper(final String str) throws IOException { */ public class Context extends AbstractBsonWriter.Context { + private final String indentation; private boolean hasElements; diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/query/BsonQuery.java b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/query/BsonQuery.java index 15c2e9337a9..af3a3106342 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/query/BsonQuery.java +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/query/BsonQuery.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.bson.query; import grails.gorm.DetachedCriteria; @@ -42,7 +41,11 @@ import org.grails.datastore.mapping.reflect.EntityReflector; import org.springframework.dao.InvalidDataAccessResourceUsageException; -import java.util.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.regex.Pattern; /** @@ -52,6 +55,7 @@ * @since 6.0 */ public abstract class BsonQuery extends Query { + public static final String PROJECT_OPERATOR = "$project"; public static final String SORT_OPERATOR = "$sort"; public static final String IN_OPERATOR = "$in"; @@ -79,13 +83,13 @@ public abstract class BsonQuery extends Query { public static final EncoderContext ENCODER_CONTEXT = EncoderContext.builder().build(); public static final String ID_REFERENCE_SUFFIX = ".$id"; - private static final String THIS_PREFIX = "this."; protected static Map queryHandlers = new HashMap<>(); protected static Map operatorHandlers = new HashMap<>(); protected static Map groupByProjectionHandlers = new HashMap<>(); - protected static Map projectProjectionHandlers = new HashMap<>(); + private static final String THIS_PREFIX = "this."; + static { queryHandlers.put(IdEquals.class, new QueryHandler() { public void handle(EmbeddedQueryEncoder queryEncoder, IdEquals criterion, Document query, PersistentEntity entity) { @@ -95,7 +99,7 @@ public void handle(EmbeddedQueryEncoder queryEncoder, IdEquals criterion, Docume Object converted = mappingContext.getConversionService().convert(value, identity.getType()); Property mappedForm = identity.getMapping().getMappedForm(); String targetProperty = mappedForm.getTargetName(); - if(targetProperty == null) { + if (targetProperty == null) { targetProperty = identity.getName(); } query.put(targetProperty, converted); @@ -202,7 +206,9 @@ public void handle(EmbeddedQueryEncoder queryEncoder, ILike like, Document query queryHandlers.put(RLike.class, new QueryHandler() { public void handle(EmbeddedQueryEncoder queryEncoder, RLike like, Document query, PersistentEntity entity) { Object value = like.getValue(); - if (value == null) value = "null"; + if (value == null) { + value = "null"; + } final String expr = value.toString(); Pattern regex = Pattern.compile(expr); String propertyName = getPropertyName(entity, like); @@ -284,7 +290,7 @@ public void handle(EmbeddedQueryEncoder queryEncoder, Negation criteria, Documen for (Criterion criterion : criteria.getCriteria()) { Document negatedQuery = new Document(); nor.add(negatedQuery); - if(criterion instanceof PropertyCriterion) { + if (criterion instanceof PropertyCriterion) { PropertyCriterion pc = (PropertyCriterion) criterion; PersistentProperty property = entity.getPropertyByName(pc.getProperty()); if (property instanceof Custom) { @@ -377,7 +383,7 @@ public void handle(EmbeddedQueryEncoder queryEncoder, SizeGreaterThanEquals crit @Override public void handle(Junction criteria, String attributeName, BsonReader queryReader) { Object value = readBsonValue(queryReader, queryReader.getCurrentBsonType()); - if(value != null && !(value instanceof NullObject)) { + if (value != null && !(value instanceof NullObject)) { criteria.add(new Query.GreaterThan(attributeName, value)); } } @@ -387,7 +393,7 @@ public void handle(Junction criteria, String attributeName, BsonReader queryRead @Override public void handle(Junction criteria, String attributeName, BsonReader queryReader) { Object value = readBsonValue(queryReader, queryReader.getCurrentBsonType()); - if(value != null && !(value instanceof NullObject)) { + if (value != null && !(value instanceof NullObject)) { criteria.add(new Query.GreaterThanEquals(attributeName, value)); } } @@ -397,7 +403,7 @@ public void handle(Junction criteria, String attributeName, BsonReader queryRead @Override public void handle(Junction criteria, String attributeName, BsonReader queryReader) { Object value = readBsonValue(queryReader, queryReader.getCurrentBsonType()); - if(value != null && !(value instanceof NullObject)) { + if (value != null && !(value instanceof NullObject)) { criteria.add(new Query.LessThan(attributeName, value)); } } @@ -406,7 +412,7 @@ public void handle(Junction criteria, String attributeName, BsonReader queryRead @Override public void handle(Junction criteria, String attributeName, BsonReader queryReader) { Object value = readBsonValue(queryReader, queryReader.getCurrentBsonType()); - if(value != null && !(value instanceof NullObject)) { + if (value != null && !(value instanceof NullObject)) { criteria.add(new Query.LessThanEquals(attributeName, value)); } } @@ -415,7 +421,7 @@ public void handle(Junction criteria, String attributeName, BsonReader queryRead @Override public void handle(Junction criteria, String attributeName, BsonReader queryReader) { Object value = readBsonValue(queryReader, queryReader.getCurrentBsonType()); - if(value != null && !(value instanceof NullObject)) { + if (value != null && !(value instanceof NullObject)) { criteria.add(new Query.NotEquals(attributeName, value)); } } @@ -424,7 +430,7 @@ public void handle(Junction criteria, String attributeName, BsonReader queryRead @Override public void handle(Junction criteria, String attributeName, BsonReader queryReader) { Object value = readBsonValue(queryReader, queryReader.getCurrentBsonType()); - if(value != null) { + if (value != null) { criteria.add(new Query.Equals(attributeName, value)); } } @@ -434,7 +440,7 @@ public void handle(Junction criteria, String attributeName, BsonReader queryRead @Override public void handle(Junction criteria, String attributeName, BsonReader queryReader) { Object value = readBsonValue(queryReader, queryReader.getCurrentBsonType()); - if(value != null && !(value instanceof NullObject)) { + if (value != null && !(value instanceof NullObject)) { criteria.add(new Query.RLike(attributeName, value.toString())); } } @@ -498,15 +504,23 @@ public void handle(Junction criteria, String attributeName, BsonReader queryRead }); } + protected BsonQuery(Session session, PersistentEntity entity) { + super(session, entity); + } + + protected BsonQuery(PersistentEntity entity) { + super(null, entity); + } + private static List readArrayOfValues(BsonReader queryReader) { List values = new ArrayList(); BsonType bsonType = queryReader.getCurrentBsonType(); - if(bsonType == BsonType.ARRAY) { + if (bsonType == BsonType.ARRAY) { queryReader.readStartArray(); bsonType = queryReader.readBsonType(); - while(bsonType != BsonType.END_OF_DOCUMENT) { + while (bsonType != BsonType.END_OF_DOCUMENT) { Object value = readBsonValue(queryReader, queryReader.getCurrentBsonType()); - if(value instanceof NullObject) { + if (value instanceof NullObject) { value = null; } values.add(value); @@ -519,25 +533,16 @@ private static List readArrayOfValues(BsonReader queryReader) { } private static void parseJunctionDocuments(Junction junction, String attributeName, BsonReader queryReader, BsonType bsonType) { - while(bsonType != BsonType.END_OF_DOCUMENT) { - if(bsonType == BsonType.DOCUMENT) { + while (bsonType != BsonType.END_OF_DOCUMENT) { + if (bsonType == BsonType.DOCUMENT) { parseQueryAttributeValue(queryReader, bsonType, attributeName, junction); - } - else { + } else { queryReader.skipValue(); } bsonType = queryReader.readBsonType(); } } - protected BsonQuery(Session session, PersistentEntity entity) { - super(session, entity); - } - - protected BsonQuery(PersistentEntity entity) { - super(null, entity); - } - /** * Creates a new query for the given registry, entity and criteria * @@ -562,10 +567,9 @@ public static Document createBsonQuery(CodecRegistry registry, PersistentEntity public static Document createBsonQuery(CodecRegistry registry, PersistentEntity entity, Junction junction) { EmbeddedQueryEncoder embeddedQueryEncoder = new CodecRegistryEmbeddedQueryEncoder(registry); Document query = new Document(); - if(junction instanceof Conjunction) { + if (junction instanceof Conjunction) { populateBsonQuery(embeddedQueryEncoder, query, junction.getCriteria(), entity); - } - else { + } else { populateBsonQuery(embeddedQueryEncoder, query, junction, entity); } return query; @@ -609,22 +613,20 @@ public static DetachedCriteria parse(Class type, BsonReader queryReade criteria.add(junction); - if(isJunction) { + if (isJunction) { queryReader.readStartArray(); bsonType = queryReader.readBsonType(); - while(bsonType != BsonType.END_OF_DOCUMENT) { - if(bsonType == BsonType.DOCUMENT) { + while (bsonType != BsonType.END_OF_DOCUMENT) { + if (bsonType == BsonType.DOCUMENT) { parseQueryAttributeValue(queryReader, queryReader.getCurrentBsonType(), attributeName, junction); - } - else { + } else { queryReader.skipValue(); } bsonType = queryReader.readBsonType(); } queryReader.readEndArray(); - } - else { - while(bsonType != BsonType.END_OF_DOCUMENT) { + } else { + while (bsonType != BsonType.END_OF_DOCUMENT) { attributeName = queryReader.readName(); bsonType = queryReader.getCurrentBsonType(); parseQueryAttributeValue(queryReader, bsonType, attributeName, junction); @@ -641,13 +643,12 @@ private static BsonType parseQueryAttributeValue(BsonReader queryReader, BsonTyp if (bsonType == BsonType.DOCUMENT) { queryReader.readStartDocument(); bsonType = queryReader.getCurrentBsonType(); - while(bsonType != BsonType.END_OF_DOCUMENT) { + while (bsonType != BsonType.END_OF_DOCUMENT) { String operator = queryReader.readName(); OperatorHandler operatorHandler = operatorHandlers.get(operator); - if(operatorHandler != null) { + if (operatorHandler != null) { operatorHandler.handle(junction, attributeName, queryReader); - } - else { + } else { parseQueryAttributeValue(queryReader, queryReader.getCurrentBsonType(), operator, junction); } bsonType = queryReader.readBsonType(); @@ -655,11 +656,10 @@ private static BsonType parseQueryAttributeValue(BsonReader queryReader, BsonTyp queryReader.readEndDocument(); } else { Object value = readBsonValue(queryReader, bsonType); - if(value != null) { - if(value instanceof NullObject) { + if (value != null) { + if (value instanceof NullObject) { junction.add(new IsNull(attributeName)); - } - else { + } else { junction.add(new Equals(attributeName, value)); } } @@ -765,10 +765,9 @@ protected static List getInListQueryValues(PersistentEntity entity, In i PersistentEntity pe = mappingContext.getPersistentEntity( value.getClass().getName()); ProxyHandler proxyHandler = mappingContext.getProxyHandler(); - if(proxyHandler.isProxy(value)) { + if (proxyHandler.isProxy(value)) { values.add(proxyHandler.getIdentifier(value)); - } - else { + } else { EntityReflector reflector = mappingContext.getEntityReflector(pe); values.add(reflector.getIdentifier(value)); } @@ -796,40 +795,6 @@ private static Integer getNumber(PropertyCriterion criterion) { throw new IllegalArgumentException("Argument to size constraint must be a number"); } - /** - * Handles an individual criterion - * - * @param - */ - protected interface QueryHandler { - void handle(EmbeddedQueryEncoder queryEncoder, T criterion, Document query, PersistentEntity entity); - } - - /** - * Handles query operators when reading BSON - */ - protected interface OperatorHandler { - void handle(Junction criteria, String attributeName, BsonReader queryReader); - } - - /** - * - * Handles a projection - * - * @param - */ - protected interface ProjectionHandler { - /** - * Handles a projection modifying the aggregation pipeline appropriately - * - * @param entity The entity - * @param groupByObject The group by object - * @param projection The projection - * @return The key to be used to obtain the projected value from the pipeline results - */ - String handle(PersistentEntity entity, Document projectObject, Document groupByObject, T projection); - } - protected static void populateBsonQuery(final EmbeddedQueryEncoder queryEncoder, Document query, List criteria, final PersistentEntity entity) { // if a query combines more than 1 item, wrap the items in individual $and or $or arguments // so that property names can't clash (e.g. for an $and containing two $ors) @@ -842,7 +807,7 @@ protected static void populateBsonQuery(final EmbeddedQueryEncoder queryEncoder, PersistentProperty property = entity.getPropertyByName(pc.getProperty()); if (property instanceof Custom) { CustomTypeMarshaller customTypeMarshaller = ((Custom) property).getCustomTypeMarshaller(); - if(!(customTypeMarshaller instanceof CodecCustomTypeMarshaller)) { + if (!(customTypeMarshaller instanceof CodecCustomTypeMarshaller)) { customTypeMarshaller.query(property, pc, query); continue; } @@ -892,4 +857,41 @@ protected static void populateBsonQuery(final EmbeddedQueryEncoder queryEncoder, } } } + + /** + * Handles an individual criterion + * + * @param + */ + protected interface QueryHandler { + + void handle(EmbeddedQueryEncoder queryEncoder, T criterion, Document query, PersistentEntity entity); + } + + /** + * Handles query operators when reading BSON + */ + protected interface OperatorHandler { + + void handle(Junction criteria, String attributeName, BsonReader queryReader); + } + + /** + * + * Handles a projection + * + * @param + */ + protected interface ProjectionHandler { + + /** + * Handles a projection modifying the aggregation pipeline appropriately + * + * @param entity The entity + * @param groupByObject The group by object + * @param projection The projection + * @return The key to be used to obtain the projected value from the pipeline results + */ + String handle(PersistentEntity entity, Document projectObject, Document groupByObject, T projection); + } } diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/query/CodecRegistryEmbeddedQueryEncoder.groovy b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/query/CodecRegistryEmbeddedQueryEncoder.groovy index c434abba60e..c00262ce1ee 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/query/CodecRegistryEmbeddedQueryEncoder.groovy +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/query/CodecRegistryEmbeddedQueryEncoder.groovy @@ -45,7 +45,7 @@ class CodecRegistryEmbeddedQueryEncoder implements EmbeddedQueryEncoder { Object encode(Embedded embedded, Object instance) { PersistentEntity associatedEntity = embedded.associatedEntity Codec codec = codecRegistry.get(associatedEntity.javaClass) - if(codec == null) { + if (codec == null) { codec = new BsonPersistentEntityCodec(codecRegistry, associatedEntity) } final BsonDocument doc = new BsonDocument(); diff --git a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/query/EmbeddedQueryEncoder.java b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/query/EmbeddedQueryEncoder.java index f3c7c985cb2..23c4e0ad0bd 100644 --- a/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/query/EmbeddedQueryEncoder.java +++ b/grails-data-mongodb/bson/src/main/groovy/org/grails/datastore/bson/query/EmbeddedQueryEncoder.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.bson.query; import org.grails.datastore.mapping.model.types.Embedded; diff --git a/grails-data-mongodb/core/build.gradle b/grails-data-mongodb/core/build.gradle index f7ac7978c80..b9b20510cde 100644 --- a/grails-data-mongodb/core/build.gradle +++ b/grails-data-mongodb/core/build.gradle @@ -155,4 +155,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/grails-data-tck-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/MongoEntity.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/MongoEntity.groovy index 0dc9b11ef57..fe92ca8010a 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/MongoEntity.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/MongoEntity.groovy @@ -51,7 +51,6 @@ import java.util.function.Function @CompileStatic trait MongoEntity implements GormEntity, DynamicAttributes { - /** * Allows accessing to dynamic properties with the dot operator * @@ -84,12 +83,12 @@ trait MongoEntity implements GormEntity, DynamicAttributes { */ @Deprecated Document getDbo() { - AbstractMongoSession session = (AbstractMongoSession)AbstractDatastore.retrieveSession(MongoDatastore) + AbstractMongoSession session = (AbstractMongoSession) AbstractDatastore.retrieveSession(MongoDatastore) // check first for embedded cached entries SessionImplementor si = (SessionImplementor) session; def persistentEntity = session.mappingContext.getPersistentEntity(getClass().name) - Document dbo = (Document)si.getCachedEntry(persistentEntity, MongoEntityPersister.createEmbeddedCacheEntryKey(this)) - if(dbo != null) return dbo + Document dbo = (Document) si.getCachedEntry(persistentEntity, MongoEntityPersister.createEmbeddedCacheEntryKey(this)) + if (dbo != null) return dbo // otherwise check if instance is contained within session if (!session.contains(this)) { dbo = new Document() @@ -97,12 +96,12 @@ trait MongoEntity implements GormEntity, DynamicAttributes { return dbo } - EntityPersister persister = (EntityPersister)session.getPersister(this) + EntityPersister persister = (EntityPersister) session.getPersister(this) def id = persister.getObjectIdentifier(this) - dbo = (Document)((SessionImplementor)session).getCachedEntry(persister.getPersistentEntity(), id) + dbo = (Document) ((SessionImplementor) session).getCachedEntry(persister.getPersistentEntity(), id) if (dbo == null) { MongoCollection coll = session.getCollection(persistentEntity) - dbo = coll.find((Bson)new Document(MongoEntityPersister.MONGO_ID_FIELD, id)) + dbo = coll.find((Bson) new Document(MongoEntityPersister.MONGO_ID_FIELD, id)) .limit(1) .first() @@ -278,16 +277,16 @@ trait MongoEntity implements GormEntity, DynamicAttributes { * @param callable The operation * @return The return value of the closure */ - static T withConnection(String connectionName, @DelegatesTo(MongoAllOperations)Closure callable) { + static T withConnection(String connectionName, @DelegatesTo(MongoAllOperations) Closure callable) { def staticApi = GormEnhancer.findStaticApi(this, connectionName) - return (T)staticApi.withNewSession { + return (T) staticApi.withNewSession { callable.setDelegate(staticApi) return callable.call() } } private static MongoStaticApi currentMongoStaticApi() { - (MongoStaticApi)GormEnhancer.findStaticApi(this) + (MongoStaticApi) GormEnhancer.findStaticApi(this) } } \ No newline at end of file diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/api/MongoAllOperations.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/api/MongoAllOperations.groovy index 6f0a6ad0bb0..e28bec8f087 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/api/MongoAllOperations.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/api/MongoAllOperations.groovy @@ -26,4 +26,5 @@ package grails.mongodb.api * @since 6.0 */ interface MongoAllOperations extends MongoInstanceOperations, MongoStaticOperations { + } \ No newline at end of file diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/api/MongoStaticOperations.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/api/MongoStaticOperations.groovy index 053d7707874..076c728ddde 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/api/MongoStaticOperations.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/api/MongoStaticOperations.groovy @@ -189,5 +189,5 @@ interface MongoStaticOperations extends GormStaticOperations { * @param limit The maximum number of results. Defaults to 5. * @return The results */ - List searchTop(String query, int limit, Map options ) + List searchTop(String query, int limit, Map options) } \ No newline at end of file diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/bootstrap/MongoDbDataStoreSpringInitializer.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/bootstrap/MongoDbDataStoreSpringInitializer.groovy index 4def13a68f3..460b131c4a9 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/bootstrap/MongoDbDataStoreSpringInitializer.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/bootstrap/MongoDbDataStoreSpringInitializer.groovy @@ -45,8 +45,8 @@ import org.springframework.util.ClassUtils class MongoDbDataStoreSpringInitializer extends AbstractDatastoreInitializer { public static final String DEFAULT_DATABASE_NAME = "test" - public static final String DATASTORE_TYPE = "mongo" + protected String mongoBeanName = "mongo" protected String mongoOptionsBeanName = "mongoOptions" protected String databaseName = DEFAULT_DATABASE_NAME @@ -87,34 +87,31 @@ class MongoDbDataStoreSpringInitializer extends AbstractDatastoreInitializer { callable.delegate = delegate callable.call() ApplicationEventPublisher eventPublisher - if(beanDefinitionRegistry instanceof ConfigurableApplicationContext){ - eventPublisher = new ConfigurableApplicationContextEventPublisher((ConfigurableApplicationContext)beanDefinitionRegistry) - } - else if(resourcePatternResolver.resourceLoader instanceof ConfigurableApplicationContext) { - eventPublisher = new ConfigurableApplicationContextEventPublisher((ConfigurableApplicationContext)resourcePatternResolver.resourceLoader) - } - else { + if (beanDefinitionRegistry instanceof ConfigurableApplicationContext) { + eventPublisher = new ConfigurableApplicationContextEventPublisher((ConfigurableApplicationContext) beanDefinitionRegistry) + } else if (resourcePatternResolver.resourceLoader instanceof ConfigurableApplicationContext) { + eventPublisher = new ConfigurableApplicationContextEventPublisher((ConfigurableApplicationContext) resourcePatternResolver.resourceLoader) + } else { eventPublisher = new DefaultApplicationEventPublisher() } - if(mongo == null) { + if (mongo == null) { mongoConnectionSourceFactory(MongoConnectionSourceFactory) { bean -> bean.autowire = true } mongoDatastore(MongoDatastore, configuration, ref('mongoConnectionSourceFactory'), eventPublisher, collectMappedClasses(DATASTORE_TYPE)) - mongo(mongoDatastore:"getMongoClient") - } - else { + mongo(mongoDatastore: "getMongoClient") + } else { mongoDatastore(MongoDatastore, mongo, configuration, eventPublisher, collectMappedClasses(DATASTORE_TYPE)) } - mongoMappingContext(mongoDatastore:"getMappingContext") + mongoMappingContext(mongoDatastore: "getMappingContext") if (!secondaryDatastore) { registerAlias "mongoMappingContext", "grailsDomainClassMappingContext" } - mongoTransactionManager(mongoDatastore:"getTransactionManager") - mongoAutoTimestampEventListener(mongoDatastore:"getAutoTimestampEventListener") + mongoTransactionManager(mongoDatastore: "getTransactionManager") + mongoAutoTimestampEventListener(mongoDatastore: "getAutoTimestampEventListener") mongoPersistenceInterceptor(getPersistenceInterceptorClass(), ref("mongoDatastore")) mongoPersistenceContextInterceptorAggregator(PersistenceContextInterceptorAggregator) def transactionManagerBeanName = TRANSACTION_MANAGER_BEAN @@ -131,7 +128,7 @@ class MongoDbDataStoreSpringInitializer extends AbstractDatastoreInitializer { } loadDataServices(secondaryDatastore ? "mongo" : null) - .each {serviceName, serviceClass-> + .each { serviceName, serviceClass -> "$serviceName"(DatastoreServiceMethodInvokingFactoryBean, serviceClass) { targetObject = ref("mongoDatastore") targetMethod = 'getService' @@ -143,7 +140,6 @@ class MongoDbDataStoreSpringInitializer extends AbstractDatastoreInitializer { } - /** * Sets the name of the Mongo bean to use */ diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Box.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Box.groovy index c8505b1bd2a..ef9cf593990 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Box.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Box.groovy @@ -25,7 +25,7 @@ import groovy.transform.EqualsAndHashCode */ @EqualsAndHashCode @CompileStatic -class Box extends Shape{ +class Box extends Shape { final Point lowerLeft, upperRight @@ -46,7 +46,7 @@ class Box extends Shape{ * * @return The list */ - List> asList() { [ lowerLeft.asList(), upperRight.asList() ] } + List> asList() { [lowerLeft.asList(), upperRight.asList()] } @Override String toString() { @@ -59,8 +59,8 @@ class Box extends Shape{ * @return A box */ static Box valueOf(List> coords) { - if(coords.size() != 2) throw new IllegalArgumentException("Coordinates should contain at least 2 entries for a Box") + if (coords.size() != 2) throw new IllegalArgumentException("Coordinates should contain at least 2 entries for a Box") - new Box( Point.getPointAtIndex(coords, 0), Point.getPointAtIndex(coords, 1) ) + new Box(Point.getPointAtIndex(coords, 0), Point.getPointAtIndex(coords, 1)) } } diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Circle.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Circle.groovy index e3706935d61..e607130cb40 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Circle.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Circle.groovy @@ -26,7 +26,8 @@ import org.springframework.util.Assert */ @EqualsAndHashCode @CompileStatic -class Circle extends Shape{ +class Circle extends Shape { + /** * The center of the circle */ @@ -50,7 +51,7 @@ class Circle extends Shape{ /** * @return The circle as a coordinate list */ - List asList() { [ center.asList(), radius] } + List asList() { [center.asList(), radius] } @Override String toString() { "[$center, $radius]" } @@ -62,18 +63,17 @@ class Circle extends Shape{ * @return The Circle instance */ static Circle valueOf(List coords) { - if(coords.size() < 2) throw new IllegalArgumentException("Coordinates should contain at least 2 entries for a Circle: The center point and the radius") + if (coords.size() < 2) throw new IllegalArgumentException("Coordinates should contain at least 2 entries for a Circle: The center point and the radius") Point center = Point.getPointAtIndex(coords, 0) def ro = coords.get(1) Number radius = null - if(ro instanceof Number) + if (ro instanceof Number) radius = (Number) ro - if(center && radius != null) { + if (center && radius != null) { return new Circle(center, radius.doubleValue()) - } - else { + } else { throw new IllegalArgumentException("Invalid Circle coordinates: $coords") } } diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/GeometryCollection.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/GeometryCollection.groovy index 9554dc4f850..ad9b00793ed 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/GeometryCollection.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/GeometryCollection.groovy @@ -14,22 +14,22 @@ */ package grails.mongodb.geo -import groovy.transform.CompileStatic import org.grails.datastore.gorm.mongo.geo.GeoJSONType /** - * Represents a GeoJSON GeometryCollection. See http://geojson.org/geojson-spec.html#geometry-collection + * Represents a GeoJSON GeometryCollection. See https://geojson.org/geojson-spec.html#geometry-collection * * @author Graeme Rocher * @since 3.0 */ class GeometryCollection extends ArrayList implements GeoJSON { + @Override List asList() { collect() { GeoJSON current -> GeoJSONType.convertToGeoDocument( - (Shape)current) + (Shape) current) } } @@ -37,11 +37,11 @@ class GeometryCollection extends ArrayList implements GeoJSON { def col = new GeometryCollection() def classLoader = GeometryCollection.classLoader - for(geo in geometries) { - if(geo instanceof Map) { + for (geo in geometries) { + if (geo instanceof Map) { String type = geo.type?.toString() def coordinates = geo.coordinates - if(type && coordinates) { + if (type && coordinates) { col << classLoader.loadClass("grails.mongodb.geo.$type").valueOf(coordinates) } } diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/LineString.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/LineString.groovy index b18f51fdc2f..08124cdab31 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/LineString.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/LineString.groovy @@ -18,26 +18,27 @@ import groovy.transform.CompileStatic import groovy.transform.EqualsAndHashCode /** - * See http://geojson.org/geojson-spec.html#linestring + * See https://geojson.org/geojson-spec.html#linestring * * @author Graeme Rocher * @since 2.0 */ @CompileStatic @EqualsAndHashCode -class LineString extends Shape implements GeoJSON{ +class LineString extends Shape implements GeoJSON { + /** * The points that constitute the LineString */ - final List coordinates + final List coordinates /** * Constructs a LineString for the given {@link Point} instances * * @param points The {@link Point} instances. Must be at least 2 points. */ - LineString(Point...points) { - if(points.size() < 2) + LineString(Point... points) { + if (points.size() < 2) throw new IllegalArgumentException("At least 2 points required for a LineString") this.coordinates = points.toList() } @@ -49,7 +50,7 @@ class LineString extends Shape implements GeoJSON{ */ @Override List> asList() { - coordinates.collect() { Point p -> p.asList()} + coordinates.collect() { Point p -> p.asList() } } @Override @@ -63,14 +64,13 @@ class LineString extends Shape implements GeoJSON{ * @return A LineString */ public static LineString valueOf(List coords) { - if(coords.size() < 2) throw new IllegalArgumentException("Coordinates should contain at least 2 entries for a LineString") + if (coords.size() < 2) throw new IllegalArgumentException("Coordinates should contain at least 2 entries for a LineString") List points = (List) coords.collect() { - if(it instanceof Point) { + if (it instanceof Point) { return it - } - else if(it instanceof List) { - return Point.valueOf((List)it) + } else if (it instanceof List) { + return Point.valueOf((List) it) } throw new IllegalArgumentException("Invalid coordinates: $coords") } diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Metric.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Metric.groovy index 06d45d4b6be..a13b9716b2a 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Metric.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Metric.groovy @@ -25,7 +25,8 @@ import groovy.transform.EqualsAndHashCode */ @EqualsAndHashCode @CompileStatic -public class Metric { +class Metric { + /** the radius of the earth in kilometers **/ static Metric KILOMETERS = new Metric(6378.137d) /** the radius of the earth in miles **/ diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/MultiLineString.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/MultiLineString.groovy index 40a2a6509a4..32106a657a9 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/MultiLineString.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/MultiLineString.groovy @@ -19,7 +19,7 @@ import groovy.transform.EqualsAndHashCode import org.springframework.util.Assert /** - * Represents a GeoJSON MultiLineString. See http://geojson.org/geojson-spec.html#multilinestring + * Represents a GeoJSON MultiLineString. See https://geojson.org/geojson-spec.html#multilinestring * * Note: Requires MongoDB 2.6 or above * @@ -28,7 +28,8 @@ import org.springframework.util.Assert */ @CompileStatic @EqualsAndHashCode -class MultiLineString extends Shape implements GeoJSON{ +class MultiLineString extends Shape implements GeoJSON { + final List coordinates MultiLineString(LineString... coordinates) { @@ -52,11 +53,10 @@ class MultiLineString extends Shape implements GeoJSON{ static MultiLineString valueOf(List coords) { List lineStrings = (List) coords.collect() { - if(it instanceof LineString) { + if (it instanceof LineString) { return it - } - else if(it instanceof List) { - return LineString.valueOf((List)it) + } else if (it instanceof List) { + return LineString.valueOf((List) it) } throw new IllegalArgumentException("Invalid coordinates: $coords") } diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/MultiPoint.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/MultiPoint.groovy index 4e88664acb4..ac062bcac15 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/MultiPoint.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/MultiPoint.groovy @@ -18,7 +18,7 @@ import groovy.transform.CompileStatic import groovy.transform.EqualsAndHashCode /** - * Represents a GeoJSON MultiPoint. See http://geojson.org/geojson-spec.html#multipoint + * Represents a GeoJSON MultiPoint. See https://geojson.org/geojson-spec.html#multipoint * * Note: Requires MongoDB 2.6 or above * @@ -27,7 +27,8 @@ import groovy.transform.EqualsAndHashCode */ @CompileStatic @EqualsAndHashCode -class MultiPoint extends Shape implements GeoJSON{ +class MultiPoint extends Shape implements GeoJSON { + final List positions MultiPoint(Point... positions) { @@ -50,11 +51,10 @@ class MultiPoint extends Shape implements GeoJSON{ public static MultiPoint valueOf(List coords) { List points = (List) coords.collect() { - if(it instanceof Point) { + if (it instanceof Point) { return it - } - else if(it instanceof List) { - return Point.valueOf((List)it) + } else if (it instanceof List) { + return Point.valueOf((List) it) } throw new IllegalArgumentException("Invalid coordinates: $coords") } diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/MultiPolygon.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/MultiPolygon.groovy index b81fa9b4a2e..cca3aadb81c 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/MultiPolygon.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/MultiPolygon.groovy @@ -18,7 +18,7 @@ import groovy.transform.CompileStatic import groovy.transform.EqualsAndHashCode /** - * Represents a GeoJSON MultiPolygon. See http://geojson.org/geojson-spec.html#multipolygon + * Represents a GeoJSON MultiPolygon. See https://geojson.org/geojson-spec.html#multipolygon * * Note: Requires MongoDB 2.6 or above * @@ -28,11 +28,13 @@ import groovy.transform.EqualsAndHashCode @CompileStatic @EqualsAndHashCode class MultiPolygon extends Shape implements GeoJSON { + final List polygons - MultiPolygon(Polygon...polygons) { + MultiPolygon(Polygon... polygons) { this.polygons = Arrays.asList(polygons) } + MultiPolygon(List polygons) { this.polygons = polygons } @@ -44,11 +46,10 @@ class MultiPolygon extends Shape implements GeoJSON { static MultiPolygon valueOf(List coords) { List polygons = (List) coords.collect() { - if(it instanceof Polygon) { + if (it instanceof Polygon) { return it - } - else if(it instanceof List) { - return Polygon.valueOf((List)it) + } else if (it instanceof List) { + return Polygon.valueOf((List) it) } throw new IllegalArgumentException("Invalid coordinates: $coords") } diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Point.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Point.groovy index bc76ba0beb9..3c421b49f47 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Point.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Point.groovy @@ -18,14 +18,14 @@ import groovy.transform.CompileStatic import groovy.transform.EqualsAndHashCode /** - * Represents a GeoJSON point for use in GeoJSON data models. See http://geojson.org/geojson-spec.html#point + * Represents a GeoJSON point for use in GeoJSON data models. See https://geojson.org/geojson-spec.html#point * * @author Graeme Rocher * @since 2.0 */ @EqualsAndHashCode @CompileStatic -class Point extends Shape implements GeoJSON{ +class Point extends Shape implements GeoJSON { /** * The x and y values that indicate the location of the point */ @@ -44,12 +44,12 @@ class Point extends Shape implements GeoJSON{ /** * @return An array representation of the point */ - double[] asArray() { [x,y] as double[] } + double[] asArray() { [x, y] as double[] } /** * @return A list representation of the point */ - List asList() { [ x, y] } + List asList() { [x, y] } @Override String toString() { "[$x,$y]" } @@ -72,10 +72,10 @@ class Point extends Shape implements GeoJSON{ * @return A Point */ static Point valueOf(List coords) { - if(coords.size() == 2) { + if (coords.size() == 2) { def x = coords.get(0) def y = coords.get(1) - if((x instanceof Number) && (y instanceof Number)) { + if ((x instanceof Number) && (y instanceof Number)) { return new Point(x.doubleValue(), y.doubleValue()) } } @@ -89,13 +89,12 @@ class Point extends Shape implements GeoJSON{ * @param index The index of the point * @return A Point */ - static Point getPointAtIndex( List coords, int index ) { + static Point getPointAtIndex(List coords, int index) { def coord = coords.get(index) - if(coord instanceof Point) { - return (Point)coord - } - else if(coord instanceof List) { - return valueOf( (List) coord ) + if (coord instanceof Point) { + return (Point) coord + } else if (coord instanceof List) { + return valueOf((List) coord) } throw new IllegalArgumentException("Invalid coordinates: $coords") } diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Polygon.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Polygon.groovy index b3df5ae04b1..94281bdbd28 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Polygon.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Polygon.groovy @@ -20,11 +20,11 @@ import org.springframework.util.Assert /** * Represents a GeoJSON polygon for use in Geo data models. - * See http://geojson.org/geojson-spec.html#polygon + * See https://geojson.org/geojson-spec.html#polygon */ @CompileStatic @EqualsAndHashCode -class Polygon extends Shape implements GeoJSON{ +class Polygon extends Shape implements GeoJSON { /** * The {@link Point} instances that constitute the Polygon @@ -39,7 +39,7 @@ class Polygon extends Shape implements GeoJSON{ * @param z The z {@link Point} * @param others The remaining {@link Point} instances */ - Polygon(Point x, Point y, Point z, Point...others) { + Polygon(Point x, Point y, Point z, Point... others) { Assert.notNull(x, "Point x is required") Assert.notNull(y, "Point y is required") Assert.notNull(z, "Point z is required") @@ -51,7 +51,7 @@ class Polygon extends Shape implements GeoJSON{ this.points = [list] } - private Polygon(List> points){ + private Polygon(List> points) { this.points = points } @@ -62,8 +62,8 @@ class Polygon extends Shape implements GeoJSON{ * @return The list */ public List>> asList() { - points.collect() { List ring -> - ring.collect { Point p -> + points.collect() { List ring -> + ring.collect { Point p -> p.asList() } } @@ -74,15 +74,14 @@ class Polygon extends Shape implements GeoJSON{ points.toString() } /** - * The inverse of {@link Polygon#asList()}, constructs a Polygon from a coordinate list - * - * @param coords The coordinate list - * @return A Polygon - */ + * The inverse of {@link Polygon#asList()}, constructs a Polygon from a coordinate list + * + * @param coords The coordinate list + * @return A Polygon + */ static Polygon valueOf(List coords) { Assert.notNull(coords, "Argument coords cannot be null") - /* * Search for list type - it could be @@ -91,40 +90,33 @@ class Polygon extends Shape implements GeoJSON{ * (3) List - a multi-ring polygon * (4) List - a multi-ring polygon with list as long/lat/alt */ - try - { - if(coords[0] instanceof Point){ - return new Polygon( [fromSingleCoordsList(coords)] ) // case (1) above - } - else if(coords[0] instanceof List ) - { - if( ((List)coords[0])[0] instanceof Number) { - return new Polygon( [fromSingleCoordsList(coords)] ) // case (2) above - } - else if( ((List)coords[0])[0] instanceof Point){ - return new Polygon( coords.collect { poly_ring -> + try { + if (coords[0] instanceof Point) { + return new Polygon([fromSingleCoordsList(coords)]) // case (1) above + } else if (coords[0] instanceof List) { + if (((List) coords[0])[0] instanceof Number) { + return new Polygon([fromSingleCoordsList(coords)]) // case (2) above + } else if (((List) coords[0])[0] instanceof Point) { + return new Polygon(coords.collect { poly_ring -> // each is a List - return fromSingleCoordsList((List)poly_ring) + return fromSingleCoordsList((List) poly_ring) }) // case (3) above - } - else if( ((List)coords[0])[0] instanceof List && ((List)((List)coords[0])[0])[0] instanceof Number ){ - return new Polygon( coords.collect { poly_ring -> + } else if (((List) coords[0])[0] instanceof List && ((List) ((List) coords[0])[0])[0] instanceof Number) { + return new Polygon(coords.collect { poly_ring -> // each is a List - return fromSingleCoordsList((List>)poly_ring) - } ) // case (4) above - } - else { + return fromSingleCoordsList((List>) poly_ring) + }) // case (4) above + } else { throw new IllegalArgumentException("Coordinate list must be Points or number-lists") } - } - else { + } else { throw new IllegalArgumentException("Coordinate list must be Points or number-lists") - } - } - catch(IndexOutOfBoundsException ioobe){ + } + } + catch (IndexOutOfBoundsException ioobe) { throw new IllegalArgumentException("Coordinate lists cannot be empty") - } - + } + } /** @@ -134,16 +126,14 @@ class Polygon extends Shape implements GeoJSON{ private static List fromSingleCoordsList(List coords) { Assert.notNull(coords, "Argument coords cannot be null") - if(coords.size() < 4) throw new IllegalArgumentException("Coordinates should contain at least 4 entries for a Polygon") + if (coords.size() < 4) throw new IllegalArgumentException("Coordinates should contain at least 4 entries for a Polygon") return coords.collect { - if(it instanceof Point) { - return (Point)it - } - else if(it instanceof List) { - return Point.valueOf((List)it) - } - else { + if (it instanceof Point) { + return (Point) it + } else if (it instanceof List) { + return Point.valueOf((List) it) + } else { throw new IllegalArgumentException("Invalid coordinates: $coords") } } diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Sphere.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Sphere.groovy index a7f74e774be..28998807940 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Sphere.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/geo/Sphere.groovy @@ -26,7 +26,7 @@ import groovy.transform.EqualsAndHashCode */ @EqualsAndHashCode @CompileStatic -class Sphere extends Shape{ +class Sphere extends Shape { /** * The center of there sphere @@ -55,7 +55,7 @@ class Sphere extends Shape{ */ @Override List asList() { - [ center.asList(), distance.inRadians() ] + [center.asList(), distance.inRadians()] } /** @@ -66,19 +66,18 @@ class Sphere extends Shape{ * * @return A Sphere */ - static Sphere valueOf( List coords, Metric metric = Metric.NEUTRAL) { - if(coords.size() < 2) throw new IllegalArgumentException("Coordinates should contain at least 2 entries for a Sphere: The center point and the distance") + static Sphere valueOf(List coords, Metric metric = Metric.NEUTRAL) { + if (coords.size() < 2) throw new IllegalArgumentException("Coordinates should contain at least 2 entries for a Sphere: The center point and the distance") Point center = Point.getPointAtIndex(coords, 0) def ro = coords.get(1) Double distance = null - if(ro instanceof Number) + if (ro instanceof Number) distance = ((Number) ro).doubleValue() - if(center && distance != null) { - return new Sphere(center, Distance.valueOf(distance, metric) ) - } - else { + if (center && distance != null) { + return new Sphere(center, Distance.valueOf(distance, metric)) + } else { throw new IllegalArgumentException("Invalid Sphere coordinates: $coords") } } diff --git a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/mapping/MappingBuilder.groovy b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/mapping/MappingBuilder.groovy index ddcaaaab892..efddcad5763 100644 --- a/grails-data-mongodb/core/src/main/groovy/grails/mongodb/mapping/MappingBuilder.groovy +++ b/grails-data-mongodb/core/src/main/groovy/grails/mongodb/mapping/MappingBuilder.groovy @@ -45,6 +45,7 @@ class MappingBuilder { @CompileStatic private static class ClosureNodeMappingDefinition implements MappingDefinition { + final Closure definition private MongoCollection mapping @@ -59,7 +60,7 @@ class MappingBuilder { @Override MongoCollection build() { - if(mapping == null) { + if (mapping == null) { MongoCollection nc = new MongoCollection() mapping = MongoCollection.configureExisting(nc, definition) } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/GeoIntersects.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/GeoIntersects.groovy index 9215291e997..6b1efb99d7e 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/GeoIntersects.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/GeoIntersects.groovy @@ -26,7 +26,8 @@ import org.springframework.util.Assert * @author Graeme Rocher * @since 2.0 */ -class GeoIntersects extends MethodExpression{ +class GeoIntersects extends MethodExpression { + GeoIntersects(Class targetClass, String propertyName) { super(targetClass, propertyName) } @@ -43,7 +44,7 @@ class GeoIntersects extends MethodExpression{ def value = arguments[0] - Assert.isTrue( (value instanceof Map) || (( value instanceof GeoJSON) ), + Assert.isTrue((value instanceof Map) || ((value instanceof GeoJSON)), "Argument must be either a Map or a GeoJSON shape (Polygon, LineString or Point)") super.setArguments(arguments) diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/GeoWithin.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/GeoWithin.groovy index 0bcc024434f..3e4b9b98a8a 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/GeoWithin.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/GeoWithin.groovy @@ -31,6 +31,7 @@ import org.springframework.util.Assert */ @CompileStatic class GeoWithin extends MethodExpression { + GeoWithin(Class targetClass, String propertyName) { super(targetClass, propertyName) } @@ -47,8 +48,8 @@ class GeoWithin extends MethodExpression { def value = arguments[0] - Assert.isTrue( (value instanceof Map) || (( value instanceof Shape) && !((value instanceof LineString) || (value instanceof Point))), - "Argument must be either a Box, Circle, Polygon or Sphere") + Assert.isTrue((value instanceof Map) || ((value instanceof Shape) && !((value instanceof LineString) || (value instanceof Point))), + "Argument must be either a Box, Circle, Polygon or Sphere") super.setArguments(arguments) } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/MongoCriteriaBuilder.java b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/MongoCriteriaBuilder.java index e4ba722c207..508e374215e 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/MongoCriteriaBuilder.java +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/MongoCriteriaBuilder.java @@ -1,25 +1,20 @@ /* Copyright (C) 2011 SpringSource -* -* Licensed 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. -*/ - + * + * Licensed 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.datastore.gorm.mongo; import grails.gorm.CriteriaBuilder; - -import java.util.List; -import java.util.Map; - import grails.mongodb.geo.Distance; import grails.mongodb.geo.GeoJSON; import grails.mongodb.geo.Point; @@ -28,12 +23,15 @@ import org.grails.datastore.mapping.mongo.query.MongoQuery; import org.grails.datastore.mapping.mongo.query.MongoQuery.Near; import org.grails.datastore.mapping.mongo.query.MongoQuery.WithinBox; -import org.grails.datastore.mapping.mongo.query.MongoQuery.WithinPolygon; import org.grails.datastore.mapping.mongo.query.MongoQuery.WithinCircle; +import org.grails.datastore.mapping.mongo.query.MongoQuery.WithinPolygon; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.api.Criteria; import org.grails.datastore.mapping.query.api.QueryArgumentsAware; +import java.util.List; +import java.util.Map; + /** * Extends the default CriteriaBuilder implementation with Geolocation methods * @@ -55,7 +53,7 @@ public MongoCriteriaBuilder(final Class targetClass, final Session session) { * Geospacial query for values near the given two dimensional list * * @param property The property - * @param value A two dimensional list of values + * @param value A two dimensional list of values * @return this Criterion */ public Criteria near(String property, List value) { @@ -68,7 +66,7 @@ public Criteria near(String property, List value) { * Geospacial query for values near the given two dimensional list * * @param property The property - * @param value A two dimensional list of values + * @param value A two dimensional list of values * @return this Criterion */ public Criteria near(String property, List value, Number maxDistance) { @@ -81,7 +79,7 @@ public Criteria near(String property, List value, Number maxDistance) { * Geospacial query for values near the given two dimensional list * * @param property The property - * @param value A two dimensional list of values + * @param value A two dimensional list of values * @return this Criterion */ public Criteria near(String property, List value, Distance maxDistance) { @@ -94,7 +92,7 @@ public Criteria near(String property, List value, Distance maxDistance) { * Geospacial query for values near the given two dimensional list * * @param property The property - * @param value A two dimensional list of values + * @param value A two dimensional list of values * @return this Criterion */ public Criteria near(String property, Point value) { @@ -107,7 +105,7 @@ public Criteria near(String property, Point value) { * Geospacial query for values near the given two dimensional list * * @param property The property - * @param value A two dimensional list of values + * @param value A two dimensional list of values * @return this Criterion */ public Criteria near(String property, Point value, Number maxDistance) { @@ -120,7 +118,7 @@ public Criteria near(String property, Point value, Number maxDistance) { * Geospacial query for values near the given two dimensional list * * @param property The property - * @param value A two dimensional list of values + * @param value A two dimensional list of values * @return this Criterion */ public Criteria near(String property, Point value, Distance maxDistance) { @@ -133,7 +131,7 @@ public Criteria near(String property, Point value, Distance maxDistance) { * Geospacial query for values near the given two dimensional list * * @param property The property - * @param value A two dimensional list of values + * @param value A two dimensional list of values * @return this Criterion */ public Criteria nearSphere(String property, List value) { @@ -146,7 +144,7 @@ public Criteria nearSphere(String property, List value) { * Geospacial query for values near the given two dimensional list * * @param property The property - * @param value A two dimensional list of values + * @param value A two dimensional list of values * @return this Criterion */ public Criteria nearSphere(String property, List value, Number maxDistance) { @@ -159,7 +157,7 @@ public Criteria nearSphere(String property, List value, Number maxDistance) { * Geospacial query for values near the given two dimensional list * * @param property The property - * @param value A two dimensional list of values + * @param value A two dimensional list of values * @return this Criterion */ public Criteria nearSphere(String property, List value, Distance maxDistance) { @@ -172,7 +170,7 @@ public Criteria nearSphere(String property, List value, Distance maxDistance) * Geospacial query for values near the given two dimensional list * * @param property The property - * @param value A two dimensional list of values + * @param value A two dimensional list of values * @return this Criterion */ public Criteria nearSphere(String property, Point value) { @@ -185,7 +183,7 @@ public Criteria nearSphere(String property, Point value) { * Geospacial query for values near the given two dimensional list * * @param property The property - * @param value A two dimensional list of values + * @param value A two dimensional list of values * @return this Criterion */ public Criteria nearSphere(String property, Point value, Number maxDistance) { @@ -198,7 +196,7 @@ public Criteria nearSphere(String property, Point value, Number maxDistance) { * Geospacial query for values near the given two dimensional list * * @param property The property - * @param value A two dimensional list of values + * @param value A two dimensional list of values * @return this Criterion */ public Criteria nearSphere(String property, Point value, Distance maxDistance) { @@ -206,13 +204,14 @@ public Criteria nearSphere(String property, Point value, Distance maxDistance) { addToCriteria(new MongoQuery.NearSphere(property, value, maxDistance)); return this; } + /** * Geospacial query for values within a given box. A box is defined as a multi-dimensional list in the form - * + *

* [[40.73083, -73.99756], [40.741404, -73.988135]] * * @param property The property - * @param value A multi-dimensional list of values + * @param value A multi-dimensional list of values * @return this Criterion */ public Criteria withinBox(String property, List value) { @@ -223,11 +222,11 @@ public Criteria withinBox(String property, List value) { /** * Geospacial query for values within a given polygon. A polygon is defined as a multi-dimensional list in the form - * + *

* [[0, 0], [3, 6], [6, 0]] * * @param property The property - * @param value A multi-dimensional list of values + * @param value A multi-dimensional list of values * @return this Criterion */ public Criteria withinPolygon(String property, List value) { @@ -238,11 +237,11 @@ public Criteria withinPolygon(String property, List value) { /** * Geospacial query for values within a given circle. A circle is defined as a multi-dimensial list containing the position of the center and the radius: - * + *

* [[50, 50], 10] * * @param property The property - * @param value A multi-dimensional list of values + * @param value A multi-dimensional list of values * @return The criteria insstance */ public Criteria withinCircle(String property, List value) { @@ -255,7 +254,7 @@ public Criteria withinCircle(String property, List value) { * Geospacial query for the given shape returning records that are found within the given shape * * @param property The property - * @param shape The shape + * @param shape The shape * @return The criteria insstance */ public Criteria geoWithin(String property, Shape shape) { @@ -268,7 +267,7 @@ public Criteria geoWithin(String property, Shape shape) { * Geospacial query for the given shape returning records that are found to intersect the given shape * * @param property The property - * @param shape The shape + * @param shape The shape * @return The criteria insstance */ public Criteria geoIntersects(String property, GeoJSON shape) { @@ -278,7 +277,7 @@ public Criteria geoIntersects(String property, GeoJSON shape) { } public Criteria arguments(Map arguments) { - ((QueryArgumentsAware)this.query).setArguments(arguments); + ((QueryArgumentsAware) this.query).setArguments(arguments); return this; } } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/MongoEntityTraitProvider.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/MongoEntityTraitProvider.groovy index fa5aae32aa6..47b43dc62da 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/MongoEntityTraitProvider.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/MongoEntityTraitProvider.groovy @@ -32,6 +32,7 @@ import org.grails.datastore.mapping.reflect.ClassUtils */ @CompileStatic class MongoEntityTraitProvider implements GormEntityTraitProvider { + final Class entityTrait = MongoEntity final boolean available = ClassUtils.isPresent("com.mongodb.client.MongoClient") diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/MongoGormEnhancer.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/MongoGormEnhancer.groovy index 0c3b0a74b53..89579d53c26 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/MongoGormEnhancer.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/MongoGormEnhancer.groovy @@ -21,10 +21,10 @@ package org.grails.datastore.gorm.mongo import groovy.transform.CompileStatic import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.gorm.finders.DynamicFinder -import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.mongo.MongoDatastore import org.grails.datastore.mapping.mongo.connections.MongoConnectionSourceSettings import org.springframework.transaction.PlatformTransactionManager + /** * GORM enhancer for Mongo. * diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/Near.java b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/Near.java index 585f5aca8e2..6e6bc07f8dc 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/Near.java +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/Near.java @@ -18,9 +18,6 @@ */ package org.grails.datastore.gorm.mongo; -import java.util.List; -import java.util.Map; - import grails.mongodb.geo.Distance; import grails.mongodb.geo.Point; import org.grails.datastore.gorm.finders.MethodExpression; @@ -28,6 +25,9 @@ import org.grails.datastore.mapping.query.Query.Criterion; import org.springframework.util.Assert; +import java.util.List; +import java.util.Map; + public class Near extends MethodExpression { public Near(Class targetClass, String propertyName) { @@ -38,13 +38,12 @@ public Near(Class targetClass, String propertyName) { public Criterion createCriterion() { MongoQuery.Near near = new MongoQuery.Near(propertyName, arguments[0]); - if(arguments.length > 1) { + if (arguments.length > 1) { Object o = arguments[1]; - if(o instanceof Number) { + if (o instanceof Number) { near.setMaxDistance(Distance.valueOf(((Number) o).doubleValue())); - } - else { - near.setMaxDistance((Distance)o); + } else { + near.setMaxDistance((Distance) o); } } return near; @@ -52,15 +51,15 @@ public Criterion createCriterion() { @Override public void setArguments(Object[] arguments) { - Assert.isTrue(arguments.length > 0 , - "Missing required arguments to findBy*Near query"); + Assert.isTrue(arguments.length > 0, + "Missing required arguments to findBy*Near query"); Object arg1 = arguments[0]; - Assert.isTrue(((arg1 instanceof Point) || (arg1 instanceof Map) || (arg1 instanceof List)) , + Assert.isTrue(((arg1 instanceof Point) || (arg1 instanceof Map) || (arg1 instanceof List)), "Argument to findBy*Near should either be a Point, coordinate List or a Map"); - if(arguments.length>1) { + if (arguments.length > 1) { Object arg2 = arguments[1]; Assert.isTrue(((arg2 instanceof Number) || (arg2 instanceof Distance)), "Second argument to findBy*Near should either the distance: either a number or an instanceof Distance"); diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/NearSphere.java b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/NearSphere.java index 9178fde6b72..37b44dde160 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/NearSphere.java +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/NearSphere.java @@ -1,17 +1,17 @@ /* Copyright (C) 2013 SpringSource -* -* Licensed 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. -*/ + * + * Licensed 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.datastore.gorm.mongo; import grails.mongodb.geo.Distance; @@ -24,7 +24,8 @@ * @author Graeme Rocher * @since 2.0 */ -public class NearSphere extends Near{ +public class NearSphere extends Near { + public NearSphere(Class targetClass, String propertyName) { super(targetClass, propertyName); } @@ -33,13 +34,12 @@ public NearSphere(Class targetClass, String propertyName) { public Query.Criterion createCriterion() { MongoQuery.NearSphere near = new MongoQuery.NearSphere(propertyName, arguments[0]); - if(arguments.length > 1) { + if (arguments.length > 1) { Object o = arguments[1]; - if(o instanceof Number) { + if (o instanceof Number) { near.setMaxDistance(Distance.valueOf(((Number) o).doubleValue())); - } - else { - near.setMaxDistance((Distance)o); + } else { + near.setMaxDistance((Distance) o); } } return near; diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/WithinBox.java b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/WithinBox.java index 2c47aa63f51..f5aece1737c 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/WithinBox.java +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/WithinBox.java @@ -1,29 +1,28 @@ /* Copyright (C) 2011 SpringSource -* -* Licensed 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. -*/ - + * + * Licensed 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.datastore.gorm.mongo; -import java.util.Collection; -import java.util.List; - import grails.mongodb.geo.Box; import org.grails.datastore.gorm.finders.MethodExpression; import org.grails.datastore.mapping.mongo.query.MongoQuery; import org.grails.datastore.mapping.query.Query.Criterion; import org.springframework.util.Assert; +import java.util.Collection; +import java.util.List; + /** * Dynamic finder expression for within box queries * @@ -39,10 +38,9 @@ public WithinBox(Class targetClass, String propertyName) { @Override public Criterion createCriterion() { Object argument = arguments[0]; - if(argument instanceof Box) { - return new MongoQuery.WithinBox(propertyName, ((Box)argument).asList()); - } - else { + if (argument instanceof Box) { + return new MongoQuery.WithinBox(propertyName, ((Box) argument).asList()); + } else { return new MongoQuery.WithinBox(propertyName, (List) argument); } } @@ -50,7 +48,7 @@ public Criterion createCriterion() { @Override public void setArguments(Object[] arguments) { Assert.isTrue(arguments.length > 0, - "Only a list of elements is supported in a 'withinBox' query"); + "Only a list of elements is supported in a 'withinBox' query"); Object arg = arguments[0]; @@ -58,7 +56,7 @@ public void setArguments(Object[] arguments) { Assert.isTrue((isList || (arg instanceof Box)), "Only a list of elements is supported in a 'withinBox' query"); - if(isList) { + if (isList) { Collection argument = (Collection) arg; Assert.isTrue(argument.size() == 2, "A 'withinBox' query requires a two dimensional list of values"); diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/WithinCircle.java b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/WithinCircle.java index 24f0d2cddbc..677254d1337 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/WithinCircle.java +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/WithinCircle.java @@ -16,18 +16,17 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.mongo; -import java.util.Collection; -import java.util.List; - import grails.mongodb.geo.Circle; import org.grails.datastore.gorm.finders.MethodExpression; import org.grails.datastore.mapping.mongo.query.MongoQuery; import org.grails.datastore.mapping.query.Query.Criterion; import org.springframework.util.Assert; +import java.util.Collection; +import java.util.List; + /** * A dynamic finder method expression that adds the ability to query within a circle * @@ -43,10 +42,9 @@ public WithinCircle(Class targetClass, String propertyName) { @Override public Criterion createCriterion() { Object argument = arguments[0]; - if(argument instanceof Circle) { - return new MongoQuery.WithinCircle(propertyName, ((Circle)argument).asList()); - } - else { + if (argument instanceof Circle) { + return new MongoQuery.WithinCircle(propertyName, ((Circle) argument).asList()); + } else { return new MongoQuery.WithinCircle(propertyName, (List) argument); } } @@ -62,7 +60,7 @@ public void setArguments(Object[] arguments) { Assert.isTrue((isList || (arg instanceof Circle)), "Only a list of elements is supported in a 'withinBox' query"); - if(isList) { + if (isList) { Collection argument = (Collection) arguments[0]; Assert.isTrue(argument.size() == 2, "A 'WithinCircle' query requires a two dimensional list of values"); diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/WithinPolygon.java b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/WithinPolygon.java index a8c0721a98a..1a798c74f09 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/WithinPolygon.java +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/WithinPolygon.java @@ -16,17 +16,16 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.mongo; -import java.util.Collection; -import java.util.List; - import org.grails.datastore.gorm.finders.MethodExpression; import org.grails.datastore.mapping.mongo.query.MongoQuery; import org.grails.datastore.mapping.query.Query.Criterion; import org.springframework.util.Assert; +import java.util.Collection; +import java.util.List; + /** * Dynamic finder expression for within polygon queries * @@ -46,11 +45,11 @@ public Criterion createCriterion() { @Override public void setArguments(Object[] arguments) { Assert.isTrue(arguments.length > 0 && arguments[0] instanceof List, - "Only a list of elements is supported in a 'withinPolygon' query"); + "Only a list of elements is supported in a 'withinPolygon' query"); Collection argument = (Collection) arguments[0]; Assert.isTrue(argument.size() == 2, - "A 'withinPolygon' query requires a two dimensional list of values"); + "A 'withinPolygon' query requires a two dimensional list of values"); super.setArguments(arguments); } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/api/MongoStaticApi.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/api/MongoStaticApi.groovy index f7bcca637c8..08d51bf8797 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/api/MongoStaticApi.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/api/MongoStaticApi.groovy @@ -81,11 +81,11 @@ class MongoStaticApi extends GormStaticApi implements MongoAllOperations mongoCollection = session.getCollection(entity) - .withDocumentClass(persistentClass) + .withDocumentClass(persistentClass) D result = options ? mongoCollection - .findOneAndDelete(filter, options) : - mongoCollection - .findOneAndDelete(filter) + .findOneAndDelete(filter, options) : + mongoCollection + .findOneAndDelete(filter) return result } @@ -102,7 +102,7 @@ class MongoStaticApi extends GormStaticApi implements MongoAllOperations + (MongoCriteriaBuilder) withSession { Session session -> def entity = session.mappingContext.getPersistentEntity(persistentClass.name) return new MongoCriteriaBuilder(entity.javaClass, session) } @@ -110,7 +110,7 @@ class MongoStaticApi extends GormStaticApi implements MongoAllOperations + (MongoDatabase) withSession({ AbstractMongoSession session -> def databaseName = session.getDatabase(session.mappingContext.getPersistentEntity(persistentClass.name)) session.getNativeInterface() .getDatabase(databaseName) @@ -120,7 +120,7 @@ class MongoStaticApi extends GormStaticApi implements MongoAllOperations + (String) withSession({ AbstractMongoSession session -> def entity = session.mappingContext.getPersistentEntity(persistentClass.name) return session.getCollectionName(entity) }) @@ -128,7 +128,7 @@ class MongoStaticApi extends GormStaticApi implements MongoAllOperations getCollection() { - (MongoCollection)withSession { AbstractMongoSession session -> + (MongoCollection) withSession { AbstractMongoSession session -> def entity = session.mappingContext.getPersistentEntity(persistentClass.name) return session.getCollection(entity) } @@ -188,11 +188,11 @@ class MongoStaticApi extends GormStaticApi implements MongoAllOperations aggregate(List pipeline, Function doWithAggregate = Function.identity()) { - (List)withSession( { AbstractMongoSession session -> + (List) withSession({ AbstractMongoSession session -> def persistentEntity = session.mappingContext.getPersistentEntity(persistentClass.name) def mongoCollection = session.getCollection(persistentEntity) - if(session instanceof MongoCodecSession) { - MongoDatastore datastore = (MongoDatastore)session.getDatastore() + if (session instanceof MongoCodecSession) { + MongoDatastore datastore = (MongoDatastore) session.getDatastore() mongoCollection = mongoCollection .withDocumentClass(persistentEntity.javaClass) .withCodecRegistry(datastore.getCodecRegistry()) @@ -203,14 +203,14 @@ class MongoStaticApi extends GormStaticApi implements MongoAllOperations aggregate(List pipeline, Function doWithAggregate, ReadPreference readPreference) { - (List)withSession( { AbstractMongoSession session -> + (List) withSession({ AbstractMongoSession session -> def persistentEntity = session.mappingContext.getPersistentEntity(persistentClass.name) List newPipeline = preparePipeline(pipeline) def mongoCollection = session.getCollection(persistentEntity) @@ -219,58 +219,56 @@ class MongoStaticApi extends GormStaticApi implements MongoAllOperations search(String query, Map options = Collections.emptyMap()) { - (List)withSession( { AbstractMongoSession session -> + (List) withSession({ AbstractMongoSession session -> def persistentEntity = session.mappingContext.getPersistentEntity(persistentClass.name) def coll = session.getCollection(persistentEntity) - if(session instanceof MongoCodecSession) { - MongoDatastore datastore = (MongoDatastore)session.datastore + if (session instanceof MongoCodecSession) { + MongoDatastore datastore = (MongoDatastore) session.datastore coll = coll .withDocumentClass(persistentEntity.javaClass) .withCodecRegistry(datastore.codecRegistry) } Bson search - if(options.language) { + if (options.language) { search = Filters.text(query, new TextSearchOptions().language(options.language.toString())) - } - else { + } else { search = Filters.text(query) } search = wrapFilterWithMultiTenancy(search) FindIterable cursor = coll.find(search) - int offset = options.offset instanceof Number ? ((Number)options.offset).intValue() : 0 - int max = options.max instanceof Number ? ((Number)options.max).intValue() : -1 - if(offset > 0) cursor.skip(offset) - if(max > -1) cursor.limit(max) - new MongoQuery.MongoResultList(cursor.iterator(), offset, (EntityPersister)session.getPersister(persistentEntity)) - } ) + int offset = options.offset instanceof Number ? ((Number) options.offset).intValue() : 0 + int max = options.max instanceof Number ? ((Number) options.max).intValue() : -1 + if (offset > 0) cursor.skip(offset) + if (max > -1) cursor.limit(max) + new MongoQuery.MongoResultList(cursor.iterator(), offset, (EntityPersister) session.getPersister(persistentEntity)) + }) } @Override List searchTop(String query, int limit = 5, Map options = Collections.emptyMap()) { - (List)withSession( { AbstractMongoSession session -> + (List) withSession({ AbstractMongoSession session -> def persistentEntity = session.mappingContext.getPersistentEntity(persistentClass.name) MongoCollection coll = session.getCollection(persistentEntity) - if(session instanceof MongoCodecSession) { - MongoDatastore datastore = (MongoDatastore)session.datastore + if (session instanceof MongoCodecSession) { + MongoDatastore datastore = (MongoDatastore) session.datastore coll = coll .withDocumentClass(persistentEntity.javaClass) .withCodecRegistry(datastore.codecRegistry) } - EntityPersister persister = (EntityPersister)session.getPersister(persistentEntity) + EntityPersister persister = (EntityPersister) session.getPersister(persistentEntity) Bson search - if(options.language) { + if (options.language) { search = Filters.text(query, new TextSearchOptions().language(options.language.toString())) - } - else { + } else { search = Filters.text(query) } @@ -278,18 +276,18 @@ class MongoStaticApi extends GormStaticApi implements MongoAllOperations extends AbstractMappingAwareCustomTypeMarshaller{ +abstract class AbstractShapeCoordsType extends AbstractMappingAwareCustomTypeMarshaller { + AbstractShapeCoordsType(Class targetType) { super(targetType) } @@ -47,7 +48,7 @@ abstract class AbstractShapeCoordsType extends AbstractMappingA @Override protected Object writeInternal(PersistentProperty property, String key, T value, Document nativeTarget) { - if(value) { + if (value) { def coords = value.asList() nativeTarget.put(key, coords) return coords @@ -57,13 +58,12 @@ abstract class AbstractShapeCoordsType extends AbstractMappingA @Override protected void queryInternal(PersistentProperty property, String key, Query.PropertyCriterion criterion, Document nativeQuery) { - if(criterion instanceof Query.Equals) { + if (criterion instanceof Query.Equals) { def value = criterion.value - if(value instanceof Box) { + if (value instanceof Box) { nativeQuery.put(key, value.asList()) } - } - else { + } else { super.queryInternal(property, key, criterion, nativeQuery) } } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/BoxType.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/BoxType.groovy index 2efd27f37ad..a7d118bfa00 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/BoxType.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/BoxType.groovy @@ -14,7 +14,6 @@ */ package org.grails.datastore.gorm.mongo.geo -import com.mongodb.DBObject import grails.mongodb.geo.Box import groovy.transform.CompileStatic import org.bson.Document @@ -27,7 +26,8 @@ import org.grails.datastore.mapping.model.PersistentProperty * @since 2.0 */ @CompileStatic -class BoxType extends AbstractShapeCoordsType{ +class BoxType extends AbstractShapeCoordsType { + BoxType() { super(Box) } @@ -35,7 +35,7 @@ class BoxType extends AbstractShapeCoordsType{ @Override protected Box readInternal(PersistentProperty property, String key, Document nativeSource) { def coords = nativeSource.get(key) - if(coords instanceof List) { + if (coords instanceof List) { return Box.valueOf(coords) } } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/CircleType.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/CircleType.groovy index 60dda2a3981..fd4cd7fc09f 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/CircleType.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/CircleType.groovy @@ -24,7 +24,8 @@ import org.grails.datastore.mapping.model.PersistentProperty * @author Graeme Rocher * @since 2.0 */ -class CircleType extends AbstractShapeCoordsType{ +class CircleType extends AbstractShapeCoordsType { + CircleType() { super(Circle) } @@ -32,7 +33,7 @@ class CircleType extends AbstractShapeCoordsType{ @Override protected Circle readInternal(PersistentProperty property, String key, Document nativeSource) { def coords = nativeSource.get(key) - if(coords instanceof List) { + if (coords instanceof List) { return Circle.valueOf(coords) } } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/GeoJSONType.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/GeoJSONType.groovy index 7a38fcbce01..a208d2afb4f 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/GeoJSONType.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/GeoJSONType.groovy @@ -27,7 +27,7 @@ import org.grails.datastore.mapping.mongo.config.MongoMappingContext import org.grails.datastore.mapping.query.Query /** - * Abstract class for persisting {@link Shape} instances in GeoJSON format. See http://geojson.org/geojson-spec.html + * Abstract class for persisting {@link Shape} instances in GeoJSON format. See https://geojson.org/geojson-spec.html * * @author Graeme Rocher * @since 2.0 @@ -54,8 +54,8 @@ abstract class GeoJSONType extends AbstractMappingAwareCustomTy @Override protected Object writeInternal(PersistentProperty property, String key, T value, Document nativeTarget) { - if(value != null) { - Document pointData = convertToGeoDocument((Shape)value) + if (value != null) { + Document pointData = convertToGeoDocument((Shape) value) nativeTarget.put(key, pointData) return pointData } @@ -71,11 +71,11 @@ abstract class GeoJSONType extends AbstractMappingAwareCustomTy @Override protected T readInternal(PersistentProperty property, String key, Document nativeSource) { def obj = nativeSource.get(key) - if(obj instanceof Document) { - Document pointData = (Document)obj + if (obj instanceof Document) { + Document pointData = (Document) obj def coords = pointData.get(COORDINATES) - if(coords instanceof List) { + if (coords instanceof List) { return createFromCoords(coords) } } @@ -86,22 +86,19 @@ abstract class GeoJSONType extends AbstractMappingAwareCustomTy @Override protected void queryInternal(PersistentProperty property, String key, Query.PropertyCriterion value, Document nativeQuery) { - if(value instanceof Query.Equals) { + if (value instanceof Query.Equals) { def v = value.getValue() - if(v instanceof GeoJSON) { + if (v instanceof GeoJSON) { Shape shape = (Shape) v def geoJson = convertToGeoDocument(shape) nativeQuery.put(key, geoJson) - } - else if( v instanceof Shape) { + } else if (v instanceof Shape) { nativeQuery.put(key, v.asList()) - } - else { + } else { super.queryInternal(property, key, value, nativeQuery) } - } - else { + } else { super.queryInternal(property, key, value, nativeQuery) } } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/GeometryCollectionType.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/GeometryCollectionType.groovy index e1a3db1a7b6..636aea98141 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/GeometryCollectionType.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/GeometryCollectionType.groovy @@ -14,16 +14,12 @@ */ package org.grails.datastore.gorm.mongo.geo -import com.mongodb.BasicDBObject -import com.mongodb.DBObject import grails.mongodb.geo.GeometryCollection import groovy.transform.CompileStatic import org.bson.Document -import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.engine.types.AbstractMappingAwareCustomTypeMarshaller import org.grails.datastore.mapping.model.MappingContext import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.mapping.mongo.MongoDatastore import org.grails.datastore.mapping.mongo.config.MongoMappingContext /** @@ -33,7 +29,7 @@ import org.grails.datastore.mapping.mongo.config.MongoMappingContext * @since 3.0 */ @CompileStatic -class GeometryCollectionType extends AbstractMappingAwareCustomTypeMarshaller{ +class GeometryCollectionType extends AbstractMappingAwareCustomTypeMarshaller { public static final String GEOMETRIES = "geometries" @@ -48,7 +44,7 @@ class GeometryCollectionType extends AbstractMappingAwareCustomTypeMarshaller { + LineStringType() { super(LineString) } @Override LineString createFromCoords(List> coords) { - if(coords.size() < 2) throw new DataAccessResourceFailureException("Invalid polygon data returned: $coords") + if (coords.size() < 2) throw new DataAccessResourceFailureException("Invalid polygon data returned: $coords") def points = coords.collect() { List pos -> new Point(pos.get(0), pos.get(1)) } return new LineString(points as Point[]) diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/MultiLineStringType.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/MultiLineStringType.groovy index d5824e1242d..1a9ff7ec720 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/MultiLineStringType.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/MultiLineStringType.groovy @@ -24,7 +24,7 @@ import groovy.transform.CompileStatic * @since 3.0 */ @CompileStatic -class MultiLineStringType extends GeoJSONType{ +class MultiLineStringType extends GeoJSONType { MultiLineStringType() { super(MultiLineString) diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/MultiPolygonType.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/MultiPolygonType.groovy index a9e6f0db8ae..8b845f7e589 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/MultiPolygonType.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/MultiPolygonType.groovy @@ -22,7 +22,8 @@ import grails.mongodb.geo.MultiPolygon * @author Graeme Rocher * @since 3.0 */ -class MultiPolygonType extends GeoJSONType{ +class MultiPolygonType extends GeoJSONType { + MultiPolygonType() { super(MultiPolygon) } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/PointType.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/PointType.groovy index 600625f2f14..194d378d7f1 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/PointType.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/PointType.groovy @@ -22,13 +22,14 @@ import grails.mongodb.geo.Point * @author Graeme Rocher * @since 2.4 */ -class PointType extends GeoJSONType{ +class PointType extends GeoJSONType { PointType() { super(Point) } + @Override Point createFromCoords(List coords) { - return new Point((double)coords.get(0), (double)coords.get(1)) + return new Point((double) coords.get(0), (double) coords.get(1)) } } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/ShapeType.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/ShapeType.groovy index 5acf7a9108d..0f54d24561a 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/ShapeType.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/geo/ShapeType.groovy @@ -19,7 +19,6 @@ import grails.mongodb.geo.LineString import grails.mongodb.geo.Point import grails.mongodb.geo.Polygon import grails.mongodb.geo.Shape -import groovy.transform.CompileStatic import org.bson.Document import org.grails.datastore.mapping.model.PersistentProperty import org.springframework.dao.DataAccessResourceFailureException @@ -32,19 +31,19 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException * @author Graeme Rocher * @since 2.0 */ -class ShapeType extends GeoJSONType{ +class ShapeType extends GeoJSONType { static Map geoJsonTypeMap = [Polygon: Polygon, LineString: LineString, Point: Point] + ShapeType() { super(Shape) } @Override protected Object writeInternal(PersistentProperty property, String key, Shape value, Document nativeTarget) { - if(value instanceof GeoJSON) { + if (value instanceof GeoJSON) { return super.writeInternal(property, key, value, nativeTarget) - } - else { + } else { throw new InvalidDataAccessResourceUsageException("Only GeoJSON shapes can be persisted using Shape inheritance.") } } @@ -52,12 +51,12 @@ class ShapeType extends GeoJSONType{ @Override protected Shape readInternal(PersistentProperty property, String key, Document nativeSource) { def geoData = nativeSource.get(key) - if(geoData && (geoData instanceof Map) ) { + if (geoData && (geoData instanceof Map)) { def geoType = geoData.get(GEO_TYPE) def coords = geoData.get(COORDINATES) - if(geoType) { + if (geoType) { def cls = geoJsonTypeMap.get(geoType.toString()) - if(cls && coords) { + if (cls && coords) { return cls.valueOf(coords) } } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/simple/EnumType.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/simple/EnumType.groovy index 893881e6dfe..476f5fd7bf3 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/simple/EnumType.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/gorm/mongo/simple/EnumType.groovy @@ -16,6 +16,7 @@ package org.grails.datastore.gorm.mongo.simple import groovy.transform.CompileDynamic import groovy.transform.CompileStatic +import jakarta.persistence.EnumType as JEnumType import org.bson.Document import org.grails.datastore.bson.query.BsonQuery import org.grails.datastore.mapping.config.Property @@ -34,12 +35,12 @@ import org.grails.datastore.mapping.query.Query.Equals import org.grails.datastore.mapping.query.Query.In import org.grails.datastore.mapping.query.Query.NotEquals -import jakarta.persistence.EnumType as JEnumType import java.lang.reflect.Array + /** * A custom type for persisting Enum which have an id field in domain classes. * For example: To save identity instead of string in database for field type. - * + * *

  *      class User {
  *          UserType type
@@ -48,17 +49,17 @@ import java.lang.reflect.Array
  *
  *      enum UserType {
  *          A(1), B(2)
- *          
+ *
  *          final int id
  *          UserType(int id) {
  *              this.id = id
  *          }
  *      }
  * 
- * + * * @author Shashank Agrawal * @author Causecode Technologies - * + * * @since 3.1.3 * */ @@ -81,11 +82,10 @@ class EnumType extends AbstractMappingAwareCustomTypeMarshaller) value).each { Document queryObject -> @@ -242,7 +242,7 @@ class EnumType extends AbstractMappingAwareCustomTypeMarshaller { + public static final String MONGO_SET_OPERATOR = "$set"; public static final String MONGO_UNSET_OPERATOR = "$unset"; - protected static final Map declaredWriteConcerns = new ConcurrentHashMap(); + protected static final Map DECLARED_WRITE_CONCERNS = new ConcurrentHashMap(); protected final String defaultDatabase; protected MongoDatastore mongoDatastore; @@ -51,6 +52,7 @@ public abstract class AbstractMongoSession extends AbstractSession public AbstractMongoSession(MongoDatastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher) { this(datastore, mappingContext, publisher, false); } + public AbstractMongoSession(MongoDatastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher, boolean stateless) { super(datastore, mappingContext, publisher, stateless); mongoDatastore = datastore; @@ -88,7 +90,7 @@ public String getDefaultDatabase() { public String getDatabase(PersistentEntity entity) { final String name = mongoDatabases.get(entity); - if(name != null) { + if (name != null) { return name; } return getDatastore().getDatabaseName(entity); @@ -105,6 +107,7 @@ public void setWriteConcern(WriteConcern writeConcern) { /** * Obtains the WriteConcern to use for the session + * * @return the WriteConcern */ public WriteConcern getWriteConcern() { @@ -116,7 +119,7 @@ public WriteConcern getDeclaredWriteConcern(PersistentEntity entity) { } private WriteConcern getDeclaredWriteConcern(WriteConcern defaultConcern, PersistentEntity entity) { - WriteConcern writeConcern = declaredWriteConcerns.get(entity); + WriteConcern writeConcern = DECLARED_WRITE_CONCERNS.get(entity); if (writeConcern == null) { Object mappedForm = entity.getMapping().getMappedForm(); if (mappedForm instanceof MongoCollection) { @@ -128,14 +131,14 @@ private WriteConcern getDeclaredWriteConcern(WriteConcern defaultConcern, Persis } if (writeConcern != null) { - declaredWriteConcerns.put(entity, writeConcern); + DECLARED_WRITE_CONCERNS.put(entity, writeConcern); } } return writeConcern; } public MongoClient getNativeInterface() { - return ((MongoDatastore)getDatastore()).getMongoClient(); + return ((MongoDatastore) getDatastore()).getMongoClient(); } public DocumentMappingContext getDocumentMappingContext() { @@ -150,7 +153,7 @@ public String getCollectionName(PersistentEntity entity) { /** * Use the given collection for the given entity * - * @param entity The entity + * @param entity The entity * @param collectionName The collection * @return The previous collection that was used */ @@ -164,29 +167,27 @@ public String useCollection(PersistentEntity entity, String collectionName) { /** * Use the given database name for the given entity * - * @param entity The entity name + * @param entity The entity name * @param databaseName The database name * @return The name of the previous database */ public String useDatabase(PersistentEntity entity, String databaseName) { - if(databaseName == null) { + if (databaseName == null) { return mongoDatabases.put(entity, getDefaultDatabase()); - } - else { + } else { return mongoDatabases.put(entity, databaseName); } } public com.mongodb.client.MongoCollection getCollection(PersistentEntity entity) { - if(entity.isRoot()) { + if (entity.isRoot()) { final String database = getDatabase(entity); final String collectionName = getCollectionName(entity); return getNativeInterface() .getDatabase(database) .getCollection(collectionName) .withCodecRegistry(getDatastore().getCodecRegistry()); - } - else { + } else { final PersistentEntity root = entity.getRootEntity(); return getCollection(root); } @@ -200,9 +201,9 @@ public MongoMappingContext getMappingContext() { /** * Decodes the given entity type from the given native object type * - * @param type A GORM entity type + * @param type A GORM entity type * @param nativeObject A native MongoDB object type (Document, FinderIterable etc.) - * @param The concrete type of the entity + * @param The concrete type of the entity * @return An instanceof the type or null if it doesn't exist */ public abstract T decode(Class type, Object nativeObject); diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoCodecSession.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoCodecSession.groovy index c8f5c954b78..7eda29056bc 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoCodecSession.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoCodecSession.groovy @@ -17,6 +17,7 @@ * under the License. */ package org.grails.datastore.mapping.mongo + import com.mongodb.WriteConcern import com.mongodb.bulk.BulkWriteResult import com.mongodb.client.FindIterable @@ -31,6 +32,7 @@ import com.mongodb.client.model.WriteModel import com.mongodb.client.result.DeleteResult import com.mongodb.client.result.UpdateResult import groovy.transform.CompileStatic +import jakarta.persistence.FlushModeType import org.bson.BsonDocumentReader import org.bson.BsonDocumentWrapper import org.bson.Document @@ -61,8 +63,8 @@ import org.grails.datastore.mapping.transactions.Transaction import org.springframework.context.ApplicationEventPublisher import org.springframework.dao.DataIntegrityViolationException -import jakarta.persistence.FlushModeType import java.util.concurrent.ConcurrentHashMap + /** * A MongoDB session for codec mapping style * @@ -71,11 +73,12 @@ import java.util.concurrent.ConcurrentHashMap */ @CompileStatic class MongoCodecSession extends AbstractMongoSession { + protected Map mongoCodecEntityPersisterMap = new ConcurrentHashMap().withDefault { Class type -> def context = getDocumentMappingContext() def entity = context.getPersistentEntity(type.name) - if(entity) { - return new MongoCodecEntityPersister(context, entity, this, publisher, cacheAdapterRepository ) + if (entity) { + return new MongoCodecEntityPersister(context, entity, this, publisher, cacheAdapterRepository) } throw new IllegalArgumentException("Type [$type] is not an entity") } @@ -83,20 +86,19 @@ class MongoCodecSession extends AbstractMongoSession { public MongoCodecSession(MongoDatastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher) { this(datastore, mappingContext, publisher, false); } + public MongoCodecSession(MongoDatastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher, boolean stateless) { super(datastore, mappingContext, publisher, stateless); - FlushModeType defaultFlushMode = datastore.getDefaultFlushMode() setFlushMode(defaultFlushMode); } @Override MongoDatastore getDatastore() { - return (MongoDatastore)super.getDatastore() + return (MongoDatastore) super.getDatastore() } - @Override void flush(WriteConcern writeConcern) { WriteConcern currentWriteConcern = this.getWriteConcern(); @@ -106,24 +108,22 @@ class MongoCodecSession extends AbstractMongoSession { final Map> pendingInserts = getPendingInserts(); final Map> pendingDeletes = getPendingDeletes(); - if(pendingUpdates.isEmpty() && pendingInserts.isEmpty() && pendingDeletes.isEmpty()) { + if (pendingUpdates.isEmpty() && pendingInserts.isEmpty() && pendingDeletes.isEmpty()) { return; } - - Map numberOfOptimisticUpdates = [:].withDefault { 0 } - Map numberOfPessimisticUpdates = [:].withDefault { 0 } + Map numberOfOptimisticUpdates = [:].withDefault { 0 } + Map numberOfPessimisticUpdates = [:].withDefault { 0 } Map>> writeModels = [:] for (PersistentEntity persistentEntity in pendingInserts.keySet()) { final Collection inserts = pendingInserts[persistentEntity] - if(inserts) { + if (inserts) { List> entityWrites = getWriteModelsForEntity(persistentEntity, writeModels) for (PendingInsert insert in inserts) { insert.run() - if(insert.vetoed) continue - + if (insert.vetoed) continue def object = insert.nativeEntry entityWrites << new InsertOneModel(object) @@ -134,21 +134,20 @@ class MongoCodecSession extends AbstractMongoSession { } } - for (PersistentEntity persistentEntity in pendingUpdates.keySet()) { final String name = persistentEntity.isRoot() ? persistentEntity.name : persistentEntity.rootEntity.name final Collection updates = pendingUpdates[persistentEntity] - if(updates) { + if (updates) { List> entityWrites = getWriteModelsForEntity(persistentEntity, writeModels); for (PendingUpdate update in updates) { update.run() - if(update.vetoed) continue + if (update.vetoed) continue DirtyCheckable changedObject = (DirtyCheckable) update.getNativeEntry() - PersistentEntityCodec codec = (PersistentEntityCodec)datastore.codecRegistry.get(changedObject.getClass()) + PersistentEntityCodec codec = (PersistentEntityCodec) datastore.codecRegistry.get(changedObject.getClass()) final Object nativeKey = update.nativeKey final Document id = new Document(MongoEntityPersister.MONGO_ID_FIELD, nativeKey) @@ -156,24 +155,23 @@ class MongoCodecSession extends AbstractMongoSession { EntityAccess entityAccess = update.entityAccess boolean isVersioned = persistentEntity.isVersioned() def currentVersion = null - if(isVersioned) { - currentVersion = entityAccess.getProperty( persistentEntity.version.name ) + if (isVersioned) { + currentVersion = entityAccess.getProperty(persistentEntity.version.name) } def updateDoc = codec.encodeUpdate(changedObject, entityAccess) - if(updateDoc) { + if (updateDoc) { - if(isVersioned) { + if (isVersioned) { // if the entity is versioned we add to the query the current version // if the query doesn't match a result this means the document has been updated by // another thread and an optimistic locking exception should be thrown - if(currentVersion == null) { - currentVersion = entityAccess.getProperty( persistentEntity.version.name ) + if (currentVersion == null) { + currentVersion = entityAccess.getProperty(persistentEntity.version.name) } id[GormProperties.VERSION] = currentVersion numberOfOptimisticUpdates[name]++ - } - else { + } else { numberOfPessimisticUpdates[name]++ } final options = new UpdateOptions() @@ -188,67 +186,62 @@ class MongoCodecSession extends AbstractMongoSession { } } - for (PersistentEntity persistentEntity in pendingDeletes.keySet()) { final Collection deletes = pendingDeletes[persistentEntity] - if(deletes) { + if (deletes) { List> entityWrites = getWriteModelsForEntity(persistentEntity, writeModels) List nativeKeys = [] for (PendingDelete delete in deletes) { delete.run() - if(delete.vetoed) continue + if (delete.vetoed) continue final Object k = delete.nativeKey - if(k) { + if (k) { nativeKeys << k final List cascadeOperations = delete.cascadeOperations addPostFlushOperations cascadeOperations } } - if(nativeKeys.size() == 1) { - entityWrites << new DeleteOneModel(new Document( MongoEntityPersister.MONGO_ID_FIELD, nativeKeys.get(0))) - } - else { - entityWrites << new DeleteManyModel(new Document( MongoEntityPersister.MONGO_ID_FIELD, new Document(BsonQuery.IN_OPERATOR, nativeKeys))) + if (nativeKeys.size() == 1) { + entityWrites << new DeleteOneModel(new Document(MongoEntityPersister.MONGO_ID_FIELD, nativeKeys.get(0))) + } else { + entityWrites << new DeleteManyModel(new Document(MongoEntityPersister.MONGO_ID_FIELD, new Document(BsonQuery.IN_OPERATOR, nativeKeys))) } } } - for (PersistentEntity persistentEntity : writeModels.keySet()) { MongoCollection collection = getCollection(persistentEntity) - .withDocumentClass(persistentEntity.javaClass) + .withDocumentClass(persistentEntity.javaClass) WriteConcern wc = writeConcern - if(wc == null) { - org.grails.datastore.mapping.mongo.config.MongoCollection mapping = (org.grails.datastore.mapping.mongo.config.MongoCollection)persistentEntity.mapping.mappedForm + if (wc == null) { + org.grails.datastore.mapping.mongo.config.MongoCollection mapping = (org.grails.datastore.mapping.mongo.config.MongoCollection) persistentEntity.mapping.mappedForm wc = mapping.writeConcern } - if(wc != null) { + if (wc != null) { collection = collection.withWriteConcern(wc) - } - else { + } else { wc = collection.writeConcern } final List> writes = writeModels[persistentEntity] - if(writes) { + if (writes) { final BulkWriteResult bulkWriteResult = collection - .bulkWrite(writes) + .bulkWrite(writes) final boolean isAcknowledged = wc.isAcknowledged() - if( !bulkWriteResult.wasAcknowledged() && isAcknowledged) { + if (!bulkWriteResult.wasAcknowledged() && isAcknowledged) { errorOccured = true; throw new DataIntegrityViolationException("Write operation was not acknowledged"); - } - else if(isAcknowledged) { + } else if (isAcknowledged) { final int matchedCount = bulkWriteResult.matchedCount final String name = persistentEntity.name final Integer numOptimistic = numberOfOptimisticUpdates[name] final Integer numPessimistic = numberOfPessimisticUpdates[name] - if((matchedCount - numPessimistic) != numOptimistic) { + if ((matchedCount - numPessimistic) != numOptimistic) { setFlushMode(FlushModeType.COMMIT) throw new OptimisticLockingException(persistentEntity, null) } @@ -279,7 +272,7 @@ class MongoCodecSession extends AbstractMongoSession { protected List> getWriteModelsForEntity(PersistentEntity persistentEntity, Map>> writeModels) { PersistentEntity key = persistentEntity.root ? persistentEntity : persistentEntity.rootEntity List> entityWrites = writeModels[key] - if(entityWrites == null) { + if (entityWrites == null) { entityWrites = new ArrayList>() writeModels[key] = entityWrites } @@ -302,11 +295,10 @@ class MongoCodecSession extends AbstractMongoSession { final Document nativeQuery = buildNativeDocumentQueryFromCriteria(criteria, entity); final MongoCollection collection = getCollection(entity) - final DeleteResult deleteResult = collection.deleteMany((Bson)nativeQuery) - if( deleteResult.wasAcknowledged() ) { + final DeleteResult deleteResult = collection.deleteMany((Bson) nativeQuery) + if (deleteResult.wasAcknowledged()) { return deleteResult.deletedCount - } - else { + } else { return 0 } } @@ -320,33 +312,31 @@ class MongoCodecSession extends AbstractMongoSession { updateOptions.upsert(false) for (Association association in entity.associations) { String associationName = association.name - if(association instanceof ToOne && properties.containsKey(associationName)) { + if (association instanceof ToOne && properties.containsKey(associationName)) { def value = properties.get(associationName) - if(value != null) { + if (value != null) { properties.put(associationName, association.associatedEntity.reflector.getIdentifier(value)) } } } final UpdateResult updateResult = collection.updateMany(nativeQuery, new Document(MONGO_SET_OPERATOR, properties), updateOptions) - if(updateResult.wasAcknowledged()) { + if (updateResult.wasAcknowledged()) { try { return updateResult.modifiedCount } catch (UnsupportedOperationException e) { // not supported on versions of MongoDB earlier than 2.6 return -1 } - } - else { + } else { return 0 } } @Override Object decode(Class type, Object nativeObject) { - if(nativeObject instanceof FindIterable) { + if (nativeObject instanceof FindIterable) { return decode(type, ((FindIterable) nativeObject).first()) - } - else if( nativeObject instanceof Document ) { + } else if (nativeObject instanceof Document) { def registry = datastore.getCodecRegistry() def codec = registry.get(type) @@ -359,7 +349,7 @@ class MongoCodecSession extends AbstractMongoSession { private Document buildNativeDocumentQueryFromCriteria(QueryableCriteria criteria, PersistentEntity entity) { def mongoQuery = new MongoQuery(this, entity) - for(Query.Criterion c in criteria.criteria) { + for (Query.Criterion c in criteria.criteria) { mongoQuery.add(c) } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoConstants.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoConstants.groovy index 0191ce45e71..94aff1596cb 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoConstants.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoConstants.groovy @@ -30,6 +30,7 @@ import groovy.transform.CompileStatic */ @CompileStatic class MongoConstants { + public static final String SET_OPERATOR = '$set'; public static final String UNSET_OPERATOR = '$unset'; public static final String CODEC_ENGINE = "codec"; @@ -40,11 +41,11 @@ class MongoConstants { @CompileDynamic - public static T mapToObject(Class targetType, Map values) { + public static T mapToObject(Class targetType, Map values) { T t = targetType.getDeclaredConstructor().newInstance() - for(String name in values.keySet()) { - if(t.respondsTo(name)) { - t."$name"( values.get(name) ) + for (String name in values.keySet()) { + if (t.respondsTo(name)) { + t."$name"(values.get(name)) } } return t diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoDatastore.java b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoDatastore.java index b15ac916faa..676c38c7352 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoDatastore.java +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoDatastore.java @@ -12,10 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.grails.datastore.mapping.mongo; - import com.mongodb.MongoClientSettings; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoIterable; @@ -23,6 +21,8 @@ import grails.gorm.multitenancy.Tenants; import grails.util.GrailsMessageSourceUtils; import groovy.lang.Closure; +import jakarta.annotation.PreDestroy; +import jakarta.persistence.FlushModeType; import org.bson.Document; import org.bson.codecs.Codec; import org.bson.codecs.configuration.CodecProvider; @@ -46,10 +46,27 @@ import org.grails.datastore.gorm.validation.listener.ValidationEventListener; import org.grails.datastore.gorm.validation.registry.support.ValidatorRegistries; import org.grails.datastore.mapping.config.Settings; -import org.grails.datastore.mapping.core.*; -import org.grails.datastore.mapping.core.connections.*; +import org.grails.datastore.mapping.core.AbstractDatastore; +import org.grails.datastore.mapping.core.Datastore; +import org.grails.datastore.mapping.core.DatastoreUtils; +import org.grails.datastore.mapping.core.Session; +import org.grails.datastore.mapping.core.StatelessDatastore; +import org.grails.datastore.mapping.core.connections.ConnectionSource; +import org.grails.datastore.mapping.core.connections.ConnectionSources; +import org.grails.datastore.mapping.core.connections.ConnectionSourcesInitializer; +import org.grails.datastore.mapping.core.connections.ConnectionSourcesListener; +import org.grails.datastore.mapping.core.connections.ConnectionSourcesSupport; +import org.grails.datastore.mapping.core.connections.DefaultConnectionSource; +import org.grails.datastore.mapping.core.connections.InMemoryConnectionSources; +import org.grails.datastore.mapping.core.connections.MultipleConnectionSourceCapableDatastore; +import org.grails.datastore.mapping.core.connections.SingletonConnectionSources; import org.grails.datastore.mapping.core.exceptions.ConfigurationException; -import org.grails.datastore.mapping.model.*; +import org.grails.datastore.mapping.model.ClassMapping; +import org.grails.datastore.mapping.model.EmbeddedPersistentEntity; +import org.grails.datastore.mapping.model.MappingContext; +import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.model.PersistentProperty; +import org.grails.datastore.mapping.model.PropertyMapping; import org.grails.datastore.mapping.mongo.config.MongoAttribute; import org.grails.datastore.mapping.mongo.config.MongoCollection; import org.grails.datastore.mapping.mongo.config.MongoMappingContext; @@ -72,12 +89,14 @@ import org.springframework.core.env.PropertyResolver; import org.springframework.transaction.PlatformTransactionManager; -import jakarta.annotation.PreDestroy; -import jakarta.persistence.FlushModeType; import java.io.Closeable; import java.io.IOException; import java.io.Serializable; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** @@ -123,15 +142,15 @@ public class MongoDatastore extends AbstractDatastore implements MappingContext. * Configures a new {@link MongoDatastore} for the given arguments * * @param connectionSources The {@link ConnectionSources} to use - * @param eventPublisher The Spring ApplicationContext - * @param mappingContext The mapping context + * @param eventPublisher The Spring ApplicationContext + * @param mappingContext The mapping context */ public MongoDatastore(final ConnectionSources connectionSources, final MongoMappingContext mappingContext, final ConfigurableApplicationEventPublisher eventPublisher) { super(mappingContext, connectionSources != null ? connectionSources.getBaseConfiguration() : null, null); - if(connectionSources == null) { + if (connectionSources == null) { throw new IllegalArgumentException("Argument [connectionSources] cannot be null"); } - if(mappingContext == null) { + if (mappingContext == null) { throw new IllegalArgumentException("Argument [mappingContext] cannot be null"); } @@ -157,7 +176,7 @@ public MongoDatastore(final ConnectionSources singletonConnectionSources) { - return new MongoDatastore(singletonConnectionSources, mappingContext, eventPublisher) { - @Override - protected MongoGormEnhancer initialize(final MongoConnectionSourceSettings settings) { - super.buildIndex(); - return null; - } - - @Override - public MongoDatastore getDatastoreForConnection(String connectionName) { - if (connectionName.equals(Settings.SETTING_DATASOURCE) || connectionName.equals(ConnectionSource.DEFAULT)) { - return parent; - } else { - MongoDatastore mongoDatastore = parent.datastoresByConnectionSource.get(connectionName); - if (mongoDatastore == null) { - throw new ConfigurationException("DataSource not found for name [" + connectionName + "] in configuration. Please check your multiple data sources configuration and try again."); - } - return mongoDatastore; - } - } - }; - } - /** * Configures a new {@link MongoDatastore} for the given arguments * * @param connectionSources The {@link ConnectionSources} to use - * @param eventPublisher The Spring ApplicationContext - * @param classes The persistent classes + * @param eventPublisher The Spring ApplicationContext + * @param classes The persistent classes */ - public MongoDatastore(ConnectionSources connectionSources, ConfigurableApplicationEventPublisher eventPublisher, Class...classes) { + public MongoDatastore(ConnectionSources connectionSources, ConfigurableApplicationEventPublisher eventPublisher, Class... classes) { this(connectionSources, createMappingContext(connectionSources, classes), eventPublisher); } /** * Configures a new {@link MongoDatastore} for the given arguments * - * @param mongoClient The {@link MongoClient} instance + * @param mongoClient The {@link MongoClient} instance * @param eventPublisher The Spring ApplicationContext * @param mappingContext The mapping context */ @@ -263,22 +256,22 @@ public MongoDatastore(MongoClient mongoClient, PropertyResolver configuration, M /** * Configures a new {@link MongoDatastore} for the given arguments * - * @param mongoClient The {@link MongoClient} instance + * @param mongoClient The {@link MongoClient} instance * @param eventPublisher The Spring ApplicationContext - * @param classes The persistent classes + * @param classes The persistent classes */ - public MongoDatastore(MongoClient mongoClient, PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Class...classes) { + public MongoDatastore(MongoClient mongoClient, PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Class... classes) { this(mongoClient, configuration, createMappingContext(configuration, classes), eventPublisher); } /** * Configures a new {@link MongoDatastore} for the given arguments * - * @param mongoClient The {@link MongoClient} instance + * @param mongoClient The {@link MongoClient} instance * @param eventPublisher The Spring ApplicationContext - * @param packages The packages to scan + * @param packages The packages to scan */ - public MongoDatastore(MongoClient mongoClient, PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Package...packages) { + public MongoDatastore(MongoClient mongoClient, PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Package... packages) { this(mongoClient, configuration, createMappingContext(configuration, new ClasspathEntityScanner().scan(packages)), eventPublisher); } @@ -286,9 +279,9 @@ public MongoDatastore(MongoClient mongoClient, PropertyResolver configuration, C * Configures a new {@link MongoDatastore} for the given arguments * * @param mongoClient The {@link MongoClient} instance - * @param classes The persistent classes + * @param classes The persistent classes */ - public MongoDatastore(MongoClient mongoClient, PropertyResolver configuration, Class...classes) { + public MongoDatastore(MongoClient mongoClient, PropertyResolver configuration, Class... classes) { this(mongoClient, configuration, createMappingContext(configuration, classes), new DefaultApplicationEventPublisher()); } @@ -296,85 +289,83 @@ public MongoDatastore(MongoClient mongoClient, PropertyResolver configuration, C * Configures a new {@link MongoDatastore} for the given arguments * * @param mongoClient The {@link MongoClient} instance - * @param packages The packages to scan + * @param packages The packages to scan */ - public MongoDatastore(MongoClient mongoClient, PropertyResolver configuration, Package...packages) { + public MongoDatastore(MongoClient mongoClient, PropertyResolver configuration, Package... packages) { this(mongoClient, configuration, createMappingContext(configuration, new ClasspathEntityScanner().scan(packages)), new DefaultApplicationEventPublisher()); } - /** * Configures a new {@link MongoDatastore} for the given arguments * * @param mongoClient The {@link MongoClient} instance - * @param classes The persistent classes + * @param classes The persistent classes */ - public MongoDatastore(MongoClient mongoClient, Class...classes) { + public MongoDatastore(MongoClient mongoClient, Class... classes) { this(mongoClient, mapToPropertyResolver(null), createMappingContext(mapToPropertyResolver(null), classes), new DefaultApplicationEventPublisher()); } /** * Configures a new {@link MongoDatastore} for the given arguments * - * @param clientOptions The {@link MongoClientSettings} instance - * @param configuration The configuration + * @param clientOptions The {@link MongoClientSettings} instance + * @param configuration The configuration * @param eventPublisher The Spring ApplicationContext * @param mappingContext The mapping context */ public MongoDatastore(MongoClientSettings.Builder clientOptions, PropertyResolver configuration, MongoMappingContext mappingContext, ConfigurableApplicationEventPublisher eventPublisher) { - this(createMongoClient(configuration, clientOptions, mappingContext), configuration, mappingContext, eventPublisher); + this(createMongoClient(configuration, clientOptions, mappingContext), configuration, mappingContext, eventPublisher); } - /** * Configures a new {@link MongoDatastore} for the given arguments * - * @param clientOptions The {@link MongoClientSettings} instance - * @param configuration The configuration + * @param clientOptions The {@link MongoClientSettings} instance + * @param configuration The configuration * @param mappingContext The mapping context */ public MongoDatastore(MongoClientSettings.Builder clientOptions, PropertyResolver configuration, MongoMappingContext mappingContext) { - this(createMongoClient(configuration, clientOptions, mappingContext), configuration, mappingContext, new DefaultApplicationEventPublisher()); + this(createMongoClient(configuration, clientOptions, mappingContext), configuration, mappingContext, new DefaultApplicationEventPublisher()); } /** * Configures a new {@link MongoDatastore} for the given arguments * - * @param configuration The configuration for the datastore + * @param configuration The configuration for the datastore * @param eventPublisher The Spring ApplicationContext * @param mappingContext The mapping context */ public MongoDatastore(PropertyResolver configuration, MongoMappingContext mappingContext, ConfigurableApplicationEventPublisher eventPublisher) { - this(ConnectionSourcesInitializer.create(new MongoConnectionSourceFactory(), configuration), mappingContext, eventPublisher); + this(ConnectionSourcesInitializer.create(new MongoConnectionSourceFactory(), configuration), mappingContext, eventPublisher); } - /** * Configures a new {@link MongoDatastore} for the given arguments * - * @param configuration The configuration for the datastore - * @param eventPublisher The Spring ApplicationContext + * @param configuration The configuration for the datastore + * @param eventPublisher The Spring ApplicationContext * @param connectionSourceFactory The connection source factory to use - * @param classes The persistent classes + * @param classes The persistent classes */ - public MongoDatastore(PropertyResolver configuration, MongoConnectionSourceFactory connectionSourceFactory, ConfigurableApplicationEventPublisher eventPublisher, Class...classes) { + public MongoDatastore(PropertyResolver configuration, MongoConnectionSourceFactory connectionSourceFactory, ConfigurableApplicationEventPublisher eventPublisher, Class... classes) { this(ConnectionSourcesInitializer.create(connectionSourceFactory, configuration), eventPublisher, classes); } + /** * Configures a new {@link MongoDatastore} for the given arguments * - * @param configuration The configuration for the datastore + * @param configuration The configuration for the datastore * @param eventPublisher The Spring ApplicationContext - * @param classes The persistent classes + * @param classes The persistent classes */ - public MongoDatastore(PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Class...classes) { + public MongoDatastore(PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Class... classes) { this(configuration, new MongoConnectionSourceFactory(), eventPublisher, classes); } /** * Configures a new {@link MongoDatastore} for the given arguments * - * @param configuration The configuration for the datastore + * @param configuration The configuration for the datastore * @param mappingContext The mapping context */ public MongoDatastore(PropertyResolver configuration, MongoMappingContext mappingContext) { @@ -385,32 +376,31 @@ public MongoDatastore(PropertyResolver configuration, MongoMappingContext mappin * Configures a new {@link MongoDatastore} for the given arguments * * @param configuration The configuration for the datastore - * @param classes The persistent classes + * @param classes The persistent classes */ - public MongoDatastore(PropertyResolver configuration, Class...classes) { + public MongoDatastore(PropertyResolver configuration, Class... classes) { this(configuration, new DefaultApplicationEventPublisher(), classes); } - /** * Configures a new {@link MongoDatastore} for the given arguments * - * @param configuration The configuration + * @param configuration The configuration * @param eventPublisher The event publisher - * @param classes The persistent classes + * @param classes The persistent classes */ - public MongoDatastore(Map configuration, ConfigurableApplicationEventPublisher eventPublisher, Class...classes) { - this(mapToPropertyResolver(configuration),eventPublisher, classes); + public MongoDatastore(Map configuration, ConfigurableApplicationEventPublisher eventPublisher, Class... classes) { + this(mapToPropertyResolver(configuration), eventPublisher, classes); } /** * Configures a new {@link MongoDatastore} for the given arguments * * @param configuration The configuration - * @param classes The persistent classes + * @param classes The persistent classes */ - public MongoDatastore(Map configuration, Class...classes) { - this(mapToPropertyResolver(configuration),new DefaultApplicationEventPublisher(), classes); + public MongoDatastore(Map configuration, Class... classes) { + this(mapToPropertyResolver(configuration), new DefaultApplicationEventPublisher(), classes); } /** @@ -418,14 +408,14 @@ public MongoDatastore(Map configuration, Class...classes) { * * @param configuration The configuration */ - public MongoDatastore(Map configuration ) { + public MongoDatastore(Map configuration) { this(configuration, new Class[0]); } /** * Configures a new {@link MongoDatastore} for the given arguments * - * @param configuration The configuration + * @param configuration The configuration * @param mappingContext The {@link MongoMappingContext} */ @@ -447,7 +437,7 @@ public MongoDatastore(MongoMappingContext mappingContext) { * * @param classes The persistent classes */ - public MongoDatastore(Class...classes) { + public MongoDatastore(Class... classes) { this(mapToPropertyResolver(null), classes); } @@ -456,7 +446,7 @@ public MongoDatastore(Class...classes) { * * @param packagesToScan The packages to scan */ - public MongoDatastore(Package...packagesToScan) { + public MongoDatastore(Package... packagesToScan) { this(new ClasspathEntityScanner().scan(packagesToScan)); } @@ -468,37 +458,64 @@ public MongoDatastore(Package...packagesToScan) { public MongoDatastore(Package packageToScan) { this(new ClasspathEntityScanner().scan(packageToScan)); } + /** * Construct a Mongo datastore scanning the given packages * - * @param configuration The configuration + * @param configuration The configuration * @param packagesToScan The packages to scan */ - public MongoDatastore(PropertyResolver configuration, Package...packagesToScan) { + public MongoDatastore(PropertyResolver configuration, Package... packagesToScan) { this(configuration, new ClasspathEntityScanner().scan(packagesToScan)); } /** * Construct a Mongo datastore scanning the given packages * - * @param configuration The configuration + * @param configuration The configuration * @param packagesToScan The packages to scan */ - public MongoDatastore(Map configuration, Package...packagesToScan) { + public MongoDatastore(Map configuration, Package... packagesToScan) { this(DatastoreUtils.createPropertyResolver(configuration), packagesToScan); } /** * Construct a Mongo datastore scanning the given packages * - * @param configuration The configuration + * @param configuration The configuration * @param eventPublisher The event publisher * @param packagesToScan The packages to scan */ - public MongoDatastore(PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Package...packagesToScan) { + public MongoDatastore(PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Package... packagesToScan) { this(configuration, eventPublisher, new ClasspathEntityScanner().scan(packagesToScan)); } + private MongoDatastore createChildDatastore(MongoMappingContext mappingContext, + ConfigurableApplicationEventPublisher eventPublisher, + final MongoDatastore parent, + SingletonConnectionSources singletonConnectionSources) { + return new MongoDatastore(singletonConnectionSources, mappingContext, eventPublisher) { + @Override + protected MongoGormEnhancer initialize(final MongoConnectionSourceSettings settings) { + super.buildIndex(); + return null; + } + + @Override + public MongoDatastore getDatastoreForConnection(String connectionName) { + if (connectionName.equals(Settings.SETTING_DATASOURCE) || connectionName.equals(ConnectionSource.DEFAULT)) { + return parent; + } else { + MongoDatastore mongoDatastore = parent.datastoresByConnectionSource.get(connectionName); + if (mongoDatastore == null) { + throw new ConfigurationException("DataSource not found for name [" + connectionName + "] in configuration. Please check your multiple data sources configuration and try again."); + } + return mongoDatastore; + } + } + }; + } + /** * @return The {@link ConnectionSources} for this datastore */ @@ -513,15 +530,15 @@ public void buildIndex() { for (PersistentEntity entity : this.mappingContext.getPersistentEntities()) { // Only create Mongo templates for entities that are mapped with Mongo if (!entity.isExternal()) { - if(entity.isMultiTenant() && multiTenancyMode == MultiTenancySettings.MultiTenancyMode.SCHEMA) continue; - + if (entity.isMultiTenant() && multiTenancyMode == MultiTenancySettings.MultiTenancyMode.SCHEMA) { + continue; + } initializeIndices(entity); } } } - /** * @return The default flush mode */ @@ -583,7 +600,7 @@ public void setMessageSource(List messageSources) { } public void setMessageSource(MessageSource messageSource) { - if(messageSource != null) { + if (messageSource != null) { configureValidatorRegistry(connectionSources.getDefaultConnectionSource().getSettings(), (MongoMappingContext) mappingContext, messageSource); } } @@ -651,12 +668,11 @@ public MongoClient getMongoClient() { } public String getDatabaseName(PersistentEntity entity) { - if(entity.isMultiTenant() && multiTenancyMode == MultiTenancySettings.MultiTenancyMode.SCHEMA) { + if (entity.isMultiTenant() && multiTenancyMode == MultiTenancySettings.MultiTenancyMode.SCHEMA) { return Tenants.currentId(getClass()).toString(); - } - else { + } else { final String databaseName = mongoDatabases.get(entity); - if(databaseName == null) { + if (databaseName == null) { mongoDatabases.put(entity, defaultDatabase); return defaultDatabase; } @@ -672,7 +688,7 @@ public String getDatabaseName(PersistentEntity entity) { */ public String getCollectionName(PersistentEntity entity) { final String collectionName = mongoCollections.get(entity); - if(collectionName == null) { + if (collectionName == null) { final String decapitalizedName = entity.isRoot() ? entity.getDecapitalizedName() : entity.getRootEntity().getDecapitalizedName(); mongoCollections.put(entity, decapitalizedName); return decapitalizedName; @@ -701,7 +717,6 @@ public MongoMappingContext getMappingContext() { return (MongoMappingContext) super.getMappingContext(); } - @Override public boolean isSchemaless() { return true; @@ -728,6 +743,7 @@ protected Session createSession(PropertyResolver connDetails) { /** * Runs the initialization sequence + * * @param settings */ protected MongoGormEnhancer initialize(final MongoConnectionSourceSettings settings) { @@ -769,21 +785,20 @@ protected GormValidationApi getValidationApi(Class cls, String qualifi private MongoDatastore getDatastoreForQualifier(Class cls, String qualifier) { String defaultConnectionSourceName = ConnectionSourcesSupport.getDefaultConnectionSourceName(getMappingContext().getPersistentEntity(cls.getName())); - if(defaultConnectionSourceName.equals(ConnectionSource.ALL)) { + if (defaultConnectionSourceName.equals(ConnectionSource.ALL)) { defaultConnectionSourceName = ConnectionSource.DEFAULT; } boolean isDefaultQualifier = qualifier.equals(ConnectionSource.DEFAULT); - if(isDefaultQualifier && defaultConnectionSourceName.equals(ConnectionSource.DEFAULT)) { + if (isDefaultQualifier && defaultConnectionSourceName.equals(ConnectionSource.DEFAULT)) { return MongoDatastore.this; - } - else { - if(isDefaultQualifier) { + } else { + if (isDefaultQualifier) { qualifier = defaultConnectionSourceName; } ConnectionSource connectionSource = connectionSources.getConnectionSource(qualifier); - if(connectionSource == null) { - throw new ConfigurationException("Invalid connection ["+defaultConnectionSourceName+"] configured for class ["+cls+"]"); + if (connectionSource == null) { + throw new ConfigurationException("Invalid connection [" + defaultConnectionSourceName + "] configured for class [" + cls + "]"); } return datastoresByConnectionSource.get(qualifier); @@ -791,7 +806,6 @@ private MongoDatastore getDatastoreForQualifier(Class cls, String qualifi } }; - } @Override @@ -808,7 +822,7 @@ protected void registerEventListeners(ConfigurableApplicationEventPublisher even eventPublisher.addApplicationListener(autoTimestampEventListener); eventPublisher.addApplicationListener(new ValidationEventListener(this)); - if(multiTenancyMode == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) { + if (multiTenancyMode == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) { eventPublisher.addApplicationListener(new MultiTenantEventListener(this)); } } @@ -880,7 +894,6 @@ protected void initializeIndices(final PersistentEntity entity) { } } - } String getMongoFieldNameForProperty(PersistentProperty property) { @@ -895,7 +908,6 @@ String getMongoFieldNameForProperty(PersistentProperty property) return propKey; } - public void persistentEntityAdded(PersistentEntity entity) { initializeIndices(entity); } @@ -912,11 +924,11 @@ public void close() { if (connectionSources != null) { connectionSources.close(); } - } catch(IOException e) { + } catch (IOException e) { LOG.error("There was an error shutting down GORM for an entity: " + e.getMessage(), e); } finally { - if(gormEnhancer != null) { + if (gormEnhancer != null) { try { gormEnhancer.close(); } catch (Throwable e) { @@ -929,8 +941,8 @@ public void close() { /** * Creates the connection sources for an existing {@link MongoClient} * - * @param mongoClient The {@link MongoClient} - * @param configuration The configuration + * @param mongoClient The {@link MongoClient} + * @param configuration The configuration * @param mappingContext The {@link MongoMappingContext} * @return The {@link ConnectionSources} */ @@ -941,14 +953,12 @@ protected static ConnectionSources c return new InMemoryConnectionSources<>(defaultConnectionSource, new MongoConnectionSourceFactory(), configuration); } - protected static MongoClient createMongoClient(PropertyResolver configuration, MongoClientSettings.Builder mongoOptions, MongoMappingContext mappingContext) { MongoConnectionSourceFactory mongoConnectionSourceFactory = new MongoConnectionSourceFactory(); mongoConnectionSourceFactory.setClientOptionsBuilder(mongoOptions); return mongoConnectionSourceFactory.create(ConnectionSource.DEFAULT, configuration).getSource(); } - protected static MongoMappingContext createMappingContext(ConnectionSources connectionSources, Class... classes) { ConnectionSource defaultConnectionSource = connectionSources.getDefaultConnectionSource(); MongoMappingContext mongoMappingContext = new MongoMappingContext(defaultConnectionSource.getSettings(), classes); @@ -959,7 +969,7 @@ protected static MongoMappingContext createMappingContext(ConnectionSources T1 withNewSession(Serializable tenantId, Closure callable) { try { DatastoreUtils.bindNewSession(session); return callable.call(session); - } - finally { + } finally { DatastoreUtils.unbindSession(session); } } + public AutoTimestampEventListener getAutoTimestampEventListener() { + return this.autoTimestampEventListener; + } + class PersistentEntityCodeRegistry implements CodecProvider { Map codecs = new HashMap(); @@ -1059,8 +1072,4 @@ public Codec get(Class clazz, CodecRegistry registry) { return codec; } } - - public AutoTimestampEventListener getAutoTimestampEventListener() { - return this.autoTimestampEventListener; - } } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoSession.java b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoSession.java index 597d2d61e0d..8e8b93486e7 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoSession.java +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoSession.java @@ -18,16 +18,25 @@ */ package org.grails.datastore.mapping.mongo; -import com.mongodb.client.MongoClient; import com.mongodb.WriteConcern; import com.mongodb.client.FindIterable; -import com.mongodb.client.model.*; +import com.mongodb.client.MongoClient; +import com.mongodb.client.model.DeleteManyModel; +import com.mongodb.client.model.InsertOneModel; +import com.mongodb.client.model.UpdateOneModel; +import com.mongodb.client.model.UpdateOptions; +import com.mongodb.client.model.WriteModel; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.UpdateResult; +import jakarta.persistence.FlushModeType; import org.bson.Document; import org.grails.datastore.bson.query.BsonQuery; import org.grails.datastore.mapping.core.OptimisticLockingException; -import org.grails.datastore.mapping.core.impl.*; +import org.grails.datastore.mapping.core.impl.PendingDelete; +import org.grails.datastore.mapping.core.impl.PendingDeleteAdapter; +import org.grails.datastore.mapping.core.impl.PendingInsert; +import org.grails.datastore.mapping.core.impl.PendingOperation; +import org.grails.datastore.mapping.core.impl.PendingUpdate; import org.grails.datastore.mapping.engine.EntityAccess; import org.grails.datastore.mapping.engine.EntityPersister; import org.grails.datastore.mapping.engine.Persister; @@ -44,9 +53,14 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.dao.DataIntegrityViolationException; -import jakarta.persistence.FlushModeType; import java.io.Serializable; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * A {@link org.grails.datastore.mapping.core.Session} implementation for the Mongo document store. @@ -56,21 +70,19 @@ */ public class MongoSession extends AbstractMongoSession { - public MongoSession(MongoDatastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher) { this(datastore, mappingContext, publisher, false); } + public MongoSession(MongoDatastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher, boolean stateless) { super(datastore, mappingContext, publisher, stateless); } - @Override public Query createQuery(@SuppressWarnings("rawtypes") Class type) { return super.createQuery(type); } - @Override protected void cacheEntry(Serializable key, Object entry, Map entryCache, boolean forDirtyCheck) { entryCache.put(key, entry); @@ -84,23 +96,24 @@ public void flush(WriteConcern writeConcern) { final Map> pendingInserts = getPendingInserts(); final Map> pendingDeletes = getPendingDeletes(); - if(pendingUpdates.isEmpty() && pendingInserts.isEmpty() && pendingDeletes.isEmpty()) { + if (pendingUpdates.isEmpty() && pendingInserts.isEmpty() && pendingDeletes.isEmpty()) { return; } - - Map numberOfOptimisticUpdates = new LinkedHashMap(); - Map numberOfPessimisticUpdates = new LinkedHashMap(); + Map numberOfOptimisticUpdates = new LinkedHashMap(); + Map numberOfPessimisticUpdates = new LinkedHashMap(); Map>> writeModels = new LinkedHashMap>>(); for (PersistentEntity persistentEntity : pendingInserts.keySet()) { final Collection inserts = pendingInserts.get(persistentEntity); - if(inserts != null && !inserts.isEmpty()) { + if (inserts != null && !inserts.isEmpty()) { List> entityWrites = getWriteModelsForEntity(persistentEntity, writeModels); for (PendingInsert insert : inserts) { insert.run(); - if(insert.isVetoed()) continue; + if (insert.isVetoed()) { + continue; + } entityWrites.add(new InsertOneModel((Document) insert.getNativeEntry())); @@ -110,7 +123,6 @@ public void flush(WriteConcern writeConcern) { } } - for (PersistentEntity persistentEntity : pendingUpdates.keySet()) { final String name = persistentEntity.isRoot() ? persistentEntity.getName() : persistentEntity.getRootEntity().getName(); @@ -118,12 +130,14 @@ public void flush(WriteConcern writeConcern) { int numberOfPessimistic = numberOfPessimisticUpdates.containsKey(name) ? numberOfPessimisticUpdates.get(name) : 0; final Collection updates = pendingUpdates.get(persistentEntity); - if(updates != null && !updates.isEmpty()) { + if (updates != null && !updates.isEmpty()) { List> entityWrites = getWriteModelsForEntity(persistentEntity, writeModels); for (PendingUpdate update : updates) { update.run(); - if(update.isVetoed()) continue; + if (update.isVetoed()) { + continue; + } Document updateDoc = (Document) update.getNativeEntry(); updateDoc.remove(MongoConstants.MONGO_ID_FIELD); @@ -132,7 +146,7 @@ public void flush(WriteConcern writeConcern) { final Document id = new Document(MongoConstants.MONGO_ID_FIELD, nativeKey); MongoEntityPersister documentEntityPersister = (MongoEntityPersister) getPersister(persistentEntity); final EntityAccess entityAccess = update.getEntityAccess(); - if(documentEntityPersister.isVersioned(entityAccess)) { + if (documentEntityPersister.isVersioned(entityAccess)) { Object currentVersion = documentEntityPersister.getCurrentVersion(entityAccess); documentEntityPersister.incrementVersion(entityAccess); @@ -141,8 +155,7 @@ public void flush(WriteConcern writeConcern) { // another thread an an optimistic locking exception should be thrown id.put(GormProperties.VERSION, currentVersion); numberOfOptimistic++; - } - else { + } else { numberOfPessimistic++; } final UpdateOptions options = new UpdateOptions(); @@ -158,23 +171,23 @@ public void flush(WriteConcern writeConcern) { } - for (PersistentEntity persistentEntity : pendingDeletes.keySet()) { final Collection deletes = pendingDeletes.get(persistentEntity); - if(deletes != null && !deletes.isEmpty()) { + if (deletes != null && !deletes.isEmpty()) { List> entityWrites = getWriteModelsForEntity(persistentEntity, writeModels); List nativeKeys = new ArrayList(); for (PendingDelete delete : deletes) { delete.run(); - if(delete.isVetoed()) continue; + if (delete.isVetoed()) { + continue; + } final Object k = delete.getNativeKey(); - if(k != null) { - if(k instanceof Document) { - entityWrites.add(new DeleteManyModel((Document)k)); - } - else { + if (k != null) { + if (k instanceof Document) { + entityWrites.add(new DeleteManyModel((Document) k)); + } else { nativeKeys.add(k); } } @@ -182,35 +195,33 @@ public void flush(WriteConcern writeConcern) { final List cascadeOperations = delete.getCascadeOperations(); addPostFlushOperations(cascadeOperations); } - entityWrites.add(new DeleteManyModel(new Document( MongoConstants.MONGO_ID_FIELD, new Document(BsonQuery.IN_OPERATOR, nativeKeys)))); + entityWrites.add(new DeleteManyModel(new Document(MongoConstants.MONGO_ID_FIELD, new Document(BsonQuery.IN_OPERATOR, nativeKeys)))); } } - for (PersistentEntity persistentEntity : writeModels.keySet()) { com.mongodb.client.MongoCollection collection = getCollection(persistentEntity); final WriteConcern wc = getWriteConcern(); - if(wc != null) { + if (wc != null) { collection = collection.withWriteConcern(wc); } final List> writes = writeModels.get(persistentEntity); - if(!writes.isEmpty()) { + if (!writes.isEmpty()) { final com.mongodb.bulk.BulkWriteResult bulkWriteResult = collection .bulkWrite(writes); - if( !bulkWriteResult.wasAcknowledged() ) { + if (!bulkWriteResult.wasAcknowledged()) { errorOccured = true; throw new DataIntegrityViolationException("Write operation was not acknowledged"); - } - else { + } else { final int matchedCount = bulkWriteResult.getMatchedCount(); final String name = persistentEntity.getName(); final Integer numOptimistic = numberOfOptimisticUpdates.get(name); final Integer numPessimistic = numberOfPessimisticUpdates.get(name); final int no = numOptimistic != null ? numOptimistic : 0; final int pe = numPessimistic != null ? numPessimistic : 0; - if((matchedCount - pe) != no) { + if ((matchedCount - pe) != no) { setFlushMode(FlushModeType.COMMIT); throw new OptimisticLockingException(persistentEntity, null); } @@ -235,7 +246,7 @@ protected Document createSetAndUnsetDoc(Document updateDoc) { final Document unsets = new Document(); for (String key : keys) { final Object v = updateDoc.get(key); - if(v == null) { + if (v == null) { unsets.put(key, ""); } } @@ -243,7 +254,7 @@ protected Document createSetAndUnsetDoc(Document updateDoc) { updateDoc.remove(key); } updateDoc = new Document(MONGO_SET_OPERATOR, updateDoc); - if(!unsets.isEmpty()) { + if (!unsets.isEmpty()) { updateDoc.put(MONGO_UNSET_OPERATOR, unsets); } return updateDoc; @@ -252,7 +263,7 @@ protected Document createSetAndUnsetDoc(Document updateDoc) { protected List> getWriteModelsForEntity(PersistentEntity persistentEntity, Map>> writeModels) { PersistentEntity key = persistentEntity.isRoot() ? persistentEntity : persistentEntity.getRootEntity(); List> entityWrites = writeModels.get(key); - if(entityWrites == null) { + if (entityWrites == null) { entityWrites = new ArrayList>(); writeModels.put(key, entityWrites); } @@ -264,13 +275,11 @@ protected void flushPendingUpdates(Map beginTransactionInternal() { return new SessionOnlyTransaction(getNativeInterface(), this); } - @Override public void delete(Iterable objects) { final Map toDelete = getDeleteMap(objects); @@ -291,12 +299,12 @@ public void delete(Iterable objects) { final MongoQuery query = new MongoQuery(this, persistentEntity); query.in(MongoEntityPersister.MONGO_ID_FIELD, toDelete.get(persistentEntity)); final Document mongoQuery = query.getMongoQuery(); - final EntityPersister persister = (EntityPersister)getPersister(persistentEntity); + final EntityPersister persister = (EntityPersister) getPersister(persistentEntity); addPendingDelete(new PendingDeleteAdapter(persistentEntity, mongoQuery, null) { @Override public void run() { for (Object o : toDelete.get(persistentEntity)) { - if( !persister.cancelDelete(persistentEntity, createEntityAccess(persistentEntity, o)) ) { + if (!persister.cancelDelete(persistentEntity, createEntityAccess(persistentEntity, o))) { clear(o); } } @@ -306,7 +314,6 @@ public void run() { } - protected Map getDeleteMap(Iterable objects) { // sort the objects into sets by Persister, in case the objects are of different types. Map toDelete = new HashMap(); @@ -320,17 +327,17 @@ protected Map getDeleteMap(Iterable objects) { } List listForPersister = toDelete.get(p); if (listForPersister == null) { - toDelete.put(p, listForPersister = new ArrayList()); + listForPersister = new ArrayList(); + toDelete.put(p, listForPersister); } Serializable id = getObjectIdentifier(object); - if(id != null) { + if (id != null) { listForPersister.add(id); } } return toDelete; } - @Override public long deleteAll(QueryableCriteria criteria) { final PersistentEntity entity = criteria.getPersistentEntity(); @@ -338,16 +345,13 @@ public long deleteAll(QueryableCriteria criteria) { final com.mongodb.client.MongoCollection collection = getCollection(entity); final DeleteResult deleteResult = collection.deleteMany(nativeQuery); - if( deleteResult.wasAcknowledged() ) { + if (deleteResult.wasAcknowledged()) { return deleteResult.getDeletedCount(); - } - else { + } else { return 0; } } - - @Override public long updateAll(QueryableCriteria criteria, Map properties) { final PersistentEntity entity = criteria.getPersistentEntity(); @@ -356,27 +360,25 @@ public long updateAll(QueryableCriteria criteria, Map properties final UpdateOptions updateOptions = new UpdateOptions(); updateOptions.upsert(false); final UpdateResult updateResult = collection.updateMany(nativeQuery, new Document("$set", properties), updateOptions); - if(updateResult.wasAcknowledged()) { + if (updateResult.wasAcknowledged()) { try { return updateResult.getModifiedCount(); } catch (UnsupportedOperationException e) { // not supported on versions of MongoDB earlier than 2.6 return -1; } - } - else { + } else { return 0; } } @Override public Object decode(Class type, Object nativeObject) { - if(nativeObject instanceof FindIterable) { + if (nativeObject instanceof FindIterable) { return decode(type, ((FindIterable) nativeObject).first()); - } - else if( nativeObject instanceof Document ){ + } else if (nativeObject instanceof Document) { Document dbo = (Document) nativeObject; - Serializable key = (Serializable)dbo.get(AbstractMongoObectEntityPersister.MONGO_ID_FIELD); + Serializable key = (Serializable) dbo.get(AbstractMongoObectEntityPersister.MONGO_ID_FIELD); final Persister persister = getPersister(type); final MongoEntityPersister mongoEntityPersister = (MongoEntityPersister) persister; return mongoEntityPersister.createObjectFromNativeEntry(mongoEntityPersister.getPersistentEntity(), key, dbo); @@ -388,7 +390,7 @@ private Document buildNativeDocumentQueryFromCriteria(QueryableCriteria criteria MongoQuery mongoQuery = new MongoQuery(this, entity); List criteriaList = criteria.getCriteria(); - for(Query.Criterion c : criteriaList) { + for (Query.Criterion c : criteriaList) { mongoQuery.add(c); } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoAttribute.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoAttribute.groovy index edcec295f43..da0705cff2b 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoAttribute.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoAttribute.groovy @@ -60,8 +60,7 @@ class MongoAttribute extends Attribute { void setIndexAttributes(Map indexAttributes) { if (this.indexAttributes == null) { this.indexAttributes = indexAttributes - } - else { + } else { this.indexAttributes.putAll(indexAttributes) } } @@ -109,12 +108,11 @@ class MongoAttribute extends Attribute { * @param indexType The geo index type */ void setGeoIndex(String indexType) { - if(Boolean.valueOf(indexType)) { + if (Boolean.valueOf(indexType)) { setIndex(true) initIndexAttributes() indexAttributes.put(INDEX_TYPE, INDEX_TYPE_2D) - } - else if (INDEX_TYPE_2D.equals(indexType) || INDEX_TYPE_2DSPHERE.equals(indexType)) { + } else if (INDEX_TYPE_2D.equals(indexType) || INDEX_TYPE_2DSPHERE.equals(indexType)) { setIndex(true) initIndexAttributes() indexAttributes.put(INDEX_TYPE, indexType) diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoClientOptionsBuilder.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoClientOptionsBuilder.groovy index 26ac71aef04..97888372b6f 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoClientOptionsBuilder.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoClientOptionsBuilder.groovy @@ -29,6 +29,7 @@ import org.springframework.core.env.PropertyResolver import org.springframework.util.ReflectionUtils import java.lang.reflect.Modifier + /** * Helper class for building {@link MongoClientSettings} from a {@link PropertyResolver} * @@ -38,6 +39,7 @@ import java.lang.reflect.Modifier @CompileStatic @Slf4j class MongoClientOptionsBuilder { + final PropertyResolver propertyResolver final String databaseName @@ -51,7 +53,7 @@ class MongoClientOptionsBuilder { private MongoCredential mongoCredential MongoClientOptionsBuilder(PropertyResolver propertyResolver) { - this(propertyResolver, propertyResolver.getProperty(MongoSettings.SETTING_DATABASE_NAME, 'test')) + this(propertyResolver, propertyResolver.getProperty(MongoSettings.SETTING_DATABASE_NAME, 'test')) } MongoClientOptionsBuilder(PropertyResolver propertyResolver, String databaseName) { @@ -62,12 +64,11 @@ class MongoClientOptionsBuilder { username = propertyResolver.getProperty(MongoSettings.SETTING_USERNAME, '') password = propertyResolver.getProperty(MongoSettings.SETTING_PASSWORD, '') uAndP = username && password ? "$username:$password@" : '' - if(host) { + if (host) { def port = propertyResolver.getProperty(MongoSettings.SETTING_PORT, '') port = port ? ":$port" : '' connectionString = new ConnectionString("mongodb://${uAndP}${host}${port}/$databaseName") - } - else { + } else { connectionString = new ConnectionString(propertyResolver.getProperty(MongoSettings.SETTING_CONNECTION_STRING, propertyResolver.getProperty(MongoSettings.SETTING_URL, "mongodb://localhost/$databaseName"))) } mongoCredential = uAndP ? MongoCredential.createCredential(username, databaseName, password.toCharArray()) : null @@ -82,22 +83,24 @@ class MongoClientOptionsBuilder { private Object buildInternal(Object builder, String startingPrefix, boolean root = false) { def builderClass = builder.getClass() def methods = builderClass.declaredMethods -\ + + \ + def applyConnectionStringMethod = ReflectionUtils.findMethod(builderClass, 'applyConnectionString', ConnectionString) - if(applyConnectionStringMethod != null) { + if (applyConnectionStringMethod != null) { applyConnectionStringMethod.invoke(builder, connectionString) } - if(mongoCredential != null) { + if (mongoCredential != null) { def credentialListMethod = ReflectionUtils.findMethod(builderClass, 'credentialList', List) - if(credentialListMethod != null) { + if (credentialListMethod != null) { credentialListMethod.invoke(builder, Arrays.asList(mongoCredential)) } } for (method in methods) { def methodName = method.name - if(!Modifier.isPublic(method.modifiers) || methodName.equals('applyConnectionString') || methodName.equals('credentialList')) { + if (!Modifier.isPublic(method.modifiers) || methodName.equals('applyConnectionString') || methodName.equals('credentialList')) { continue } @@ -106,7 +109,7 @@ class MongoClientOptionsBuilder { Class argType = parameterTypes[0] def builderMethod = ReflectionUtils.findMethod(argType, 'builder') - String propertyPath = "${startingPrefix}.${ methodName}" + String propertyPath = "${startingPrefix}.${methodName}" if (builderMethod != null && Modifier.isStatic(builderMethod.modifiers)) { if (propertyResolver.containsProperty(propertyPath)) { def newBuilder = builderMethod.invoke(argType) @@ -116,11 +119,11 @@ class MongoClientOptionsBuilder { method.invoke(builder, buildInternal(newBuilder, propertyPath)) } } else { - if(argType.isEnum()) { + if (argType.isEnum()) { def value = propertyResolver.getProperty(propertyPath, "") if (value) { try { - method.invoke(builder, Enum.valueOf((Class)argType, value)) + method.invoke(builder, Enum.valueOf((Class) argType, value)) } catch (Throwable e) { log.warn("Error occurred reading setting [$propertyPath]: ${e.message}", e) } @@ -131,18 +134,17 @@ class MongoClientOptionsBuilder { if (valueOfMethod != null && Modifier.isStatic(valueOfMethod.modifiers)) { try { def value = propertyResolver.getProperty(propertyPath, "") - if(value) { + if (value) { def converted = valueOfMethod.invoke(argType, value) method.invoke(builder, converted) } } catch (e) { log.warn("Error occurred reading setting [$propertyPath]: ${e.message}", e) } - } - else if(!List.isAssignableFrom(argType)){ + } else if (!List.isAssignableFrom(argType)) { try { def value = propertyResolver.getProperty(propertyPath, (Class) argType, null) - if(value != null) { + if (value != null) { method.invoke(builder, value) } } catch (Throwable e) { @@ -154,10 +156,9 @@ class MongoClientOptionsBuilder { } - if(!root) { + if (!root) { return doBuild(builder) - } - else { + } else { return builder } } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoCollection.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoCollection.groovy index da1f92827fb..782b6b2871d 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoCollection.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoCollection.groovy @@ -54,7 +54,7 @@ class MongoCollection extends Collection { Query.Order getSort() { - return (Query.Order)super.getSort() + return (Query.Order) super.getSort() } /** @@ -64,7 +64,7 @@ class MongoCollection extends Collection { */ MongoCollection setSort(Object s) { if (s instanceof Query.Order) { - super.setSort( (Query.Order) s ) + super.setSort((Query.Order) s) } if (s instanceof Map) { Map m = (Map) s @@ -72,15 +72,13 @@ class MongoCollection extends Collection { Map.Entry entry = (Map.Entry) m.entrySet().iterator().next() Object key = entry.getKey() if ("desc".equalsIgnoreCase(entry.getValue().toString())) { - super.setSort( Query.Order.desc(key.toString()) ) - } - else { - super.setSort( Query.Order.asc(key.toString()) ) + super.setSort(Query.Order.desc(key.toString())) + } else { + super.setSort(Query.Order.asc(key.toString())) } } - } - else { - super.setSort( Query.Order.asc(s.toString()) ) + } else { + super.setSort(Query.Order.asc(s.toString())) } return this } @@ -108,7 +106,7 @@ class MongoCollection extends Collection { * @param definition The index definition */ void index(Map definition) { - index(definition, Collections.emptyMap()) + index(definition, Collections. emptyMap()) } /** @@ -118,7 +116,7 @@ class MongoCollection extends Collection { * @param options The index options */ void index(Map definition, Map options) { - if(definition != null && !definition.isEmpty()) { + if (definition != null && !definition.isEmpty()) { indices.add(new Index(definition, options)) } } @@ -174,17 +172,18 @@ class MongoCollection extends Collection { @Override MongoAttribute property(@DelegatesTo(MongoAttribute.class) Closure propertyConfig) { - return (MongoAttribute)super.property(propertyConfig) + return (MongoAttribute) super.property(propertyConfig) } @Override MongoAttribute property(Map propertyConfig) { - return (MongoAttribute)super.property(propertyConfig) + return (MongoAttribute) super.property(propertyConfig) } /** * Definition of an index */ static class Index { + Map definition = new HashMap() Map options = new HashMap() diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoMappingContext.java b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoMappingContext.java index 36ca060a8d6..2f7ccb7911e 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoMappingContext.java +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoMappingContext.java @@ -20,23 +20,39 @@ import com.mongodb.ConnectionString; import groovy.lang.Closure; - -import java.beans.PropertyDescriptor; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.*; -import java.util.regex.Pattern; - import org.bson.Document; import org.bson.codecs.Codec; import org.bson.codecs.configuration.CodecConfigurationException; import org.bson.codecs.configuration.CodecRegistries; import org.bson.codecs.configuration.CodecRegistry; import org.bson.conversions.Bson; -import org.bson.types.*; -import org.grails.datastore.bson.codecs.*; +import org.bson.types.Binary; +import org.bson.types.Code; +import org.bson.types.Decimal128; +import org.bson.types.ObjectId; +import org.bson.types.Symbol; +import org.grails.datastore.bson.codecs.BigDecimalCodec; +import org.grails.datastore.bson.codecs.CodecCustomTypeMarshaller; +import org.grails.datastore.bson.codecs.CodecExtensions; +import org.grails.datastore.bson.codecs.InstantCodec; +import org.grails.datastore.bson.codecs.LocalDateCodec; +import org.grails.datastore.bson.codecs.LocalDateTimeCodec; +import org.grails.datastore.bson.codecs.LocalTimeCodec; +import org.grails.datastore.bson.codecs.OffsetDateTimeCodec; +import org.grails.datastore.bson.codecs.OffsetTimeCodec; +import org.grails.datastore.bson.codecs.PeriodCodec; +import org.grails.datastore.bson.codecs.ZonedDateTimeCodec; import org.grails.datastore.bson.codecs.encoders.SimpleEncoder; -import org.grails.datastore.gorm.mongo.geo.*; +import org.grails.datastore.gorm.mongo.geo.BoxType; +import org.grails.datastore.gorm.mongo.geo.CircleType; +import org.grails.datastore.gorm.mongo.geo.GeometryCollectionType; +import org.grails.datastore.gorm.mongo.geo.LineStringType; +import org.grails.datastore.gorm.mongo.geo.MultiLineStringType; +import org.grails.datastore.gorm.mongo.geo.MultiPointType; +import org.grails.datastore.gorm.mongo.geo.MultiPolygonType; +import org.grails.datastore.gorm.mongo.geo.PointType; +import org.grails.datastore.gorm.mongo.geo.PolygonType; +import org.grails.datastore.gorm.mongo.geo.ShapeType; import org.grails.datastore.gorm.mongo.simple.EnumType; import org.grails.datastore.mapping.config.AbstractGormMappingFactory; import org.grails.datastore.mapping.config.ConfigurationUtils; @@ -44,8 +60,13 @@ import org.grails.datastore.mapping.document.config.Attribute; import org.grails.datastore.mapping.document.config.Collection; import org.grails.datastore.mapping.document.config.DocumentMappingContext; -import org.grails.datastore.mapping.model.*; - +import org.grails.datastore.mapping.model.AbstractClassMapping; +import org.grails.datastore.mapping.model.ClassMapping; +import org.grails.datastore.mapping.model.EmbeddedPersistentEntity; +import org.grails.datastore.mapping.model.MappingContext; +import org.grails.datastore.mapping.model.MappingFactory; +import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.model.PropertyMapping; import org.grails.datastore.mapping.model.types.Custom; import org.grails.datastore.mapping.model.types.Identity; import org.grails.datastore.mapping.mongo.MongoConstants; @@ -56,6 +77,20 @@ import org.springframework.core.convert.converter.ConverterRegistry; import org.springframework.core.env.PropertyResolver; +import java.beans.PropertyDescriptor; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.regex.Pattern; + /** * Models a {@link org.grails.datastore.mapping.model.MappingContext} for Mongo. * @@ -63,6 +98,7 @@ */ @SuppressWarnings("rawtypes") public class MongoMappingContext extends DocumentMappingContext { + private static final String DECIMAL_TYPE_CLASS_NAME = "org.bson.types.Decimal128"; /** * Java types supported as mongo property types. @@ -108,10 +144,10 @@ public MongoMappingContext(String defaultDatabaseName, Closure defaultMapping) { * Constructs a new {@link MongoMappingContext} for the given arguments * * @param defaultDatabaseName The default database name - * @param defaultMapping The default database mapping configuration - * @param classes The persistent classes + * @param defaultMapping The default database mapping configuration + * @param classes The persistent classes */ - public MongoMappingContext(String defaultDatabaseName, Closure defaultMapping, Class...classes) { + public MongoMappingContext(String defaultDatabaseName, Closure defaultMapping, Class... classes) { super(defaultDatabaseName, defaultMapping); initialize(classes); @@ -121,12 +157,12 @@ public MongoMappingContext(String defaultDatabaseName, Closure defaultMapping, C * Constructs a new {@link MongoMappingContext} for the given arguments * * @param configuration The configuration - * @param classes The persistent classes - * @deprecated Use {@link #MongoMappingContext(AbstractMongoConnectionSourceSettings, Class[])} instead + * @param classes The persistent classes + * @deprecated Use {@link #MongoMappingContext(AbstractMongoConnectionSourceSettings, Class[])} instead * */ @Deprecated - public MongoMappingContext(PropertyResolver configuration, Class...classes) { + public MongoMappingContext(PropertyResolver configuration, Class... classes) { this(getDefaultDatabaseName(configuration), configuration.getProperty(MongoSettings.SETTING_DEFAULT_MAPPING, Closure.class, null), classes); } @@ -134,7 +170,7 @@ public MongoMappingContext(PropertyResolver configuration, Class...classes) { * Construct a new context for the given settings and classes * * @param settings The settings - * @param classes The classes + * @param classes The classes */ public MongoMappingContext(AbstractMongoConnectionSourceSettings settings, Class... classes) { super(settings.getDatabase(), settings); @@ -155,7 +191,7 @@ protected void initialize(ConnectionSourceSettings settings) { AbstractMongoConnectionSourceSettings mongoConnectionSourceSettings = (AbstractMongoConnectionSourceSettings) settings; List> codecClasses = mongoConnectionSourceSettings.getCodecs(); - if(mongoConnectionSourceSettings.isDecimalType() && ClassUtils.isPresent(DECIMAL_TYPE_CLASS_NAME)) { + if (mongoConnectionSourceSettings.isDecimalType() && ClassUtils.isPresent(DECIMAL_TYPE_CLASS_NAME)) { MONGO_NATIVE_TYPES.add(BigDecimal.class.getName()); MONGO_NATIVE_TYPES.add(BigInteger.class.getName()); SimpleEncoder.enableBigDecimalEncoding(); @@ -179,13 +215,12 @@ protected void initialize(ConnectionSourceSettings settings) { codecs.add(codec); } - if(mongoConnectionSourceSettings.getCodecRegistry() != null) { + if (mongoConnectionSourceSettings.getCodecRegistry() != null) { this.codecRegistry = CodecRegistries.fromRegistries( mongoConnectionSourceSettings.getCodecRegistry(), CodecRegistries.fromCodecs(codecs) ); - } - else { + } else { this.codecRegistry = CodecRegistries.fromCodecs(codecs); } } @@ -196,10 +231,9 @@ private void initialize(Class[] classes) { converterRegistry.addConverter(new Converter() { public ObjectId convert(String source) { - if(ObjectId.isValid(source)) { + if (ObjectId.isValid(source)) { return new ObjectId(source); - } - else { + } else { return null; } } @@ -230,7 +264,7 @@ public BigDecimal convert(Decimal128 source) { } }); - converterRegistry.addConverter(new Converter() { + converterRegistry.addConverter(new Converter() { @Override public Decimal128 convert(BigDecimal source) { return new Decimal128(source); @@ -244,7 +278,7 @@ public BigInteger convert(Decimal128 source) { } }); - converterRegistry.addConverter(new Converter() { + converterRegistry.addConverter(new Converter() { @Override public Decimal128 convert(BigInteger source) { return new Decimal128(new BigDecimal(source.toString())); @@ -262,12 +296,13 @@ public Decimal128 convert(BigInteger source) { /** * Check whether a type is a native mongo type that can be stored by the mongo driver without conversion. + * * @param clazz The class to check. * @return true if no conversion is required and the type can be stored natively. */ public static boolean isMongoNativeType(Class clazz) { return MongoMappingContext.MONGO_NATIVE_TYPES.contains(clazz.getName()) || - Bson.class.isAssignableFrom(clazz.getClass()) ; + Bson.class.isAssignableFrom(clazz.getClass()); } public static String getDefaultDatabaseName(PropertyResolver configuration) { @@ -275,15 +310,58 @@ public static String getDefaultDatabaseName(PropertyResolver configuration) { if (connectionString != null) { String database = new ConnectionString(connectionString).getDatabase(); - if(database != null) { + if (database != null) { return database; } } return configuration.getProperty(MongoSettings.SETTING_DATABASE_NAME, "test"); } + private boolean hasCodecForType(Class propType) { + if (hasCodecCache.containsKey(propType)) { + return hasCodecCache.get(propType); + } else { + Boolean hasCodec; + try { + hasCodec = codecRegistry.get(propType) != null; + } catch (CodecConfigurationException e) { + hasCodec = false; + } + hasCodecCache.put(propType, hasCodec); + return hasCodec; + } + } + + protected void registerMongoTypes() { + MappingFactory mappingFactory = getMappingFactory(); + mappingFactory.registerCustomType(new GeometryCollectionType()); + mappingFactory.registerCustomType(new PointType()); + mappingFactory.registerCustomType(new PolygonType()); + mappingFactory.registerCustomType(new LineStringType()); + mappingFactory.registerCustomType(new MultiLineStringType()); + mappingFactory.registerCustomType(new MultiPointType()); + mappingFactory.registerCustomType(new MultiPolygonType()); + mappingFactory.registerCustomType(new ShapeType()); + mappingFactory.registerCustomType(new BoxType()); + mappingFactory.registerCustomType(new CircleType()); + mappingFactory.registerCustomType(new EnumType()); + } + + @Override + protected MappingFactory createDocumentMappingFactory(Closure defaultMapping) { + MongoDocumentMappingFactory mongoDocumentMappingFactory = new MongoDocumentMappingFactory(); + mongoDocumentMappingFactory.setDefaultMapping(defaultMapping); + return mongoDocumentMappingFactory; + } + + @Override + public PersistentEntity createEmbeddedEntity(Class type) { + return new DocumentEmbeddedPersistentEntity(type, this); + } + private final class MongoDocumentMappingFactory extends AbstractGormMappingFactory { + @Override protected Class getPropertyMappedFormType() { return MongoAttribute.class; @@ -294,7 +372,6 @@ protected Class getEntityMappedFormType() { return MongoCollection.class; } - @Override public Identity createIdentity(PersistentEntity owner, MappingContext context, PropertyDescriptor pd) { Identity identity = super.createIdentity(owner, context, pd); @@ -309,75 +386,33 @@ public boolean isCustomType(Class propertyType) { @Override public Custom createCustom(PersistentEntity owner, MappingContext context, final PropertyDescriptor pd) { - if(hasCodecForType(pd.getPropertyType())) { + if (hasCodecForType(pd.getPropertyType())) { CodecCustomTypeMarshaller customTypeMarshaller = new CodecCustomTypeMarshaller(codecRegistry.get(pd.getPropertyType()), MongoMappingContext.this); return new Custom(owner, context, pd, customTypeMarshaller) { PropertyMapping propertyMapping = createPropertyMapping(this, owner); + public PropertyMapping getMapping() { return propertyMapping; } }; - } - else { + } else { return super.createCustom(owner, context, pd); } } @Override public boolean isSimpleType(Class propType) { - if (propType == null) return false; + if (propType == null) { + return false; + } if (propType.isArray()) { return isSimpleType(propType.getComponentType()) || super.isSimpleType(propType); } - return isMongoNativeType(propType) || super.isSimpleType(propType); - } - } - - private boolean hasCodecForType(Class propType) { - if(hasCodecCache.containsKey(propType)) { - return hasCodecCache.get(propType); - } - else { - Boolean hasCodec; - try { - hasCodec = codecRegistry.get(propType) != null; - } catch (CodecConfigurationException e) { - hasCodec = false; - } - hasCodecCache.put(propType, hasCodec); - return hasCodec; + return isMongoNativeType(propType) || super.isSimpleType(propType); } } - - protected void registerMongoTypes() { - MappingFactory mappingFactory = getMappingFactory(); - mappingFactory.registerCustomType(new GeometryCollectionType()); - mappingFactory.registerCustomType(new PointType()); - mappingFactory.registerCustomType(new PolygonType()); - mappingFactory.registerCustomType(new LineStringType()); - mappingFactory.registerCustomType(new MultiLineStringType()); - mappingFactory.registerCustomType(new MultiPointType()); - mappingFactory.registerCustomType(new MultiPolygonType()); - mappingFactory.registerCustomType(new ShapeType()); - mappingFactory.registerCustomType(new BoxType()); - mappingFactory.registerCustomType(new CircleType()); - mappingFactory.registerCustomType(new EnumType()); - } - - @Override - protected MappingFactory createDocumentMappingFactory(Closure defaultMapping) { - MongoDocumentMappingFactory mongoDocumentMappingFactory = new MongoDocumentMappingFactory(); - mongoDocumentMappingFactory.setDefaultMapping(defaultMapping); - return mongoDocumentMappingFactory; - } - - @Override - public PersistentEntity createEmbeddedEntity(Class type) { - return new DocumentEmbeddedPersistentEntity(type, this); - } - - class DocumentEmbeddedPersistentEntity extends EmbeddedPersistentEntity { + static class DocumentEmbeddedPersistentEntity extends EmbeddedPersistentEntity { private DocumentCollectionMapping classMapping; @@ -397,15 +432,17 @@ public ClassMapping getMapping() { } public class DocumentCollectionMapping extends AbstractClassMapping { + private Collection mappedForm; public DocumentCollectionMapping(PersistentEntity entity, MappingContext context) { super(entity, context); this.mappedForm = (Collection) context.getMappingFactory().createMappedForm(DocumentEmbeddedPersistentEntity.this); } + @Override public Collection getMappedForm() { - return mappedForm ; + return mappedForm; } } } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoSettings.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoSettings.groovy index 9ae721c2227..1809ebb2379 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoSettings.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/config/MongoSettings.groovy @@ -28,6 +28,7 @@ import org.grails.datastore.mapping.config.Settings * @since 6.0 */ interface MongoSettings extends Settings { + /** * The default database name if none is specified */ diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/connections/AbstractMongoConnectionSourceSettings.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/connections/AbstractMongoConnectionSourceSettings.groovy index c78dae6909b..c25ad072a1f 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/connections/AbstractMongoConnectionSourceSettings.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/connections/AbstractMongoConnectionSourceSettings.groovy @@ -105,10 +105,9 @@ abstract class AbstractMongoConnectionSourceSettings extends ConnectionSourceSet * @return Obtain the final URL whether from the connection string or the host/port setting */ ConnectionString getUrl() { - if(connectionString != null) { + if (connectionString != null) { return connectionString - } - else { + } else { String uAndP = username && password ? "$username:$password@" : '' String portStr = port ? ":$port" : '' return new ConnectionString("mongodb://${uAndP}${host}${portStr}/$database") @@ -126,10 +125,9 @@ abstract class AbstractMongoConnectionSourceSettings extends ConnectionSourceSet * @return Obtain the database name */ String getDatabase() { - if(connectionString != null) { + if (connectionString != null) { return connectionString.database ?: databaseName - } - else { + } else { return databaseName } } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/connections/MongoConnectionSourceFactory.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/connections/MongoConnectionSourceFactory.groovy index c8ab47eaaa5..9ad15da9bef 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/connections/MongoConnectionSourceFactory.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/connections/MongoConnectionSourceFactory.groovy @@ -71,13 +71,13 @@ class MongoConnectionSourceFactory extends AbstractConnectionSourceFactory>) - if(this.codecRegistry != null) { + if (this.codecRegistry != null) { codecRegistry = CodecRegistries.fromRegistries(codecRegistry, this.codecRegistry) } settings.codecRegistry = codecRegistry @@ -104,7 +104,7 @@ class MongoConnectionSourceFactory extends AbstractConnectionSourceFactory{ +class MongoConnectionSourceSettingsBuilder extends ConfigurationBuilder { MongoClientSettings.Builder clientOptionsBuilder @@ -64,8 +64,8 @@ class MongoConnectionSourceSettingsBuilder extends ConfigurationBuilder { + private static final String CONNECTION_NAME = "name" MongoConnectionSources(ConnectionSource defaultConnectionSource, ConnectionSourceFactory connectionSourceFactory, PropertyResolver configuration) { @@ -50,11 +51,11 @@ class MongoConnectionSources extends InMemoryConnectionSources connectionSource) { MongoCollection mongoCollection = getConnectionsCollection(connectionSource) FindIterable findIterable = mongoCollection - .find() + .find() - for(Document d in findIterable) { + for (Document d in findIterable) { String connectionName = d.getString(CONNECTION_NAME) - if(connectionName) { + if (connectionName) { super.addConnectionSource(connectionName, DatastoreUtils.createPropertyResolver(d)) } } @@ -72,7 +73,7 @@ class MongoConnectionSources extends InMemoryConnectionSources addConnectionSource(String name, Map configuration) { + ConnectionSource addConnectionSource(String name, Map configuration) { return addConnectionSource(name, new Document(configuration)) } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/AbstractMongoObectEntityPersister.java b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/AbstractMongoObectEntityPersister.java index 5fe325e3c46..8166832a408 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/AbstractMongoObectEntityPersister.java +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/AbstractMongoObectEntityPersister.java @@ -16,14 +16,21 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.mongo.engine; import com.mongodb.DBRef; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.core.SessionImplementor; -import org.grails.datastore.mapping.engine.*; -import org.grails.datastore.mapping.model.*; +import org.grails.datastore.mapping.engine.AssociationIndexer; +import org.grails.datastore.mapping.engine.EntityAccess; +import org.grails.datastore.mapping.engine.NativeEntryEntityPersister; +import org.grails.datastore.mapping.engine.Persister; +import org.grails.datastore.mapping.engine.PropertyValueIndexer; +import org.grails.datastore.mapping.model.EmbeddedPersistentEntity; +import org.grails.datastore.mapping.model.MappingContext; +import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.model.PersistentProperty; +import org.grails.datastore.mapping.model.PropertyMapping; import org.grails.datastore.mapping.model.types.Association; import org.grails.datastore.mapping.model.types.Identity; import org.grails.datastore.mapping.model.types.ManyToMany; @@ -36,22 +43,30 @@ import org.springframework.core.convert.ConversionService; import java.io.Serializable; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; /** * Abstract implementation of MongoDB mongo object mapping entity persister. - * + *

* This entity persister converts to and from MongoDB BSON object types (either Document or DBObject) * * @author Graeme Rocher * @since 5.0 */ public abstract class AbstractMongoObectEntityPersister extends NativeEntryEntityPersister { + public static final String INSTANCE_PREFIX = "instance:"; public static final String MONGO_ID_FIELD = "_id"; public static final String MONGO_CLASS_FIELD = "_class"; protected static final String NEXT_ID_SUFFIX = ".next_id"; - static Logger log = LoggerFactory.getLogger(AbstractMongoObectEntityPersister.class); + static final Logger LOG = LoggerFactory.getLogger(AbstractMongoObectEntityPersister.class); protected boolean hasNumericalIdentifier = false; protected boolean hasStringIdentifier = false; @@ -76,7 +91,6 @@ public String getEntityFamily() { return getMongoSession().getCollectionName(getPersistentEntity()); } - public MongoSession getMongoSession() { return (MongoSession) getSession(); } @@ -90,7 +104,6 @@ public AssociationIndexer getAssociationIndexer(T nativeEntry, Association assoc return new MongoAssociationIndexer(nativeEntry, association, (MongoSession) session); } - @Override public PropertyValueIndexer getPropertyIndexer(PersistentProperty property) { // We don't need to implement this for Mongo since Mongo automatically creates indexes for us @@ -103,13 +116,13 @@ public boolean isDirty(Object instance, Object entry) { return true; } - T dbo = (T)entry; + T dbo = (T) entry; PersistentEntity entity = getPersistentEntity(); EntityAccess entityAccess = createEntityAccess(entity, instance, dbo); - T cached = (T)((SessionImplementor)getSession()).getCachedEntry( - entity, (Serializable)entityAccess.getIdentifier(), true); + T cached = (T) ((SessionImplementor) getSession()).getCachedEntry( + entity, (Serializable) entityAccess.getIdentifier(), true); return !dbo.equals(cached); } @@ -133,7 +146,6 @@ protected void setEmbedded(T nativeEntry, String key, T embeddedEntry) { getValueRetrievalStrategy().setValue(nativeEntry, key, embeddedEntry); } - @Override protected void cascadeDeleteCollection(EntityAccess entityAccess, Association association) { Object propValue = entityAccess.getProperty(association.getName()); @@ -145,11 +157,11 @@ protected void cascadeDeleteCollection(EntityAccess entityAccess, Association as for (Iterator iter = collection.iterator(); iter.hasNext(); ) { Object child = iter.next(); if (child == null) { - log.warn("Encountered a null associated reference while cascade-deleting '{}' as part of {} (ID {})", + LOG.warn("Encountered a null associated reference while cascade-deleting '{}' as part of {} (ID {})", association.getReferencedPropertyName(), entityAccess.getEntity().getClass().getName(), entityAccess.getIdentifier()); continue; } - if(persister == null) { + if (persister == null) { persister = session.getPersister(child); } persister.delete(child); @@ -192,6 +204,7 @@ protected void setEmbeddedCollectionKeys(Association association, EntityAccess e } getValueRetrievalStrategy().setValue(embeddedEntry, association.getName(), dbRefs); } + /** * Implementors who want to support one-to-many associations embedded should implement this method * @@ -215,11 +228,9 @@ protected List loadEmbeddedCollectionKeys(Association association, EntityAccess if (o instanceof DBRef) { DBRef dbref = (DBRef) o; keys.add(dbref.getId()); - } - else if (o != null) { + } else if (o != null) { keys.add(o); - } - else { + } else { keys.add(null); } } @@ -244,8 +255,7 @@ protected List retrieveAllEntities(PersistentEntity persistentEntity, } query.in(identity.getName(), actualKeys); - } - else { + } else { List keyList = new ArrayList(); for (Serializable key : keys) { keyList.add(key); @@ -294,14 +304,11 @@ protected void refreshObjectStateFromNativeEntry(PersistentEntity persistentEnti if (isEmbedded) { Object id = getValueRetrievalStrategy().getValue(nativeEntry, MONGO_ID_FIELD); super.refreshObjectStateFromNativeEntry(persistentEntity, obj, (Serializable) id, nativeEntry, isEmbedded); - } - else { + } else { super.refreshObjectStateFromNativeEntry(persistentEntity, obj, nativeKey, nativeEntry, isEmbedded); } } - - @Override protected Object getEntryValue(T nativeEntry, String property) { Object value = getValueRetrievalStrategy().getValue(nativeEntry, property); @@ -341,7 +348,6 @@ protected PersistentEntity discriminatePersistentEntity(PersistentEntity persist return super.discriminatePersistentEntity(persistentEntity, nativeEntry); } - protected abstract String getCollectionName(PersistentEntity persistentEntity, T nativeEntry); protected boolean isReference(Association association) { @@ -358,7 +364,7 @@ protected boolean isReference(Association association) { @Override protected Collection getManyToManyKeys(PersistentEntity persistentEntity, Object object, Serializable nativeKey, T nativeEntry, ManyToMany manyToMany) { - return (Collection)getValueRetrievalStrategy().getValue(nativeEntry, manyToMany.getName() + "_$$manyToManyIds"); + return (Collection) getValueRetrievalStrategy().getValue(nativeEntry, manyToMany.getName() + "_$$manyToManyIds"); } @Override @@ -371,8 +377,7 @@ protected void setManyToMany(PersistentEntity persistentEntity, Object obj, for (Object o : associatedObjects) { if (o == null) { ids.add(null); - } - else { + } else { PersistentEntity childPersistentEntity = getMappingContext().getPersistentEntity(o.getClass().getName()); EntityAccess entityAccess = createEntityAccess(childPersistentEntity, o); @@ -396,12 +401,14 @@ protected void setManyToMany(PersistentEntity persistentEntity, Object obj, * @param The native type */ static interface ValueRetrievalStrategy { + Object getValue(T t, String name); void setValue(T t, String name, Object value); } protected class MongoAssociationIndexer implements AssociationIndexer { + private T nativeEntry; private Association association; private MongoSession session; @@ -427,8 +434,7 @@ public void preIndex(final Object primaryKey, final List foreignKeys) { for (Object foreignKey : foreignKeys) { if (isReference) { dbRefs.add(new DBRef(getCollectionName(association.getAssociatedEntity()), foreignKey)); - } - else { + } else { dbRefs.add(foreignKey); } } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/MongoCodecEntityPersister.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/MongoCodecEntityPersister.groovy index 9b3296c5d77..0e7d2014602 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/MongoCodecEntityPersister.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/MongoCodecEntityPersister.groovy @@ -24,6 +24,7 @@ import com.mongodb.client.model.FindOneAndUpdateOptions import com.mongodb.client.model.ReturnDocument import grails.gorm.DetachedCriteria import groovy.transform.CompileStatic +import jakarta.persistence.CascadeType import org.bson.Document import org.bson.types.ObjectId import org.grails.datastore.mapping.cache.TPCacheAdapterRepository @@ -41,8 +42,16 @@ import org.grails.datastore.mapping.dirty.checking.DirtyCheckingSupport import org.grails.datastore.mapping.engine.EntityAccess import org.grails.datastore.mapping.engine.ThirdPartyCacheEntityPersister import org.grails.datastore.mapping.engine.internal.MappingUtils -import org.grails.datastore.mapping.model.* -import org.grails.datastore.mapping.model.types.* +import org.grails.datastore.mapping.model.ClassMapping +import org.grails.datastore.mapping.model.IdentityMapping +import org.grails.datastore.mapping.model.MappingContext +import org.grails.datastore.mapping.model.PersistentEntity +import org.grails.datastore.mapping.model.PersistentProperty +import org.grails.datastore.mapping.model.types.Basic +import org.grails.datastore.mapping.model.types.Embedded +import org.grails.datastore.mapping.model.types.ManyToMany +import org.grails.datastore.mapping.model.types.OneToMany +import org.grails.datastore.mapping.model.types.ToOne import org.grails.datastore.mapping.mongo.MongoCodecSession import org.grails.datastore.mapping.mongo.MongoConstants import org.grails.datastore.mapping.mongo.MongoDatastore @@ -55,8 +64,6 @@ import org.springframework.context.ApplicationEventPublisher import org.springframework.dao.CannotAcquireLockException import org.springframework.dao.DataIntegrityViolationException -import jakarta.persistence.CascadeType - /** * An {@org.grails.datastore.mapping.engine.EntityPersister} that uses the MongoDB 3.0 {@link org.bson.codecs.configuration.CodecRegistry} infrastructure * @@ -69,11 +76,11 @@ class MongoCodecEntityPersister extends ThirdPartyCacheEntityPersister { public static final String INSTANCE_PREFIX = "instance:" public static final String MONGO_ID_FIELD = MongoConstants.MONGO_ID_FIELD public static final String MONGO_CLASS_FIELD = MongoConstants.MONGO_CLASS_FIELD - protected static final String NEXT_ID = "next_id" - protected static final String NEXT_ID_SUFFIX = ".$NEXT_ID" public static final String INC_OPERATOR = MongoConstants.INC_OPERATOR public static final String ASSIGNED_IDENTIFIER_MAPPING = MongoConstants.ASSIGNED_IDENTIFIER_MAPPING + protected static final String NEXT_ID_SUFFIX = ".$NEXT_ID" + protected static final String NEXT_ID = "next_id" protected final MongoCodecSession mongoSession protected final MongoDatastore mongoDatastore @@ -168,7 +175,6 @@ class MongoCodecEntityPersister extends ThirdPartyCacheEntityPersister { @Override protected Serializable persistEntity(PersistentEntity entity, Object obj, boolean isInsert) { - ProxyFactory proxyFactory = getProxyFactory() // if called internally, obj can potentially be a proxy, which won't work. obj = proxyFactory.unwrap(obj) @@ -181,7 +187,6 @@ class MongoCodecEntityPersister extends ThirdPartyCacheEntityPersister { return (Serializable) id } - final boolean idIsNull = id == null boolean isUpdate = !idIsNull && !isInsert def mongoCodecSession = mongoSession @@ -213,11 +218,13 @@ class MongoCodecEntityPersister extends ThirdPartyCacheEntityPersister { if (!isUpdate) { MongoCodecEntityPersister self = this mongoCodecSession.addPendingInsert(new PendingInsertAdapter(entity, id, obj, entityAccess) { + @Override void run() { if (!cancelInsert(entity, entityAccess)) { updateCaches(entity, obj, id) addCascadeOperation(new PendingOperationAdapter(entity, id, obj) { + @Override void run() { self.firePostInsertEvent(entity, entityAccess) @@ -230,11 +237,13 @@ class MongoCodecEntityPersister extends ThirdPartyCacheEntityPersister { }) } else { mongoCodecSession.addPendingUpdate(new PendingUpdateAdapter(entity, id, obj, entityAccess) { + @Override void run() { if (!cancelUpdate(entity, entityAccess)) { updateCaches(entity, obj, id) addCascadeOperation(new PendingOperationAdapter(entity, id, obj) { + @Override void run() { firePostUpdateEvent(entity, entityAccess) @@ -415,7 +424,6 @@ class MongoCodecEntityPersister extends ThirdPartyCacheEntityPersister { return objectId.toString() } - @Override protected void deleteEntity(PersistentEntity pe, Object obj) { @@ -431,12 +439,14 @@ class MongoCodecEntityPersister extends ThirdPartyCacheEntityPersister { if (id != null) { MongoCodecEntityPersister self = this mongoSession.addPendingDelete(new PendingDeleteAdapter(pe, id, obj) { + @Override void run() { def entityAccess = self.createEntityAccess(pe, obj) if (!self.cancelDelete(pe, entityAccess)) { mongoSession.clear(obj) addCascadeOperation(new PendingOperationAdapter(pe, id, obj) { + @Override void run() { self.firePostDeleteEvent pe, entityAccess @@ -534,7 +544,6 @@ class MongoCodecEntityPersister extends ThirdPartyCacheEntityPersister { return mongoCollection } - protected String getCollectionName(PersistentEntity pe) { mongoSession.getCollectionName(pe) } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/MongoEntityPersister.java b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/MongoEntityPersister.java index f988327b2d9..0aa0b266a20 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/MongoEntityPersister.java +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/MongoEntityPersister.java @@ -18,16 +18,7 @@ */ package org.grails.datastore.mapping.mongo.engine; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import com.mongodb.*; +import com.mongodb.DBObject; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.model.FindOneAndUpdateOptions; @@ -50,6 +41,15 @@ import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + /** * A {@link org.grails.datastore.mapping.engine.EntityPersister} implementation for the Mongo document store * @@ -76,22 +76,21 @@ public MongoEntityPersister(MappingContext mappingContext, PersistentEntity enti super(mappingContext, entity, mongoSession, publisher); } - @Override protected void loadEmbeddedCollection(EmbeddedCollection embeddedCollection, EntityAccess ea, Object embeddedInstances, String propertyKey) { - if(Map.class.isAssignableFrom(embeddedCollection.getType())) { - if(embeddedInstances instanceof Document) { + if (Map.class.isAssignableFrom(embeddedCollection.getType())) { + if (embeddedInstances instanceof Document) { Map instances = new HashMap(); - Document embedded = (Document)embeddedInstances; + Document embedded = (Document) embeddedInstances; for (String key : embedded.keySet()) { Object o = embedded.get(key); - if(o instanceof Document) { + if (o instanceof Document) { Document nativeEntry = (Document) o; Object instance = createObjectFromEmbeddedNativeEntry(embeddedCollection.getAssociatedEntity(), nativeEntry); - SessionImplementor si = (SessionImplementor)getSession(); + SessionImplementor si = (SessionImplementor) getSession(); si.cacheEntry(embeddedCollection.getAssociatedEntity(), createEmbeddedCacheEntryKey(instance), nativeEntry); instances.put(key, instance); } @@ -99,18 +98,17 @@ protected void loadEmbeddedCollection(EmbeddedCollection embeddedCollection, } ea.setProperty(embeddedCollection.getName(), instances); } - } - else { + } else { Collection instances = MappingUtils.createConcreteCollection(embeddedCollection.getType()); if (embeddedInstances instanceof Collection) { - Collection coll = (Collection)embeddedInstances; + Collection coll = (Collection) embeddedInstances; for (Object dbo : coll) { if (dbo instanceof Document) { - Document nativeEntry = (Document)dbo; + Document nativeEntry = (Document) dbo; Object instance = createObjectFromEmbeddedNativeEntry(embeddedCollection.getAssociatedEntity(), nativeEntry); - SessionImplementor si = (SessionImplementor)getSession(); + SessionImplementor si = (SessionImplementor) getSession(); si.cacheEntry(embeddedCollection.getAssociatedEntity(), createEmbeddedCacheEntryKey(instance), nativeEntry); instances.add(instance); } @@ -130,20 +128,18 @@ public Query createQuery() { return new MongoQuery((MongoSession) getSession(), getPersistentEntity()); } - @Override protected void deleteEntry(String family, final Object key, final Object entry) { final MongoSession session = (MongoSession) getSession(); session. - addPendingDelete(new PendingDeleteAdapter(getPersistentEntity(), key, entry) { - public void run() { - session.clear(entry); - } - }); + addPendingDelete(new PendingDeleteAdapter(getPersistentEntity(), key, entry) { + public void run() { + session.clear(entry); + } + }); } - @Override protected Object generateIdentifier(final PersistentEntity persistentEntity, final Document nativeEntry) { @@ -156,11 +152,10 @@ protected Object generateIdentifier(final PersistentEntity persistentEntity, fin final MongoClient client = mongoSession .getNativeInterface(); - final MongoCollection dbCollection = client + final MongoCollection dbCollection = client .getDatabase(mongoSession.getDatabase(persistentEntity)) .getCollection(collectionName + NEXT_ID_SUFFIX); - int attempts = 0; while (true) { @@ -175,7 +170,7 @@ protected Object generateIdentifier(final PersistentEntity persistentEntity, fin } else { attempts++; if (attempts > 3) { - throw new IdentityGenerationException("Unable to generate identity for ["+persistentEntity.getName()+"] using findAndModify after 3 attempts"); + throw new IdentityGenerationException("Unable to generate identity for [" + persistentEntity.getName() + "] using findAndModify after 3 attempts"); } } } @@ -194,21 +189,18 @@ protected Object generateIdentifier(final PersistentEntity persistentEntity, fin return stringId; } - @Override protected Document createNewEntry(String family, Object instance) { - SessionImplementor si = (SessionImplementor)getSession(); + SessionImplementor si = (SessionImplementor) getSession(); Document dbo = si.getCachedEntry(getPersistentEntity(), createInstanceCacheEntryKey(instance)); - if(dbo != null) { + if (dbo != null) { return dbo; - } - else { + } else { return super.createNewEntry(family, instance); } } - @Override protected Document createNewEntry(String family) { Document dbo = new Document(); @@ -220,14 +212,12 @@ protected Document createNewEntry(String family) { return dbo; } - @Override protected void setEntryValue(Document nativeEntry, String key, Object value) { MappingContext mappingContext = getMappingContext(); setDBObjectValue(nativeEntry, key, value, mappingContext); } - public static void setDBObjectValue(Document nativeEntry, String key, Object value, MappingContext mappingContext) { Object nativeValue = getSimpleNativePropertyValue(value, mappingContext); nativeEntry.put(key, nativeValue); @@ -236,7 +226,8 @@ public static void setDBObjectValue(Document nativeEntry, String key, Object val /** * Convert a value into a type suitable for use in Mongo. Collections and maps are converted recursively. The * mapping context is used for the conversion if possible, otherwise toString() is the eventual fallback. - * @param value The value to convert (or null) + * + * @param value The value to convert (or null) * @param mappingContext The mapping context. * @return The converted value (or null) */ @@ -258,16 +249,16 @@ public static Object getSimpleNativePropertyValue(Object value, MappingContext m } nativeValue = nativeColl; } else if (value instanceof Collection) { - Collection existingColl = (Collection)value; + Collection existingColl = (Collection) value; List nativeColl = new ArrayList(existingColl.size()); for (Object item : existingColl) { nativeColl.add(getSimpleNativePropertyValue(item, mappingContext)); } nativeValue = nativeColl; } else if (value instanceof Map) { - Map existingMap = (Map)value; + Map existingMap = (Map) value; Map newMap = new LinkedHashMap(); - for (Map.Entry entry :existingMap.entrySet()) { + for (Map.Entry entry : existingMap.entrySet()) { newMap.put(entry.getKey(), getSimpleNativePropertyValue(entry.getValue(), mappingContext)); } nativeValue = newMap; @@ -298,7 +289,6 @@ private static Object convertPrimitiveToNative(Object item, MappingContext mappi return nativeValue; } - @Override protected Document retrieveEntry(final PersistentEntity persistentEntity, String family, final Serializable key) { @@ -306,8 +296,8 @@ protected Document retrieveEntry(final PersistentEntity persistentEntity, final MongoCollection collection = mongoSession .getNativeInterface() - .getDatabase( mongoSession.getDatabase(persistentEntity)) - .getCollection( mongoSession.getCollectionName(persistentEntity )); + .getDatabase(mongoSession.getDatabase(persistentEntity)) + .getCollection(mongoSession.getCollectionName(persistentEntity)); return collection.find(createDBObjectWithKey(key)).limit(1).first(); } @@ -317,19 +307,19 @@ private Document removeNullEntries(Document nativeEntry) { if (o == null) { nativeEntry.remove(key); } else if (o instanceof Object[]) { - for (Object o2 : (Object[])o) { + for (Object o2 : (Object[]) o) { if (o2 instanceof Document) { - removeNullEntries((Document)o2); + removeNullEntries((Document) o2); } } } else if (o instanceof List) { - for (Object o2 : (List)o) { + for (Object o2 : (List) o) { if (o2 instanceof Document) { - removeNullEntries((Document)o2); + removeNullEntries((Document) o2); } } } else if (o instanceof Document) { - removeNullEntries((Document)o); + removeNullEntries((Document) o); } } return nativeEntry; @@ -348,8 +338,7 @@ protected String getCollectionName(PersistentEntity persistentEntity, Document n if (persistentEntity.isRoot()) { MongoSession mongoSession = (MongoSession) getSession(); collectionName = mongoSession.getCollectionName(persistentEntity); - } - else { + } else { MongoSession mongoSession = (MongoSession) getSession(); collectionName = mongoSession.getCollectionName(persistentEntity.getRootEntity()); } @@ -364,22 +353,23 @@ private Document modifyNullsToUnsets(Document nativeEntry) { if (o == null) { unsets.put(key, 1); } else if ("_id".equals(key)) { + // ignored } else if (o instanceof Object[]) { sets.put(key, o); - for (Object o2 : (Object[])o) { + for (Object o2 : (Object[]) o) { if (o2 instanceof Document) { - removeNullEntries((Document)o2); + removeNullEntries((Document) o2); } } } else if (o instanceof List) { sets.put(key, o); - for (Object o2 : (List)o) { + for (Object o2 : (List) o) { if (o2 instanceof Document) { - removeNullEntries((Document)o2); + removeNullEntries((Document) o2); } } } else if (o instanceof DBObject) { - sets.put(key, removeNullEntries((Document)o)); + sets.put(key, removeNullEntries((Document) o)); } else { sets.put(key, o); } @@ -408,7 +398,7 @@ protected void deleteEntries(String family, final List keys) { final MongoCollection dbCollection = getMongoSession().getCollection(getPersistentEntity()); MongoSession mongoSession = (MongoSession) getSession(); - MongoQuery query = (MongoQuery)mongoSession.createQuery(getPersistentEntity().getJavaClass()); + MongoQuery query = (MongoQuery) mongoSession.createQuery(getPersistentEntity().getJavaClass()); query.in(getPersistentEntity().getIdentity().getName(), keys); dbCollection.deleteMany(query.getMongoQuery()); @@ -419,17 +409,14 @@ protected Document createDBObjectWithKey(Object key) { Document dbo = new Document(); if (hasNumericalIdentifier || hasStringIdentifier) { dbo.put(MONGO_ID_FIELD, key); - } - else { + } else { if (key instanceof ObjectId) { dbo.put(MONGO_ID_FIELD, key); - } - else { + } else { dbo.put(MONGO_ID_FIELD, new ObjectId(key.toString())); } } return dbo; } - } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/codecs/PersistentEntityCodec.groovy b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/codecs/PersistentEntityCodec.groovy index 170385af534..86fdcf32dae 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/codecs/PersistentEntityCodec.groovy +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/codecs/PersistentEntityCodec.groovy @@ -20,7 +20,16 @@ package org.grails.datastore.mapping.mongo.engine.codecs import com.mongodb.DBRef import groovy.transform.CompileStatic -import org.bson.* +import jakarta.persistence.FetchType +import org.bson.BsonArray +import org.bson.BsonDocument +import org.bson.BsonDocumentWriter +import org.bson.BsonReader +import org.bson.BsonString +import org.bson.BsonType +import org.bson.BsonValue +import org.bson.BsonWriter +import org.bson.Document import org.bson.codecs.Codec import org.bson.codecs.DecoderContext import org.bson.codecs.EncoderContext @@ -52,9 +61,16 @@ import org.grails.datastore.mapping.engine.internal.MappingUtils import org.grails.datastore.mapping.model.EmbeddedPersistentEntity import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.mapping.model.PropertyMapping import org.grails.datastore.mapping.model.config.GormProperties -import org.grails.datastore.mapping.model.types.* +import org.grails.datastore.mapping.model.types.Association +import org.grails.datastore.mapping.model.types.Embedded +import org.grails.datastore.mapping.model.types.EmbeddedCollection +import org.grails.datastore.mapping.model.types.Identity +import org.grails.datastore.mapping.model.types.ManyToMany +import org.grails.datastore.mapping.model.types.ManyToOne +import org.grails.datastore.mapping.model.types.OneToMany +import org.grails.datastore.mapping.model.types.OneToOne +import org.grails.datastore.mapping.model.types.ToOne import org.grails.datastore.mapping.mongo.MongoCodecSession import org.grails.datastore.mapping.mongo.MongoConstants import org.grails.datastore.mapping.mongo.MongoDatastore @@ -63,7 +79,6 @@ import org.grails.datastore.mapping.mongo.engine.MongoCodecEntityPersister import org.grails.datastore.mapping.query.Query import org.grails.datastore.mapping.reflect.FieldEntityAccess -import jakarta.persistence.FetchType /** * A MongoDB codec for persisting {@link PersistentEntity} instances * @@ -72,15 +87,17 @@ import jakarta.persistence.FetchType */ @CompileStatic class PersistentEntityCodec extends BsonPersistentEntityCodec { - private static final String BLANK_STRING = "" + public static final String MONGO_SET_OPERATOR = '$set' public static final String MONGO_UNSET_OPERATOR = '$unset' - public static final String DB_REF_ID_FIELD = '$id' public static final String SCHEMALESS_ATTRIBUTES = "schemaless.attributes" + private static final String BLANK_STRING = "" + static { registerEncoder(Identity, (PropertyEncoder) new IdentityEncoder() { + @Override protected String getIdentifierName(Identity property) { MongoConstants.MONGO_ID_FIELD @@ -88,6 +105,7 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { }) registerEncoder(Embedded, (PropertyEncoder) new EmbeddedEncoder() { + @Override protected BsonPersistentEntityCodec createEmbeddedEntityCodec(CodecRegistry codecRegistry, PersistentEntity associatedEntity) { return new PersistentEntityCodec(codecRegistry, associatedEntity) @@ -95,6 +113,7 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { }) registerDecoder(Embedded, (PropertyDecoder) new EmbeddedDecoder() { + @Override protected BsonPersistentEntityCodec createEmbeddedEntityCodec(CodecRegistry codecRegistry, PersistentEntity associatedEntity) { return new PersistentEntityCodec(codecRegistry, associatedEntity) @@ -102,6 +121,7 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { }) registerEncoder(EmbeddedCollection, (PropertyEncoder) new EmbeddedCollectionEncoder() { + @Override protected BsonPersistentEntityCodec createEmbeddedEntityCodec(CodecRegistry codecRegistry, PersistentEntity associatedEntity) { return new PersistentEntityCodec(codecRegistry, associatedEntity) @@ -109,6 +129,7 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { }) registerDecoder(EmbeddedCollection, (PropertyDecoder) new EmbeddedCollectionDecoder() { + @Override protected BsonPersistentEntityCodec createEmbeddedEntityCodec(CodecRegistry codecRegistry, PersistentEntity associatedEntity) { return new PersistentEntityCodec(codecRegistry, associatedEntity) @@ -117,10 +138,10 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { registerEncoder(OneToOne, new ToOneEncoder()) registerDecoder(OneToOne, new ToOneDecoder()) - registerEncoder(ManyToOne,new ToOneEncoder()) - registerDecoder(ManyToOne,new ToOneDecoder()) + registerEncoder(ManyToOne, new ToOneEncoder()) + registerDecoder(ManyToOne, new ToOneDecoder()) registerEncoder(OneToMany, new OneToManyEncoder()) - registerDecoder(OneToMany,new OneToManyDecoder()) + registerDecoder(OneToMany, new OneToManyDecoder()) registerEncoder(ManyToMany, new OneToManyEncoder()) registerDecoder(ManyToMany, new OneToManyDecoder()) } @@ -139,10 +160,9 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { Closure callback = { Session session -> decodeAssociations(session, access) } - if(entity instanceof EmbeddedPersistentEntity) { - callback( AbstractDatastore.retrieveSession(MongoDatastore) ) - } - else { + if (entity instanceof EmbeddedPersistentEntity) { + callback(AbstractDatastore.retrieveSession(MongoDatastore)) + } else { GormEnhancer.findStaticApi(entity.javaClass).withSession callback } } @@ -156,10 +176,9 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { } return cachedInstance } - if(entity instanceof EmbeddedPersistentEntity) { - callback( AbstractDatastore.retrieveSession(MongoDatastore) ) - } - else { + if (entity instanceof EmbeddedPersistentEntity) { + callback(AbstractDatastore.retrieveSession(MongoDatastore)) + } else { GormEnhancer.findStaticApi(entity.javaClass).withSession callback } } @@ -179,7 +198,6 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { query.eq(association.inverseSide.name, access.identifier) .projections().id() - def id = query.singleResult() boolean lazy = ((Property) association.mapping.mappedForm).fetchStrategy == FetchType.LAZY access.setPropertyNoConversion( @@ -204,95 +222,87 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { def entity = access.persistentEntity def proxyFactory = mappingContext.proxyFactory - if( proxyFactory.isProxy(value) ) { + if (proxyFactory.isProxy(value)) { value = proxyFactory.unwrap(value) } - if(value instanceof DirtyCheckable) { + if (value instanceof DirtyCheckable) { def sets = new BsonDocument() def unsets = new Document() BsonWriter writer = new BsonDocumentWriter(sets) writer.writeStartDocument() - DirtyCheckable dirty = (DirtyCheckable)value + DirtyCheckable dirty = (DirtyCheckable) value Set processed = [] def dirtyProperties = new ArrayList(dirty.listDirtyPropertyNames()) boolean isNew = dirtyProperties.isEmpty() && dirty.hasChanged() def isVersioned = entity.isVersioned() - if(isNew) { + if (isNew) { // if it is new it can only be an embedded entity that has now been updated // so we get all properties dirtyProperties = entity.persistentPropertyNames - if(!entity.isRoot()) { + if (!entity.isRoot()) { sets.put(MongoConstants.MONGO_CLASS_FIELD, new BsonString(entity.discriminator)) } - if(isVersioned) { + if (isVersioned) { EntityPersister.incrementEntityVersion(access) } - } - else { + } else { // schedule lastUpdated if necessary - if( entity.getPropertyByName(GormProperties.LAST_UPDATED) != null) { + if (entity.getPropertyByName(GormProperties.LAST_UPDATED) != null) { dirtyProperties.add(GormProperties.LAST_UPDATED) } } - - for(propertyName in dirtyProperties) { + for (propertyName in dirtyProperties) { def prop = entity.getPropertyByName(propertyName) - if(prop != null) { + if (prop != null) { processed << propertyName Object v = access.getProperty(prop.name) if (v != null) { - if(prop instanceof Embedded) { - encodeEmbeddedUpdate(sets,unsets, (Association)prop, v) - } - else if(prop instanceof EmbeddedCollection) { - encodeEmbeddedCollectionUpdate(access, sets, unsets, (Association)prop, v) - } - else { + if (prop instanceof Embedded) { + encodeEmbeddedUpdate(sets, unsets, (Association) prop, v) + } else if (prop instanceof EmbeddedCollection) { + encodeEmbeddedCollectionUpdate(access, sets, unsets, (Association) prop, v) + } else { def propKind = prop.getClass().superclass - PropertyEncoder propertyEncoder = getPropertyEncoder((Class)propKind) + PropertyEncoder propertyEncoder = getPropertyEncoder((Class) propKind) propertyEncoder?.encode(writer, prop, v, access, encoderContext, codecRegistry) } - } - else if(embedded || !isNew) { + } else if (embedded || !isNew) { unsets[prop.name] = BLANK_STRING } } } - if(value instanceof DynamicAttributes) { + if (value instanceof DynamicAttributes) { Map attributes = ((DynamicAttributes) value).attributes() - for(attr in attributes.keySet()) { + for (attr in attributes.keySet()) { Object v = attributes.get(attr) - if(v == null) { - unsets.put(attr,BLANK_STRING) - } - else { + if (v == null) { + unsets.put(attr, BLANK_STRING) + } else { writer.writeName(attr) - Codec codec = (Codec)codecRegistry.get(v.getClass()) + Codec codec = (Codec) codecRegistry.get(v.getClass()) codec.encode(writer, v, encoderContext) } } - } - else { + } else { GormEnhancer.findStaticApi(entity.javaClass).withSession { Session mongoSession -> - if(mongoSession != null) { - Document schemaless = (Document)mongoSession.getAttribute(value, SCHEMALESS_ATTRIBUTES) - if(schemaless != null) { - for(name in schemaless.keySet()) { + if (mongoSession != null) { + Document schemaless = (Document) mongoSession.getAttribute(value, SCHEMALESS_ATTRIBUTES) + if (schemaless != null) { + for (name in schemaless.keySet()) { def v = schemaless.get(name) - if(v == null) { - unsets.put(name,BLANK_STRING) - } - else { + if (v == null) { + unsets.put(name, BLANK_STRING) + } else { writer.writeName(name) - Codec codec = (Codec)codecRegistry.get(v.getClass()) + Codec codec = (Codec) codecRegistry.get(v.getClass()) codec.encode(writer, v, encoderContext) } } @@ -302,39 +312,36 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { } - for(association in entity.associations) { - if(processed.contains( association.name )) continue - if(association instanceof OneToMany) { + for (association in entity.associations) { + if (processed.contains(association.name)) continue + if (association instanceof OneToMany) { def v = access.getProperty(association.name) if (v != null) { // TODO: handle unprocessed association } - } - else if(association instanceof ToOne) { + } else if (association instanceof ToOne) { def v = access.getProperty(association.name) - if( v instanceof DirtyCheckable ) { - if(((DirtyCheckable)v).hasChanged()) { - if(association instanceof Embedded) { + if (v instanceof DirtyCheckable) { + if (((DirtyCheckable) v).hasChanged()) { + if (association instanceof Embedded) { encodeEmbeddedUpdate(sets, unsets, association, v) } } } - } - else if(association instanceof EmbeddedCollection) { + } else if (association instanceof EmbeddedCollection) { def v = access.getProperty(association.name) - if( v instanceof DirtyCheckableCollection ) { - if(((DirtyCheckableCollection)v).hasChanged()) { + if (v instanceof DirtyCheckableCollection) { + if (((DirtyCheckableCollection) v).hasChanged()) { encodeEmbeddedCollectionUpdate(access, sets, unsets, association, v) } } } } - boolean hasSets = !sets.isEmpty() boolean hasUnsets = !unsets.isEmpty() - if(hasSets && isVersioned) { + if (hasSets && isVersioned) { def version = entity.version def propKind = version.getClass().superclass MongoCodecEntityPersister.incrementEntityVersion(access) @@ -344,14 +351,13 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { writer.writeEndDocument() - if(hasSets) { + if (hasSets) { update.put(MONGO_SET_OPERATOR, sets) } - if(hasUnsets) { - update.put(MONGO_UNSET_OPERATOR,unsets) + if (hasUnsets) { + update.put(MONGO_UNSET_OPERATOR, unsets) } - } - else { + } else { // TODO: Support non-dirty checkable objects? } @@ -364,13 +370,13 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { } protected void encodeEmbeddedCollectionUpdate(EntityAccess parentAccess, BsonDocument sets, Document unsets, Association association, Object v) { - if(v instanceof Collection) { - if((v instanceof DirtyCheckableCollection) && !((DirtyCheckableCollection)v).hasChangedSize()) { + if (v instanceof Collection) { + if ((v instanceof DirtyCheckableCollection) && !((DirtyCheckableCollection) v).hasChangedSize()) { int i = 0 - for(o in (v as Collection)) { + for (o in (v as Collection)) { def embeddedUpdate = encodeUpdate(o, createEntityAccess(o), EncoderContext.builder().build(), true) def embeddedSets = embeddedUpdate.get(MONGO_SET_OPERATOR) - if(embeddedSets != null) { + if (embeddedSets != null) { def map = (Map) embeddedSets for (key in map.keySet()) { @@ -378,7 +384,7 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { } } def embeddedUnsets = embeddedUpdate.get(MONGO_UNSET_OPERATOR) - if(embeddedUnsets) { + if (embeddedUnsets) { def map = (Map) embeddedUnsets for (key in map.keySet()) { unsets.put("${association.name}.${i}.$key".toString(), BLANK_STRING) @@ -386,17 +392,16 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { } i++ } - } - else { + } else { // if this is not a dirty checkable collection or the collection has changed size then a whole new collection has been // set so we overwrite existing def associatedEntity = association.associatedEntity def rootClass = associatedEntity.javaClass - PersistentEntityCodec entityCodec = (PersistentEntityCodec)codecRegistry.get(rootClass) + PersistentEntityCodec entityCodec = (PersistentEntityCodec) codecRegistry.get(rootClass) def inverseProperty = association.inverseSide - List documents =[] - for(o in v) { - if(o == null) { + List documents = [] + for (o in v) { + if (o == null) { documents << null continue } @@ -404,44 +409,44 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { PersistentEntityCodec codec = entityCodec def cls = o.getClass() - if(rootClass != cls) { + if (rootClass != cls) { // a subclass, so lookup correct codec entity = mappingContext.getPersistentEntity(cls.name) - if(entity == null) { - throw new DatastoreException("Value [$o] is not a valid type for association [$association]" ) + if (entity == null) { + throw new DatastoreException("Value [$o] is not a valid type for association [$association]") } - codec = (PersistentEntityCodec)codecRegistry.get(cls) + codec = (PersistentEntityCodec) codecRegistry.get(cls) } def ea = createEntityAccess(entity, o) - if(inverseProperty != null) { - if(inverseProperty instanceof ToOne) { - ea.setPropertyNoConversion( inverseProperty.name, parentAccess.entity) + if (inverseProperty != null) { + if (inverseProperty instanceof ToOne) { + ea.setPropertyNoConversion(inverseProperty.name, parentAccess.entity) } } def doc = new BsonDocument() def id = ea.identifier - codec.encode( new BsonDocumentWriter(doc), o, DEFAULT_ENCODER_CONTEXT, id != null ) - documents.add( doc ) + codec.encode(new BsonDocumentWriter(doc), o, DEFAULT_ENCODER_CONTEXT, id != null) + documents.add(doc) } def bsonArray = new BsonArray(documents) - sets.put( association.name, bsonArray) + sets.put(association.name, bsonArray) } - } - else { + } else { // TODO: Map handling } } + protected void encodeEmbeddedUpdate(BsonDocument sets, Document unsets, Association association, v) { - if (v instanceof DirtyCheckable ) { + if (v instanceof DirtyCheckable) { v.markDirty() } def embeddedUpdate = encodeUpdate(v, createEntityAccess(v), DEFAULT_ENCODER_CONTEXT, true) def embeddedSets = embeddedUpdate.get(MONGO_SET_OPERATOR) - if(embeddedSets != null) { + if (embeddedSets != null) { def map = (Map) embeddedSets for (key in map.keySet()) { @@ -450,7 +455,7 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { } def embeddedUnsets = embeddedUpdate.get(MONGO_UNSET_OPERATOR) - if(embeddedUnsets) { + if (embeddedUnsets) { def map = (Map) embeddedUnsets for (key in map.keySet()) { unsets.put("${association.name}.$key".toString(), BLANK_STRING) @@ -459,48 +464,45 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { } static class OneToManyDecoder implements PropertyDecoder { + @Override void decode(BsonReader reader, Association property, EntityAccess entityAccess, DecoderContext decoderContext, CodecRegistry codecRegistry) { def session = AbstractDatastore.retrieveSession(MongoDatastore) - if(property.isBidirectional() && !(property instanceof ManyToMany)) { + if (property.isBidirectional() && !(property instanceof ManyToMany)) { initializePersistentCollection(session, entityAccess, property) - } - else { + } else { def type = property.type def propertyName = property.name def listCodec = codecRegistry.get(List) def identifiers = listCodec.decode(reader, decoderContext) - MongoAttribute attr = (MongoAttribute)property.mapping.mappedForm - if(attr?.isReference()) { + MongoAttribute attr = (MongoAttribute) property.mapping.mappedForm + if (attr?.isReference()) { identifiers = identifiers.collect { - if(it instanceof DBRef) { - return ((DBRef)it).id - } - else if(it instanceof Map) { - return ((Map)it).get(DB_REF_ID_FIELD) + if (it instanceof DBRef) { + return ((DBRef) it).id + } else if (it instanceof Map) { + return ((Map) it).get(DB_REF_ID_FIELD) } return it } } def associatedType = property.associatedEntity.javaClass - if(SortedSet.isAssignableFrom(type)) { + if (SortedSet.isAssignableFrom(type)) { entityAccess.setPropertyNoConversion( propertyName, - new PersistentSortedSet( identifiers, associatedType, session) + new PersistentSortedSet(identifiers, associatedType, session) ) - } - else if(Set.isAssignableFrom(type)) { + } else if (Set.isAssignableFrom(type)) { entityAccess.setPropertyNoConversion( propertyName, - new PersistentSet( identifiers, associatedType, session) + new PersistentSet(identifiers, associatedType, session) ) - } - else { + } else { entityAccess.setPropertyNoConversion( propertyName, - new PersistentList( identifiers, associatedType, session) + new PersistentList(identifiers, associatedType, session) ) } } @@ -511,65 +513,63 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { def propertyName = property.name def identifier = (Serializable) entityAccess.identifier - if(SortedSet.isAssignableFrom(type)) { + if (SortedSet.isAssignableFrom(type)) { entityAccess.setPropertyNoConversion( propertyName, - new PersistentSortedSet( property, identifier, session) + new PersistentSortedSet(property, identifier, session) ) - } - else if(Set.isAssignableFrom(type)) { + } else if (Set.isAssignableFrom(type)) { entityAccess.setPropertyNoConversion( propertyName, - new PersistentSet( property, identifier, session) + new PersistentSet(property, identifier, session) ) - } - else { + } else { entityAccess.setPropertyNoConversion( propertyName, - new PersistentList( property, identifier, session) + new PersistentList(property, identifier, session) ) } } } + static class OneToManyEncoder implements PropertyEncoder { @Override void encode(BsonWriter writer, Association property, Object value, EntityAccess parentAccess, EncoderContext encoderContext, CodecRegistry codecRegistry) { boolean shouldEncodeIds = !property.isBidirectional() || (property instanceof ManyToMany) - MongoCodecSession mongoSession = (MongoCodecSession)AbstractDatastore.retrieveSession(MongoDatastore) - if(shouldEncodeIds) { + MongoCodecSession mongoSession = (MongoCodecSession) AbstractDatastore.retrieveSession(MongoDatastore) + if (shouldEncodeIds) { // if it is unidirectional we encode the values inside the current // document, otherwise nothing to do, encoding foreign key stored in inverse side def associatedEntity = property.associatedEntity - if(value instanceof Collection) { + if (value instanceof Collection) { boolean updateCollection = false - if((value instanceof DirtyCheckableCollection)) { + if ((value instanceof DirtyCheckableCollection)) { def persistentCollection = (DirtyCheckableCollection) value updateCollection = persistentCollection.hasChanged() - } - else { + } else { // write new collection updateCollection = true } - if(updateCollection) { + if (updateCollection) { // update existing collection - Collection identifiers = (Collection)mongoSession.getAttribute(parentAccess.entity, "${property}.ids") - if(identifiers == null) { + Collection identifiers = (Collection) mongoSession.getAttribute(parentAccess.entity, "${property}.ids") + if (identifiers == null) { def entityReflector = FieldEntityAccess.getOrIntializeReflector(associatedEntity) - identifiers = ((Collection)value).collect() { + identifiers = ((Collection) value).collect() { entityReflector.getIdentifier(it) } } - writer.writeName MappingUtils.getTargetKey((PersistentProperty)property) + writer.writeName MappingUtils.getTargetKey((PersistentProperty) property) def listCodec = codecRegistry.get(List) def identifierList = identifiers.toList() - MongoAttribute attr = (MongoAttribute)property.mapping.mappedForm - if(attr?.isReference()) { + MongoAttribute attr = (MongoAttribute) property.mapping.mappedForm + if (attr?.isReference()) { def collectionName = mongoSession.getCollectionName(property.associatedEntity) - identifierList = identifierList.findAll(){ it != null }.collect { + identifierList = identifierList.findAll() { it != null }.collect { new DBRef(collectionName, it) } } @@ -588,31 +588,29 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { @Override void encode(BsonWriter writer, ToOne property, Object value, EntityAccess parentAccess, EncoderContext encoderContext, CodecRegistry codecRegistry) { - if(value) { + if (value) { def associatedEntity = property.associatedEntity Object associationId - if(!property.isForeignKeyInChild()) { + if (!property.isForeignKeyInChild()) { def mappingContext = parentAccess.persistentEntity.mappingContext def proxyFactory = mappingContext.proxyFactory - if(proxyFactory.isProxy(value)) { + if (proxyFactory.isProxy(value)) { associationId = proxyFactory.getIdentifier(value) - } - else { + } else { def associationAccess = mappingContext.getEntityReflector(associatedEntity) associationId = associationAccess.getIdentifier(value) } - if(associationId != null) { + if (associationId != null) { writer.writeName MappingUtils.getTargetKey(property) - MongoAttribute attr = (MongoAttribute)property.mapping.mappedForm - if(attr?.isReference()) { + MongoAttribute attr = (MongoAttribute) property.mapping.mappedForm + if (attr?.isReference()) { def identityEncoder = codecRegistry.get(DBRef) - MongoCodecSession mongoSession = (MongoCodecSession)AbstractDatastore.retrieveSession(MongoDatastore) - def ref = new DBRef(mongoSession.getCollectionName( associatedEntity),associationId) + MongoCodecSession mongoSession = (MongoCodecSession) AbstractDatastore.retrieveSession(MongoDatastore) + def ref = new DBRef(mongoSession.getCollectionName(associatedEntity), associationId) identityEncoder.encode writer, ref, encoderContext - } - else { + } else { Codec identityEncoder = (Codec) codecRegistry.get((Class) associationId.getClass()) identityEncoder.encode writer, associationId, encoderContext } @@ -629,49 +627,46 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { @Override void decode(BsonReader bsonReader, ToOne property, EntityAccess entityAccess, DecoderContext decoderContext, CodecRegistry codecRegistry) { - MongoCodecSession mongoSession = (MongoCodecSession)AbstractDatastore.retrieveSession(MongoDatastore) - MongoAttribute attr = (MongoAttribute)property.mapping.mappedForm + MongoCodecSession mongoSession = (MongoCodecSession) AbstractDatastore.retrieveSession(MongoDatastore) + MongoAttribute attr = (MongoAttribute) property.mapping.mappedForm boolean isLazy = isLazyAssociation(attr) def associatedEntity = property.associatedEntity - if(associatedEntity == null) { + if (associatedEntity == null) { bsonReader.skipValue() return } Serializable associationId - if(attr.reference && bsonReader.currentBsonType == BsonType.DOCUMENT) { + if (attr.reference && bsonReader.currentBsonType == BsonType.DOCUMENT) { def dbRefCodec = codecRegistry.get(Document) def dBRef = dbRefCodec.decode(bsonReader, decoderContext) - associationId = (Serializable)dBRef.get(DB_REF_ID_FIELD) - } - else { - switch(associatedEntity.identity.type) { + associationId = (Serializable) dBRef.get(DB_REF_ID_FIELD) + } else { + switch (associatedEntity.identity.type) { case ObjectId: associationId = bsonReader.readObjectId() break case Long: - associationId = (Long)bsonReader.readInt64() + associationId = (Long) bsonReader.readInt64() break case Integer: - associationId = (Integer)bsonReader.readInt32() + associationId = (Integer) bsonReader.readInt32() break default: associationId = bsonReader.readString() } } - - if(isLazy) { + if (isLazy) { entityAccess.setPropertyNoConversion( property.name, - mongoSession.proxy(associatedEntity.javaClass, associationId ) + mongoSession.proxy(associatedEntity.javaClass, associationId) ) - } - else { + } else { entityAccess.setPropertyNoConversion( property.name, - mongoSession.retrieve(associatedEntity.javaClass, associationId ) + mongoSession.retrieve(associatedEntity.javaClass, associationId) ) } @@ -687,7 +682,4 @@ class PersistentEntityCodec extends BsonPersistentEntityCodec { } - - - } diff --git a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/query/MongoQuery.java b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/query/MongoQuery.java index dfc5cc6747f..747c5d0214d 100644 --- a/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/query/MongoQuery.java +++ b/grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/query/MongoQuery.java @@ -19,7 +19,14 @@ import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCursor; import com.mongodb.client.MongoIterable; -import grails.mongodb.geo.*; +import grails.mongodb.geo.Box; +import grails.mongodb.geo.Circle; +import grails.mongodb.geo.Distance; +import grails.mongodb.geo.GeoJSON; +import grails.mongodb.geo.Point; +import grails.mongodb.geo.Polygon; +import grails.mongodb.geo.Shape; +import grails.mongodb.geo.Sphere; import groovy.lang.Closure; import org.bson.BsonDocument; import org.bson.BsonDocumentReader; @@ -40,7 +47,12 @@ import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.model.types.*; +import org.grails.datastore.mapping.model.types.Association; +import org.grails.datastore.mapping.model.types.Basic; +import org.grails.datastore.mapping.model.types.Custom; +import org.grails.datastore.mapping.model.types.Embedded; +import org.grails.datastore.mapping.model.types.EmbeddedCollection; +import org.grails.datastore.mapping.model.types.ToOne; import org.grails.datastore.mapping.mongo.AbstractMongoSession; import org.grails.datastore.mapping.mongo.MongoCodecSession; import org.grails.datastore.mapping.mongo.MongoDatastore; @@ -58,7 +70,15 @@ import java.io.Closeable; import java.io.IOException; import java.io.Serializable; -import java.util.*; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; /** * A {@link org.grails.datastore.mapping.query.Query} implementation for the Mongo document store. @@ -69,45 +89,32 @@ @SuppressWarnings("rawtypes") public class MongoQuery extends BsonQuery implements QueryArgumentsAware { - public static final String MONGO_IN_OPERATOR = IN_OPERATOR; - public static final String MONGO_OR_OPERATOR = OR_OPERATOR; + public static final String BOX_OPERATOR = "$box"; + public static final String CENTER_OPERATOR = "$center"; + public static final String CENTER_SPHERE_OPERATOR = "$centerSphere"; + public static final String GEOMETRY_OPERATOR = "$geometry"; + public static final String GEO_INTERSECTS_OPERATOR = "$geoIntersects"; + public static final String GEO_WITHIN_OPERATOR = "$geoWithin"; + public static final String MAX_DISTANCE_OPERATOR = "$maxDistance"; public static final String MONGO_AND_OPERATOR = AND_OPERATOR; public static final String MONGO_GTE_OPERATOR = GTE_OPERATOR; - public static final String MONGO_LTE_OPERATOR = LTE_OPERATOR; public static final String MONGO_GT_OPERATOR = GT_OPERATOR; + public static final String MONGO_IN_OPERATOR = IN_OPERATOR; + public static final String MONGO_LTE_OPERATOR = LTE_OPERATOR; public static final String MONGO_LT_OPERATOR = LT_OPERATOR; public static final String MONGO_NE_OPERATOR = NE_OPERATOR; public static final String MONGO_NIN_OPERATOR = NIN_OPERATOR; + public static final String MONGO_OR_OPERATOR = OR_OPERATOR; public static final String MONGO_REGEX_OPERATOR = REGEX_OPERATOR; - public static final String MONGO_WHERE_OPERATOR = WHERE_OPERATOR; - - public static final String HINT_ARGUMENT = "hint"; - public static final String READ_CONCERN_ARGUMENT = "readConcern"; - - private Map queryArguments = Collections.emptyMap(); - public static final String NEAR_OPERATOR = "$near"; - - public static final String BOX_OPERATOR = "$box"; - + public static final String NEAR_SPHERE_OPERATOR = "$nearSphere"; public static final String POLYGON_OPERATOR = "$polygon"; - public static final String WITHIN_OPERATOR = "$within"; + public static final String HINT_ARGUMENT = "hint"; + public static final String READ_CONCERN_ARGUMENT = "readConcern"; - public static final String CENTER_OPERATOR = "$center"; - - public static final String GEO_WITHIN_OPERATOR = "$geoWithin"; - - public static final String GEOMETRY_OPERATOR = "$geometry"; - - public static final String CENTER_SPHERE_OPERATOR = "$centerSphere"; - - public static final String GEO_INTERSECTS_OPERATOR = "$geoIntersects"; - - public static final String MAX_DISTANCE_OPERATOR = "$maxDistance"; - - public static final String NEAR_SPHERE_OPERATOR = "$nearSphere"; + private Map queryArguments = Collections.emptyMap(); static { queryHandlers.put(IdEquals.class, new QueryHandler() { @@ -143,10 +150,6 @@ public void handle(EmbeddedQueryEncoder queryEncoder, AssociationQuery criterion } }); - - - - queryHandlers.put(WithinBox.class, new QueryHandler() { public void handle(EmbeddedQueryEncoder queryEncoder, WithinBox withinBox, Document query, PersistentEntity entity) { Document nearQuery = new Document(); @@ -350,6 +353,26 @@ public String handle(PersistentEntity entity, Document projectObject, Document g } + private final AbstractMongoSession mongoSession; + private final EntityPersister mongoEntityPersister; + private final ManualProjections manualProjections; + private boolean isCodecPersister = false; + + public MongoQuery(AbstractMongoSession session, PersistentEntity entity) { + super(session, entity); + this.mongoSession = session; + this.manualProjections = new ManualProjections(entity); + if (session != null) { + + this.mongoEntityPersister = (EntityPersister) session.getPersister(entity); + if (this.mongoEntityPersister instanceof MongoCodecEntityPersister) { + this.isCodecPersister = true; + } + } else { + mongoEntityPersister = null; + } + } + private static Document getIdObjectForGroupBy(Document groupBy) { Object value = groupBy.get(MongoEntityPersister.MONGO_ID_FIELD); Document id; @@ -365,33 +388,12 @@ private static Document getIdObjectForGroupBy(Document groupBy) { private static String addProjectionToGroupBy(Document projectObject, Document groupBy, PropertyProjection projection, String operator, String prefix) { projectObject.put(projection.getPropertyName(), 1); String property = projection.getPropertyName(); - String projectionValueKey = prefix + property.replace('.','_'); + String projectionValueKey = prefix + property.replace('.', '_'); Document averageProjection = new Document(operator, "$" + property); groupBy.put(projectionValueKey, averageProjection); return projectionValueKey; } - private final AbstractMongoSession mongoSession; - private final EntityPersister mongoEntityPersister; - private final ManualProjections manualProjections; - private boolean isCodecPersister = false; - - public MongoQuery(AbstractMongoSession session, PersistentEntity entity) { - super(session, entity); - this.mongoSession = session; - this.manualProjections = new ManualProjections(entity); - if(session != null) { - - this.mongoEntityPersister = (EntityPersister) session.getPersister(entity); - if(this.mongoEntityPersister instanceof MongoCodecEntityPersister) { - this.isCodecPersister = true; - } - } - else { - mongoEntityPersister = null; - } - } - @Override protected void flushBeforeQuery() { // with Mongo we only flush the session if a transaction is not active to allow for session-managed transactions @@ -418,7 +420,7 @@ protected List executeQuery(final PersistentEntity entity, final Junction criter final List projectionList = projections().getProjectionList(); if (uniqueResult && projectionList.isEmpty()) { - if(isCodecPersister) { + if (isCodecPersister) { collection = collection .withDocumentClass(entity.getJavaClass()); } @@ -435,31 +437,29 @@ protected List executeQuery(final PersistentEntity entity, final Junction criter dbObject = ((FindIterable) setHint(cursor)).limit(1) .first(); } - if(dbObject == null) { + if (dbObject == null) { return wrapObjectResultInList(dbObject); } - if(isCodecPersister) { - if(!mongoSession.contains(dbObject)) { + if (isCodecPersister) { + if (!mongoSession.contains(dbObject)) { final EntityAccess entityAccess = mongoSession.createEntityAccess(entity, dbObject); mongoEntityPersister.firePostLoadEvent(entity, entityAccess); mongoSession.cacheInstance(dbObject.getClass(), (Serializable) entityAccess.getIdentifier(), dbObject); } return wrapObjectResultInList(dbObject); - } - else { - return wrapObjectResultInList(createObjectFromDBObject((Document)dbObject)); + } else { + return wrapObjectResultInList(createObjectFromDBObject((Document) dbObject)); } } MongoCursor cursor; Document query = createQueryObject(entity); - if (projectionList.isEmpty()) { - if(isCodecPersister) { + if (isCodecPersister) { collection = collection .withDocumentClass(entity.getJavaClass()) - .withCodecRegistry( mongoSession.getDatastore().getCodecRegistry()); + .withCodecRegistry(mongoSession.getDatastore().getCodecRegistry()); } cursor = executeQuery(entity, criteria, collection, query); return new MongoResultList(cursor, offset, mongoEntityPersister); @@ -472,7 +472,6 @@ protected List executeQuery(final PersistentEntity entity, final Junction criter List projectedKeys = aggregatePipeline.getProjectedKeys(); List projectedResults = new ArrayList(); - AggregateIterable aggregatedResults = collection.aggregate(aggregationPipeline); aggregatedResults = (AggregateIterable) setHint(aggregatedResults); final MongoCursor aggregateCursor = aggregatedResults.iterator(); @@ -500,7 +499,6 @@ protected List executeQuery(final PersistentEntity entity, final Junction criter return projectedResults; - } protected AggregatePipeline buildAggregatePipeline(PersistentEntity entity, Document query, List projectionList) { @@ -551,9 +549,9 @@ private MongoIterable setHint(MongoIterable cursor) { protected FindIterable executeQueryAndApplyPagination(com.mongodb.client.MongoCollection collection, Document query) { Object readConcernObject = queryArguments.get(READ_CONCERN_ARGUMENT); - if(readConcernObject instanceof ReadConcern) { + if (readConcernObject instanceof ReadConcern) { collection = collection.withReadConcern( - (ReadConcern) readConcernObject + (ReadConcern) readConcernObject ); } @@ -564,7 +562,7 @@ protected FindIterable executeQueryAndApplyPagination(com.mongodb.clie if (max > -1) { iterable.limit(max); } - if(uniqueResult) { + if (uniqueResult) { iterable.limit(1); } @@ -598,7 +596,7 @@ private Document getClassFieldDocument(final PersistentEntity entity) { HashMap classValue = new HashMap<>(); ArrayList classes = new ArrayList<>(); classes.add(entity.getDiscriminator()); - for(PersistentEntity childEntity: childEntities) { + for (PersistentEntity childEntity : childEntities) { classes.add(childEntity.getDiscriminator()); } classValue.put(MONGO_IN_OPERATOR, classes); @@ -621,7 +619,7 @@ protected Document createQueryObject(PersistentEntity persistentEntity) { public static void populateMongoQuery(final AbstractMongoSession session, Document query, Junction criteria, final PersistentEntity entity) { EmbeddedQueryEncoder queryEncoder; - if(session instanceof MongoCodecSession) { + if (session instanceof MongoCodecSession) { final MongoDatastore datastore = session.getDatastore(); final CodecRegistry codecRegistry = datastore.getCodecRegistry(); queryEncoder = new EmbeddedQueryEncoder() { @@ -633,13 +631,12 @@ public Object encode(Embedded embedded, Object instance) { return doc; } }; - } - else { + } else { queryEncoder = new EmbeddedQueryEncoder() { @Override public Object encode(Embedded embedded, Object instance) { MongoEntityPersister persister = (MongoEntityPersister) session.getPersister(entity.getJavaClass()); - return persister.createNativeObjectForEmbedded(embedded, instance); + return persister.createNativeObjectForEmbedded(embedded, instance); } }; @@ -676,7 +673,7 @@ public static void populateMongoQuery(final EmbeddedQueryEncoder queryEncoder, D PersistentProperty property = entity.getPropertyByName(pc.getProperty()); if (property instanceof Custom) { CustomTypeMarshaller customTypeMarshaller = ((Custom) property).getCustomTypeMarshaller(); - if(!(customTypeMarshaller instanceof CodecCustomTypeMarshaller)) { + if (!(customTypeMarshaller instanceof CodecCustomTypeMarshaller)) { customTypeMarshaller.query(property, pc, query); continue; } @@ -689,14 +686,13 @@ public static void populateMongoQuery(final EmbeddedQueryEncoder queryEncoder, D } } - private Object createObjectFromDBObject(Document dbObject) { // we always use the session cached version where available. final Object id = dbObject.get(MongoEntityPersister.MONGO_ID_FIELD); Class type = mongoEntityPersister.getPersistentEntity().getJavaClass(); Object instance = mongoSession.getCachedInstance(type, (Serializable) id); if (instance == null) { - instance = ((MongoEntityPersister)mongoEntityPersister).createObjectFromNativeEntry( + instance = ((MongoEntityPersister) mongoEntityPersister).createObjectFromNativeEntry( mongoEntityPersister.getPersistentEntity(), (Serializable) id, dbObject); mongoSession.cacheInstance(type, (Serializable) id, instance); } @@ -735,7 +731,6 @@ public Query near(String property, Point value) { return this; } - /** * Geospacial query for values near the given two dimensional list * @@ -760,7 +755,6 @@ public Query near(String property, Point value, Distance maxDistance) { return this; } - /** * Geospacial query for values near the given two dimensional list * @@ -809,7 +803,6 @@ public Query nearSphere(String property, Point value) { return this; } - /** * Geospacial query for values near the given two dimensional list * @@ -834,7 +827,6 @@ public Query nearSphere(String property, Point value, Distance maxDistance) { return this; } - /** * Geospacial query for values near the given two dimensional list * @@ -958,7 +950,6 @@ public void setMaxDistance(Distance maxDistance) { } } - /** * Used for Geospacial querying with the $nearSphere operator * @@ -966,6 +957,7 @@ public void setMaxDistance(Distance maxDistance) { * @since 1.0 */ public static class NearSphere extends Near { + public NearSphere(String name, Object value) { super(name, value); } @@ -1050,18 +1042,19 @@ public GeoCriterion(String name, Object value) { } public static class GeoWithin extends GeoCriterion { + public GeoWithin(String name, Object value) { super(name, value); } } public static class GeoIntersects extends GeoCriterion { + public GeoIntersects(String name, Object value) { super(name, value); } } - public static class AggregatedResultList extends AbstractList implements Closeable { private MongoCursor cursor; @@ -1091,7 +1084,9 @@ public String toString() { @Override public Object get(int index) { - if (containsAssociations) initializeFully(); + if (containsAssociations) { + initializeFully(); + } if (initializedObjects.size() > index) { return initializedObjects.get(index); } else if (!initialized) { @@ -1104,13 +1099,14 @@ public Object get(int index) { return projected; } } - if (!hasResults) handleNoResults(); + if (!hasResults) { + handleNoResults(); + } initialized = true; } throw new ArrayIndexOutOfBoundsException("Index value " + index + " exceeds size of aggregate list"); } - @Override public Object set(int index, Object element) { initializeFully(); @@ -1129,7 +1125,9 @@ public ListIterator listIterator(int index) { } protected void initializeFully() { - if (initialized) return; + if (initialized) { + return; + } if (containsAssociations) { if (projectedProperties.size() == 1) { ProjectedProperty projectedProperty = projectedProperties.get(0); @@ -1144,27 +1142,25 @@ protected void initializeFully() { } if (!hasResults) { handleNoResults(); - } - else if(property instanceof Embedded) { - Embedded embedded = (Embedded)property; + } else if (property instanceof Embedded) { + Embedded embedded = (Embedded) property; List embeddedList = new ArrayList(); CodecRegistry codecRegistry = session.getDatastore().getCodecRegistry(); PersistentEntityCodec codec = new PersistentEntityCodec(codecRegistry, embedded.getAssociatedEntity()); for (Serializable embeddedDoc : identifiers) { - if(embeddedDoc instanceof Document) { + if (embeddedDoc instanceof Document) { Document documentObject = (Document) embeddedDoc; Object decoded = codec.decode(new BsonDocumentReader(documentObject.toBsonDocument(Document.class, codecRegistry))); embeddedList.add( - decoded + decoded ); } } this.initializedObjects = embeddedList; - } - else { + } else { this.initializedObjects = session.retrieveAll(property.getType(), identifiers); } } else { @@ -1180,7 +1176,7 @@ else if(property instanceof Embedded) { PersistentProperty property = projectedProperty.property; Object value = getProjectedValue(dbo, projectedProperty.projectionKey); if (property instanceof Association) { - if( (!(property instanceof Embedded) && !(property instanceof EmbeddedCollection) && !(property instanceof Basic))) { + if ((!(property instanceof Embedded) && !(property instanceof EmbeddedCollection) && !(property instanceof Basic))) { Map> identifierMap = associationMap.get(index); Class type = ((Association) property).getAssociatedEntity().getJavaClass(); identifierMap.get(type).add((Serializable) value); @@ -1273,7 +1269,9 @@ public Iterator iterator() { @Override public boolean hasNext() { boolean hasMore = cursor.hasNext(); - if (!hasMore) initialized = true; + if (!hasMore) { + initialized = true; + } return hasMore; } @@ -1336,8 +1334,6 @@ public void close() throws IOException { } } - - @SuppressWarnings("serial") public static class MongoResultList extends AbstractResultList { @@ -1347,14 +1343,12 @@ public static class MongoResultList extends AbstractResultList { @SuppressWarnings("unchecked") public MongoResultList(MongoCursor cursor, int offset, EntityPersister mongoEntityPersister) { - super(offset,cursor); + super(offset, cursor); this.cursor = cursor; this.mongoEntityPersister = mongoEntityPersister; this.isCodecPersister = mongoEntityPersister instanceof MongoCodecEntityPersister; } - - @Override public void close() throws IOException { cursor.close(); @@ -1376,13 +1370,13 @@ public MongoCursor getCursor() { @Override protected Object nextDecoded() { final Object o = cursor.next(); - if(isCodecPersister) { + if (isCodecPersister) { final AbstractMongoSession session = (AbstractMongoSession) mongoEntityPersister.getSession(); - if(!session.contains(o)) { + if (!session.contains(o)) { final PersistentEntity entity = mongoEntityPersister.getPersistentEntity(); final EntityAccess entityAccess = session.createEntityAccess(entity, o); final Object id = entityAccess.getIdentifier(); - if(id != null) { + if (id != null) { session.cacheInstance(entity.getJavaClass(), (Serializable) id, o); } mongoEntityPersister.firePostLoadEvent(entity, entityAccess); @@ -1417,15 +1411,17 @@ protected Object convertDBObject(Object object) { } - - public static class ProjectedProperty { + + //CHECKSTYLE:OFF public Projection projection; public String projectionKey; public PersistentProperty property; + //CHECKSTYLE:ON } protected static class AggregatePipeline { + private PersistentEntity entity; private Document query; private List projectionList; @@ -1441,7 +1437,6 @@ public AggregatePipeline(MongoQuery mongoQuery, PersistentEntity entity, Documen this.projectionList = projectionList; } - public List getAggregationPipeline() { return aggregationPipeline; } @@ -1481,18 +1476,15 @@ public AggregatePipeline build() { aggregationPipeline.add(new Document("$skip", offset)); } - projectedKeys = new ArrayList(); singleResult = true; Document projectObject = new Document(); - Document groupByObject = new Document(); groupByObject.put(MongoEntityPersister.MONGO_ID_FIELD, 0); Document additionalGroupBy = null; - for (Projection projection : projectionList) { ProjectionHandler projectionHandler = projectProjectionHandlers.get(projection.getClass()); ProjectedProperty projectedProperty = new ProjectedProperty(); @@ -1504,7 +1496,7 @@ public AggregatePipeline build() { PersistentProperty property = entity.getPropertyByName(propertyName); if (property != null) { projectedProperty.property = property; - } else if(!propertyName.contains(".")) { + } else if (!propertyName.contains(".")) { throw new InvalidDataAccessResourceUsageException("Attempt to project on a non-existent project [" + propertyName + "]"); } } diff --git a/grails-data-mongodb/core/src/test/groovy/grails/gorm/tests/Person.groovy b/grails-data-mongodb/core/src/test/groovy/grails/gorm/tests/Person.groovy index eabc2b05769..e4b0f9aa579 100644 --- a/grails-data-mongodb/core/src/test/groovy/grails/gorm/tests/Person.groovy +++ b/grails-data-mongodb/core/src/test/groovy/grails/gorm/tests/Person.groovy @@ -24,7 +24,7 @@ import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform @Entity @ApplyDetachedCriteriaTransform -//@groovy.transform.EqualsAndHashCode - breaks gorm-neo4j: TODO: http://jira.grails.org/browse/GPNEO4J-10 +//@groovy.transform.EqualsAndHashCode - breaks gorm-neo4j: TODO: GPNEO4J-10 @EqualsAndHashCode(includes = ['firstName', 'lastName', 'age']) class Person implements Serializable, Comparable { static simpsons = where { diff --git a/grails-data-mongodb/docs/src/docs/asciidoc/gettingStarted/outsideGrails.adoc b/grails-data-mongodb/docs/src/docs/asciidoc/gettingStarted/outsideGrails.adoc index 2f838120b40..cae7a5af2f7 100644 --- a/grails-data-mongodb/docs/src/docs/asciidoc/gettingStarted/outsideGrails.adoc +++ b/grails-data-mongodb/docs/src/docs/asciidoc/gettingStarted/outsideGrails.adoc @@ -48,7 +48,7 @@ For configuration you can either pass a map or an instance of the `org.springfra [source,groovy] ---- -def initializer = new MongoDatastore(['grails.mongodb.url':'http://myserver'], Person) +def initializer = new MongoDatastore(['grails.mongodb.url':'https://myserver'], Person) println Person.count() ---- diff --git a/grails-data-mongodb/ext/build.gradle b/grails-data-mongodb/ext/build.gradle index 86bcaa1539a..0af7434bea8 100644 --- a/grails-data-mongodb/ext/build.gradle +++ b/grails-data-mongodb/ext/build.gradle @@ -90,4 +90,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/mongodb-test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-data-mongodb/ext/src/main/groovy/org/grails/datastore/gorm/mongo/extensions/MongoExtensions.groovy b/grails-data-mongodb/ext/src/main/groovy/org/grails/datastore/gorm/mongo/extensions/MongoExtensions.groovy index 17cb020a1bc..01cb196ef11 100644 --- a/grails-data-mongodb/ext/src/main/groovy/org/grails/datastore/gorm/mongo/extensions/MongoExtensions.groovy +++ b/grails-data-mongodb/ext/src/main/groovy/org/grails/datastore/gorm/mongo/extensions/MongoExtensions.groovy @@ -22,8 +22,24 @@ import com.mongodb.BasicDBObject import com.mongodb.DBObject import com.mongodb.ReadPreference import com.mongodb.WriteConcern -import com.mongodb.client.* -import com.mongodb.client.model.* +import com.mongodb.client.AggregateIterable +import com.mongodb.client.ChangeStreamIterable +import com.mongodb.client.DistinctIterable +import com.mongodb.client.FindIterable +import com.mongodb.client.MongoCollection +import com.mongodb.client.MongoDatabase +import com.mongodb.client.MongoIterable +import com.mongodb.client.model.CountOptions +import com.mongodb.client.model.CreateCollectionOptions +import com.mongodb.client.model.DeleteOptions +import com.mongodb.client.model.DropIndexOptions +import com.mongodb.client.model.FindOneAndDeleteOptions +import com.mongodb.client.model.FindOneAndReplaceOptions +import com.mongodb.client.model.FindOneAndUpdateOptions +import com.mongodb.client.model.IndexOptions +import com.mongodb.client.model.InsertManyOptions +import com.mongodb.client.model.ReplaceOptions +import com.mongodb.client.model.UpdateOptions import com.mongodb.client.result.DeleteResult import com.mongodb.client.result.UpdateResult import com.mongodb.lang.Nullable @@ -51,38 +67,32 @@ import static java.util.Arrays.asList @CompileStatic class MongoExtensions { - static T asType(Document document, Class cls) { - if(Document.isAssignableFrom(cls)) { - return (T)document - } - else { + if (Document.isAssignableFrom(cls)) { + return (T) document + } else { def datastore = GormEnhancer.findDatastore(cls) - AbstractMongoSession session = (AbstractMongoSession)datastore.currentSession + AbstractMongoSession session = (AbstractMongoSession) datastore.currentSession if (session != null) { return session.decode(cls, document) - } - else if(cls.name == 'grails.converters.JSON') { - return cls.newInstance( document ) - } - else { + } else if (cls.name == 'grails.converters.JSON') { + return cls.newInstance(document) + } else { throw new IllegalArgumentException("Cannot convert DBOject [$document] to writer type $cls. Type is not a persistent entity") } } } static T asType(FindIterable iterable, Class cls) { - if(FindIterable.isAssignableFrom(cls)) { - return (T)iterable - } - else { + if (FindIterable.isAssignableFrom(cls)) { + return (T) iterable + } else { def datastore = GormEnhancer.findDatastore(cls) - AbstractMongoSession session = (AbstractMongoSession)datastore.currentSession + AbstractMongoSession session = (AbstractMongoSession) datastore.currentSession if (session != null) { return session.decode(cls, iterable) - } - else { + } else { throw new IllegalArgumentException("Cannot convert DBOject [$iterable] to writer type $cls. Type is not a persistent entity") } } @@ -90,11 +100,11 @@ class MongoExtensions { static List toList(FindIterable iterable, Class cls) { def datastore = GormEnhancer.findDatastore(cls) - AbstractMongoSession session = (AbstractMongoSession)datastore.currentSession + AbstractMongoSession session = (AbstractMongoSession) datastore.currentSession - MongoEntityPersister p = (MongoEntityPersister)session.getPersister(cls) + MongoEntityPersister p = (MongoEntityPersister) session.getPersister(cls) if (p) - return new MongoQuery.MongoResultList(((FindIterable)iterable).iterator(),0,p) + return new MongoQuery.MongoResultList(((FindIterable) iterable).iterator(), 0, p) else { throw new IllegalArgumentException("Cannot convert DBCursor [$iterable] to writer type $cls. Type is not a persistent entity") } @@ -103,19 +113,17 @@ class MongoExtensions { @CompileStatic static DBObject toDBObject(Document document) { def object = new BasicDBObject() - for(key in document.keySet()) { + for (key in document.keySet()) { def value = document.get(key) - if(value instanceof Document) { - value = toDBObject((Document)value) - } - else if(value instanceof Collection) { - Collection col = (Collection)value + if (value instanceof Document) { + value = toDBObject((Document) value) + } else if (value instanceof Collection) { + Collection col = (Collection) value Collection newCol = [] - for(i in col) { - if(i instanceof Document) { - newCol << toDBObject((Document)i) - } - else { + for (i in col) { + if (i instanceof Document) { + newCol << toDBObject((Document) i) + } else { newCol << i } } @@ -162,24 +170,28 @@ class MongoExtensions { list.collect { toBson(it) } } - /************** FindIterable Extensions *************/ static FindIterable filter(FindIterable iterable, @Nullable Map filter) { iterable.filter(toBson(filter)) } + static FindIterable projection(FindIterable iterable, @Nullable Map projection) { iterable.projection(toBson(projection)) } + static FindIterable sort(FindIterable iterable, @Nullable Map sort) { iterable.sort(toBson(sort)) } + static FindIterable hint(FindIterable iterable, @Nullable Map hint) { iterable.hint(toBson(hint)) } + static FindIterable max(FindIterable iterable, @Nullable Map max) { iterable.max(toBson(max)) } + static FindIterable min(FindIterable iterable, @Nullable Map min) { iterable.min(toBson(min)) } @@ -230,7 +242,7 @@ class MongoExtensions { .countDocuments(toBson(query)) } - static long getCount(MongoCollection collection, final Map query, final Map options) { + static long getCount(MongoCollection collection, final Map query, final Map options) { collection.countDocuments(toBson(query), MongoConstants.mapToObject(CountOptions, options)) } @@ -245,7 +257,7 @@ class MongoExtensions { static Document findOne(MongoCollection collection, ObjectId id) { def query = new Document() query.put(AbstractMongoObectEntityPersister.MONGO_ID_FIELD, id) - collection.find((Bson)query) + collection.find((Bson) query) .limit(1) .first() } @@ -253,7 +265,7 @@ class MongoExtensions { static Document findOne(MongoCollection collection, CharSequence id) { def query = new Document() query.put(AbstractMongoObectEntityPersister.MONGO_ID_FIELD, id) - collection.find((Bson)query) + collection.find((Bson) query) .limit(1) .first() } @@ -262,12 +274,12 @@ class MongoExtensions { def query = new Document() query.put(AbstractMongoObectEntityPersister.MONGO_ID_FIELD, id) collection - .find((Bson)query, type) + .find((Bson) query, type) .limit(1) .first() } - static Document findOne(MongoCollection collection, final Map query, final Map projection) { + static Document findOne(MongoCollection collection, final Map query, final Map projection) { collection .find(toBson(query)) .projection(toBson(projection)) @@ -275,7 +287,7 @@ class MongoExtensions { .first() } - static Document findOne(MongoCollection collection, final Map query, final Map projection, final Map sort) { + static Document findOne(MongoCollection collection, final Map query, final Map projection, final Map sort) { collection .find(toBson(query)) .projection(toBson(projection)) @@ -290,7 +302,7 @@ class MongoExtensions { .first() } - static Document findOne(MongoCollection collection, final Map query, final Map projection, final ReadPreference readPreference) { + static Document findOne(MongoCollection collection, final Map query, final Map projection, final ReadPreference readPreference) { collection .withReadPreference(readPreference) .find(toBson(query)) @@ -300,9 +312,9 @@ class MongoExtensions { } static Document findOne(MongoCollection collection, - final Map query, - final Map projection, - final Map sort, + final Map query, + final Map projection, + final Map sort, final ReadPreference readPreference) { collection .withReadPreference(readPreference) @@ -317,7 +329,7 @@ class MongoExtensions { collection.find(toBson(query)) } - static FindIterable find(MongoCollection collection, final Map query, Class type) { + static FindIterable find(MongoCollection collection, final Map query, Class type) { collection.find(toBson(query), type) } @@ -369,11 +381,11 @@ class MongoExtensions { collection.watch(toBson(pipeline), resultClass) } - static DeleteResult deleteMany(final MongoCollection collection, final Map query) { + static DeleteResult deleteMany(final MongoCollection collection, final Map query) { collection.deleteMany(toBson(query)) } - static DeleteResult remove(final MongoCollection collection, final Map query) { + static DeleteResult remove(final MongoCollection collection, final Map query) { deleteMany collection, query } @@ -382,63 +394,63 @@ class MongoExtensions { return collection } - static DeleteResult deleteMany(final MongoCollection collection, final Map query, final WriteConcern writeConcern) { + static DeleteResult deleteMany(final MongoCollection collection, final Map query, final WriteConcern writeConcern) { collection .withWriteConcern(writeConcern) .deleteMany(toBson(query)) } - static DeleteResult deleteOne(final MongoCollection collection, final Map query) { + static DeleteResult deleteOne(final MongoCollection collection, final Map query) { collection.deleteOne(toBson(query)) } - static DeleteResult deleteOne(final MongoCollection collection, final Map query, final WriteConcern writeConcern) { + static DeleteResult deleteOne(final MongoCollection collection, final Map query, final WriteConcern writeConcern) { collection .withWriteConcern(writeConcern) .deleteOne(toBson(query)) } - static DeleteResult deleteOne(final MongoCollection collection, final Map query, final Map options) { + static DeleteResult deleteOne(final MongoCollection collection, final Map query, final Map options) { collection.deleteOne(toBson(query), MongoConstants.mapToObject(DeleteOptions, options)) } - static DeleteResult deleteMany(final MongoCollection collection, final Map query, final Map options) { + static DeleteResult deleteMany(final MongoCollection collection, final Map query, final Map options) { collection.deleteMany(toBson(query), MongoConstants.mapToObject(DeleteOptions, options)) } - static UpdateResult updateOne(final MongoCollection collection, Map filter, Map update) { + static UpdateResult updateOne(final MongoCollection collection, Map filter, Map update) { collection.updateOne(toBson(filter), toBson(update)) } - static UpdateResult update(final MongoCollection collection, Map filter, Map update) { + static UpdateResult update(final MongoCollection collection, Map filter, Map update) { collection.updateOne(toBson(filter), toBson(update)) } - static UpdateResult updateOne(final MongoCollection collection, Map filter, Map update, Map options) { + static UpdateResult updateOne(final MongoCollection collection, Map filter, Map update, Map options) { collection.updateOne(toBson(filter), toBson(update), MongoConstants.mapToObject(UpdateOptions, options)) } - static UpdateResult update(final MongoCollection collection, Map filter, Map update, Map options) { + static UpdateResult update(final MongoCollection collection, Map filter, Map update, Map options) { collection.updateOne(toBson(filter), toBson(update), MongoConstants.mapToObject(UpdateOptions, options)) } - static UpdateResult updateOne(final MongoCollection collection, Map filter, Map update, UpdateOptions updateOptions) { + static UpdateResult updateOne(final MongoCollection collection, Map filter, Map update, UpdateOptions updateOptions) { collection.updateOne(toBson(filter), toBson(update), updateOptions) } - static UpdateResult update(final MongoCollection collection, Map filter, Map update, UpdateOptions updateOptions) { + static UpdateResult update(final MongoCollection collection, Map filter, Map update, UpdateOptions updateOptions) { collection.updateOne(toBson(filter), toBson(update), updateOptions) } - static UpdateResult updateMany(final MongoCollection collection, Map filter, Map update) { + static UpdateResult updateMany(final MongoCollection collection, Map filter, Map update) { collection.updateMany(toBson(filter), toBson(update)) } - static UpdateResult updateMany(final MongoCollection collection, Map filter, Map update, Map options) { + static UpdateResult updateMany(final MongoCollection collection, Map filter, Map update, Map options) { collection.updateMany(toBson(filter), toBson(update), MongoConstants.mapToObject(UpdateOptions, options)) } - static UpdateResult updateMany(final MongoCollection collection, Map filter, Map update, UpdateOptions updateOptions) { + static UpdateResult updateMany(final MongoCollection collection, Map filter, Map update, UpdateOptions updateOptions) { collection.updateMany(toBson(filter), toBson(update), updateOptions) } @@ -535,7 +547,7 @@ class MongoExtensions { insert(collection, documents, writeConcern); } - static MongoCollection insert(final MongoCollection collection, final Map[] documents, final WriteConcern writeConcern) { + static MongoCollection insert(final MongoCollection collection, final Map[] documents, final WriteConcern writeConcern) { insert(collection, asList(documents), writeConcern); } @@ -560,11 +572,11 @@ class MongoExtensions { return collection } - static MongoCollection save(final MongoCollection collection, final Map document) { + static MongoCollection save(final MongoCollection collection, final Map document) { insert collection, document } - static MongoCollection save(final MongoCollection collection, final Map document, final WriteConcern writeConcern) { + static MongoCollection save(final MongoCollection collection, final Map document, final WriteConcern writeConcern) { insert collection, document, writeConcern } @@ -572,7 +584,7 @@ class MongoExtensions { collection.replaceOne(toBson(filter), replacement) } - static UpdateResult replaceOne(MongoCollection collection, Map filter, Document replacement, Map options) { + static UpdateResult replaceOne(MongoCollection collection, Map filter, Document replacement, Map options) { collection.replaceOne( toBson(filter), replacement, @@ -580,27 +592,27 @@ class MongoExtensions { } static Document findOneAndDelete(MongoCollection collection, Map filter) { - collection.findOneAndDelete( toBson(filter) ) + collection.findOneAndDelete(toBson(filter)) } static Document findOneAndDelete(MongoCollection collection, Map filter, Map options) { - collection.findOneAndDelete( toBson(filter), MongoConstants.mapToObject(FindOneAndDeleteOptions, options) ) + collection.findOneAndDelete(toBson(filter), MongoConstants.mapToObject(FindOneAndDeleteOptions, options)) } static Document findOneAndReplace(MongoCollection collection, Map filter, Map replacement) { - collection.findOneAndReplace( toBson(filter), new Document(replacement) ) + collection.findOneAndReplace(toBson(filter), new Document(replacement)) } static Document findOneAndReplace(MongoCollection collection, Map filter, Map replacement, Map options) { - collection.findOneAndReplace( toBson(filter), new Document(replacement), MongoConstants.mapToObject(FindOneAndReplaceOptions, options) ) + collection.findOneAndReplace(toBson(filter), new Document(replacement), MongoConstants.mapToObject(FindOneAndReplaceOptions, options)) } static Document findOneAndUpdate(MongoCollection collection, Map filter, Map update) { - collection.findOneAndUpdate( toBson(filter), new Document(update) ) + collection.findOneAndUpdate(toBson(filter), new Document(update)) } static Document findOneAndUpdate(MongoCollection collection, Map filter, Map update, Map options) { - collection.findOneAndUpdate( toBson(filter), new Document(update), MongoConstants.mapToObject(FindOneAndUpdateOptions, options) ) + collection.findOneAndUpdate(toBson(filter), new Document(update), MongoConstants.mapToObject(FindOneAndUpdateOptions, options)) } } diff --git a/grails-data-mongodb/grails-plugin/build.gradle b/grails-data-mongodb/grails-plugin/build.gradle index db68de1d369..70a01b1224c 100644 --- a/grails-data-mongodb/grails-plugin/build.gradle +++ b/grails-data-mongodb/grails-plugin/build.gradle @@ -133,4 +133,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/grails-extension-gradle-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-data-mongodb/grails-plugin/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy b/grails-data-mongodb/grails-plugin/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy index 8484ac385dc..2eaca9c6131 100644 --- a/grails-data-mongodb/grails-plugin/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy +++ b/grails-data-mongodb/grails-plugin/src/main/groovy/grails/plugins/mongodb/MongodbGrailsPlugin.groovy @@ -34,6 +34,7 @@ import org.springframework.core.env.PropertyResolver import org.springframework.transaction.PlatformTransactionManager class MongodbGrailsPlugin extends Plugin { + def license = 'Apache 2.0 License' def organization = [name: 'Grails', url: 'https://grails.org/'] def issueManagement = [system: 'Github', url: 'https://github.com/grails/gorm-mongodb'] @@ -53,17 +54,17 @@ class MongodbGrailsPlugin extends Plugin { initializer.registerApplicationIfNotPresent = false def applicationName = Metadata.getCurrent().getApplicationName() - if(!applicationName.contains('@')) { + if (!applicationName.contains('@')) { initializer.databaseName = applicationName } initializer.setSecondaryDatastore(hasHibernatePlugin()) - return initializer.getBeanDefinitions((BeanDefinitionRegistry)applicationContext) + return initializer.getBeanDefinitions((BeanDefinitionRegistry) applicationContext) } @CompileStatic protected boolean hasHibernatePlugin() { - manager.allPlugins.any() { GrailsPlugin plugin -> plugin.name ==~ /hibernate\d*/} + manager.allPlugins.any() { GrailsPlugin plugin -> plugin.name ==~ /hibernate\d*/ } } @Override diff --git a/grails-data-mongodb/grails-plugin/src/testFixtures/groovy/grails/test/mongodb/MongoSpec.groovy b/grails-data-mongodb/grails-plugin/src/testFixtures/groovy/grails/test/mongodb/MongoSpec.groovy index 200b0203813..16881b1abda 100644 --- a/grails-data-mongodb/grails-plugin/src/testFixtures/groovy/grails/test/mongodb/MongoSpec.groovy +++ b/grails-data-mongodb/grails-plugin/src/testFixtures/groovy/grails/test/mongodb/MongoSpec.groovy @@ -90,8 +90,8 @@ abstract class MongoSpec extends Specification { } Map mapPropertySource = propertySources - .findAll { it.getSource() } - .collectEntries { it.getSource() as Map } + .findAll { it.getSource() } + .collectEntries { it.getSource() as Map } Config config = new PropertySourcesConfig(mapPropertySource) @@ -109,8 +109,7 @@ abstract class MongoSpec extends Specification { } else { mongoDatastore = new MongoDatastore((PropertyResolver) config, pkg) } - } - else { + } else { MongoClient mongoClient = createMongoClient() if (mongoClient) { mongoDatastore = new MongoDatastore(mongoClient, config, domainClasses as Class[]) @@ -160,8 +159,8 @@ abstract class MongoSpec extends Specification { private boolean canLoadFileExtension(PropertySourceLoader loader, String name) { return Arrays - .stream(loader.fileExtensions) - .map { String extension -> extension.toLowerCase() } - .anyMatch { String extension -> name.toLowerCase().endsWith(extension) } + .stream(loader.fileExtensions) + .map { String extension -> extension.toLowerCase() } + .anyMatch { String extension -> name.toLowerCase().endsWith(extension) } } } diff --git a/grails-data-mongodb/gson-templates/build.gradle b/grails-data-mongodb/gson-templates/build.gradle index f276cd8ca40..57327eceaa9 100644 --- a/grails-data-mongodb/gson-templates/build.gradle +++ b/grails-data-mongodb/gson-templates/build.gradle @@ -72,4 +72,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/mongodb-test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-data-mongodb/gson-templates/src/templates/org/bson/types/_objectId.gson b/grails-data-mongodb/gson-templates/src/templates/org/bson/types/_objectId.gson index 258f98d3a9f..cd4e58f4761 100644 --- a/grails-data-mongodb/gson-templates/src/templates/org/bson/types/_objectId.gson +++ b/grails-data-mongodb/gson-templates/src/templates/org/bson/types/_objectId.gson @@ -17,7 +17,6 @@ * under the License. */ - import org.bson.types.* import groovy.transform.* import grails.plugin.json.builder.* diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/gradle.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/gradle.properties index 577d09fd84d..7e47c128dc6 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/gradle.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages.properties index 09d392c8811..d71a1fc5cb9 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_cs_CZ.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_cs_CZ.properties index dc71c205fe9..24799b956a5 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_cs_CZ.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_cs_CZ.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_da.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_da.properties index c3ac9b19299..8effe79084c 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_da.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_da.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_de.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_de.properties index 18cd4a68b23..fccc6d561e3 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_de.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_de.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_es.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_es.properties index f8d257c24ac..c76df877613 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_es.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_es.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_fr.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_fr.properties index 93d4bc05f73..686f8722431 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_fr.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_fr.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_it.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_it.properties index 22353b03366..3bb0abe4030 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_it.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_it.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_ja.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_ja.properties index ba1daf0d6a0..bcd6bb99bf4 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_ja.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_ja.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_nb.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_nb.properties index b2bcb4cfa5c..8485b66145e 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_nb.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_nb.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_nl.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_nl.properties index eb5245ccf5a..57360d5c39d 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_nl.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_nl.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_pl.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_pl.properties index efb954c5fff..199f7d26e0e 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_pl.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_pl.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_pt_BR.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_pt_BR.properties index 2244a405398..474cf326f9a 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_pt_BR.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_pt_BR.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_pt_PT.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_pt_PT.properties index d432eb5f6e0..27aa38dd2b2 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_pt_PT.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_pt_PT.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_ru.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_ru.properties index 2c7e7cdde79..c5e1d93446f 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_ru.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_ru.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_sv.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_sv.properties index 694ac13f23b..49079027e54 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_sv.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_sv.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_th.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_th.properties index 1219a71e4b4..9d2ba5ea9d5 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_th.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_th.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_zh_CN.properties b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_zh_CN.properties index 61a0705aef2..181f0a372e2 100644 --- a/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_zh_CN.properties +++ b/grails-data-neo4j/examples/grails3-neo4j-hibernate/grails-app/i18n/messages_zh_CN.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/gradle.properties b/grails-data-neo4j/examples/grails3-neo4j/gradle.properties index 577d09fd84d..7e47c128dc6 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/gradle.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages.properties index 09d392c8811..d71a1fc5cb9 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_cs_CZ.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_cs_CZ.properties index dc71c205fe9..24799b956a5 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_cs_CZ.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_cs_CZ.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_da.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_da.properties index c3ac9b19299..8effe79084c 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_da.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_da.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_de.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_de.properties index 18cd4a68b23..fccc6d561e3 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_de.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_de.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_es.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_es.properties index f8d257c24ac..c76df877613 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_es.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_es.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_fr.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_fr.properties index 93d4bc05f73..686f8722431 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_fr.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_fr.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_it.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_it.properties index 22353b03366..3bb0abe4030 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_it.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_it.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_ja.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_ja.properties index ba1daf0d6a0..bcd6bb99bf4 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_ja.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_ja.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_nb.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_nb.properties index b2bcb4cfa5c..8485b66145e 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_nb.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_nb.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_nl.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_nl.properties index eb5245ccf5a..57360d5c39d 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_nl.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_nl.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_pl.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_pl.properties index efb954c5fff..199f7d26e0e 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_pl.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_pl.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_pt_BR.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_pt_BR.properties index 2244a405398..474cf326f9a 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_pt_BR.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_pt_BR.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_pt_PT.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_pt_PT.properties index d432eb5f6e0..27aa38dd2b2 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_pt_PT.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_pt_PT.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_ru.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_ru.properties index 2c7e7cdde79..c5e1d93446f 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_ru.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_ru.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_sv.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_sv.properties index 694ac13f23b..49079027e54 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_sv.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_sv.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_th.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_th.properties index 1219a71e4b4..9d2ba5ea9d5 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_th.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_th.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_zh_CN.properties b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_zh_CN.properties index 61a0705aef2..181f0a372e2 100644 --- a/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_zh_CN.properties +++ b/grails-data-neo4j/examples/grails3-neo4j/grails-app/i18n/messages_zh_CN.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/neo4j-spring-boot/gradle.properties b/grails-data-neo4j/examples/neo4j-spring-boot/gradle.properties index 577d09fd84d..7e47c128dc6 100644 --- a/grails-data-neo4j/examples/neo4j-spring-boot/gradle.properties +++ b/grails-data-neo4j/examples/neo4j-spring-boot/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/neo4j-standalone/gradle.properties b/grails-data-neo4j/examples/neo4j-standalone/gradle.properties index 577d09fd84d..7e47c128dc6 100644 --- a/grails-data-neo4j/examples/neo4j-standalone/gradle.properties +++ b/grails-data-neo4j/examples/neo4j-standalone/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/test-data-service/gradle.properties b/grails-data-neo4j/examples/test-data-service/gradle.properties index 577d09fd84d..7e47c128dc6 100644 --- a/grails-data-neo4j/examples/test-data-service/gradle.properties +++ b/grails-data-neo4j/examples/test-data-service/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/examples/test-data-service/grails-app/i18n/messages.properties b/grails-data-neo4j/examples/test-data-service/grails-app/i18n/messages.properties index 6d72d209d5d..a1ac5a2fd78 100644 --- a/grails-data-neo4j/examples/test-data-service/grails-app/i18n/messages.properties +++ b/grails-data-neo4j/examples/test-data-service/grails-app/i18n/messages.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/gradle.properties b/grails-data-neo4j/gradle.properties index 525b7557bf9..d860b09526b 100644 --- a/grails-data-neo4j/gradle.properties +++ b/grails-data-neo4j/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/grails-datastore-gorm-neo4j/src/test/resources/neo4j-server.properties b/grails-data-neo4j/grails-datastore-gorm-neo4j/src/test/resources/neo4j-server.properties index 238faacbabb..d7a5a75bf10 100644 --- a/grails-data-neo4j/grails-datastore-gorm-neo4j/src/test/resources/neo4j-server.properties +++ b/grails-data-neo4j/grails-datastore-gorm-neo4j/src/test/resources/neo4j-server.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-neo4j/grails-datastore-gorm-neo4j/src/test/resources/spy.properties b/grails-data-neo4j/grails-datastore-gorm-neo4j/src/test/resources/spy.properties index b10f569a2fd..41d82f4f5df 100644 --- a/grails-data-neo4j/grails-datastore-gorm-neo4j/src/test/resources/spy.properties +++ b/grails-data-neo4j/grails-datastore-gorm-neo4j/src/test/resources/spy.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-data-simple/build.gradle b/grails-data-simple/build.gradle index a603bcff0f6..176cd258ddc 100644 --- a/grails-data-simple/build.gradle +++ b/grails-data-simple/build.gradle @@ -96,4 +96,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapDatastore.java b/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapDatastore.java index 9094cdb0541..1e4aed04b31 100644 --- a/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapDatastore.java +++ b/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapDatastore.java @@ -18,20 +18,16 @@ */ package org.grails.datastore.mapping.simple; -import java.io.Closeable; -import java.io.IOException; -import java.io.Serializable; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - import groovy.lang.Closure; import org.grails.datastore.gorm.GormEnhancer; import org.grails.datastore.gorm.GormInstanceApi; import org.grails.datastore.gorm.GormStaticApi; import org.grails.datastore.gorm.GormValidationApi; -import org.grails.datastore.gorm.events.*; +import org.grails.datastore.gorm.events.AutoTimestampEventListener; +import org.grails.datastore.gorm.events.ConfigurableApplicationContextEventPublisher; +import org.grails.datastore.gorm.events.ConfigurableApplicationEventPublisher; +import org.grails.datastore.gorm.events.DefaultApplicationEventPublisher; +import org.grails.datastore.gorm.events.DomainEventListener; import org.grails.datastore.gorm.multitenancy.MultiTenantEventListener; import org.grails.datastore.gorm.utils.ClasspathEntityScanner; import org.grails.datastore.mapping.config.Settings; @@ -39,7 +35,17 @@ import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.DatastoreUtils; import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.core.connections.*; +import org.grails.datastore.mapping.core.connections.ConnectionSource; +import org.grails.datastore.mapping.core.connections.ConnectionSourceFactory; +import org.grails.datastore.mapping.core.connections.ConnectionSourceSettings; +import org.grails.datastore.mapping.core.connections.ConnectionSources; +import org.grails.datastore.mapping.core.connections.ConnectionSourcesInitializer; +import org.grails.datastore.mapping.core.connections.ConnectionSourcesProvider; +import org.grails.datastore.mapping.core.connections.ConnectionSourcesSupport; +import org.grails.datastore.mapping.core.connections.DefaultConnectionSource; +import org.grails.datastore.mapping.core.connections.InMemoryConnectionSources; +import org.grails.datastore.mapping.core.connections.MultipleConnectionSourceCapableDatastore; +import org.grails.datastore.mapping.core.connections.SingletonConnectionSources; import org.grails.datastore.mapping.core.exceptions.ConfigurationException; import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext; import org.grails.datastore.mapping.model.MappingContext; @@ -55,6 +61,14 @@ import org.springframework.core.env.PropertyResolver; import org.springframework.transaction.PlatformTransactionManager; +import java.io.Closeable; +import java.io.IOException; +import java.io.Serializable; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + /** * A simple implementation of the {@link org.grails.datastore.mapping.core.Datastore} interface that backs onto an in-memory map. * Mainly used for mocking and testing scenarios. @@ -63,19 +77,20 @@ * @since 1.0 */ @SuppressWarnings("rawtypes") -public class SimpleMapDatastore extends AbstractDatastore implements Closeable, TransactionCapableDatastore, MultipleConnectionSourceCapableDatastore, SchemaMultiTenantCapableDatastore, ConnectionSourceSettings>, ConnectionSourcesProvider, ConnectionSourceSettings> { +public class SimpleMapDatastore extends AbstractDatastore implements Closeable, TransactionCapableDatastore, MultipleConnectionSourceCapableDatastore, SchemaMultiTenantCapableDatastore, ConnectionSourceSettings>, ConnectionSourcesProvider, ConnectionSourceSettings> { + + protected final GormEnhancer gormEnhancer; + protected final Map datastoresByConnectionSource = new LinkedHashMap<>(); + protected final boolean failOnError; private final Map inmemoryData; private final TenantResolver tenantResolver; - protected final GormEnhancer gormEnhancer; private final ConfigurableApplicationEventPublisher eventPublisher; - private Map indices = new ConcurrentHashMap(); private final PlatformTransactionManager transactionManager; - private final ConnectionSources, ConnectionSourceSettings> connectionSources; + private final ConnectionSources, ConnectionSourceSettings> connectionSources; private final MultiTenancySettings.MultiTenancyMode multiTenancyMode; - protected final Map datastoresByConnectionSource = new LinkedHashMap<>(); - protected final boolean failOnError; + private final Map indices = new ConcurrentHashMap(); - public SimpleMapDatastore(ConnectionSources, ConnectionSourceSettings> connectionSources, MappingContext mappingContext, ConfigurableApplicationEventPublisher eventPublisher) { + public SimpleMapDatastore(ConnectionSources, ConnectionSourceSettings> connectionSources, MappingContext mappingContext, ConfigurableApplicationEventPublisher eventPublisher) { super(mappingContext); this.connectionSources = connectionSources; ConnectionSource, ConnectionSourceSettings> defaultConnectionSource = connectionSources.getDefaultConnectionSource(); @@ -88,17 +103,15 @@ public SimpleMapDatastore(ConnectionSources, ConnectionSourceSet this.tenantResolver = multiTenancy.getTenantResolver(); PropertyResolver config = connectionSources.getBaseConfiguration(); this.failOnError = config.getProperty(Settings.SETTING_FAIL_ON_ERROR, Boolean.class, false); - if(!(connectionSources instanceof SingletonConnectionSources)) { - - Iterable, ConnectionSourceSettings>> allConnectionSources = connectionSources.getAllConnectionSources(); - for (ConnectionSource, ConnectionSourceSettings> connectionSource : allConnectionSources) { + if (!(connectionSources instanceof SingletonConnectionSources)) { + Iterable, ConnectionSourceSettings>> allConnectionSources = connectionSources.getAllConnectionSources(); + for (ConnectionSource, ConnectionSourceSettings> connectionSource : allConnectionSources) { SingletonConnectionSources singletonConnectionSources = new SingletonConnectionSources(connectionSource, connectionSources.getBaseConfiguration()); SimpleMapDatastore childDatastore; - if(ConnectionSource.DEFAULT.equals(connectionSource.getName())) { + if (ConnectionSource.DEFAULT.equals(connectionSource.getName())) { childDatastore = this; - } - else { + } else { childDatastore = new SimpleMapDatastore(singletonConnectionSources, mappingContext, eventPublisher) { @Override protected GormEnhancer initialize(ConnectionSourceSettings settings) { @@ -113,11 +126,11 @@ protected GormEnhancer initialize(ConnectionSourceSettings settings) { this.gormEnhancer = initialize(defaultConnectionSource.getSettings()); } - public SimpleMapDatastore(ConnectionSources, ConnectionSourceSettings> connectionSources, ConfigurableApplicationEventPublisher eventPublisher, Class... classes) { - this(connectionSources, createMappingContext(connectionSources,classes), eventPublisher); + public SimpleMapDatastore(ConnectionSources, ConnectionSourceSettings> connectionSources, ConfigurableApplicationEventPublisher eventPublisher, Class... classes) { + this(connectionSources, createMappingContext(connectionSources, classes), eventPublisher); } - public SimpleMapDatastore(PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Class...classes) { + public SimpleMapDatastore(PropertyResolver configuration, ConfigurableApplicationEventPublisher eventPublisher, Class... classes) { this(ConnectionSourcesInitializer.create(new SimpleMapConnectionSourceFactory(), configuration), eventPublisher, classes); } @@ -125,41 +138,39 @@ public SimpleMapDatastore() { this(DatastoreUtils.createPropertyResolver(null), new DefaultApplicationEventPublisher()); } - public SimpleMapDatastore(final Iterable dataSourceNames, Class...classes) { - this(createMultipleDataSources(dataSourceNames, DatastoreUtils.createPropertyResolver(null)),new DefaultApplicationEventPublisher(), classes); + public SimpleMapDatastore(final Iterable dataSourceNames, Class... classes) { + this(createMultipleDataSources(dataSourceNames, DatastoreUtils.createPropertyResolver(null)), new DefaultApplicationEventPublisher(), classes); } - public SimpleMapDatastore(Class...classes) { - this(DatastoreUtils.createPropertyResolver(null),new DefaultApplicationEventPublisher(), classes); + public SimpleMapDatastore(Class... classes) { + this(DatastoreUtils.createPropertyResolver(null), new DefaultApplicationEventPublisher(), classes); } - - public SimpleMapDatastore(PropertyResolver configuration, final Iterable dataSourceNames, Class...classes) { - this(createMultipleDataSources(dataSourceNames, configuration),new DefaultApplicationEventPublisher(), classes); + public SimpleMapDatastore(PropertyResolver configuration, final Iterable dataSourceNames, Class... classes) { + this(createMultipleDataSources(dataSourceNames, configuration), new DefaultApplicationEventPublisher(), classes); } - public SimpleMapDatastore(PropertyResolver configuration, final Iterable dataSourceNames, Package...packages) { - this(createMultipleDataSources(dataSourceNames, configuration),new DefaultApplicationEventPublisher(), new ClasspathEntityScanner().scan(packages)); + public SimpleMapDatastore(PropertyResolver configuration, final Iterable dataSourceNames, Package... packages) { + this(createMultipleDataSources(dataSourceNames, configuration), new DefaultApplicationEventPublisher(), new ClasspathEntityScanner().scan(packages)); } - - public SimpleMapDatastore(Map configuration, final Iterable dataSourceNames, Package...packages) { - this(createMultipleDataSources(dataSourceNames, DatastoreUtils.createPropertyResolver(configuration)),new DefaultApplicationEventPublisher(), new ClasspathEntityScanner().scan(packages)); + public SimpleMapDatastore(Map configuration, final Iterable dataSourceNames, Package... packages) { + this(createMultipleDataSources(dataSourceNames, DatastoreUtils.createPropertyResolver(configuration)), new DefaultApplicationEventPublisher(), new ClasspathEntityScanner().scan(packages)); } - public SimpleMapDatastore(Map configuration, Package...packages) { - this(DatastoreUtils.createPropertyResolver(configuration),new DefaultApplicationEventPublisher(), new ClasspathEntityScanner().scan(packages)); + public SimpleMapDatastore(Map configuration, Package... packages) { + this(DatastoreUtils.createPropertyResolver(configuration), new DefaultApplicationEventPublisher(), new ClasspathEntityScanner().scan(packages)); } public SimpleMapDatastore(PropertyResolver configuration, final Iterable dataSourceNames, Package packageToScan) { - this(createMultipleDataSources(dataSourceNames, configuration),new DefaultApplicationEventPublisher(), new ClasspathEntityScanner().scan(packageToScan)); + this(createMultipleDataSources(dataSourceNames, configuration), new DefaultApplicationEventPublisher(), new ClasspathEntityScanner().scan(packageToScan)); } /** * Creates a map based datastore backing onto the specified map * * @param datastore The datastore to back on to - * @param ctx the application context + * @param ctx the application context */ @Deprecated public SimpleMapDatastore(Map datastore, ConfigurableApplicationContext ctx) { @@ -167,16 +178,6 @@ public SimpleMapDatastore(Map datastore, ConfigurableApplicationCon setApplicationContext(ctx); } - private static PropertyResolver getConfiguration(ConfigurableApplicationContext ctx) { - PropertyResolver propertyResolver; - try { - propertyResolver = ctx.getBean(PropertyResolver.class); - } catch (Exception e) { - propertyResolver = DatastoreUtils.createPropertyResolver(null); - } - return propertyResolver; - } - @Deprecated public SimpleMapDatastore(ConfigurableApplicationContext ctx) { this(getConfiguration(ctx), new ConfigurableApplicationContextEventPublisher(ctx)); @@ -193,6 +194,16 @@ public SimpleMapDatastore(MappingContext mappingContext, ConfigurableApplication this(ConnectionSourcesInitializer.create(new SimpleMapConnectionSourceFactory(), DatastoreUtils.createPropertyResolver(null)), mappingContext, new ConfigurableApplicationContextEventPublisher(ctx)); } + private static PropertyResolver getConfiguration(ConfigurableApplicationContext ctx) { + PropertyResolver propertyResolver; + try { + propertyResolver = ctx.getBean(PropertyResolver.class); + } catch (Exception e) { + propertyResolver = DatastoreUtils.createPropertyResolver(null); + } + return propertyResolver; + } + protected static KeyValueMappingContext createMappingContext(ConnectionSources, ConnectionSourceSettings> connectionSources, Class... classes) { KeyValueMappingContext ctx = new KeyValueMappingContext("test", connectionSources.getDefaultConnectionSource().getSettings()); ctx.addPersistentEntities(classes); @@ -248,16 +259,15 @@ protected GormInstanceApi getInstanceApi(Class cls, String qualifier) private SimpleMapDatastore getDatastoreForQualifier(Class cls, String qualifier) { String defaultConnectionSourceName = ConnectionSourcesSupport.getDefaultConnectionSourceName(getMappingContext().getPersistentEntity(cls.getName())); boolean isDefaultQualifier = qualifier.equals(ConnectionSource.DEFAULT); - if(isDefaultQualifier && defaultConnectionSourceName.equals(ConnectionSource.DEFAULT)) { + if (isDefaultQualifier && defaultConnectionSourceName.equals(ConnectionSource.DEFAULT)) { return SimpleMapDatastore.this; - } - else { - if(isDefaultQualifier) { + } else { + if (isDefaultQualifier) { qualifier = defaultConnectionSourceName; } - ConnectionSource, ConnectionSourceSettings> connectionSource = connectionSources.getConnectionSource(qualifier); - if(connectionSource == null) { - throw new ConfigurationException("Invalid connection ["+defaultConnectionSourceName+"] configured for class ["+cls+"]"); + ConnectionSource, ConnectionSourceSettings> connectionSource = connectionSources.getConnectionSource(qualifier); + if (connectionSource == null) { + throw new ConfigurationException("Invalid connection [" + defaultConnectionSourceName + "] configured for class [" + cls + "]"); } return SimpleMapDatastore.this.datastoresByConnectionSource.get(qualifier); } @@ -268,7 +278,7 @@ private SimpleMapDatastore getDatastoreForQualifier(Class cls, String qua protected void registerEventListeners(ConfigurableApplicationEventPublisher eventPublisher) { eventPublisher.addApplicationListener(new DomainEventListener(this)); eventPublisher.addApplicationListener(new AutoTimestampEventListener(this)); - if(multiTenancyMode == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) { + if (multiTenancyMode == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) { eventPublisher.addApplicationListener(new MultiTenantEventListener(this)); } } @@ -318,10 +328,10 @@ public TenantResolver getTenantResolver() { @Override public Datastore getDatastoreForTenantId(Serializable tenantId) { - if(multiTenancyMode == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) { + if (multiTenancyMode == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) { return this; } - if(tenantId != null) { + if (tenantId != null) { return getDatastoreForConnection(tenantId.toString()); } return this; @@ -334,8 +344,7 @@ public T1 withNewSession(Serializable tenantId, Closure callable) { try { DatastoreUtils.bindNewSession(session); return callable.call(session); - } - finally { + } finally { DatastoreUtils.unbindSession(session); } } @@ -344,8 +353,8 @@ public T1 withNewSession(Serializable tenantId, Closure callable) { public Datastore getDatastoreForConnection(String connectionName) { SimpleMapDatastore childDatastore = datastoresByConnectionSource.get(connectionName); - if(childDatastore == null) { - throw new ConfigurationException("No datastore found for connection named ["+connectionName+"]"); + if (childDatastore == null) { + throw new ConfigurationException("No datastore found for connection named [" + connectionName + "]"); } return childDatastore; } @@ -366,10 +375,9 @@ public void addTenantForSchema(String schemaName) { SingletonConnectionSources singletonConnectionSources = new SingletonConnectionSources(connectionSource, connectionSources.getBaseConfiguration()); SimpleMapDatastore childDatastore; - if(ConnectionSource.DEFAULT.equals(connectionSource.getName())) { + if (ConnectionSource.DEFAULT.equals(connectionSource.getName())) { childDatastore = this; - } - else { + } else { childDatastore = new SimpleMapDatastore(singletonConnectionSources, mappingContext, eventPublisher) { @Override protected GormEnhancer initialize(ConnectionSourceSettings settings) { diff --git a/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapSession.java b/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapSession.java index 47c3575656e..d5924613f18 100644 --- a/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapSession.java +++ b/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/SimpleMapSession.java @@ -18,15 +18,15 @@ */ package org.grails.datastore.mapping.simple; -import java.util.Map; - -import org.springframework.context.ApplicationEventPublisher; import org.grails.datastore.mapping.core.AbstractSession; import org.grails.datastore.mapping.engine.Persister; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.simple.engine.SimpleMapEntityPersister; import org.grails.datastore.mapping.transactions.Transaction; +import org.springframework.context.ApplicationEventPublisher; + +import java.util.Map; /** * A simple implementation of the {@link org.grails.datastore.mapping.core.Session} interface that backs onto an in-memory map. @@ -37,10 +37,11 @@ */ @SuppressWarnings("rawtypes") public class SimpleMapSession extends AbstractSession { + private Map datastore; public SimpleMapSession(SimpleMapDatastore datastore, MappingContext mappingContext, - ApplicationEventPublisher publisher) { + ApplicationEventPublisher publisher) { super(datastore, mappingContext, publisher); this.datastore = datastore.getBackingMap(); } @@ -57,7 +58,7 @@ protected Persister createPersister(Class cls, MappingContext mappingContext) { return null; } return new SimpleMapEntityPersister(mappingContext, entity, this, - (SimpleMapDatastore) getDatastore(), publisher); + (SimpleMapDatastore) getDatastore(), publisher); } public Map getBackingMap() { @@ -74,6 +75,7 @@ public Map getNativeInterface() { } private class MockTransaction implements Transaction { + public MockTransaction(SimpleMapSession simpleMapSession) { } diff --git a/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/connections/SimpleMapConnectionSourceFactory.groovy b/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/connections/SimpleMapConnectionSourceFactory.groovy index 25d27e8fa49..837077d48fc 100644 --- a/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/connections/SimpleMapConnectionSourceFactory.groovy +++ b/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/connections/SimpleMapConnectionSourceFactory.groovy @@ -20,7 +20,11 @@ package org.grails.datastore.mapping.simple.connections import groovy.transform.CompileStatic -import org.grails.datastore.mapping.core.connections.* +import org.grails.datastore.mapping.core.connections.AbstractConnectionSourceFactory +import org.grails.datastore.mapping.core.connections.ConnectionSource +import org.grails.datastore.mapping.core.connections.ConnectionSourceSettings +import org.grails.datastore.mapping.core.connections.ConnectionSourceSettingsBuilder +import org.grails.datastore.mapping.core.connections.DefaultConnectionSource import org.springframework.core.env.PropertyResolver import java.util.concurrent.ConcurrentHashMap @@ -32,11 +36,13 @@ import java.util.concurrent.ConcurrentHashMap * @since 6.0 */ @CompileStatic -class SimpleMapConnectionSourceFactory extends AbstractConnectionSourceFactory, ConnectionSourceSettings> { +class SimpleMapConnectionSourceFactory extends AbstractConnectionSourceFactory, ConnectionSourceSettings> { + @Override ConnectionSource, ConnectionSourceSettings> create(String name, ConnectionSourceSettings settings) { - return new DefaultConnectionSource, ConnectionSourceSettings>(name, new ConcurrentHashMap(), settings) + return new DefaultConnectionSource, ConnectionSourceSettings>(name, new ConcurrentHashMap(), settings) } + @Override Serializable getConnectionSourcesConfigurationKey() { return PREFIX + ".connections" diff --git a/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/engine/SimpleMapEntityPersister.groovy b/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/engine/SimpleMapEntityPersister.groovy index 707c5429348..a3413a5b0ae 100644 --- a/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/engine/SimpleMapEntityPersister.groovy +++ b/grails-data-simple/src/main/groovy/org/grails/datastore/mapping/simple/engine/SimpleMapEntityPersister.groovy @@ -63,8 +63,7 @@ class SimpleMapEntityPersister extends AbstractKeyValueEntityPersister - Query.Junction queryCriteria = aq.criteria - return executeAssociationSubQuery(datastore[getFamily(association.associatedEntity)], association.associatedEntity,queryCriteria, aq.association) - }, - - (FunctionCallingCriterion): { allEntities, Association association, FunctionCallingCriterion fcc -> - def criterion = fcc.propertyCriterion - def handler = associationQueryHandlers[criterion.class] - def function = functionHandlers[fcc.functionName] - if (handler != null && function != null) { - try { - return handler.call(allEntities, association,criterion, function) - } - catch(MissingMethodException ignored) { + (AssociationQuery) : { allEntities, Association association, AssociationQuery aq -> + Query.Junction queryCriteria = aq.criteria + return executeAssociationSubQuery(datastore[getFamily(association.associatedEntity)], association.associatedEntity, queryCriteria, aq.association) + }, + + (FunctionCallingCriterion): { allEntities, Association association, FunctionCallingCriterion fcc -> + def criterion = fcc.propertyCriterion + def handler = associationQueryHandlers[criterion.class] + def function = functionHandlers[fcc.functionName] + if (handler != null && function != null) { + try { + return handler.call(allEntities, association, criterion, function) + } + catch (MissingMethodException ignored) { + throw new InvalidDataAccessResourceUsageException("Unsupported function '$function' used in query") + } + } else { throw new InvalidDataAccessResourceUsageException("Unsupported function '$function' used in query") } + }, + (Query.Like) : { allEntities, Association association, Query.Like like, Closure function = { it } -> + queryAssociation(allEntities, association) { + def regexFormat = like.pattern.replaceAll('%', '.*?') + function(resolveIfEmbedded(like.property, it)) ==~ regexFormat + } + }, + (Query.RLike) : { allEntities, Association association, Query.RLike like, Closure function = { it } -> + queryAssociation(allEntities, association) { + def regexFormat = like.pattern + function(resolveIfEmbedded(like.property, it)) ==~ regexFormat + } + }, + (Query.ILike) : { allEntities, Association association, Query.Like like, Closure function = { it } -> + queryAssociation(allEntities, association) { + def regexFormat = like.pattern.replaceAll('%', '.*?') + def pattern = Pattern.compile(regexFormat, Pattern.CASE_INSENSITIVE) + pattern.matcher(function(resolveIfEmbedded(like.property, it))).find() + } + }, + (Query.Equals) : { allEntities, Association association, Query.Equals eq, Closure function = { it } -> + queryAssociation(allEntities, association) { + final value = subqueryIfNecessary(eq) + function(resolveIfEmbedded(eq.property, it)) == value + } + }, + (Query.IsNull) : { allEntities, Association association, Query.IsNull eq, Closure function = { it } -> + queryAssociation(allEntities, association) { + function(resolveIfEmbedded(eq.property, it)) == null + } + }, + (Query.NotEquals) : { allEntities, Association association, Query.NotEquals eq, Closure function = { it } -> + queryAssociation(allEntities, association) { + final value = subqueryIfNecessary(eq) + function(resolveIfEmbedded(eq.property, it)) != value + } + }, + (Query.IsNotNull) : { allEntities, Association association, Query.IsNotNull eq, Closure function = { it } -> + queryAssociation(allEntities, association) { + function(resolveIfEmbedded(eq.property, it)) != null + } + }, + (Query.IdEquals) : { allEntities, Association association, Query.IdEquals eq, Closure function = { it } -> + queryAssociation(allEntities, association) { + function(resolveIfEmbedded(eq.property, it)) == eq.value + } + }, + (Query.Between) : { allEntities, Association association, Query.Between between, Closure function = { it } -> + queryAssociation(allEntities, association) { + def from = between.from + def to = between.to + function(resolveIfEmbedded(between.property, it)) >= from && function(resolveIfEmbedded(between.property, it)) <= to + } + }, + (Query.GreaterThan) : { allEntities, Association association, Query.GreaterThan gt, Closure function = { it } -> + queryAssociation(allEntities, association) { + final value = subqueryIfNecessary(gt) + function(resolveIfEmbedded(gt.property, it)) > value + } + }, + (Query.LessThan) : { allEntities, Association association, Query.LessThan lt, Closure function = { it } -> + queryAssociation(allEntities, association) { + final value = subqueryIfNecessary(lt) + function(resolveIfEmbedded(lt.property, it)) < value + } + }, + (Query.GreaterThanEquals) : { allEntities, Association association, Query.GreaterThanEquals gt, Closure function = { it } -> + queryAssociation(allEntities, association) { + final value = subqueryIfNecessary(gt) + function(resolveIfEmbedded(gt.property, it)) >= value + } + }, + (Query.LessThanEquals) : { allEntities, Association association, Query.LessThanEquals lt, Closure function = { it } -> + queryAssociation(allEntities, association) { + final value = subqueryIfNecessary(lt) + function(resolveIfEmbedded(lt.property, it)) <= value + } + }, + (Query.In) : { allEntities, Association association, Query.In inList, Closure function = { it } -> + queryAssociation(allEntities, association) { + inList.values?.contains function(resolveIfEmbedded(inList.property, it)) + } } - else { - throw new InvalidDataAccessResourceUsageException("Unsupported function '$function' used in query") - } - }, - (Query.Like): { allEntities, Association association, Query.Like like, Closure function = {it} -> - queryAssociation(allEntities, association) { - def regexFormat = like.pattern.replaceAll('%', '.*?') - function(resolveIfEmbedded(like.property, it)) ==~ regexFormat - } - }, - (Query.RLike): { allEntities, Association association, Query.RLike like, Closure function = {it} -> - queryAssociation(allEntities, association) { - def regexFormat = like.pattern - function(resolveIfEmbedded(like.property, it)) ==~ regexFormat - } - }, - (Query.ILike): { allEntities, Association association, Query.Like like, Closure function = {it} -> - queryAssociation(allEntities, association) { - def regexFormat = like.pattern.replaceAll('%', '.*?') - def pattern = Pattern.compile(regexFormat, Pattern.CASE_INSENSITIVE) - pattern.matcher(function(resolveIfEmbedded(like.property, it))).find() - } - }, - (Query.Equals): { allEntities, Association association, Query.Equals eq, Closure function = {it} -> - queryAssociation(allEntities, association) { - final value = subqueryIfNecessary(eq) - function(resolveIfEmbedded(eq.property, it)) == value - } - }, - (Query.IsNull): { allEntities, Association association, Query.IsNull eq, Closure function = {it} -> - queryAssociation(allEntities, association) { - function(resolveIfEmbedded(eq.property, it)) == null - } - }, - (Query.NotEquals): { allEntities, Association association, Query.NotEquals eq , Closure function = {it}-> - queryAssociation(allEntities, association) { - final value = subqueryIfNecessary(eq) - function(resolveIfEmbedded(eq.property, it)) != value - } - }, - (Query.IsNotNull): { allEntities, Association association, Query.IsNotNull eq , Closure function = {it}-> - queryAssociation(allEntities, association) { - function(resolveIfEmbedded(eq.property, it)) != null - } - }, - (Query.IdEquals): { allEntities, Association association, Query.IdEquals eq , Closure function = {it}-> - queryAssociation(allEntities, association) { - function(resolveIfEmbedded(eq.property, it)) == eq.value - } - }, - (Query.Between): { allEntities, Association association, Query.Between between, Closure function = {it} -> - queryAssociation(allEntities, association) { - def from = between.from - def to = between.to - function(resolveIfEmbedded(between.property, it)) >= from && function(resolveIfEmbedded(between.property, it)) <= to - } - }, - (Query.GreaterThan):{ allEntities, Association association, Query.GreaterThan gt, Closure function = {it} -> - queryAssociation(allEntities, association) { - final value = subqueryIfNecessary(gt) - function(resolveIfEmbedded(gt.property, it)) > value - } - }, - (Query.LessThan):{ allEntities, Association association, Query.LessThan lt, Closure function = {it} -> - queryAssociation(allEntities, association) { - final value = subqueryIfNecessary(lt) - function(resolveIfEmbedded(lt.property, it)) < value - } - }, - (Query.GreaterThanEquals):{ allEntities, Association association, Query.GreaterThanEquals gt, Closure function = {it} -> - queryAssociation(allEntities, association) { - final value = subqueryIfNecessary(gt) - function(resolveIfEmbedded(gt.property, it)) >= value - } - }, - (Query.LessThanEquals):{ allEntities, Association association, Query.LessThanEquals lt, Closure function = {it} -> - queryAssociation(allEntities, association) { - final value = subqueryIfNecessary(lt) - function(resolveIfEmbedded(lt.property, it)) <= value - } - }, - (Query.In):{ allEntities, Association association, Query.In inList, Closure function = {it} -> - queryAssociation(allEntities, association) { - inList.values?.contains function(resolveIfEmbedded(inList.property, it)) - } - } ] protected queryAssociation(allEntities, Association association, Closure callable) { @@ -294,7 +282,7 @@ class SimpleMapQuery extends Query { // If the entity isn't mocked properly this will happen and can cause a NPE. PersistentEntity associatedEntity = association.associatedEntity - if( associatedEntity == null ) { + if (associatedEntity == null) { throw new IllegalStateException("No associated entity found for ${association.owner}.${association.name}") } @@ -302,8 +290,7 @@ class SimpleMapQuery extends Query { if (associated) { callable.call(associated) } - } - else { + } else { def indexer = entityPersister.getAssociationIndexer(it.value, association) def results = indexer.query(it.key) if (results) { @@ -329,10 +316,9 @@ class SimpleMapQuery extends Query { if (handler) { resultList << handler.call(allEntities, property, criterion) - } - else if (criterion instanceof Query.Junction) { + } else if (criterion instanceof Query.Junction) { Query.Junction junction = criterion - resultList << executeAssociationSubQuery(allEntities,associatedEntity, junction, property) + resultList << executeAssociationSubQuery(allEntities, associatedEntity, junction, property) } } return applyJunctionToResults(queryCriteria, resultList) @@ -341,282 +327,278 @@ class SimpleMapQuery extends Query { def functionHandlers = [ second: { it[Calendar.SECOND] }, minute: { it[Calendar.MINUTE] }, - hour: { it[Calendar.HOUR_OF_DAY] }, - year: { it[Calendar.YEAR] }, + hour : { it[Calendar.HOUR_OF_DAY] }, + year : { it[Calendar.YEAR] }, month: { it[Calendar.MONTH] }, - day: { it[Calendar.DAY_OF_MONTH] }, + day : { it[Calendar.DAY_OF_MONTH] }, lower: { it.toString().toLowerCase() }, upper: { it.toString().toUpperCase() }, - trim: { it.toString().trim() }, + trim : { it.toString().trim() }, length: { it.toString().size() } ] def handlers = [ - (FunctionCallingCriterion): { FunctionCallingCriterion fcc, PersistentProperty property -> - def criterion = fcc.propertyCriterion - def handler = handlers[criterion.class] - def function = functionHandlers[fcc.functionName] - if (handler != null && function != null) { - try { - handler.call(criterion, property, function, fcc.onValue) - } - catch(MissingMethodException e) { + (FunctionCallingCriterion) : { FunctionCallingCriterion fcc, PersistentProperty property -> + def criterion = fcc.propertyCriterion + def handler = handlers[criterion.class] + def function = functionHandlers[fcc.functionName] + if (handler != null && function != null) { + try { + handler.call(criterion, property, function, fcc.onValue) + } + catch (MissingMethodException e) { + throw new InvalidDataAccessResourceUsageException("Unsupported function '$function' used in query") + } + } else { throw new InvalidDataAccessResourceUsageException("Unsupported function '$function' used in query") } - } - else { - throw new InvalidDataAccessResourceUsageException("Unsupported function '$function' used in query") - } - }, - (AssociationQuery): { AssociationQuery aq, PersistentProperty property -> - Query.Junction queryCriteria = aq.criteria - return executeAssociationSubQuery(datastore[family], aq.association.associatedEntity, queryCriteria, property) - }, - (Query.EqualsAll):{ Query.EqualsAll equalsAll, PersistentProperty property, Closure function=null, boolean onValue = false -> - def name = equalsAll.property - final values = subqueryIfNecessary(equalsAll, false) - Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") - def allEntities = datastore[family] - allEntities.findAll { entry -> - values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) == it } - } - .collect { it.key } - }, - (Query.NotEqualsAll):{ Query.NotEqualsAll notEqualsAll, PersistentProperty property, Closure function=null, boolean onValue = false -> - def name = notEqualsAll.property - final values = subqueryIfNecessary(notEqualsAll, false) - Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") - def allEntities = datastore[family] - allEntities.findAll { entry -> - values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) != it } - } - .collect { it.key } - }, - (Query.GreaterThanAll):{ Query.GreaterThanAll greaterThanAll, PersistentProperty property, Closure function=null, boolean onValue = false -> - def name = greaterThanAll.property - final values = subqueryIfNecessary(greaterThanAll, false) - Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") - def allEntities = datastore[family] - allEntities.findAll { entry -> - values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) > it } - } - .collect { it.key } - }, - (Query.LessThanAll):{ Query.LessThanAll lessThanAll, PersistentProperty property, Closure function=null, boolean onValue = false -> - def name = lessThanAll.property - final values = subqueryIfNecessary(lessThanAll, false) - Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") - def allEntities = datastore[family] - allEntities.findAll { entry -> - values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) < it } - } - .collect { it.key } - }, - (Query.LessThanEqualsAll):{ Query.LessThanEqualsAll lessThanEqualsAll, PersistentProperty property, Closure function=null, boolean onValue = false -> - def name = lessThanEqualsAll.property - final values = subqueryIfNecessary(lessThanEqualsAll, false) - Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") - def allEntities = datastore[family] - allEntities.findAll { entry -> - values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) <= it } - } - .collect { it.key } - }, - (Query.GreaterThanEqualsAll):{ Query.GreaterThanEqualsAll greaterThanAll, PersistentProperty property, Closure function=null, boolean onValue = false -> - def name = greaterThanAll.property - final values = subqueryIfNecessary(greaterThanAll, false) - Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") - def allEntities = datastore[family] - allEntities.findAll { entry -> - values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) >= it } - } - .collect { it.key } - }, - (Query.Equals): { Query.Equals equals, PersistentProperty property, Closure function = null, boolean onValue = false -> - def indexer = entityPersister.getPropertyIndexer(property) - def value = subqueryIfNecessary(equals) - - if(value && property instanceof ToOne && property.type.isInstance(value)) { - value = entityPersister.getObjectIdentifier(value) - } - - if (function != null) { + }, + (AssociationQuery) : { AssociationQuery aq, PersistentProperty property -> + Query.Junction queryCriteria = aq.criteria + return executeAssociationSubQuery(datastore[family], aq.association.associatedEntity, queryCriteria, property) + }, + (Query.EqualsAll) : { Query.EqualsAll equalsAll, PersistentProperty property, Closure function = null, boolean onValue = false -> + def name = equalsAll.property + final values = subqueryIfNecessary(equalsAll, false) + Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") def allEntities = datastore[family] - allEntities.findAll { - def calculatedValue = function(it.value[property.name]) - calculatedValue == value - }.collect { it.key } - } - else { - if (equals.property.contains('.') || value == null) { + allEntities.findAll { entry -> + values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) == it } + } + .collect { it.key } + }, + (Query.NotEqualsAll) : { Query.NotEqualsAll notEqualsAll, PersistentProperty property, Closure function = null, boolean onValue = false -> + def name = notEqualsAll.property + final values = subqueryIfNecessary(notEqualsAll, false) + Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") + def allEntities = datastore[family] + allEntities.findAll { entry -> + values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) != it } + } + .collect { it.key } + }, + (Query.GreaterThanAll) : { Query.GreaterThanAll greaterThanAll, PersistentProperty property, Closure function = null, boolean onValue = false -> + def name = greaterThanAll.property + final values = subqueryIfNecessary(greaterThanAll, false) + Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") + def allEntities = datastore[family] + allEntities.findAll { entry -> + values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) > it } + } + .collect { it.key } + }, + (Query.LessThanAll) : { Query.LessThanAll lessThanAll, PersistentProperty property, Closure function = null, boolean onValue = false -> + def name = lessThanAll.property + final values = subqueryIfNecessary(lessThanAll, false) + Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") + def allEntities = datastore[family] + allEntities.findAll { entry -> + values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) < it } + } + .collect { it.key } + }, + (Query.LessThanEqualsAll) : { Query.LessThanEqualsAll lessThanEqualsAll, PersistentProperty property, Closure function = null, boolean onValue = false -> + def name = lessThanEqualsAll.property + final values = subqueryIfNecessary(lessThanEqualsAll, false) + Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") + def allEntities = datastore[family] + allEntities.findAll { entry -> + values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) <= it } + } + .collect { it.key } + }, + (Query.GreaterThanEqualsAll) : { Query.GreaterThanEqualsAll greaterThanAll, PersistentProperty property, Closure function = null, boolean onValue = false -> + def name = greaterThanAll.property + final values = subqueryIfNecessary(greaterThanAll, false) + Assert.isTrue(values.every { property.type.isInstance(it) }, "Subquery returned values that are not compatible with the type of property '$name': $values") + def allEntities = datastore[family] + allEntities.findAll { entry -> + values.every { (function != null ? function(resolveIfEmbedded(name, entry.value)) : resolveIfEmbedded(name, entry.value)) >= it } + } + .collect { it.key } + }, + (Query.Equals) : { Query.Equals equals, PersistentProperty property, Closure function = null, boolean onValue = false -> + def indexer = entityPersister.getPropertyIndexer(property) + def value = subqueryIfNecessary(equals) + + if (value && property instanceof ToOne && property.type.isInstance(value)) { + value = entityPersister.getObjectIdentifier(value) + } + + if (function != null) { def allEntities = datastore[family] - return allEntities.findAll { resolveIfEmbedded(equals.property, it.value) == value }.collect { it.key } + allEntities.findAll { + def calculatedValue = function(it.value[property.name]) + calculatedValue == value + }.collect { it.key } + } else { + if (equals.property.contains('.') || value == null) { + def allEntities = datastore[family] + return allEntities.findAll { resolveIfEmbedded(equals.property, it.value) == value }.collect { it.key } + } else { + return indexer.query(value) + } } - else { - return indexer.query(value) + }, + (Query.IsNull) : { Query.IsNull equals, PersistentProperty property, Closure function = null, boolean onValue = false -> + handlers[Query.Equals].call(new Query.Equals(equals.property, null), property, function) + }, + (Query.IdEquals) : { Query.IdEquals equals, PersistentProperty property -> + def indexer = entityPersister.getPropertyIndexer(property) + return indexer.query(equals.value) + }, + (Query.NotEquals) : { Query.NotEquals equals, PersistentProperty property, Closure function = null, boolean onValue = false -> + def indexed = handlers[Query.Equals].call(new Query.Equals(equals.property, equals.value), property, function) + return negateResults(indexed) + }, + (Query.IsNotNull) : { Query.IsNotNull equals, PersistentProperty property, Closure function = null, boolean onValue = false -> + def indexed = handlers[Query.Equals].call(new Query.Equals(equals.property, null), property, function) + return negateResults(indexed) + }, + (Query.Like) : { Query.Like like, PersistentProperty property -> + def indexer = entityPersister.getPropertyIndexer(property) + + def root = indexer.indexRoot + def regexFormat = like.pattern.replaceAll('%', '.*?') + def pattern = "${root}:${regexFormat}" + def matchingIndices = entityPersister.indices.findAll { key, value -> + key ==~ pattern } - } - }, - (Query.IsNull): { Query.IsNull equals, PersistentProperty property, Closure function = null , boolean onValue = false-> - handlers[Query.Equals].call(new Query.Equals(equals.property, null), property, function) - }, - (Query.IdEquals): { Query.IdEquals equals, PersistentProperty property -> - def indexer = entityPersister.getPropertyIndexer(property) - return indexer.query(equals.value) - }, - (Query.NotEquals): { Query.NotEquals equals, PersistentProperty property, Closure function = null, boolean onValue = false -> - def indexed = handlers[Query.Equals].call(new Query.Equals(equals.property, equals.value), property, function) - return negateResults(indexed) - }, - (Query.IsNotNull): { Query.IsNotNull equals, PersistentProperty property, Closure function = null, boolean onValue = false -> - def indexed = handlers[Query.Equals].call(new Query.Equals(equals.property, null), property, function) - return negateResults(indexed) - }, - (Query.Like): { Query.Like like, PersistentProperty property -> - def indexer = entityPersister.getPropertyIndexer(property) - - def root = indexer.indexRoot - def regexFormat = like.pattern.replaceAll('%', '.*?') - def pattern = "${root}:${regexFormat}" - def matchingIndices = entityPersister.indices.findAll { key, value -> - key ==~ pattern - } - Set result = [] - for (indexed in matchingIndices) { - result.addAll(indexed.value) - } + Set result = [] + for (indexed in matchingIndices) { + result.addAll(indexed.value) + } - return result.toList() - }, - (Query.ILike): { Query.ILike like, PersistentProperty property -> - def regexFormat = like.pattern.replaceAll('%', '.*?') - return executeLikeWithRegex(entityPersister, property, regexFormat) - }, - (Query.RLike): { Query.RLike like, PersistentProperty property -> - def regexFormat = like.pattern - return executeLikeWithRegex(entityPersister, property, regexFormat) - }, - (Query.In): { Query.In inList, PersistentProperty property -> - def disjunction = new Query.Disjunction() - for (value in inList.values) { - disjunction.add(Restrictions.eq(inList.name, value)) - } + return result.toList() + }, + (Query.ILike) : { Query.ILike like, PersistentProperty property -> + def regexFormat = like.pattern.replaceAll('%', '.*?') + return executeLikeWithRegex(entityPersister, property, regexFormat) + }, + (Query.RLike) : { Query.RLike like, PersistentProperty property -> + def regexFormat = like.pattern + return executeLikeWithRegex(entityPersister, property, regexFormat) + }, + (Query.In) : { Query.In inList, PersistentProperty property -> + def disjunction = new Query.Disjunction() + for (value in inList.values) { + disjunction.add(Restrictions.eq(inList.name, value)) + } + + executeSubQueryInternal(disjunction, disjunction.criteria) + }, + (Query.Between) : { Query.Between between, PersistentProperty property, Closure function = null, boolean onValue = false -> + def from = between.from + def to = between.to + def name = between.property + def allEntities = datastore[family] - executeSubQueryInternal(disjunction, disjunction.criteria) - }, - (Query.Between): { Query.Between between, PersistentProperty property, Closure function = null, boolean onValue = false -> - def from = between.from - def to = between.to - def name = between.property - def allEntities = datastore[family] + if (function != null) { + allEntities.findAll { function(resolveIfEmbedded(name, it.value)) >= from && function(resolveIfEmbedded(name, it.value)) <= to }.collect { it.key } + } else { + allEntities.findAll { resolveIfEmbedded(name, it.value) >= from && resolveIfEmbedded(name, it.value) <= to }.collect { it.key } + } + }, + (Query.GreaterThan) : { Query.GreaterThan gt, PersistentProperty property, Closure function = null, boolean onValue = false -> + def name = gt.property + final value = subqueryIfNecessary(gt) + def allEntities = datastore[family] - if (function != null) { - allEntities.findAll { function(resolveIfEmbedded(name, it.value)) >= from && function(resolveIfEmbedded(name, it.value)) <= to }.collect { it.key } - } - else { - allEntities.findAll { resolveIfEmbedded(name, it.value) >= from && resolveIfEmbedded(name, it.value) <= to }.collect { it.key } + allEntities.findAll { (function != null ? function(resolveIfEmbedded(name, it.value)) : resolveIfEmbedded(name, it.value)) > value }.collect { it.key } + }, + (Query.GreaterThanProperty) : { Query.GreaterThanProperty gt, PersistentProperty property, Closure function = null, boolean onValue = false -> + def name = gt.property + def other = gt.otherProperty + def allEntities = datastore[family] + + allEntities.findAll { (function != null ? function(resolveIfEmbedded(name, it.value)) : resolveIfEmbedded(name, it.value)) > it.value[other] }.collect { it.key } + }, + (Query.GreaterThanEqualsProperty): { Query.GreaterThanEqualsProperty gt, PersistentProperty property, Closure function = null, boolean onValue = false -> + def name = gt.property + def other = gt.otherProperty + def allEntities = datastore[family] + + allEntities.findAll { resolveIfEmbedded(name, it.value) >= it.value[other] }.collect { it.key } + }, + (Query.LessThanProperty) : { Query.LessThanProperty gt, PersistentProperty property -> + def name = gt.property + def other = gt.otherProperty + def allEntities = datastore[family] + + allEntities.findAll { resolveIfEmbedded(name, it.value) < it.value[other] }.collect { it.key } + }, + (Query.LessThanEqualsProperty) : { Query.LessThanEqualsProperty gt, PersistentProperty property -> + def name = gt.property + def other = gt.otherProperty + def allEntities = datastore[family] + + allEntities.findAll { resolveIfEmbedded(name, it.value) <= it.value[other] }.collect { it.key } + }, + (Query.EqualsProperty) : { Query.EqualsProperty gt, PersistentProperty property -> + def name = gt.property + def other = gt.otherProperty + def allEntities = datastore[family] + + allEntities.findAll { resolveIfEmbedded(name, it.value) == it.value[other] }.collect { it.key } + }, + (Query.NotEqualsProperty) : { Query.NotEqualsProperty gt, PersistentProperty property -> + def name = gt.property + def other = gt.otherProperty + def allEntities = datastore[family] + + allEntities.findAll { resolveIfEmbedded(name, it.value) != it.value[other] }.collect { it.key } + }, + (Query.SizeEquals) : { Query.SizeEquals se, PersistentProperty property -> + def allEntities = datastore[family] + final value = subqueryIfNecessary(se) + queryAssociationList(allEntities, property) { it.size() == value } + }, + (Query.SizeNotEquals) : { Query.SizeNotEquals se, PersistentProperty property -> + def allEntities = datastore[family] + final value = subqueryIfNecessary(se) + queryAssociationList(allEntities, property) { it.size() != value } + }, + (Query.SizeGreaterThan) : { Query.SizeGreaterThan se, PersistentProperty property -> + def allEntities = datastore[family] + final value = subqueryIfNecessary(se) + queryAssociationList(allEntities, property) { it.size() > value } + }, + (Query.SizeGreaterThanEquals) : { Query.SizeGreaterThanEquals se, PersistentProperty property -> + def allEntities = datastore[family] + final value = subqueryIfNecessary(se) + queryAssociationList(allEntities, property) { it.size() >= value } + }, + (Query.SizeLessThan) : { Query.SizeLessThan se, PersistentProperty property -> + def allEntities = datastore[family] + final value = subqueryIfNecessary(se) + queryAssociationList(allEntities, property) { it.size() < value } + }, + (Query.SizeLessThanEquals) : { Query.SizeLessThanEquals se, PersistentProperty property -> + def allEntities = datastore[family] + final value = subqueryIfNecessary(se) + queryAssociationList(allEntities, property) { it.size() <= value } + }, + (Query.GreaterThanEquals) : { Query.GreaterThanEquals gt, PersistentProperty property -> + def name = gt.property + final value = subqueryIfNecessary(gt) + def allEntities = datastore[family] + + allEntities.findAll { resolveIfEmbedded(name, it.value) >= value }.collect { it.key } + }, + (Query.LessThan) : { Query.LessThan lt, PersistentProperty property -> + def name = lt.property + final value = subqueryIfNecessary(lt) + def allEntities = datastore[family] + + allEntities.findAll { resolveIfEmbedded(name, it.value) < value }.collect { it.key } + }, + (Query.LessThanEquals) : { Query.LessThanEquals lte, PersistentProperty property -> + def name = lte.property + final value = subqueryIfNecessary(lte) + def allEntities = datastore[family] + + allEntities.findAll { resolveIfEmbedded(name, it.value) <= value }.collect { it.key } } - }, - (Query.GreaterThan): { Query.GreaterThan gt, PersistentProperty property, Closure function = null, boolean onValue = false -> - def name = gt.property - final value = subqueryIfNecessary(gt) - def allEntities = datastore[family] - - allEntities.findAll { (function != null ? function(resolveIfEmbedded(name, it.value)) : resolveIfEmbedded(name, it.value)) > value }.collect { it.key } - }, - (Query.GreaterThanProperty): { Query.GreaterThanProperty gt, PersistentProperty property, Closure function = null, boolean onValue = false -> - def name = gt.property - def other = gt.otherProperty - def allEntities = datastore[family] - - allEntities.findAll { (function != null ? function(resolveIfEmbedded(name, it.value)) : resolveIfEmbedded(name, it.value)) > it.value[other] }.collect { it.key } - }, - (Query.GreaterThanEqualsProperty): { Query.GreaterThanEqualsProperty gt, PersistentProperty property, Closure function = null, boolean onValue = false -> - def name = gt.property - def other = gt.otherProperty - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) >= it.value[other] }.collect { it.key } - }, - (Query.LessThanProperty): { Query.LessThanProperty gt, PersistentProperty property -> - def name = gt.property - def other = gt.otherProperty - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) < it.value[other] }.collect { it.key } - }, - (Query.LessThanEqualsProperty): { Query.LessThanEqualsProperty gt, PersistentProperty property -> - def name = gt.property - def other = gt.otherProperty - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) <= it.value[other] }.collect { it.key } - }, - (Query.EqualsProperty): { Query.EqualsProperty gt, PersistentProperty property -> - def name = gt.property - def other = gt.otherProperty - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) == it.value[other] }.collect { it.key } - }, - (Query.NotEqualsProperty): { Query.NotEqualsProperty gt, PersistentProperty property -> - def name = gt.property - def other = gt.otherProperty - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) != it.value[other] }.collect { it.key } - }, - (Query.SizeEquals): { Query.SizeEquals se, PersistentProperty property -> - def allEntities = datastore[family] - final value = subqueryIfNecessary(se) - queryAssociationList(allEntities, property) { it.size() == value } - }, - (Query.SizeNotEquals): { Query.SizeNotEquals se, PersistentProperty property -> - def allEntities = datastore[family] - final value = subqueryIfNecessary(se) - queryAssociationList(allEntities, property) { it.size() != value } - }, - (Query.SizeGreaterThan): { Query.SizeGreaterThan se, PersistentProperty property -> - def allEntities = datastore[family] - final value = subqueryIfNecessary(se) - queryAssociationList(allEntities, property) { it.size() > value } - }, - (Query.SizeGreaterThanEquals): { Query.SizeGreaterThanEquals se, PersistentProperty property -> - def allEntities = datastore[family] - final value = subqueryIfNecessary(se) - queryAssociationList(allEntities, property) { it.size() >= value } - }, - (Query.SizeLessThan): { Query.SizeLessThan se, PersistentProperty property -> - def allEntities = datastore[family] - final value = subqueryIfNecessary(se) - queryAssociationList(allEntities, property) { it.size() < value } - }, - (Query.SizeLessThanEquals): { Query.SizeLessThanEquals se, PersistentProperty property -> - def allEntities = datastore[family] - final value = subqueryIfNecessary(se) - queryAssociationList(allEntities, property) { it.size() <= value } - }, - (Query.GreaterThanEquals): { Query.GreaterThanEquals gt, PersistentProperty property -> - def name = gt.property - final value = subqueryIfNecessary(gt) - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) >= value }.collect { it.key } - }, - (Query.LessThan): { Query.LessThan lt, PersistentProperty property -> - def name = lt.property - final value = subqueryIfNecessary(lt) - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) < value }.collect { it.key } - }, - (Query.LessThanEquals): { Query.LessThanEquals lte, PersistentProperty property -> - def name = lte.property - final value = subqueryIfNecessary(lte) - def allEntities = datastore[family] - - allEntities.findAll { resolveIfEmbedded(name, it.value) <= value }.collect { it.key } - } ] protected def subqueryIfNecessary(Query.PropertyCriterion pc, boolean uniqueResult = true) { @@ -625,8 +607,7 @@ class SimpleMapQuery extends Query { QueryableCriteria criteria = value if (uniqueResult) { value = criteria.find() - } - else { + } else { value = criteria.list() } } @@ -642,11 +623,10 @@ class SimpleMapQuery extends Query { * @return */ protected resolveIfEmbedded(propertyName, obj) { - if( propertyName.contains('.') ) { + if (propertyName.contains('.')) { def (embeddedProperty, nestedProperty) = propertyName.tokenize('.') obj?."${embeddedProperty}"?."${nestedProperty}" - } - else { + } else { obj?."${propertyName}" } } @@ -689,16 +669,14 @@ class SimpleMapQuery extends Query { for (Query.Criterion criterion in criteriaList) { if (criterion instanceof Query.Junction) { resultList.results << executeSubQueryInternal(criterion, criterion.criteria) - } - else { + } else { PersistentProperty property = getValidProperty(criterion) if ((property instanceof Custom) && (criterion instanceof Query.PropertyCriterion)) { CustomTypeMarshaller customTypeMarshaller = ((Custom) property).getCustomTypeMarshaller() customTypeMarshaller.query(property, criterion, resultList) continue - } - else { + } else { def handler = handlers[criterion.getClass()] def results = handler?.call(criterion, property) ?: [] @@ -706,7 +684,7 @@ class SimpleMapQuery extends Query { } } } - return applyJunctionToResults(criteria,resultList.results) + return applyJunctionToResults(criteria, resultList.results) } private List applyJunctionToResults(Query.Junction criteria, List resultList) { @@ -720,24 +698,20 @@ class SimpleMapQuery extends Query { def secondList = resultList[num] finalIdentifiers = finalIdentifiers.intersect(secondList) } - } - else if (criteria instanceof Query.Negation) { + } else if (criteria instanceof Query.Negation) { def total = resultList.size() finalIdentifiers = negateResults(resultList[0]) for (num in 1.. * When the annotation is applied to a field, the value assigned to the - * annotation should be a Closure which accepts 1 parameter. The - * parameter is the object that data binding is being applied to. + * annotation should be a Closure which accepts 1 parameter. The + * parameter is the object that data binding is being applied to. * The value returned by the Closure will be bound to the field. The * following code demonstrates using this technique to bind a contact * to user with the same account as the user. * -
-class Contact{
-  Account account
-  String firstName
-} 
-class User {
-    @BindInitializer({
-        obj -> new Contact(account:obj.account)
-    })
-    Contact contact
-    Account account
-}
-
- + *
+ * class Contact{
+ *   Account account
+ *   String firstName
+ * }
+ * class User {
+ *     @BindInitializer({
+ *         obj -> new Contact(account:obj.account)
+ *     })
+ *     Contact contact
+ *     Account account
+ * }
+ * 
* - * @since 3.2.11 * @see BindingHelper * @see DataBindingSource + * @since 3.2.11 */ @Retention(RetentionPolicy.RUNTIME) public @interface BindInitializer { + Class value(); } diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/BindUsing.java b/grails-databinding-core/src/main/groovy/grails/databinding/BindUsing.java index c4583bd2115..e5dafd20eff 100755 --- a/grails-databinding-core/src/main/groovy/grails/databinding/BindUsing.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/BindUsing.java @@ -18,16 +18,13 @@ */ package grails.databinding; -import grails.databinding.BindingHelper; -import grails.databinding.DataBindingSource; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * This annotation may be applied to a class or to a field to * customize the data binding process. - * + *

* When the annotation is applied to a field, the value assigned to the * annotation should be a Closure which accepts 2 parameters. The first * parameter is the object that data binding is being applied to. The second @@ -36,34 +33,35 @@ * following code demonstrates using this technique to bind an upper * case version of the value in the DataBindingSource to the field. * -

-class SomeClass {
-    @BindUsing({
-        obj, source -> source['name']?.toUpperCase()
-    })
-    String name
-}
-
- * + *
+ * class SomeClass {
+ *     @BindUsing({
+ *         obj, source -> source['name']?.toUpperCase()
+ *     })
+ *     String name
+ * }
+ * 
+ *

* When the annotation is applied to a class, the value assigned to the * annotation should be a class which implements the {@link BindingHelper} * interface. An instance of that class will be used any time a value * is bound to a property in the class that this annotation has been * applied to. -

-@BindUsing(SomeClassWhichImplementsBindingHelper)
-class SomeClass {
-    String someProperty
-    Integer someOtherProperty
-}
-
+ *
+ * @BindUsing(SomeClassWhichImplementsBindingHelper)
+ * class SomeClass {
+ *     String someProperty
+ *     Integer someOtherProperty
+ * }
+ * 
* * @author Jeff Brown - * @since 2.3 * @see BindingHelper * @see DataBindingSource + * @since 2.3 */ @Retention(RetentionPolicy.RUNTIME) public @interface BindUsing { + Class value(); } diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/BindingFormat.java b/grails-databinding-core/src/main/groovy/grails/databinding/BindingFormat.java index 29eab75011d..11d1ed06dd8 100644 --- a/grails-databinding-core/src/main/groovy/grails/databinding/BindingFormat.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/BindingFormat.java @@ -18,23 +18,23 @@ */ package grails.databinding; +import org.codehaus.groovy.transform.GroovyASTTransformationClass; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.codehaus.groovy.transform.GroovyASTTransformationClass; - /** * Apply BindingFormat to a field to provide a format * to be used when binding a String to this field. * -
-class DateContainer {
-    @BindingFormat('MMddyyyy')
-    Date someDate
-}
-
+ *
+ * class DateContainer {
+ * @BindingFormat('MMddyyyy')
+ * Date someDate
+ * }
+ * 
* * @author Jeff Brown * @since 2.3 @@ -43,6 +43,8 @@ class DateContainer { @Target(ElementType.FIELD) @GroovyASTTransformationClass("org.grails.databinding.compiler.BindingFormatASTTransformation") public @interface BindingFormat { + String value() default ""; + String code() default ""; } diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/BindingHelper.java b/grails-databinding-core/src/main/groovy/grails/databinding/BindingHelper.java index 2c93802469e..faac2b9f700 100755 --- a/grails-databinding-core/src/main/groovy/grails/databinding/BindingHelper.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/BindingHelper.java @@ -24,8 +24,8 @@ * data binder by applying the {@link BindUsing} annotation to a class. * * @author Jeff Brown - * @since 3.0 * @see BindUsing + * @since 3.0 */ public interface BindingHelper { @@ -33,9 +33,9 @@ public interface BindingHelper { * The value returned from this method will be bound to * the property specified by propertyName. * - * @param obj The object that data binding is being applied to + * @param obj The object that data binding is being applied to * @param propertyName The name of the property data binding is being applied to - * @param source The Map containing all of the values being bound to this object + * @param source The Map containing all of the values being bound to this object * @return The value which should be bound to propertyName */ T getPropertyValue(Object obj, String propertyName, DataBindingSource source); diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/CollectionDataBindingSource.java b/grails-databinding-core/src/main/groovy/grails/databinding/CollectionDataBindingSource.java index 837102147e3..f3b84403a31 100644 --- a/grails-databinding-core/src/main/groovy/grails/databinding/CollectionDataBindingSource.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/CollectionDataBindingSource.java @@ -25,5 +25,6 @@ * @since 3.0 */ public interface CollectionDataBindingSource { + List getDataBindingSources(); } diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/DataBinder.java b/grails-databinding-core/src/main/groovy/grails/databinding/DataBinder.java index 9d49609721c..af7b637831e 100644 --- a/grails-databinding-core/src/main/groovy/grails/databinding/DataBinder.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/DataBinder.java @@ -32,21 +32,21 @@ public interface DataBinder { String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.S"; /** - * - * @param obj The object being bound to - * @param source The data binding source - * @param filter Only properties beginning with filter will be included in the - * data binding. For example, if filter is "person" and the binding - * source contains data for properties "person.name" and "author.name" - * the value of "person.name" will be bound to obj.name. The value of - * "author.name" will be ignored. - * @param whiteList A list of property names to be included during this - * data binding. All other properties represented in the binding source - * will be ignored + * + * @param obj The object being bound to + * @param source The data binding source + * @param filter Only properties beginning with filter will be included in the + * data binding. For example, if filter is "person" and the binding + * source contains data for properties "person.name" and "author.name" + * the value of "person.name" will be bound to obj.name. The value of + * "author.name" will be ignored. + * @param whiteList A list of property names to be included during this + * data binding. All other properties represented in the binding source + * will be ignored * @param blackList A list of properties names to be excluded during - * this data binding. - * @param listener A listener which will be notified of data binding events triggered - * by this binding + * this data binding. + * @param listener A listener which will be notified of data binding events triggered + * by this binding * @see DataBindingSource * @see DataBindingListener */ @@ -54,71 +54,71 @@ void bind(Object obj, DataBindingSource source, String filter, List whit List blackList, DataBindingListener listener); /** - * - * @param obj The object being bound to - * @param source The data binding source - * @param filter Only properties beginning with filter will be included in the - * data binding. For example, if filter is "person" and the binding - * source contains data for properties "person.name" and "author.name" - * the value of "person.name" will be bound to obj.name. The value of - * "author.name" will be ignored. - * @param whiteList A list of property names to be included during this - * data binding. All other properties represented in the binding source - * will be ignored + * + * @param obj The object being bound to + * @param source The data binding source + * @param filter Only properties beginning with filter will be included in the + * data binding. For example, if filter is "person" and the binding + * source contains data for properties "person.name" and "author.name" + * the value of "person.name" will be bound to obj.name. The value of + * "author.name" will be ignored. + * @param whiteList A list of property names to be included during this + * data binding. All other properties represented in the binding source + * will be ignored * @param blackList A list of properties names to be excluded during - * this data binding. + * this data binding. * @see DataBindingSource */ void bind(Object obj, DataBindingSource source, String filter, List whiteList, List blackList); /** - * - * @param obj The object being bound to - * @param gpath A GPathResult which represents the data being bound. + * + * @param obj The object being bound to + * @param gpath A GPathResult which represents the data being bound. * @see DataBindingSource */ void bind(Object obj, GPathResult gpath); /** - * - * @param obj The object being bound to - * @param source The data binding source - * @param whiteList A list of property names to be included during this - * data binding. All other properties represented in the binding source - * will be ignored + * + * @param obj The object being bound to + * @param source The data binding source + * @param whiteList A list of property names to be included during this + * data binding. All other properties represented in the binding source + * will be ignored * @param blackList A list of properties names to be excluded during - * this data binding. + * this data binding. * @see DataBindingSource */ void bind(Object obj, DataBindingSource source, List whiteList, List blackList); /** - * - * @param obj The object being bound to - * @param source The data binding source - * @param whiteList A list of property names to be included during this - * data binding. All other properties represented in the binding source - * will be ignored + * + * @param obj The object being bound to + * @param source The data binding source + * @param whiteList A list of property names to be included during this + * data binding. All other properties represented in the binding source + * will be ignored * @see DataBindingSource */ void bind(Object obj, DataBindingSource source, List whiteList); /** - * - * @param obj The object being bound to - * @param source The data binding source + * + * @param obj The object being bound to + * @param source The data binding source * @param listener A listener which will be notified of data binding events triggered - * by this binding + * by this binding * @see DataBindingSource * @see DataBindingListener */ void bind(Object obj, DataBindingSource source, DataBindingListener listener); /** - * - * @param obj The object being bound to + * + * @param obj The object being bound to * @param source The data binding source * @see DataBindingSource */ diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/DataBindingSource.java b/grails-databinding-core/src/main/groovy/grails/databinding/DataBindingSource.java index 90039aa3f9f..5ea9100d8f1 100644 --- a/grails-databinding-core/src/main/groovy/grails/databinding/DataBindingSource.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/DataBindingSource.java @@ -27,6 +27,7 @@ * @since 3.0 */ public interface DataBindingSource { + /** * * @return the names of properties represented @@ -42,6 +43,7 @@ public interface DataBindingSource { /** * Convencience operator overloading + * * @param propertyName the name of a property * @return the value associated with propertyName, or null if propertyName is not represented */ diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/SimpleDataBinder.groovy b/grails-databinding-core/src/main/groovy/grails/databinding/SimpleDataBinder.groovy index 50e1973e0f5..4efafb43696 100755 --- a/grails-databinding-core/src/main/groovy/grails/databinding/SimpleDataBinder.groovy +++ b/grails-databinding-core/src/main/groovy/grails/databinding/SimpleDataBinder.groovy @@ -29,7 +29,11 @@ import org.codehaus.groovy.reflection.CachedMethod import org.grails.databinding.ClosureValueConverter import org.grails.databinding.ClosureValueInitializer import org.grails.databinding.IndexedPropertyReferenceDescriptor -import org.grails.databinding.converters.* +import org.grails.databinding.converters.ConversionService +import org.grails.databinding.converters.FormattedDateValueConverter +import org.grails.databinding.converters.StructuredCalendarBindingEditor +import org.grails.databinding.converters.StructuredDateBindingEditor +import org.grails.databinding.converters.StructuredSqlDateBindingEditor import org.grails.databinding.errors.SimpleBindingError import org.grails.databinding.xml.GPathResultMap @@ -43,25 +47,25 @@ import java.security.ProtectionDomain /** * A data binder that will bind nested Maps to an object. * -
- class Person {
-     String firstName
-     Address homeAddress
- }
-
- class Address {
-     String city
-     String state
- }
-
- def person = new Person()
- def binder = new SimpleDataBinder()
- binder.bind person, [firstName: 'Steven', homeAddress: [city: 'St. Louis', state: 'Missouri']]
- assert person.firstName == 'Steven'
- assert person.homeAddress.city == 'St. Louis'
- assert person.homeAddress.state == 'Missouri'
-
- 
+ *
+ * class Person {
+ *     String firstName
+ *     Address homeAddress
+ * }
+ *
+ * class Address {
+ *     String city
+ *     String state
+ * }
+ *
+ * def person = new Person()
+ * def binder = new SimpleDataBinder()
+ * binder.bind person, [firstName: 'Steven', homeAddress: [city: 'St. Louis', state: 'Missouri']]
+ * assert person.firstName == 'Steven'
+ * assert person.homeAddress.city == 'St. Louis'
+ * assert person.homeAddress.state == 'Missouri'
+ *
+ * 
* * @author Jeff Brown * @author Graeme Rocher @@ -76,15 +80,15 @@ class SimpleDataBinder implements DataBinder { protected Map> conversionHelpers = [:].withDefault { c -> [] } protected Map formattedValueConversionHelpers = new HashMap() protected static final List BASIC_TYPES = [ - String, - Boolean, - Byte, - Short, - Integer, - Long, - Float, - Double, - Character + String, + Boolean, + Byte, + Short, + Integer, + Long, + Float, + Double, + Character ] as List static final INDEXED_PROPERTY_REGEX = /(.*)\[\s*([^\s]*)\s*\]\s*$/ @@ -106,12 +110,13 @@ class SimpleDataBinder implements DataBinder { void registerConverter(ValueConverter converter) { conversionHelpers[converter.targetType] << converter } + void registerFormattedValueConverter(FormattedValueConverter converter) { formattedValueConversionHelpers[converter.targetType] = converter } /** - * + * * @param obj The object being bound to * @param source The data binding source * @see DataBindingSource @@ -121,20 +126,19 @@ class SimpleDataBinder implements DataBinder { } /** - * + * * @param obj The object being bound to * @param source The data binding source * @param listener A listener which will be notified of data binding events triggered * by this binding - * @see DataBindingSource - * @see DataBindingListener + * @see DataBindingSource* @see DataBindingListener */ void bind(obj, DataBindingSource source, DataBindingListener listener) { bind obj, source, null, null, null, listener } /** - * + * * @param obj The object being bound to * @param source The data binding source * @param whiteList A list of property names to be included during this @@ -147,7 +151,7 @@ class SimpleDataBinder implements DataBinder { } /** - * + * * @param obj The object being bound to * @param source The data binding source * @param whiteList A list of property names to be included during this @@ -162,7 +166,7 @@ class SimpleDataBinder implements DataBinder { } /** - * + * * @param obj The object being bound to * @param gpath A GPathResult which represents the data being bound. * @see DataBindingSource @@ -172,7 +176,7 @@ class SimpleDataBinder implements DataBinder { } /** - * + * * @param obj The object being bound to * @param source The data binding source * @param filter Only properties beginning with filter will be included in the @@ -192,7 +196,7 @@ class SimpleDataBinder implements DataBinder { } /** - * + * * @param obj The object being bound to * @param source The data binding source * @param filter Only properties beginning with filter will be included in the @@ -207,8 +211,7 @@ class SimpleDataBinder implements DataBinder { * this data binding. * @param listener A listener which will be notified of data binding events triggered * by this binding - * @see DataBindingSource - * @see DataBindingListener + * @see DataBindingSource* @see DataBindingListener */ void bind(obj, DataBindingSource source, String filter, List whiteList, List blackList, DataBindingListener listener) { doBind obj, source, filter, whiteList, blackList, listener, null @@ -221,7 +224,7 @@ class SimpleDataBinder implements DataBinder { if (!filter || key.startsWith(filter + '.')) { String propName = key if (filter) { - propName = key[(1+filter.size())..-1] + propName = key[(1 + filter.size())..-1] } def metaProperty = obj.metaClass.getMetaProperty propName @@ -230,7 +233,7 @@ class SimpleDataBinder implements DataBinder { def val = source[key] try { def converter = getValueConverter(obj, metaProperty.name) - if(converter) { + if (converter) { bindProperty obj, source, metaProperty, converter.convert(source), listener, errors } else { processProperty obj, metaProperty, preprocessValue(val), source, listener, errors @@ -264,7 +267,7 @@ class SimpleDataBinder implements DataBinder { } protected boolean isOkToBind(String propName, List whiteList, List blackList) { - 'class' != propName && 'classLoader' != propName && 'protectionDomain' != propName && 'metaClass' != propName && 'metaPropertyValues' != propName && 'properties' != propName && !blackList?.contains(propName) && (!whiteList || whiteList.contains(propName) || whiteList.find { it -> it?.toString()?.startsWith(propName + '.')}) + 'class' != propName && 'classLoader' != propName && 'protectionDomain' != propName && 'metaClass' != propName && 'metaPropertyValues' != propName && 'properties' != propName && !blackList?.contains(propName) && (!whiteList || whiteList.contains(propName) || whiteList.find { it -> it?.toString()?.startsWith(propName + '.') }) } protected boolean isOkToBind(MetaProperty property, List whitelist, List blacklist) { @@ -302,7 +305,7 @@ class SimpleDataBinder implements DataBinder { def propName = indexedPropertyReferenceDescriptor.propertyName Map structValues = new HashMap() String prefix = indexedPropertyReferenceDescriptor.toString() - for (String propertyName: source.propertyNames) { + for (String propertyName : source.propertyNames) { if (propertyName.startsWith(prefix)) { String deIndexedPropertyName = propName String[] parts = propertyName.split('_') @@ -316,7 +319,7 @@ class SimpleDataBinder implements DataBinder { } protected processIndexedProperty(obj, MetaProperty metaProperty, IndexedPropertyReferenceDescriptor indexedPropertyReferenceDescriptor, - val, DataBindingSource source, DataBindingListener listener, errors) { + val, DataBindingSource source, DataBindingListener listener, errors) { def propName = indexedPropertyReferenceDescriptor.propertyName def propertyType = metaProperty.type @@ -337,7 +340,7 @@ class SimpleDataBinder implements DataBinder { def index = Integer.parseInt(indexedPropertyReferenceDescriptor.index) Collection collectionInstance = initializeCollection obj, propName, propertyType def indexedInstance = null - if(!(Set.isAssignableFrom(propertyType))) { + if (!(Set.isAssignableFrom(propertyType))) { indexedInstance = collectionInstance[index] } if (indexedInstance == null) { @@ -346,7 +349,7 @@ class SimpleDataBinder implements DataBinder { addElementToCollectionAt obj, propName, collectionInstance, index, val } else if (isBasicType(genericType)) { addElementToCollectionAt obj, propName, collectionInstance, index, convert(genericType, val) - } else if (val instanceof Map){ + } else if (val instanceof Map) { indexedInstance = genericType.getDeclaredConstructor().newInstance() bind indexedInstance, new SimpleMapDataBindingSource(val), listener addElementToCollectionAt obj, propName, collectionInstance, index, indexedInstance @@ -354,7 +357,7 @@ class SimpleDataBinder implements DataBinder { indexedInstance = genericType.getDeclaredConstructor().newInstance() bind indexedInstance, val, listener addElementToCollectionAt obj, propName, collectionInstance, index, indexedInstance - } else if(genericType.isEnum() && val instanceof CharSequence) { + } else if (genericType.isEnum() && val instanceof CharSequence) { def enumValue = convertStringToEnum(genericType, val.toString()) addElementToCollectionAt obj, propName, collectionInstance, index, enumValue } else { @@ -377,7 +380,7 @@ class SimpleDataBinder implements DataBinder { if (mapInstance.size() < autoGrowCollectionLimit || mapInstance.containsKey(indexedPropertyReferenceDescriptor.index)) { def referencedType = getReferencedTypeForCollection propName, obj if (referencedType != null) { - if(val instanceof Map) { + if (val instanceof Map) { mapInstance[indexedPropertyReferenceDescriptor.index] = referencedType.newInstance(val) } else { mapInstance[indexedPropertyReferenceDescriptor.index] = convert(referencedType, val) @@ -389,7 +392,6 @@ class SimpleDataBinder implements DataBinder { } } - @CompileStatic(TypeCheckingMode.SKIP) protected initializeArray(obj, String propertyName, Class arrayType, int index) { Object[] array = obj[propertyName] @@ -408,17 +410,16 @@ class SimpleDataBinder implements DataBinder { protected boolean isBasicType(Class c) { BASIC_TYPES.contains(c) || c.isPrimitive() } - - + protected Class getReferencedTypeForCollectionInClass(String propertyName, Class clazz) { Class referencedType def field = getField(clazz, propertyName) - if(field) { + if (field) { def genericType = field.genericType if (genericType instanceof ParameterizedType) { - ParameterizedType pt = (ParameterizedType)genericType + ParameterizedType pt = (ParameterizedType) genericType Class rawType = pt.getRawType() - if(Map.isAssignableFrom(rawType)) { + if (Map.isAssignableFrom(rawType)) { referencedType = pt.getActualTypeArguments()[1] } else { referencedType = pt.getActualTypeArguments()[0] @@ -464,21 +465,21 @@ class SimpleDataBinder implements DataBinder { if (obj[propertyName] == null) { obj[propertyName] = [:] } - return (Map)obj[propertyName] + return (Map) obj[propertyName] } protected Collection initializeCollection(obj, String propertyName, Class type, boolean reuseExistingCollectionIfExists = true) { def val = null - if(reuseExistingCollectionIfExists) { + if (reuseExistingCollectionIfExists) { val = obj[propertyName] } if (val == null) { val = getDefaultCollectionInstanceForType(type) obj[propertyName] = val } - return (Collection)val + return (Collection) val } - + protected getDefaultCollectionInstanceForType(Class type) { def val if (List.isAssignableFrom(type)) { @@ -508,8 +509,8 @@ class SimpleDataBinder implements DataBinder { converter = { SimpleMapDataBindingSource source -> def value = preprocessValue(source.getPropertyValue(field.name)) def convertedValue = null - if(value != null) { - convertedValue = formattedConverter.convert (value, formattingValue) + if (value != null) { + convertedValue = formattedConverter.convert(value, formattingValue) } convertedValue } as ValueConverter @@ -523,7 +524,7 @@ class SimpleDataBinder implements DataBinder { field = clazz.getDeclaredField(fieldName) } catch (NoSuchFieldException ignored) { def superClass = clazz.getSuperclass() - if(superClass != Object) { + if (superClass != Object) { field = getField(superClass, fieldName) } } @@ -539,7 +540,7 @@ class SimpleDataBinder implements DataBinder { if (annotation) { def valueClass = getValueOfBindUsing(annotation) if (Closure.isAssignableFrom(valueClass)) { - Closure closure = (Closure)valueClass.newInstance(null, null) + Closure closure = (Closure) valueClass.newInstance(null, null) converter = new ClosureValueConverter(converterClosure: closure.curry(obj), targetType: field.type) } } else { @@ -553,7 +554,7 @@ class SimpleDataBinder implements DataBinder { } catch (Exception ignored) { } } - + /** * @param annotation An instance of grails.databinding.BindingUsing or org.grails.databinding.BindingUsing * @return the value Class of the annotation @@ -564,7 +565,7 @@ class SimpleDataBinder implements DataBinder { return ((BindUsing) annotation).value() } } - + /** * @param annotation An instance of grails.databinding.BindingFormat or org.grails.databinding.BindingFormat * @return the value String of the annotation @@ -602,43 +603,44 @@ class SimpleDataBinder implements DataBinder { protected convertStringToEnum(Class enumClass, String value) { try { enumClass.valueOf(value) - } catch (IllegalArgumentException iae) {} + } catch (IllegalArgumentException iae) { + } } - + protected preprocessValue(propertyValue) { propertyValue } protected setPropertyValue(obj, DataBindingSource source, MetaProperty metaProperty, propertyValue, DataBindingListener listener) { def convertCollectionElements = false - if(propertyValue instanceof Collection) { + if (propertyValue instanceof Collection) { def referencedType = getReferencedTypeForCollection(metaProperty.name, obj) - if(referencedType) { - def nonAssignableValue = propertyValue.find { it != null && !(referencedType.isAssignableFrom(it.getClass()))} - if(nonAssignableValue != null) { + if (referencedType) { + def nonAssignableValue = propertyValue.find { it != null && !(referencedType.isAssignableFrom(it.getClass())) } + if (nonAssignableValue != null) { convertCollectionElements = true } } } - + setPropertyValue obj, source, metaProperty, propertyValue, listener, convertCollectionElements } - + protected setPropertyValue(obj, DataBindingSource source, MetaProperty metaProperty, propertyValue, DataBindingListener listener, boolean convertCollectionElements) { def propName = metaProperty.name def propertyType def propertyGetter if (metaProperty instanceof MetaBeanProperty) { - def mbp = (MetaBeanProperty)metaProperty + def mbp = (MetaBeanProperty) metaProperty propertyType = mbp.getter?.returnType ?: mbp.field?.type - if(propertyType && (propertyType.interface || Modifier.isAbstract(propertyType.modifiers))) { + if (propertyType && (propertyType.interface || Modifier.isAbstract(propertyType.modifiers))) { propertyType = mbp.field?.type } propertyGetter = mbp.getter } if (propertyType == null || propertyType == Object) { propertyType = metaProperty.type - if(propertyType == null || propertyType == Object) { + if (propertyType == null || propertyType == Object) { propertyType = getField(obj.getClass(), propName)?.type ?: Object } } @@ -649,16 +651,16 @@ class SimpleDataBinder implements DataBinder { obj[propName] = propertyValue } } else if (propertyValue instanceof List && - Set.isAssignableFrom(propertyType) && - !SortedSet.isAssignableFrom(propertyType)) { + Set.isAssignableFrom(propertyType) && + !SortedSet.isAssignableFrom(propertyType)) { addElementsToCollection(obj, propName, propertyValue, true) } else { if (propertyValue instanceof Map) { if (Collection.isAssignableFrom(propertyType) && - propertyValue.size() == 1 && - ((Map)propertyValue)[propertyValue.keySet()[0]] instanceof List) { + propertyValue.size() == 1 && + ((Map) propertyValue)[propertyValue.keySet()[0]] instanceof List) { def key = propertyValue.keySet()[0] - List list = (List)((Map)propertyValue)[key] + List list = (List) ((Map) propertyValue)[key] addElementsToCollection(obj, propName, list) } else { if (obj[propName] == null) { @@ -668,10 +670,10 @@ class SimpleDataBinder implements DataBinder { } } else if (propertyValue instanceof DataBindingSource) { if (Collection.isAssignableFrom(propertyType) && - propertyValue.size() == 1 && - ((Map)propertyValue)[propertyValue.getPropertyNames()[0]] instanceof List) { + propertyValue.size() == 1 && + ((Map) propertyValue)[propertyValue.getPropertyNames()[0]] instanceof List) { def key = propertyValue.getPropertyNames()[0] - List list = (List)((Map)propertyValue)[key] + List list = (List) ((Map) propertyValue)[key] addElementsToCollection(obj, propName, list) } else { if (obj[propName] == null) { @@ -679,17 +681,18 @@ class SimpleDataBinder implements DataBinder { } bind obj[propName], propertyValue, listener } - } else if(Collection.isAssignableFrom(propertyType) && propertyValue instanceof String) { + } else if (Collection.isAssignableFrom(propertyType) && propertyValue instanceof String) { addElementToCollection obj, propName, propertyType, propertyValue, true - } else if(Collection.isAssignableFrom(propertyType) && propertyValue instanceof Number) { + } else if (Collection.isAssignableFrom(propertyType) && propertyValue instanceof Number) { addElementToCollection obj, propName, propertyType, propertyValue, true - } else if(Collection.isAssignableFrom(propertyType) && propertyValue.getClass().isArray()) { + } else if (Collection.isAssignableFrom(propertyType) && propertyValue.getClass().isArray()) { addElementsToCollection obj, propName, propertyValue as Collection, true } else { obj[propName] = convert(propertyType, propertyValue) } } } + protected addElementToCollection(obj, String propName, Class propertyType, propertyValue, boolean clearCollection) { boolean isSet = false def coll = initializeCollection obj, propName, propertyType @@ -739,7 +742,7 @@ class SimpleDataBinder implements DataBinder { if (removeExistingElements == true) { coll.clear() } - for(element in collection) { + for (element in collection) { if (element == null || referencedType == null || referencedType.isAssignableFrom(element.getClass())) { coll << element } else { @@ -750,16 +753,15 @@ class SimpleDataBinder implements DataBinder { } protected initializeProperty(obj, String propName, Class propertyType, DataBindingSource source) { - def initializer = getPropertyInitializer(obj,propName) - if(initializer){ + def initializer = getPropertyInitializer(obj, propName) + if (initializer) { obj[propName] = initializer.initialize() - } - else{ + } else { obj[propName] = propertyType.getDeclaredConstructor().newInstance() - } + } } - - protected ValueInitializer getPropertyInitializer(obj, String propName){ + + protected ValueInitializer getPropertyInitializer(obj, String propName) { def initializer = getValueInitializerForField obj, propName initializer } @@ -773,7 +775,7 @@ class SimpleDataBinder implements DataBinder { if (annotation) { def valueClass = getValueOfBindInitializer(annotation) if (Closure.isAssignableFrom(valueClass)) { - Closure closure = (Closure)valueClass.newInstance(null, null) + Closure closure = (Closure) valueClass.newInstance(null, null) initializer = new ClosureValueInitializer(initializerClosure: closure.curry(obj), targetType: field.type) } } @@ -789,12 +791,12 @@ class SimpleDataBinder implements DataBinder { protected Class getValueOfBindInitializer(Annotation annotation) { assert annotation instanceof BindInitializer def value - if(annotation instanceof BindInitializer) { - value = ((BindInitializer)annotation).value() + if (annotation instanceof BindInitializer) { + value = ((BindInitializer) annotation).value() } value } - + protected convert(Class typeToConvertTo, value) { if (value == null || typeToConvertTo.isAssignableFrom(value?.getClass())) { return value diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/StructuredBindingEditor.java b/grails-databinding-core/src/main/groovy/grails/databinding/StructuredBindingEditor.java index e11cf70325b..77de1b380e2 100644 --- a/grails-databinding-core/src/main/groovy/grails/databinding/StructuredBindingEditor.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/StructuredBindingEditor.java @@ -24,57 +24,58 @@ * into an object. Typically a structured editor will pull * several values out of the Map that are necessary to initialize * the state of the object. - -class Address { - String state - String city -} -class StructuredAddressBindingEditor implements StructuredBindingEditor { - - public Object getPropertyValue(Object obj, String propertyName, Map<String, Object> source) { - def address = new Address() - - address.state = source[propertyName + '_someState'] - address.city = source[propertyName + '_someCity'] - - address - } -} - -def binder = new SimpleDataBinder() -binder.registerStructuredEditor Address, new StructuredAddressBindingEditor() -def resident = new Resident() -def bindingSource = [:] -bindingSource.name = 'Scott' -bindingSource.homeAddress_someCity = "Scott's Home City" -bindingSource.homeAddress_someState = "Scott's Home State" -bindingSource.workAddress_someState = "Scott's Work State" -bindingSource.workAddress = 'struct' -bindingSource.homeAddress = 'struct' - -binder.bind resident, bindingSource - -resident.name == 'Scott' -resident.homeAddress -assert resident.homeAddress.city == "Scott's Home City" -assert resident.homeAddress.state == "Scott's Home State" -assert resident.workAddress -assert resident.workAddress.state == "Scott's Work State" -assert resident.workAddress.city == null - + *
+ * class Address {
+ *     String state
+ *     String city
+ * }
+ * class StructuredAddressBindingEditor implements StructuredBindingEditor {
+ *
+ *     public Object getPropertyValue(Object obj, String propertyName, Map<String, Object> source) {
+ *         def address = new Address()
+ *
+ *         address.state = source[propertyName + '_someState']
+ *         address.city = source[propertyName + '_someCity']
+ *
+ *         address
+ *     }
+ * }
+ *
+ * def binder = new SimpleDataBinder()
+ * binder.registerStructuredEditor Address, new StructuredAddressBindingEditor()
+ * def resident = new Resident()
+ * def bindingSource = [:]
+ * bindingSource.name = 'Scott'
+ * bindingSource.homeAddress_someCity = "Scott's Home City"
+ * bindingSource.homeAddress_someState = "Scott's Home State"
+ * bindingSource.workAddress_someState = "Scott's Work State"
+ * bindingSource.workAddress = 'struct'
+ * bindingSource.homeAddress = 'struct'
+ *
+ * binder.bind resident, bindingSource
+ *
+ * resident.name == 'Scott'
+ * resident.homeAddress
+ * assert resident.homeAddress.city == "Scott's Home City"
+ * assert resident.homeAddress.state == "Scott's Home State"
+ * assert resident.workAddress
+ * assert resident.workAddress.state == "Scott's Work State"
+ * assert resident.workAddress.city == null
+ * 
* * @author Jeff Brown - * @since 3.0 * @see SimpleDataBinder#registerStructuredEditor(Class, StructuredBindingEditor) + * @since 3.0 */ public interface StructuredBindingEditor extends BindingHelper { + /** * The value returned from this method will be bound to * the property specified by propertyName. * - * @param obj The object that data binding is being applied to + * @param obj The object that data binding is being applied to * @param propertyName The name of the property data binding is being applied to - * @param source The source containing all of the values being bound to this object + * @param source The source containing all of the values being bound to this object * @return The value which should be bound to propertyName */ T getPropertyValue(Object obj, String propertyName, DataBindingSource source); diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/TypedStructuredBindingEditor.java b/grails-databinding-core/src/main/groovy/grails/databinding/TypedStructuredBindingEditor.java index d4b946f1881..9f1905df365 100644 --- a/grails-databinding-core/src/main/groovy/grails/databinding/TypedStructuredBindingEditor.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/TypedStructuredBindingEditor.java @@ -18,16 +18,15 @@ */ package grails.databinding; - /** - * - * @since 3.0 + * * @see StructuredBindingEditor + * @since 3.0 */ public interface TypedStructuredBindingEditor extends StructuredBindingEditor { /** - * + * * @return the type that this editor is used for binding to */ Class getTargetType(); diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/converters/FormattedValueConverter.java b/grails-databinding-core/src/main/groovy/grails/databinding/converters/FormattedValueConverter.java index 7ec460dec2b..8e86d61a1be 100644 --- a/grails-databinding-core/src/main/groovy/grails/databinding/converters/FormattedValueConverter.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/converters/FormattedValueConverter.java @@ -21,37 +21,38 @@ /** * Classes which implement this interface may participate * in the data binding process as formatted value converters. -
-import org.grails.databinding.converters.FormattedValueConverter
-
-class FormattedStringValueConverter implements FormattedValueConverter {
-    def convert(value, String format) {
-        if('UPPERCASE' == format) {
-            value = value.toUpperCase()
-        } else if('LOWERCASE' == format) {
-            value = value.toLowerCase()
-        }
-        value
-    }
-
-    Class getTargetType() {
-        // specifies the type to which this converter may be applied
-        String
-    }
-}
-
+ *
+ * import org.grails.databinding.converters.FormattedValueConverter
+ *
+ * class FormattedStringValueConverter implements FormattedValueConverter {
+ *     def convert(value, String format) {
+ *         if('UPPERCASE' == format) {
+ *             value = value.toUpperCase()
+ *         } else if('LOWERCASE' == format) {
+ *             value = value.toLowerCase()
+ *         }
+ *         value
+ *     }
+ *
+ *     Class getTargetType() {
+ *         // specifies the type to which this converter may be applied
+ *         String
+ *     }
+ * }
+ * 
* * @author Jeff Brown - * @since 3.0 * @see grails.databinding.BindingFormat * @see grails.databinding.SimpleDataBinder * @see grails.databinding.SimpleDataBinder#registerFormattedValueConverter(FormattedValueConverter) + * @since 3.0 */ public interface FormattedValueConverter { + /** * Return a formatted value * - * @param value The value to be formatted + * @param value The value to be formatted * @param format The format String * @return the formatted value */ diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/converters/ValueConverter.java b/grails-databinding-core/src/main/groovy/grails/databinding/converters/ValueConverter.java index 0e8d5871f9f..17a9868370a 100755 --- a/grails-databinding-core/src/main/groovy/grails/databinding/converters/ValueConverter.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/converters/ValueConverter.java @@ -23,7 +23,10 @@ * @since 3.0 */ public interface ValueConverter { + boolean canConvert(Object value); + Object convert(Object value); + Class getTargetType(); } diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/errors/BindingError.java b/grails-databinding-core/src/main/groovy/grails/databinding/errors/BindingError.java index 8ccf898741f..2031a269201 100755 --- a/grails-databinding-core/src/main/groovy/grails/databinding/errors/BindingError.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/errors/BindingError.java @@ -20,31 +20,32 @@ /** * Represents a problem which occurred during data binding. - * + * * @author Jeff Brown * @since 3.0 */ public interface BindingError { + /** - * + * * @return the object that data binding was being imposed upon */ Object getObject(); /** - * + * * @return the name of the property that the data binding error occurred on */ String getPropertyName(); /** - * + * * @return The value which could not be bound to the property */ Object getRejectedValue(); /** - * + * * @return an exception thrown during the data binding process */ Throwable getCause(); diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/events/DataBindingListener.java b/grails-databinding-core/src/main/groovy/grails/databinding/events/DataBindingListener.java index b7fc9c7fc0e..9a7657e77e0 100755 --- a/grails-databinding-core/src/main/groovy/grails/databinding/events/DataBindingListener.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/events/DataBindingListener.java @@ -24,8 +24,8 @@ * A listener which will be notified of events generated during data binding. * * @author Jeff Brown - * @since 3.0 * @see DataBindingListenerAdapter + * @since 3.0 */ public interface DataBindingListener { @@ -36,7 +36,7 @@ public interface DataBindingListener { /** * Called when data binding is about to start. - * + * * @param target The object data binding is being imposed upon * @param errors the Spring Errors instance (a org.springframework.validation.BindingResult) * @return true if data binding should continue @@ -46,10 +46,10 @@ public interface DataBindingListener { /** * Called when data binding is about to imposed on a property * - * @param target The object data binding is being imposed upon + * @param target The object data binding is being imposed upon * @param propertyName The name of the property being bound to - * @param value The value of the property being bound - * @param errors the Spring Errors instance (a org.springframework.validation.BindingResult) + * @param value The value of the property being bound + * @param errors the Spring Errors instance (a org.springframework.validation.BindingResult) * @return true if data binding should continue, otherwise return false */ Boolean beforeBinding(Object target, String propertyName, Object value, Object errors); @@ -57,15 +57,15 @@ public interface DataBindingListener { /** * Called after data binding has been imposed on a property * - * @param target The object data binding is being imposed upon + * @param target The object data binding is being imposed upon * @param propertyName The name of the property that was bound to - * @param errors the Spring Errors instance (a org.springframework.validation.BindingResult) + * @param errors the Spring Errors instance (a org.springframework.validation.BindingResult) */ void afterBinding(Object target, String propertyName, Object errors); /** * Called after data binding has finished. - * + * * @param target The object data binding is being imposed upon * @param errors the Spring Errors instance (a org.springframework.validation.BindingResult) */ @@ -73,7 +73,8 @@ public interface DataBindingListener { /** * Called when an error occurs binding to a property - * @param error encapsulates information about the binding error + * + * @param error encapsulates information about the binding error * @param errors the Spring Errors instance (a org.springframework.validation.BindingResult) * @see BindingError */ diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/events/DataBindingListenerAdapter.java b/grails-databinding-core/src/main/groovy/grails/databinding/events/DataBindingListenerAdapter.java index 2635824e8a7..49043b853e1 100755 --- a/grails-databinding-core/src/main/groovy/grails/databinding/events/DataBindingListenerAdapter.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/events/DataBindingListenerAdapter.java @@ -22,8 +22,8 @@ /** * @author Jeff Brown - * @since 3.0 * @see DataBindingListener + * @since 3.0 */ public class DataBindingListenerAdapter implements DataBindingListener { diff --git a/grails-databinding-core/src/main/groovy/grails/databinding/initializers/ValueInitializer.java b/grails-databinding-core/src/main/groovy/grails/databinding/initializers/ValueInitializer.java index 7e3b82f2ebd..2c54bb615e7 100644 --- a/grails-databinding-core/src/main/groovy/grails/databinding/initializers/ValueInitializer.java +++ b/grails-databinding-core/src/main/groovy/grails/databinding/initializers/ValueInitializer.java @@ -16,11 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - package grails.databinding.initializers; - public interface ValueInitializer { + Object initialize(); + Class getTargetType(); } diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/ClosureValueConverter.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/ClosureValueConverter.groovy index 3e67d8b9d2e..2426f588cb2 100755 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/ClosureValueConverter.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/ClosureValueConverter.groovy @@ -18,7 +18,7 @@ */ package org.grails.databinding -import grails.databinding.converters.ValueConverter; +import grails.databinding.converters.ValueConverter import groovy.transform.CompileStatic /** diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/ClosureValueInitializer.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/ClosureValueInitializer.groovy index a3674d0d8fe..b396c877070 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/ClosureValueInitializer.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/ClosureValueInitializer.groovy @@ -27,7 +27,7 @@ class ClosureValueInitializer implements ValueInitializer { Closure initializerClosure Class targetType - + @Override Object initialize() { diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/IndexedPropertyReferenceDescriptor.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/IndexedPropertyReferenceDescriptor.groovy index d0a4ef1c731..6441f35695c 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/IndexedPropertyReferenceDescriptor.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/IndexedPropertyReferenceDescriptor.groovy @@ -23,6 +23,7 @@ package org.grails.databinding * @since 2.3 */ class IndexedPropertyReferenceDescriptor { + String propertyName String index diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/compiler/BindingFormatASTTransformation.java b/grails-databinding-core/src/main/groovy/org/grails/databinding/compiler/BindingFormatASTTransformation.java index 48afe367ba8..f315b1b46de 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/compiler/BindingFormatASTTransformation.java +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/compiler/BindingFormatASTTransformation.java @@ -16,11 +16,8 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.databinding.compiler; -import java.util.Map; - import org.apache.grails.common.compiler.GroovyTransformOrder; import org.codehaus.groovy.ast.ASTNode; import org.codehaus.groovy.ast.AnnotationNode; @@ -34,37 +31,39 @@ import org.codehaus.groovy.transform.GroovyASTTransformation; import org.codehaus.groovy.transform.TransformWithPriority; +import java.util.Map; + @GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS) public class BindingFormatASTTransformation implements ASTTransformation, TransformWithPriority { - @Override - public void visit(final ASTNode[] astNodes, final SourceUnit source) { - if (!(astNodes[0] instanceof AnnotationNode) || !(astNodes[1] instanceof FieldNode)) { - throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class"); - } + @Override + public void visit(final ASTNode[] astNodes, final SourceUnit source) { + if (!(astNodes[0] instanceof AnnotationNode) || !(astNodes[1] instanceof FieldNode)) { + throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class"); + } + + final AnnotationNode annotationNode = (AnnotationNode) astNodes[0]; + final FieldNode fieldNode = (FieldNode) astNodes[1]; + final Map members = annotationNode.getMembers(); + if (members == null || (!members.containsKey("code") && !members.containsKey("value"))) { + final String message = "The @BindingFormat annotation on the field [" + + fieldNode.getName() + + "] in class [" + + fieldNode.getDeclaringClass().getName() + + "] must provide a value for either the value() or code() attribute."; + + error(source, fieldNode, message); + } + } - final AnnotationNode annotationNode = (AnnotationNode) astNodes[0]; - final FieldNode fieldNode = (FieldNode) astNodes[1]; - final Map members = annotationNode.getMembers(); - if(members == null || (!members.containsKey("code") && !members.containsKey("value"))) { - final String message = "The @BindingFormat annotation on the field [" - + fieldNode.getName() + - "] in class [" + - fieldNode.getDeclaringClass().getName() + - "] must provide a value for either the value() or code() attribute."; - - error(source, fieldNode, message); - } - } - - protected void error(final SourceUnit sourceUnit, final ASTNode astNode, final String message) { - final SyntaxException syntaxException = new SyntaxException(message, astNode.getLineNumber(), astNode.getColumnNumber()); - final SyntaxErrorMessage syntaxErrorMessage = new SyntaxErrorMessage(syntaxException, sourceUnit); - sourceUnit.getErrorCollector().addError(syntaxErrorMessage, false); - } + protected void error(final SourceUnit sourceUnit, final ASTNode astNode, final String message) { + final SyntaxException syntaxException = new SyntaxException(message, astNode.getLineNumber(), astNode.getColumnNumber()); + final SyntaxErrorMessage syntaxErrorMessage = new SyntaxErrorMessage(syntaxException, sourceUnit); + sourceUnit.getErrorCollector().addError(syntaxErrorMessage, false); + } - @Override - public int priority() { - return GroovyTransformOrder.BINDING_FORMAT_ORDER; - } + @Override + public int priority() { + return GroovyTransformOrder.BINDING_FORMAT_ORDER; + } } diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/AbstractStructuredDateBindingEditor.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/AbstractStructuredDateBindingEditor.groovy index aad5ce9c1ff..d3c315517fb 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/AbstractStructuredDateBindingEditor.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/AbstractStructuredDateBindingEditor.groovy @@ -18,8 +18,8 @@ */ package org.grails.databinding.converters -import grails.databinding.DataBindingSource; -import grails.databinding.StructuredBindingEditor; +import grails.databinding.DataBindingSource +import grails.databinding.StructuredBindingEditor import groovy.transform.CompileStatic /** @@ -33,16 +33,16 @@ abstract class AbstractStructuredDateBindingEditor implements StructuredBindi final prefix = propertyName + '_' assert fieldValues.containsProperty(prefix + "year"), "Can't populate a date without a year" - def yearString = (String)fieldValues.getPropertyValue(prefix + "year") + def yearString = (String) fieldValues.getPropertyValue(prefix + "year") def monthString = (String) fieldValues.getPropertyValue(prefix + "month") def dayString = (String) fieldValues.getPropertyValue(prefix + "day") def hourString = (String) fieldValues.getPropertyValue(prefix + "hour") def minuteString = (String) fieldValues.getPropertyValue(prefix + "minute") if (!yearString && - !monthString && - !dayString && - !hourString && - !minuteString) { + !monthString && + !dayString && + !hourString && + !minuteString) { return null } def year @@ -56,7 +56,7 @@ abstract class AbstractStructuredDateBindingEditor implements StructuredBindi int hour = getIntegerValue(fieldValues, prefix + "hour", 0) int minute = getIntegerValue(fieldValues, prefix + "minute", 0) - def c = new GregorianCalendar(year,month - 1,day,hour,minute) + def c = new GregorianCalendar(year, month - 1, day, hour, minute) return getDate(c) } catch (NumberFormatException nfe) { diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/ConversionService.java b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/ConversionService.java index fe16f0b7e90..7bb155ced12 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/ConversionService.java +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/ConversionService.java @@ -23,6 +23,8 @@ * @since 2.3 */ public interface ConversionService { + boolean canConvert(Class source, Class target); + Object convert(Object objet, Class targetType); } diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/CurrencyValueConverter.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/CurrencyValueConverter.groovy index 664e42d7ffb..598d3bae30f 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/CurrencyValueConverter.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/CurrencyValueConverter.groovy @@ -22,28 +22,27 @@ import grails.databinding.converters.ValueConverter import groovy.transform.CompileStatic /** - * + * * A ValueConverter for converting String to Currency. - * - * @see ValueConverter - * @since 2.3.10 + * + * @see ValueConverter* @since 2.3.10 * */ @CompileStatic class CurrencyValueConverter implements ValueConverter { @Override - public boolean canConvert(Object value) { + boolean canConvert(Object value) { value instanceof String } @Override - public Object convert(Object value) { + Object convert(Object value) { Currency.getInstance(value as String) } @Override - public Class getTargetType() { + Class getTargetType() { Currency } diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/DateConversionHelper.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/DateConversionHelper.groovy index 32b317eeeb4..9c857a1dabe 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/DateConversionHelper.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/DateConversionHelper.groovy @@ -18,7 +18,7 @@ */ package org.grails.databinding.converters -import grails.databinding.converters.ValueConverter; +import grails.databinding.converters.ValueConverter import groovy.transform.CompileStatic import java.text.DateFormat @@ -46,7 +46,7 @@ class DateConversionHelper implements ValueConverter { Object convert(value) { Date dateValue if (value instanceof String) { - if(!value) { + if (!value) { return null } Exception firstException @@ -55,13 +55,13 @@ class DateConversionHelper implements ValueConverter { DateFormat formatter = new SimpleDateFormat(format) try { formatter.lenient = dateParsingLenient - dateValue = formatter.parse((String)value) + dateValue = formatter.parse((String) value) } catch (Exception e) { firstException = firstException ?: e } } } - if(dateValue == null && firstException) { + if (dateValue == null && firstException) { throw firstException } } diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/FormattedDateValueConverter.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/FormattedDateValueConverter.groovy index a80f3467911..d94829b6b15 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/FormattedDateValueConverter.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/FormattedDateValueConverter.groovy @@ -18,7 +18,7 @@ */ package org.grails.databinding.converters -import grails.databinding.converters.FormattedValueConverter; +import grails.databinding.converters.FormattedValueConverter import groovy.transform.CompileStatic import java.text.SimpleDateFormat @@ -31,15 +31,13 @@ import java.text.SimpleDateFormat class FormattedDateValueConverter implements FormattedValueConverter { def convert(value, String format) { - if(value instanceof Date) { + if (value instanceof Date) { return value - } - else if(value instanceof CharSequence) { + } else if (value instanceof CharSequence) { String dateStr = value.toString() - if(!dateStr) { + if (!dateStr) { return null - } - else { + } else { def fmt = new SimpleDateFormat(format) fmt.lenient = false fmt.parse((String) value) diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/FormattedLocalDateTimeValueConverter.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/FormattedLocalDateTimeValueConverter.groovy index 9793a8d6a09..ac6e14f243a 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/FormattedLocalDateTimeValueConverter.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/FormattedLocalDateTimeValueConverter.groovy @@ -18,7 +18,7 @@ */ package org.grails.databinding.converters -import grails.databinding.converters.FormattedValueConverter; +import grails.databinding.converters.FormattedValueConverter import groovy.transform.CompileStatic import java.time.LocalDateTime @@ -31,15 +31,13 @@ import java.time.LocalDateTime class FormattedLocalDateTimeValueConverter implements FormattedValueConverter { def convert(value, String format) { - if(value instanceof LocalDateTime) { + if (value instanceof LocalDateTime) { return value - } - else if(value instanceof CharSequence) { + } else if (value instanceof CharSequence) { String dateStr = value.toString() - if(!dateStr) { + if (!dateStr) { return null - } - else { + } else { LocalDateTime.parse((String) value) } } diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/LocalDateTimeConverter.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/LocalDateTimeConverter.groovy index 3c63c59b372..56d8569d24b 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/LocalDateTimeConverter.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/LocalDateTimeConverter.groovy @@ -31,6 +31,7 @@ import java.time.LocalDateTime */ @CompileStatic class LocalDateTimeConverter implements ValueConverter { + @Override boolean canConvert(Object value) { return value instanceof String || value instanceof LocalDateTime diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/StructuredCalendarBindingEditor.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/StructuredCalendarBindingEditor.groovy index 2058bc906e3..03ee4e2b3b7 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/StructuredCalendarBindingEditor.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/StructuredCalendarBindingEditor.groovy @@ -18,8 +18,6 @@ */ package org.grails.databinding.converters -import java.util.Calendar; - /** * @author Jeff Brown * @since 2.3 diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/TimeZoneConverter.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/TimeZoneConverter.groovy index 2c9ebf9aa14..59c79b9ba43 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/TimeZoneConverter.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/TimeZoneConverter.groovy @@ -18,7 +18,7 @@ */ package org.grails.databinding.converters -import grails.databinding.converters.ValueConverter; +import grails.databinding.converters.ValueConverter import groovy.transform.CompileStatic /** @@ -35,7 +35,7 @@ class TimeZoneConverter implements ValueConverter { @Override def convert(value) { - TimeZone.getTimeZone((String)value) + TimeZone.getTimeZone((String) value) } @Override diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/UUIDConverter.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/UUIDConverter.groovy index 6991d1b677b..051139468bc 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/UUIDConverter.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/converters/UUIDConverter.groovy @@ -18,7 +18,7 @@ */ package org.grails.databinding.converters -import grails.databinding.converters.ValueConverter; +import grails.databinding.converters.ValueConverter import groovy.transform.CompileStatic @CompileStatic @@ -31,10 +31,10 @@ class UUIDConverter implements ValueConverter { @Override def convert(value) { - if(value) { + if (value) { try { return UUID.fromString(value as String) - } catch(IllegalArgumentException ignore) { + } catch (IllegalArgumentException ignore) { return null } } diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/errors/SimpleBindingError.java b/grails-databinding-core/src/main/groovy/org/grails/databinding/errors/SimpleBindingError.java index 36d0aa75c2b..08d598742b2 100755 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/errors/SimpleBindingError.java +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/errors/SimpleBindingError.java @@ -32,7 +32,7 @@ public class SimpleBindingError implements BindingError { private final Throwable cause; public SimpleBindingError(Object object, String propertyName, - Object rejectedValue, Throwable cause) { + Object rejectedValue, Throwable cause) { this.object = object; this.propertyName = propertyName; this.rejectedValue = rejectedValue; diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/xml/GPathResultCollectionDataBindingSource.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/xml/GPathResultCollectionDataBindingSource.groovy index 7ea03f0b246..561ca4144b6 100644 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/xml/GPathResultCollectionDataBindingSource.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/xml/GPathResultCollectionDataBindingSource.groovy @@ -18,9 +18,9 @@ */ package org.grails.databinding.xml -import grails.databinding.CollectionDataBindingSource; -import grails.databinding.DataBindingSource; -import grails.databinding.SimpleMapDataBindingSource; +import grails.databinding.CollectionDataBindingSource +import grails.databinding.DataBindingSource +import grails.databinding.SimpleMapDataBindingSource import groovy.transform.CompileStatic import groovy.xml.slurpersupport.GPathResult @@ -31,7 +31,7 @@ class GPathResultCollectionDataBindingSource implements CollectionDataBindingSou GPathResultCollectionDataBindingSource(GPathResult gpath) { dataBindingSources = gpath?.children()?.collect { child -> - def map = new GPathResultMap((GPathResult)child) + def map = new GPathResultMap((GPathResult) child) DataBindingSource bindingSource = new SimpleMapDataBindingSource(map) bindingSource } diff --git a/grails-databinding-core/src/main/groovy/org/grails/databinding/xml/GPathResultMap.groovy b/grails-databinding-core/src/main/groovy/org/grails/databinding/xml/GPathResultMap.groovy index de779e104a3..e438953cc0f 100755 --- a/grails-databinding-core/src/main/groovy/org/grails/databinding/xml/GPathResultMap.groovy +++ b/grails-databinding-core/src/main/groovy/org/grails/databinding/xml/GPathResultMap.groovy @@ -27,6 +27,7 @@ import groovy.xml.slurpersupport.NodeChild * @since 2.3 */ class GPathResultMap implements Map { + protected GPathResult gpath protected id @@ -44,7 +45,7 @@ class GPathResultMap implements Map { } boolean containsKey(key) { - if(key == 'id') { + if (key == 'id') { return this.@id != null || gpath['id'].size() } gpath[key].size() @@ -60,30 +61,30 @@ class GPathResultMap implements Map { def value = get name entries << new AbstractMap.SimpleImmutableEntry(name, value) } - if(this.@id != null) { + if (this.@id != null) { entries << new AbstractMap.SimpleImmutableEntry('id', this.@id) } return entries } Object get(key) { - if('id' == key && this.@id) { + if ('id' == key && this.@id) { return this.@id } def value = gpath.children().findAll { it.name() == key } - if(value.size() == 0) { + if (value.size() == 0) { return null } - if(value.size() > 1) { + if (value.size() > 1) { def list = [] value.iterator().each { def theId = it.@id.text() - if(!''.equals(theId)) { + if (!''.equals(theId)) { def theMap = new GPathResultMap(it) list << theMap } else { - if(it.children().size() > 0) { + if (it.children().size() > 0) { def theMap = new GPathResultMap(it) list << theMap } else { @@ -93,8 +94,8 @@ class GPathResultMap implements Map { } return list } - if(value.children().size() == 0) { - if(value.@id.text()) { + if (value.children().size() == 0) { + if (value.@id.text()) { return [id: value.@id.text()] } return value.text() @@ -106,7 +107,7 @@ class GPathResultMap implements Map { def keys = gpath.children().collect { getPropertyNameForNodeChild it } as Set - if(this.@id != null) { + if (this.@id != null) { keys << 'id' } keys diff --git a/grails-databinding/build.gradle b/grails-databinding/build.gradle index 49e1646bf26..3c1abc01e20 100644 --- a/grails-databinding/build.gradle +++ b/grails-databinding/build.gradle @@ -73,4 +73,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-databinding/src/main/groovy/org/grails/databinding/converters/Jsr310ConvertersConfiguration.groovy b/grails-databinding/src/main/groovy/org/grails/databinding/converters/Jsr310ConvertersConfiguration.groovy index 9ec59aa59c3..5379c372a08 100644 --- a/grails-databinding/src/main/groovy/org/grails/databinding/converters/Jsr310ConvertersConfiguration.groovy +++ b/grails-databinding/src/main/groovy/org/grails/databinding/converters/Jsr310ConvertersConfiguration.groovy @@ -17,17 +17,24 @@ * under the License. */ -package org.grails.databinding.converters; +package org.grails.databinding.converters import grails.databinding.TypedStructuredBindingEditor import grails.databinding.converters.FormattedValueConverter import grails.databinding.converters.ValueConverter +import jakarta.inject.Inject import org.grails.plugins.databinding.DataBindingConfigurationProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import jakarta.inject.Inject -import java.time.* +import java.time.Instant +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.OffsetDateTime +import java.time.OffsetTime +import java.time.Period +import java.time.ZonedDateTime import java.time.format.DateTimeFormatter @Configuration @@ -46,9 +53,10 @@ class Jsr310ConvertersConfiguration { @Bean FormattedValueConverter offsetDateTimeConverter() { new FormattedValueConverter() { + @Override Object convert(Object value, String format) { - OffsetDateTime.parse((CharSequence)value, DateTimeFormatter.ofPattern(format)) + OffsetDateTime.parse((CharSequence) value, DateTimeFormatter.ofPattern(format)) } @Override @@ -61,10 +69,11 @@ class Jsr310ConvertersConfiguration { @Bean ValueConverter offsetDateTimeValueConverter() { new Jsr310DateValueConverter() { + @Override OffsetDateTime convert(Object value) { convert(value) { String format -> - OffsetDateTime.parse((CharSequence)value, DateTimeFormatter.ofPattern(format)) + OffsetDateTime.parse((CharSequence) value, DateTimeFormatter.ofPattern(format)) } } @@ -78,6 +87,7 @@ class Jsr310ConvertersConfiguration { @Bean TypedStructuredBindingEditor offsetDateTimeStructuredBindingEditor() { new CustomDateBindingEditor() { + @Override OffsetDateTime getDate(Calendar c) { OffsetDateTime.ofInstant(c.toInstant(), c.timeZone.toZoneId()) @@ -93,6 +103,7 @@ class Jsr310ConvertersConfiguration { @Bean FormattedValueConverter offsetTimeConverter() { new FormattedValueConverter() { + @Override Object convert(Object value, String format) { OffsetTime.parse((CharSequence) value, DateTimeFormatter.ofPattern(format)) @@ -108,10 +119,11 @@ class Jsr310ConvertersConfiguration { @Bean ValueConverter offsetTimeValueConverter() { new Jsr310DateValueConverter() { + @Override OffsetTime convert(Object value) { convert(value) { String format -> - OffsetTime.parse((CharSequence)value, DateTimeFormatter.ofPattern(format)) + OffsetTime.parse((CharSequence) value, DateTimeFormatter.ofPattern(format)) } } @@ -125,6 +137,7 @@ class Jsr310ConvertersConfiguration { @Bean TypedStructuredBindingEditor offsetTimeStructuredBindingEditor() { new CustomDateBindingEditor() { + @Override OffsetTime getDate(Calendar c) { OffsetTime.ofInstant(c.toInstant(), c.timeZone.toZoneId()) @@ -140,6 +153,7 @@ class Jsr310ConvertersConfiguration { @Bean FormattedValueConverter localDateTimeConverter() { new FormattedValueConverter() { + @Override Object convert(Object value, String format) { LocalDateTime.parse((CharSequence) value, DateTimeFormatter.ofPattern(format)) @@ -155,10 +169,11 @@ class Jsr310ConvertersConfiguration { @Bean ValueConverter localDateTimeValueConverter() { new Jsr310DateValueConverter() { + @Override LocalDateTime convert(Object value) { convert(value) { String format -> - LocalDateTime.parse((CharSequence)value, DateTimeFormatter.ofPattern(format)) + LocalDateTime.parse((CharSequence) value, DateTimeFormatter.ofPattern(format)) } } @@ -172,6 +187,7 @@ class Jsr310ConvertersConfiguration { @Bean TypedStructuredBindingEditor localDateTimeStructuredBindingEditor() { new CustomDateBindingEditor() { + @Override LocalDateTime getDate(Calendar c) { LocalDateTime.ofInstant(c.toInstant(), c.timeZone.toZoneId()) @@ -187,6 +203,7 @@ class Jsr310ConvertersConfiguration { @Bean FormattedValueConverter localDateConverter() { new FormattedValueConverter() { + @Override Object convert(Object value, String format) { LocalDate.parse((CharSequence) value, DateTimeFormatter.ofPattern(format)) @@ -202,10 +219,11 @@ class Jsr310ConvertersConfiguration { @Bean ValueConverter localDateValueConverter() { new Jsr310DateValueConverter() { + @Override LocalDate convert(Object value) { convert(value) { String format -> - LocalDate.parse((CharSequence)value, DateTimeFormatter.ofPattern(format)) + LocalDate.parse((CharSequence) value, DateTimeFormatter.ofPattern(format)) } } @@ -219,9 +237,10 @@ class Jsr310ConvertersConfiguration { @Bean TypedStructuredBindingEditor localDateStructuredBindingEditor() { new CustomDateBindingEditor() { + @Override LocalDate getDate(Calendar c) { - LocalDate.of(c.get(Calendar.YEAR), c.get(Calendar.MONTH)+1, c.get(Calendar.DAY_OF_MONTH)) + LocalDate.of(c.get(Calendar.YEAR), c.get(Calendar.MONTH) + 1, c.get(Calendar.DAY_OF_MONTH)) } @Override @@ -234,6 +253,7 @@ class Jsr310ConvertersConfiguration { @Bean FormattedValueConverter localTimeConverter() { new FormattedValueConverter() { + @Override Object convert(Object value, String format) { LocalTime.parse((CharSequence) value, DateTimeFormatter.ofPattern(format)) @@ -249,10 +269,11 @@ class Jsr310ConvertersConfiguration { @Bean ValueConverter localTimeValueConverter() { new Jsr310DateValueConverter() { + @Override LocalTime convert(Object value) { convert(value) { String format -> - LocalTime.parse((CharSequence)value, DateTimeFormatter.ofPattern(format)) + LocalTime.parse((CharSequence) value, DateTimeFormatter.ofPattern(format)) } } @@ -266,6 +287,7 @@ class Jsr310ConvertersConfiguration { @Bean TypedStructuredBindingEditor localTimeStructuredBindingEditor() { new CustomDateBindingEditor() { + @Override LocalTime getDate(Calendar c) { LocalTime.of(c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE), c.get(Calendar.SECOND)) @@ -281,9 +303,10 @@ class Jsr310ConvertersConfiguration { @Bean FormattedValueConverter zonedDateTimeConverter() { new FormattedValueConverter() { + @Override Object convert(Object value, String format) { - ZonedDateTime.parse((CharSequence)value, DateTimeFormatter.ofPattern(format)) + ZonedDateTime.parse((CharSequence) value, DateTimeFormatter.ofPattern(format)) } @Override @@ -296,10 +319,11 @@ class Jsr310ConvertersConfiguration { @Bean ValueConverter zonedDateTimeValueConverter() { new Jsr310DateValueConverter() { + @Override ZonedDateTime convert(Object value) { convert(value) { String format -> - ZonedDateTime.parse((CharSequence)value, DateTimeFormatter.ofPattern(format)) + ZonedDateTime.parse((CharSequence) value, DateTimeFormatter.ofPattern(format)) } } @@ -313,6 +337,7 @@ class Jsr310ConvertersConfiguration { @Bean TypedStructuredBindingEditor zonedDateTimeStructuredBindingEditor() { new CustomDateBindingEditor() { + @Override ZonedDateTime getDate(Calendar c) { ZonedDateTime.ofInstant(c.toInstant(), c.timeZone.toZoneId()) @@ -328,6 +353,7 @@ class Jsr310ConvertersConfiguration { @Bean ValueConverter periodValueConverter() { new Jsr310DateValueConverter() { + @Override Period convert(Object value) { Period.parse((CharSequence) value) @@ -343,10 +369,12 @@ class Jsr310ConvertersConfiguration { @Bean ValueConverter instantStringValueConverter() { new ValueConverter() { + @Override boolean canConvert(Object value) { value instanceof CharSequence } + @Override Object convert(Object value) { Instant.parse((CharSequence) value) @@ -362,6 +390,7 @@ class Jsr310ConvertersConfiguration { @Bean ValueConverter instantValueConverter() { new ValueConverter() { + @Override boolean canConvert(Object value) { value instanceof Number @@ -389,20 +418,20 @@ class Jsr310ConvertersConfiguration { T convert(Object value, Closure callable) { T dateValue if (value instanceof String) { - if(!value) { + if (!value) { return null } def firstException formatStrings.each { String format -> if (dateValue == null) { try { - dateValue = (T)callable.call(format) + dateValue = (T) callable.call(format) } catch (Exception e) { firstException = firstException ?: e } } } - if(dateValue == null && firstException) { + if (dateValue == null && firstException) { throw firstException } } diff --git a/grails-databinding/src/main/groovy/org/grails/databinding/converters/web/LocaleAwareBigDecimalConverter.groovy b/grails-databinding/src/main/groovy/org/grails/databinding/converters/web/LocaleAwareBigDecimalConverter.groovy index 661cfa7efe6..e15df6259ba 100644 --- a/grails-databinding/src/main/groovy/org/grails/databinding/converters/web/LocaleAwareBigDecimalConverter.groovy +++ b/grails-databinding/src/main/groovy/org/grails/databinding/converters/web/LocaleAwareBigDecimalConverter.groovy @@ -41,7 +41,7 @@ class LocaleAwareBigDecimalConverter extends LocaleAwareNumberConverter { throw new IllegalStateException("Cannot support non-DecimalFormat: " + nf) } - ((DecimalFormat)nf).setParseBigDecimal(true) + ((DecimalFormat) nf).setParseBigDecimal(true) nf } } diff --git a/grails-databinding/src/main/groovy/org/grails/databinding/converters/web/LocaleAwareNumberConverter.groovy b/grails-databinding/src/main/groovy/org/grails/databinding/converters/web/LocaleAwareNumberConverter.groovy index efbab1ad7fd..c2b6e98ba4f 100644 --- a/grails-databinding/src/main/groovy/org/grails/databinding/converters/web/LocaleAwareNumberConverter.groovy +++ b/grails-databinding/src/main/groovy/org/grails/databinding/converters/web/LocaleAwareNumberConverter.groovy @@ -18,24 +18,21 @@ */ package org.grails.databinding.converters.web -import grails.databinding.converters.ValueConverter; +import grails.databinding.converters.ValueConverter import groovy.transform.CompileStatic - -import java.text.NumberFormat -import java.text.ParsePosition - import jakarta.servlet.http.HttpServletRequest - import org.grails.web.servlet.mvc.GrailsWebRequest import org.springframework.beans.factory.annotation.Autowired import org.springframework.web.servlet.LocaleResolver +import java.text.NumberFormat +import java.text.ParsePosition /** * A ValueConverter that knows how to convert a String to any numeric type and is Locale aware. The * converter will use the Locale of the current request if being invoked as part of a * request, otherwise will use Locale.getDefault() - * + * * @author Jeff Brown * @since 2.3 * @@ -44,21 +41,21 @@ import org.springframework.web.servlet.LocaleResolver class LocaleAwareNumberConverter implements ValueConverter { Class targetType - - @Autowired(required=false) + + @Autowired(required = false) LocaleResolver localeResolver @Override - public boolean canConvert(Object value) { + boolean canConvert(Object value) { value instanceof String } @Override - public Object convert(Object value) { + Object convert(Object value) { def trimmedValue = value.toString().trim() def parsePosition = new ParsePosition(0) - def result = numberFormatter.parse((String)value, parsePosition).asType(getTargetType()) - if(parsePosition.index != trimmedValue.size()) { + def result = numberFormatter.parse((String) value, parsePosition).asType(getTargetType()) + if (parsePosition.index != trimmedValue.size()) { throw new NumberFormatException("Unable to parse number [${value}]") } result @@ -71,10 +68,10 @@ class LocaleAwareNumberConverter implements ValueConverter { protected Locale getLocale() { def locale def request = GrailsWebRequest.lookup()?.currentRequest - if(request instanceof HttpServletRequest) { + if (request instanceof HttpServletRequest) { locale = localeResolver?.resolveLocale(request) } - if(locale == null) { + if (locale == null) { locale = Locale.default } return locale diff --git a/grails-databinding/src/main/groovy/org/grails/plugins/databinding/AbstractDataBindingGrailsPlugin.groovy b/grails-databinding/src/main/groovy/org/grails/plugins/databinding/AbstractDataBindingGrailsPlugin.groovy index f31a70a1dd2..f89e1cf7601 100644 --- a/grails-databinding/src/main/groovy/org/grails/plugins/databinding/AbstractDataBindingGrailsPlugin.groovy +++ b/grails-databinding/src/main/groovy/org/grails/plugins/databinding/AbstractDataBindingGrailsPlugin.groovy @@ -23,8 +23,13 @@ import grails.plugins.Plugin import grails.util.GrailsUtil import grails.web.databinding.DataBindingUtils import grails.web.databinding.GrailsWebDataBinder +import org.grails.databinding.converters.CurrencyValueConverter +import org.grails.databinding.converters.DateConversionHelper import org.grails.databinding.converters.Jsr310ConvertersConfiguration +import org.grails.databinding.converters.TimeZoneConverter import org.grails.databinding.converters.UUIDConverter +import org.grails.databinding.converters.web.LocaleAwareBigDecimalConverter +import org.grails.databinding.converters.web.LocaleAwareNumberConverter import org.grails.web.databinding.bindingsource.DataBindingSourceRegistry import org.grails.web.databinding.bindingsource.DefaultDataBindingSourceRegistry import org.grails.web.databinding.bindingsource.HalJsonDataBindingSourceCreator @@ -32,11 +37,6 @@ import org.grails.web.databinding.bindingsource.HalXmlDataBindingSourceCreator import org.grails.web.databinding.bindingsource.JsonApiDataBindingSourceCreator import org.grails.web.databinding.bindingsource.JsonDataBindingSourceCreator import org.grails.web.databinding.bindingsource.XmlDataBindingSourceCreator -import org.grails.databinding.converters.CurrencyValueConverter -import org.grails.databinding.converters.DateConversionHelper -import org.grails.databinding.converters.TimeZoneConverter -import org.grails.databinding.converters.web.LocaleAwareBigDecimalConverter -import org.grails.databinding.converters.web.LocaleAwareNumberConverter /** * Plugin for configuring the data binding features of Grails @@ -53,68 +53,70 @@ abstract class AbstractDataBindingGrailsPlugin extends Plugin { public static final String DEFAULT_JSR310_LOCAL_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss" public static final String DEFAULT_JSR310_LOCAL_DATE_FORMAT = "yyyy-MM-dd" public static final String DEFAULT_JSR310_LOCAL_TIME_FORMAT = "HH:mm:ss" - public static final List DEFAULT_DATE_FORMATS = ['yyyy-MM-dd HH:mm:ss.S',"yyyy-MM-dd'T'HH:mm:ss'Z'","yyyy-MM-dd HH:mm:ss.S z","yyyy-MM-dd'T'HH:mm:ss.SSSX", DEFAULT_JSR310_OFFSET_ZONED_DATE_TIME_FORMAT, DEFAULT_JSR310_OFFSET_TIME_FORMAT, DEFAULT_JSR310_LOCAL_DATE_TIME_FORMAT, DEFAULT_JSR310_LOCAL_DATE_FORMAT, DEFAULT_JSR310_LOCAL_TIME_FORMAT] + public static final List DEFAULT_DATE_FORMATS = ['yyyy-MM-dd HH:mm:ss.S', "yyyy-MM-dd'T'HH:mm:ss'Z'", "yyyy-MM-dd HH:mm:ss.S z", "yyyy-MM-dd'T'HH:mm:ss.SSSX", DEFAULT_JSR310_OFFSET_ZONED_DATE_TIME_FORMAT, DEFAULT_JSR310_OFFSET_TIME_FORMAT, DEFAULT_JSR310_LOCAL_DATE_TIME_FORMAT, DEFAULT_JSR310_LOCAL_DATE_FORMAT, DEFAULT_JSR310_LOCAL_TIME_FORMAT] def version = GrailsUtil.getGrailsVersion() @Override - Closure doWithSpring() {{-> - def application = grailsApplication - def config = application.config - boolean trimStringsSetting = config.getProperty(Settings.TRIM_STRINGS, Boolean, true) - boolean convertEmptyStringsToNullSetting = config.getProperty(Settings.CONVERT_EMPTY_STRINGS_TO_NULL, Boolean, true) - boolean dateParsingLenientSetting = config.getProperty(Settings.DATE_LENIENT_PARSING, Boolean, false) - Integer autoGrowCollectionLimitSetting = config.getProperty(Settings.AUTO_GROW_COLLECTION_LIMIT, Integer, 256) - List dateFormats = config.getProperty(Settings.DATE_FORMATS, List, DEFAULT_DATE_FORMATS) + Closure doWithSpring() { + { -> + def application = grailsApplication + def config = application.config + boolean trimStringsSetting = config.getProperty(Settings.TRIM_STRINGS, Boolean, true) + boolean convertEmptyStringsToNullSetting = config.getProperty(Settings.CONVERT_EMPTY_STRINGS_TO_NULL, Boolean, true) + boolean dateParsingLenientSetting = config.getProperty(Settings.DATE_LENIENT_PARSING, Boolean, false) + Integer autoGrowCollectionLimitSetting = config.getProperty(Settings.AUTO_GROW_COLLECTION_LIMIT, Integer, 256) + List dateFormats = config.getProperty(Settings.DATE_FORMATS, List, DEFAULT_DATE_FORMATS) - "${DataBindingUtils.DATA_BINDER_BEAN_NAME}"(GrailsWebDataBinder, grailsApplication) { - // trimStrings defaults to TRUE - trimStrings = trimStringsSetting - // convertEmptyStringsToNull defaults to TRUE - convertEmptyStringsToNull = convertEmptyStringsToNullSetting - // autoGrowCollectionLimit defaults to 256 - autoGrowCollectionLimit = autoGrowCollectionLimitSetting - } + "${DataBindingUtils.DATA_BINDER_BEAN_NAME}"(GrailsWebDataBinder, grailsApplication) { + // trimStrings defaults to TRUE + trimStrings = trimStringsSetting + // convertEmptyStringsToNull defaults to TRUE + convertEmptyStringsToNull = convertEmptyStringsToNullSetting + // autoGrowCollectionLimit defaults to 256 + autoGrowCollectionLimit = autoGrowCollectionLimitSetting + } - dataBindingConfigurationProperties(DataBindingConfigurationProperties) - timeZoneConverter(TimeZoneConverter) - uuidConverter(UUIDConverter) + dataBindingConfigurationProperties(DataBindingConfigurationProperties) + timeZoneConverter(TimeZoneConverter) + uuidConverter(UUIDConverter) - defaultDateConverter(DateConversionHelper) { - formatStrings = dateFormats - // dateParsingLenient defaults to false - dateParsingLenient = dateParsingLenientSetting - } - [Short, Short.TYPE, - Integer, Integer.TYPE, - Float, Float.TYPE, - Long, Long.TYPE, - Double, Double.TYPE].each { numberType -> - "defaultGrails${numberType.simpleName}Converter"(LocaleAwareNumberConverter) { - targetType = numberType + defaultDateConverter(DateConversionHelper) { + formatStrings = dateFormats + // dateParsingLenient defaults to false + dateParsingLenient = dateParsingLenientSetting + } + [Short, Short.TYPE, + Integer, Integer.TYPE, + Float, Float.TYPE, + Long, Long.TYPE, + Double, Double.TYPE].each { numberType -> + "defaultGrails${numberType.simpleName}Converter"(LocaleAwareNumberConverter) { + targetType = numberType + } + } + defaultGrailsBigDecimalConverter(LocaleAwareBigDecimalConverter) { + targetType = BigDecimal + } + defaultGrailsBigIntegerConverter(LocaleAwareBigDecimalConverter) { + targetType = BigInteger } - } - defaultGrailsBigDecimalConverter(LocaleAwareBigDecimalConverter) { - targetType = BigDecimal - } - defaultGrailsBigIntegerConverter(LocaleAwareBigDecimalConverter) { - targetType = BigInteger - } - jsr310DataBinding(Jsr310ConvertersConfiguration) { - formatStrings = dateFormats - } + jsr310DataBinding(Jsr310ConvertersConfiguration) { + formatStrings = dateFormats + } - "${DataBindingSourceRegistry.BEAN_NAME}"(DefaultDataBindingSourceRegistry) + "${DataBindingSourceRegistry.BEAN_NAME}"(DefaultDataBindingSourceRegistry) - xmlDataBindingSourceCreator(XmlDataBindingSourceCreator) - jsonDataBindingSourceCreator(JsonDataBindingSourceCreator) - halJsonDataBindingSourceCreator(HalJsonDataBindingSourceCreator) - halXmlDataBindingSourceCreator(HalXmlDataBindingSourceCreator) - jsonApiDataBindingSourceCreator(JsonApiDataBindingSourceCreator) + xmlDataBindingSourceCreator(XmlDataBindingSourceCreator) + jsonDataBindingSourceCreator(JsonDataBindingSourceCreator) + halJsonDataBindingSourceCreator(HalJsonDataBindingSourceCreator) + halXmlDataBindingSourceCreator(HalXmlDataBindingSourceCreator) + jsonApiDataBindingSourceCreator(JsonApiDataBindingSourceCreator) - defaultCurrencyConverter CurrencyValueConverter - }} + defaultCurrencyConverter CurrencyValueConverter + } + } } diff --git a/grails-databinding/src/main/groovy/org/grails/plugins/databinding/DataBindingConfiguration.java b/grails-databinding/src/main/groovy/org/grails/plugins/databinding/DataBindingConfiguration.java index ad5cf12154f..011b9529e6e 100644 --- a/grails-databinding/src/main/groovy/org/grails/plugins/databinding/DataBindingConfiguration.java +++ b/grails-databinding/src/main/groovy/org/grails/plugins/databinding/DataBindingConfiguration.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.plugins.databinding; import grails.core.GrailsApplication; @@ -28,7 +27,13 @@ import grails.web.databinding.GrailsWebDataBinder; import org.grails.databinding.bindingsource.DataBindingSourceCreator; import org.grails.databinding.converters.DefaultConvertersConfiguration; -import org.grails.web.databinding.bindingsource.*; +import org.grails.web.databinding.bindingsource.DataBindingSourceRegistry; +import org.grails.web.databinding.bindingsource.DefaultDataBindingSourceRegistry; +import org.grails.web.databinding.bindingsource.HalJsonDataBindingSourceCreator; +import org.grails.web.databinding.bindingsource.HalXmlDataBindingSourceCreator; +import org.grails.web.databinding.bindingsource.JsonApiDataBindingSourceCreator; +import org.grails.web.databinding.bindingsource.JsonDataBindingSourceCreator; +import org.grails.web.databinding.bindingsource.XmlDataBindingSourceCreator; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; @@ -84,7 +89,7 @@ protected GrailsWebDataBinder grailsWebDataBinder( dataBinder.setStructuredBindingEditors(GrailsArrayUtils.concat(structuredBindingEditors, mainContextStructuredBindingEditors)); final DataBindingListener[] mainContextDataBindingListeners = mainContext .getBeansOfType(DataBindingListener.class).values().toArray(new DataBindingListener[0]); - dataBinder.setDataBindingListeners(GrailsArrayUtils.concat(dataBindingListeners,mainContextDataBindingListeners)); + dataBinder.setDataBindingListeners(GrailsArrayUtils.concat(dataBindingListeners, mainContextDataBindingListeners)); dataBinder.setMessageSource(mainContext.getBean("messageSource", MessageSource.class)); return dataBinder; } diff --git a/grails-datamapping-async/build.gradle b/grails-datamapping-async/build.gradle index 81458a5169e..a5b3644cdab 100644 --- a/grails-datamapping-async/build.gradle +++ b/grails-datamapping-async/build.gradle @@ -77,4 +77,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-datamapping-async/src/main/groovy/grails/gorm/async/AsyncEntity.groovy b/grails-datamapping-async/src/main/groovy/grails/gorm/async/AsyncEntity.groovy index 0d8fcfcca3b..c25826efa24 100644 --- a/grails-datamapping-async/src/main/groovy/grails/gorm/async/AsyncEntity.groovy +++ b/grails-datamapping-async/src/main/groovy/grails/gorm/async/AsyncEntity.groovy @@ -32,6 +32,7 @@ import org.grails.datastore.gorm.async.GormAsyncStaticApi */ @CompileStatic trait AsyncEntity extends GormEntity { + /** * @return The async version of the GORM static API */ diff --git a/grails-datamapping-async/src/main/groovy/org/grails/datastore/gorm/async/AsyncQuery.groovy b/grails-datamapping-async/src/main/groovy/org/grails/datastore/gorm/async/AsyncQuery.groovy index 6486a6fe9fa..3cb0248058e 100644 --- a/grails-datamapping-async/src/main/groovy/org/grails/datastore/gorm/async/AsyncQuery.groovy +++ b/grails-datamapping-async/src/main/groovy/org/grails/datastore/gorm/async/AsyncQuery.groovy @@ -27,19 +27,19 @@ import org.grails.datastore.gorm.query.GormOperations */ class AsyncQuery implements PromiseDecoratorProvider { - @DelegateAsync GormOperations gormOperations + @DelegateAsync + GormOperations gormOperations /** * Wraps each promise in a new persistence session */ - private List decorators = [ { Closure callable -> + private List decorators = [{ Closure callable -> return { args -> gormOperations.persistentClass.withNewSession { callable.call(*args) } } - } as PromiseDecorator ] - + } as PromiseDecorator] AsyncQuery(GormOperations gormOperations) { this.gormOperations = gormOperations diff --git a/grails-datamapping-async/src/main/groovy/org/grails/datastore/gorm/async/GormAsyncStaticApi.groovy b/grails-datamapping-async/src/main/groovy/org/grails/datastore/gorm/async/GormAsyncStaticApi.groovy index 627c2e81551..2ca759d2f22 100644 --- a/grails-datamapping-async/src/main/groovy/org/grails/datastore/gorm/async/GormAsyncStaticApi.groovy +++ b/grails-datamapping-async/src/main/groovy/org/grails/datastore/gorm/async/GormAsyncStaticApi.groovy @@ -29,16 +29,17 @@ import org.grails.datastore.gorm.async.transform.DelegateAsync * @author Graeme Rocher * @since 2.3 */ -class GormAsyncStaticApi implements PromiseDecoratorProvider{ +class GormAsyncStaticApi implements PromiseDecoratorProvider { - @DelegateAsync GormStaticOperations staticApi + @DelegateAsync + GormStaticOperations staticApi /** * Wraps each promise in a new persistence session */ - private List decorators = [ { Closure callable -> - return { args -> staticApi.withNewSession{ callable.call(*args) } } - } as PromiseDecorator ] + private List decorators = [{ Closure callable -> + return { args -> staticApi.withNewSession { callable.call(*args) } } + } as PromiseDecorator] GormAsyncStaticApi(GormStaticApi staticApi) { this.staticApi = staticApi @@ -58,6 +59,6 @@ class GormAsyncStaticApi implements PromiseDecoratorProvider{ @CompileStatic public Promise task(Closure callable) { callable.delegate = staticApi.gormPersistentEntity.javaClass - (Promise)Promises.createPromise(callable, decorators) + (Promise) Promises.createPromise(callable, decorators) } } \ No newline at end of file diff --git a/grails-datamapping-core/build.gradle b/grails-datamapping-core/build.gradle index 52ef07e4b8c..6625aaadd88 100644 --- a/grails-datamapping-core/build.gradle +++ b/grails-datamapping-core/build.gradle @@ -121,4 +121,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/CriteriaBuilder.java b/grails-datamapping-core/src/main/groovy/grails/gorm/CriteriaBuilder.java index 480978c83e8..5bfcc31b524 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/CriteriaBuilder.java +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/CriteriaBuilder.java @@ -16,11 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - package grails.gorm; import groovy.lang.Closure; import groovy.lang.DelegatesTo; +import jakarta.persistence.criteria.JoinType; import org.grails.datastore.gorm.query.criteria.AbstractCriteriaBuilder; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.model.MappingContext; @@ -30,7 +30,6 @@ import org.grails.datastore.mapping.query.api.Criteria; import org.grails.datastore.mapping.query.api.ProjectionList; -import jakarta.persistence.criteria.JoinType; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -99,8 +98,8 @@ public BuildableCriteria select(String property) { /** * Defines and executes a list query in a single call. Example: Foo.createCriteria.list { } - * @param callable The closure to execute * + * @param callable The closure to execute * @return The result list */ public List list(Closure callable) { @@ -113,9 +112,7 @@ public List list(Closure callable) { /** * Defines and executes a get query (a single result) in a single call. Example: Foo.createCriteria.get { } * - * * @param callable The closure to execute - * * @return A single result */ public Object get(Closure callable) { @@ -128,8 +125,8 @@ public Object get(Closure callable) { /** * Defines and executes a list distinct query in a single call. Example: Foo.createCriteria.listDistinct { } - * @param callable The closure to execute * + * @param callable The closure to execute * @return The result list */ public List listDistinct(Closure callable) { @@ -155,8 +152,8 @@ public List list(Map paginateParams, Closure callable) { /** * Defines and executes a count query in a single call. Example: Foo.createCriteria.count { } - * @param callable The closure to execute * + * @param callable The closure to execute * @return The result count */ public Number count(Closure callable) { @@ -166,11 +163,10 @@ public Number count(Closure callable) { query.projections().count(); return (Number) query.singleResult(); } - + @Override public Object scroll(@DelegatesTo(Criteria.class) Closure c) { return invokeMethod(SCROLL_CALL, new Object[]{c}); } - } diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/DetachedCriteria.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/DetachedCriteria.groovy index 9c2a621b218..dc1134e16d0 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/DetachedCriteria.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/DetachedCriteria.groovy @@ -20,7 +20,7 @@ package grails.gorm import groovy.transform.CompileStatic -import groovy.transform.TypeCheckingMode +import jakarta.persistence.criteria.JoinType import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.gorm.GormStaticApi import org.grails.datastore.gorm.finders.DynamicFinder @@ -28,14 +28,11 @@ import org.grails.datastore.gorm.query.GormOperations import org.grails.datastore.gorm.query.criteria.AbstractDetachedCriteria import org.grails.datastore.mapping.core.Session import org.grails.datastore.mapping.query.Query -import org.grails.datastore.mapping.query.api.Criteria import org.grails.datastore.mapping.query.api.ProjectionList import org.grails.datastore.mapping.query.api.QueryAliasAwareSession import org.grails.datastore.mapping.query.api.QueryArgumentsAware import org.grails.datastore.mapping.query.api.QueryableCriteria -import jakarta.persistence.criteria.JoinType - /** * Represents criteria that is not bound to the current connection and can be built up and re-used at a later date. * @@ -54,7 +51,6 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe super(targetClass, alias) } - /** * Where method derives a new query from this query. This method will not mutate the original query, but instead return a new one. * @@ -69,14 +65,14 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe @Override DetachedCriteria withConnection(String name) { - return (DetachedCriteria)super.withConnection(name) + return (DetachedCriteria) super.withConnection(name) } /** - * Where method derives a new query from this query. This method will not mutate the original query, but instead return a new one. - * - * @param additionalQuery The additional query - * @return A new query - */ + * Where method derives a new query from this query. This method will not mutate the original query, but instead return a new one. + * + * @param additionalQuery The additional query + * @return A new query + */ @Override DetachedCriteria whereLazy(@DelegatesTo(DetachedCriteria) Closure additionalQuery) { DetachedCriteria newQuery = clone() @@ -116,7 +112,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe * @return A single entity */ T get(Map args = Collections.emptyMap(), @DelegatesTo(DetachedCriteria) Closure additionalCriteria = null) { - (T)withPopulatedQuery(args, additionalCriteria) { Query query -> + (T) withPopulatedQuery(args, additionalCriteria) { Query query -> query.singleResult() } } @@ -136,7 +132,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe * @return A list of matching instances */ List list(Map args = Collections.emptyMap(), @DelegatesTo(DetachedCriteria) Closure additionalCriteria = null) { - (List)withPopulatedQuery(args, additionalCriteria) { Query query -> + (List) withPopulatedQuery(args, additionalCriteria) { Query query -> if (args?.max) { return new PagedResultList(query) } @@ -160,352 +156,352 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe @Override DetachedCriteria join(String property) { - return (DetachedCriteria)super.join(property) + return (DetachedCriteria) super.join(property) } @Override DetachedCriteria join(String property, JoinType joinType) { - return (DetachedCriteria)super.join(property, joinType) + return (DetachedCriteria) super.join(property, joinType) } @Override DetachedCriteria select(String property) { - return (DetachedCriteria)super.select(property) + return (DetachedCriteria) super.select(property) } @Override DetachedCriteria and(@DelegatesTo(AbstractDetachedCriteria) Closure callable) { - return (DetachedCriteria)super.and(callable) + return (DetachedCriteria) super.and(callable) } @Override DetachedCriteria or(@DelegatesTo(AbstractDetachedCriteria) Closure callable) { - return (DetachedCriteria)super.or(callable) + return (DetachedCriteria) super.or(callable) } @Override DetachedCriteria not(@DelegatesTo(AbstractDetachedCriteria) Closure callable) { - return (DetachedCriteria)super.not(callable) + return (DetachedCriteria) super.not(callable) } @Override DetachedCriteria "in"(String propertyName, Collection values) { - return (DetachedCriteria)super.in(propertyName, values) + return (DetachedCriteria) super.in(propertyName, values) } @Override DetachedCriteria "in"(String propertyName, QueryableCriteria subquery) { - return (DetachedCriteria)super.in(propertyName, subquery) + return (DetachedCriteria) super.in(propertyName, subquery) } @Override DetachedCriteria inList(String propertyName, QueryableCriteria subquery) { - return (DetachedCriteria)super.inList(propertyName, subquery) + return (DetachedCriteria) super.inList(propertyName, subquery) } @Override DetachedCriteria "in"(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure subquery) { - return (DetachedCriteria)super.in(propertyName, subquery) + return (DetachedCriteria) super.in(propertyName, subquery) } @Override DetachedCriteria inList(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure subquery) { - return (DetachedCriteria)super.inList(propertyName, subquery) + return (DetachedCriteria) super.inList(propertyName, subquery) } @Override DetachedCriteria "in"(String propertyName, Object[] values) { - return (DetachedCriteria)super.in(propertyName, values) + return (DetachedCriteria) super.in(propertyName, values) } @Override DetachedCriteria notIn(String propertyName, QueryableCriteria subquery) { - return (DetachedCriteria)super.notIn(propertyName, subquery) + return (DetachedCriteria) super.notIn(propertyName, subquery) } @Override DetachedCriteria notIn(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure subquery) { - return (DetachedCriteria)super.notIn(propertyName, subquery) + return (DetachedCriteria) super.notIn(propertyName, subquery) } @Override DetachedCriteria order(String propertyName) { - return (DetachedCriteria)super.order(propertyName) + return (DetachedCriteria) super.order(propertyName) } @Override DetachedCriteria order(Query.Order o) { - return (DetachedCriteria)super.order(o) + return (DetachedCriteria) super.order(o) } @Override DetachedCriteria order(String propertyName, String direction) { - return (DetachedCriteria)super.order(propertyName, direction) + return (DetachedCriteria) super.order(propertyName, direction) } @Override DetachedCriteria inList(String propertyName, Collection values) { - return (DetachedCriteria)super.inList(propertyName, values) + return (DetachedCriteria) super.inList(propertyName, values) } @Override DetachedCriteria inList(String propertyName, Object[] values) { - return (DetachedCriteria)super.inList(propertyName, values) + return (DetachedCriteria) super.inList(propertyName, values) } @Override DetachedCriteria sizeEq(String propertyName, int size) { - return (DetachedCriteria)super.sizeEq(propertyName, size) + return (DetachedCriteria) super.sizeEq(propertyName, size) } @Override DetachedCriteria sizeGt(String propertyName, int size) { - return (DetachedCriteria)super.sizeGt(propertyName, size) + return (DetachedCriteria) super.sizeGt(propertyName, size) } @Override DetachedCriteria sizeGe(String propertyName, int size) { - return (DetachedCriteria)super.sizeGe(propertyName, size) + return (DetachedCriteria) super.sizeGe(propertyName, size) } @Override DetachedCriteria sizeLe(String propertyName, int size) { - return (DetachedCriteria)super.sizeLe(propertyName, size) + return (DetachedCriteria) super.sizeLe(propertyName, size) } @Override DetachedCriteria sizeLt(String propertyName, int size) { - return (DetachedCriteria)super.sizeLt(propertyName, size) + return (DetachedCriteria) super.sizeLt(propertyName, size) } @Override DetachedCriteria sizeNe(String propertyName, int size) { - return (DetachedCriteria)super.sizeNe(propertyName, size) + return (DetachedCriteria) super.sizeNe(propertyName, size) } @Override DetachedCriteria eqProperty(String propertyName, String otherPropertyName) { - return (DetachedCriteria)super.eqProperty(propertyName, otherPropertyName) + return (DetachedCriteria) super.eqProperty(propertyName, otherPropertyName) } @Override DetachedCriteria neProperty(String propertyName, String otherPropertyName) { - return (DetachedCriteria)super.neProperty(propertyName, otherPropertyName) + return (DetachedCriteria) super.neProperty(propertyName, otherPropertyName) } @Override DetachedCriteria allEq(Map propertyValues) { - return (DetachedCriteria)super.allEq(propertyValues) + return (DetachedCriteria) super.allEq(propertyValues) } @Override DetachedCriteria gtProperty(String propertyName, String otherPropertyName) { - return (DetachedCriteria)super.gtProperty(propertyName, otherPropertyName) + return (DetachedCriteria) super.gtProperty(propertyName, otherPropertyName) } @Override DetachedCriteria geProperty(String propertyName, String otherPropertyName) { - return (DetachedCriteria)super.geProperty(propertyName, otherPropertyName) + return (DetachedCriteria) super.geProperty(propertyName, otherPropertyName) } @Override DetachedCriteria ltProperty(String propertyName, String otherPropertyName) { - return (DetachedCriteria)super.ltProperty(propertyName, otherPropertyName) + return (DetachedCriteria) super.ltProperty(propertyName, otherPropertyName) } @Override DetachedCriteria leProperty(String propertyName, String otherPropertyName) { - return (DetachedCriteria)super.leProperty(propertyName, otherPropertyName) + return (DetachedCriteria) super.leProperty(propertyName, otherPropertyName) } @Override DetachedCriteria idEquals(Object value) { - return (DetachedCriteria)super.idEquals(value) + return (DetachedCriteria) super.idEquals(value) } @Override DetachedCriteria exists(QueryableCriteria subquery) { - return (DetachedCriteria)super.exists(subquery) + return (DetachedCriteria) super.exists(subquery) } @Override DetachedCriteria notExists(QueryableCriteria subquery) { - return (DetachedCriteria)super.notExists(subquery) + return (DetachedCriteria) super.notExists(subquery) } @Override DetachedCriteria isEmpty(String propertyName) { - return (DetachedCriteria)super.isEmpty(propertyName) + return (DetachedCriteria) super.isEmpty(propertyName) } @Override DetachedCriteria isNotEmpty(String propertyName) { - return (DetachedCriteria)super.isNotEmpty(propertyName) + return (DetachedCriteria) super.isNotEmpty(propertyName) } @Override DetachedCriteria isNull(String propertyName) { - return (DetachedCriteria)super.isNull(propertyName) + return (DetachedCriteria) super.isNull(propertyName) } @Override DetachedCriteria isNotNull(String propertyName) { - return (DetachedCriteria)super.isNotNull(propertyName) + return (DetachedCriteria) super.isNotNull(propertyName) } @Override DetachedCriteria eq(String propertyName, Object propertyValue) { - return (DetachedCriteria)super.eq(propertyName, propertyValue) + return (DetachedCriteria) super.eq(propertyName, propertyValue) } @Override DetachedCriteria idEq(Object propertyValue) { - return (DetachedCriteria)super.idEq(propertyValue) + return (DetachedCriteria) super.idEq(propertyValue) } @Override DetachedCriteria ne(String propertyName, Object propertyValue) { - return (DetachedCriteria)super.ne(propertyName, propertyValue) + return (DetachedCriteria) super.ne(propertyName, propertyValue) } @Override DetachedCriteria between(String propertyName, Object start, Object finish) { - return (DetachedCriteria)super.between(propertyName, start, finish) + return (DetachedCriteria) super.between(propertyName, start, finish) } @Override DetachedCriteria gte(String property, Object value) { - return (DetachedCriteria)super.gte(property, value) + return (DetachedCriteria) super.gte(property, value) } @Override DetachedCriteria ge(String property, Object value) { - return (DetachedCriteria)super.ge(property, value) + return (DetachedCriteria) super.ge(property, value) } @Override DetachedCriteria gt(String property, Object value) { - return (DetachedCriteria)super.gt(property, value) + return (DetachedCriteria) super.gt(property, value) } @Override DetachedCriteria lte(String property, Object value) { - return (DetachedCriteria)super.lte(property, value) + return (DetachedCriteria) super.lte(property, value) } @Override DetachedCriteria le(String property, Object value) { - return (DetachedCriteria)super.le(property, value) + return (DetachedCriteria) super.le(property, value) } @Override DetachedCriteria lt(String property, Object value) { - return (DetachedCriteria)super.lt(property, value) + return (DetachedCriteria) super.lt(property, value) } @Override DetachedCriteria like(String propertyName, Object propertyValue) { - return (DetachedCriteria)super.like(propertyName, propertyValue) + return (DetachedCriteria) super.like(propertyName, propertyValue) } @Override DetachedCriteria ilike(String propertyName, Object propertyValue) { - return (DetachedCriteria)super.ilike(propertyName, propertyValue) + return (DetachedCriteria) super.ilike(propertyName, propertyValue) } @Override DetachedCriteria rlike(String propertyName, Object propertyValue) { - return (DetachedCriteria)super.rlike(propertyName, propertyValue) + return (DetachedCriteria) super.rlike(propertyName, propertyValue) } @Override DetachedCriteria eqAll(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) { - return (DetachedCriteria)super.eqAll(propertyName, propertyValue) + return (DetachedCriteria) super.eqAll(propertyName, propertyValue) } @Override DetachedCriteria gtAll(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) { - return (DetachedCriteria)super.gtAll(propertyName, propertyValue) + return (DetachedCriteria) super.gtAll(propertyName, propertyValue) } @Override DetachedCriteria ltAll(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) { - return (DetachedCriteria)super.ltAll(propertyName, propertyValue) + return (DetachedCriteria) super.ltAll(propertyName, propertyValue) } @Override DetachedCriteria geAll(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) { - return (DetachedCriteria)super.geAll(propertyName, propertyValue) + return (DetachedCriteria) super.geAll(propertyName, propertyValue) } @Override DetachedCriteria leAll(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) { - return (DetachedCriteria)super.leAll(propertyName, propertyValue) + return (DetachedCriteria) super.leAll(propertyName, propertyValue) } @Override DetachedCriteria eqAll(String propertyName, QueryableCriteria propertyValue) { - return (DetachedCriteria)super.eqAll(propertyName, propertyValue) + return (DetachedCriteria) super.eqAll(propertyName, propertyValue) } @Override DetachedCriteria gtAll(String propertyName, QueryableCriteria propertyValue) { - return (DetachedCriteria)super.gtAll(propertyName, propertyValue) + return (DetachedCriteria) super.gtAll(propertyName, propertyValue) } @Override DetachedCriteria gtSome(String propertyName, QueryableCriteria propertyValue) { - return (DetachedCriteria)super.gtSome(propertyName, propertyValue) + return (DetachedCriteria) super.gtSome(propertyName, propertyValue) } @Override DetachedCriteria gtSome(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) { - return (DetachedCriteria)super.gtSome(propertyName, propertyValue) + return (DetachedCriteria) super.gtSome(propertyName, propertyValue) } @Override DetachedCriteria geSome(String propertyName, QueryableCriteria propertyValue) { - return (DetachedCriteria)super.geSome(propertyName, propertyValue) + return (DetachedCriteria) super.geSome(propertyName, propertyValue) } @Override DetachedCriteria geSome(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) { - return (DetachedCriteria)super.geSome(propertyName, propertyValue) + return (DetachedCriteria) super.geSome(propertyName, propertyValue) } @Override DetachedCriteria ltSome(String propertyName, QueryableCriteria propertyValue) { - return (DetachedCriteria)super.ltSome(propertyName, propertyValue) + return (DetachedCriteria) super.ltSome(propertyName, propertyValue) } @Override DetachedCriteria ltSome(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) { - return (DetachedCriteria)super.ltSome(propertyName, propertyValue) + return (DetachedCriteria) super.ltSome(propertyName, propertyValue) } @Override DetachedCriteria leSome(String propertyName, QueryableCriteria propertyValue) { - return (DetachedCriteria)super.leSome(propertyName, propertyValue) + return (DetachedCriteria) super.leSome(propertyName, propertyValue) } @Override DetachedCriteria leSome(String propertyName, @DelegatesTo(AbstractDetachedCriteria) Closure propertyValue) { - return (DetachedCriteria)super.leSome(propertyName, propertyValue) + return (DetachedCriteria) super.leSome(propertyName, propertyValue) } @Override DetachedCriteria ltAll(String propertyName, QueryableCriteria propertyValue) { - return (DetachedCriteria)super.ltAll(propertyName, propertyValue) + return (DetachedCriteria) super.ltAll(propertyName, propertyValue) } @Override DetachedCriteria geAll(String propertyName, QueryableCriteria propertyValue) { - return (DetachedCriteria)super.geAll(propertyName, propertyValue) + return (DetachedCriteria) super.geAll(propertyName, propertyValue) } @Override DetachedCriteria leAll(String propertyName, QueryableCriteria propertyValue) { - return (DetachedCriteria)super.leAll(propertyName, propertyValue) + return (DetachedCriteria) super.leAll(propertyName, propertyValue) } /** * Counts the number of records returned by the query @@ -514,7 +510,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe * @return The count */ Number count(Map args = Collections.emptyMap(), @DelegatesTo(DetachedCriteria) Closure additionalCriteria = null) { - (Number)withPopulatedQuery(args, additionalCriteria) { Query query -> + (Number) withPopulatedQuery(args, additionalCriteria) { Query query -> query.projections().count() query.singleResult() } @@ -527,7 +523,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe * @return The count */ Number count(@DelegatesTo(DetachedCriteria) Closure additionalCriteria) { - (Number)withPopulatedQuery(Collections.emptyMap(), additionalCriteria) { Query query -> + (Number) withPopulatedQuery(Collections.emptyMap(), additionalCriteria) { Query query -> query.projections().count() query.singleResult() } @@ -548,9 +544,9 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe */ boolean asBoolean(@DelegatesTo(DetachedCriteria) Closure additionalCriteria = null) { - (Boolean)withPopulatedQuery(Collections.emptyMap(), additionalCriteria) { Query query -> + (Boolean) withPopulatedQuery(Collections.emptyMap(), additionalCriteria) { Query query -> query.projections().count() - ((Number)query.singleResult()) > 0 + ((Number) query.singleResult()) > 0 } } @@ -586,7 +582,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe */ @Override DetachedCriteria build(@DelegatesTo(DetachedCriteria) Closure callable) { - (DetachedCriteria)super.build(callable) + (DetachedCriteria) super.build(callable) } /** @@ -597,7 +593,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe */ @Override DetachedCriteria buildLazy(@DelegatesTo(DetachedCriteria) Closure callable) { - (DetachedCriteria)super.buildLazy(callable) + (DetachedCriteria) super.buildLazy(callable) } /** @@ -608,7 +604,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe */ @Override DetachedCriteria max(int max) { - (DetachedCriteria)super.max(max) + (DetachedCriteria) super.max(max) } /** @@ -619,7 +615,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe */ @Override DetachedCriteria offset(int offset) { - (DetachedCriteria)super.offset(offset) + (DetachedCriteria) super.offset(offset) } /** @@ -629,7 +625,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe * @return This criteria instance */ DetachedCriteria sort(String property) { - (DetachedCriteria)super.sort(property) + (DetachedCriteria) super.sort(property) } /** @@ -640,7 +636,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe * @return This criteria instance */ DetachedCriteria sort(String property, String direction) { - (DetachedCriteria)super.sort(property,direction) + (DetachedCriteria) super.sort(property, direction) } /** @@ -650,7 +646,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe * @return This criteria instance */ DetachedCriteria property(String property) { - (DetachedCriteria)super.property(property) + (DetachedCriteria) super.property(property) } /** @@ -660,7 +656,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe * @return This criteria instance */ DetachedCriteria id() { - (DetachedCriteria)super.id() + (DetachedCriteria) super.id() } /** @@ -670,7 +666,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe * @return This criteria instance */ DetachedCriteria avg(String property) { - (DetachedCriteria)super.avg(property) + (DetachedCriteria) super.avg(property) } /** @@ -680,7 +676,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe * @return This criteria instance */ DetachedCriteria sum(String property) { - (DetachedCriteria)super.sum(property) + (DetachedCriteria) super.sum(property) } /** @@ -690,7 +686,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe * @return This criteria instance */ DetachedCriteria min(String property) { - (DetachedCriteria)super.min(property) + (DetachedCriteria) super.min(property) } /** @@ -700,7 +696,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe * @return This criteria instance */ DetachedCriteria max(String property) { - (DetachedCriteria)super.max(property) + (DetachedCriteria) super.max(property) } /** @@ -710,10 +706,9 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe * @return This criteria instance */ DetachedCriteria distinct(String property) { - (DetachedCriteria)super.distinct(property) + (DetachedCriteria) super.distinct(property) } - @Override protected DetachedCriteria newInstance() { new DetachedCriteria(targetClass, alias) @@ -721,7 +716,7 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe @Override protected DetachedCriteria clone() { - return (DetachedCriteria)super.clone() + return (DetachedCriteria) super.clone() } protected void handleJunction(Closure callable) { @@ -740,16 +735,15 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe return new DetachedCriteria(targetClass).build(queryClosure) } - private withPopulatedQuery(Map args, Closure additionalCriteria, Closure callable) { + private withPopulatedQuery(Map args, Closure additionalCriteria, Closure callable) { GormStaticApi staticApi = persistentEntity.isMultiTenant() ? GormEnhancer.findStaticApi(targetClass) : GormEnhancer.findStaticApi(targetClass, connectionName) staticApi.withDatastoreSession { Session session -> applyLazyCriteria() Query query - if(alias && (session instanceof QueryAliasAwareSession)) { + if (alias && (session instanceof QueryAliasAwareSession)) { query = session.createQuery(targetClass, alias) - } - else { + } else { query = session.createQuery(targetClass) } @@ -761,8 +755,8 @@ class DetachedCriteria extends AbstractDetachedCriteria implements GormOpe } DynamicFinder.applyDetachedCriteria(query, this) - if(query instanceof QueryArgumentsAware) { - ((QueryArgumentsAware)query).arguments = args + if (query instanceof QueryArgumentsAware) { + ((QueryArgumentsAware) query).arguments = args } if (additionalCriteria != null) { diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/MultiTenant.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/MultiTenant.groovy index 8f179e517be..6a58eb13726 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/MultiTenant.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/MultiTenant.groovy @@ -61,6 +61,6 @@ trait MultiTenant extends Entity { * @return The operations */ static GormAllOperations withTenant(Serializable tenantId) { - (GormAllOperations)GormEnhancer.findStaticApi(this).withTenant(tenantId) + (GormAllOperations) GormEnhancer.findStaticApi(this).withTenant(tenantId) } } \ No newline at end of file diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/PagedResultList.java b/grails-datamapping-core/src/main/groovy/grails/gorm/PagedResultList.java index f6767b9d15c..c7537542373 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/PagedResultList.java +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/PagedResultList.java @@ -18,12 +18,16 @@ */ package grails.gorm; +import org.grails.datastore.mapping.query.Query; + import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.util.*; - -import org.grails.datastore.mapping.query.Query; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; /** * A result list implementation that provides an additional property called 'totalCount' to obtain the total number of @@ -35,13 +39,13 @@ @SuppressWarnings({"rawtypes", "unchecked"}) public class PagedResultList implements Serializable, List { - private static final long serialVersionUID = -5820655628956173929L; - private final Query query; protected List resultList; protected int totalCount = Integer.MIN_VALUE; + private final Query query; + public PagedResultList(Query query) { this.query = query; this.resultList = query == null ? Collections.emptyList() : query.list(); @@ -105,7 +109,7 @@ protected void initialize() { if (query == null) { totalCount = 0; } else { - Query newQuery = (Query)query.clone(); + Query newQuery = (Query) query.clone(); newQuery.projections().count(); Number result = (Number) newQuery.singleResult(); totalCount = result == null ? 0 : result.intValue(); diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/annotation/Entity.java b/grails-datamapping-core/src/main/groovy/grails/gorm/annotation/Entity.java index 328c24c0494..783ec0408ad 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/annotation/Entity.java +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/annotation/Entity.java @@ -18,13 +18,13 @@ */ package grails.gorm.annotation; +import org.codehaus.groovy.transform.GroovyASTTransformationClass; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.codehaus.groovy.transform.GroovyASTTransformationClass; - /** * A class annotation used to make a class into a GORM domain class. * diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/annotation/JpaEntity.java b/grails-datamapping-core/src/main/groovy/grails/gorm/annotation/JpaEntity.java index bc59f9cefce..269e4a11bd2 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/annotation/JpaEntity.java +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/annotation/JpaEntity.java @@ -35,4 +35,5 @@ @Target({ElementType.TYPE}) @GroovyASTTransformationClass("org.grails.compiler.gorm.JpaGormEntityTransformation") public @interface JpaEntity { + } diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/api/GormInstanceOperations.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/api/GormInstanceOperations.groovy index bf46951760e..309b674c8d3 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/api/GormInstanceOperations.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/api/GormInstanceOperations.groovy @@ -19,12 +19,11 @@ package grails.gorm.api - /** * Instance methods of the GORM API. * * @author Graeme Rocher - * @param the entity/domain class + * @param the entity/domain class */ interface GormInstanceOperations { /** @@ -61,7 +60,6 @@ interface GormInstanceOperations { */ D refresh(D instance) - /** * Saves an object the datastore * @return Returns the instance diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/api/GormStaticOperations.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/api/GormStaticOperations.groovy index 79b6d8034d8..2fa85ebc539 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/api/GormStaticOperations.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/api/GormStaticOperations.groovy @@ -21,7 +21,6 @@ package grails.gorm.api import grails.gorm.DetachedCriteria import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.gorm.query.GormQueryOperations import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.query.api.BuildableCriteria import org.grails.datastore.mapping.query.api.Criteria @@ -91,7 +90,6 @@ interface GormStaticOperations { */ D find(Closure callable) - /** * Saves a list of objects in one go * @param objectsToSave The objects to save @@ -414,7 +412,7 @@ interface GormStaticOperations { * @param callable the closure * @return The result of the closure */ - public T withSession(Closure callable) + public T withSession(Closure callable) /** * Same as withSession, but present for the case where withSession is overridden to use the Hibernate session @@ -422,7 +420,7 @@ interface GormStaticOperations { * @param callable the closure * @return The result of the closure */ - public T withDatastoreSession(Closure callable) + public T withDatastoreSession(Closure callable) /** * Executes the closure within the context of a transaction, creating one if none is present or joining @@ -434,7 +432,7 @@ interface GormStaticOperations { * @see #withNewTransaction(Closure) * @see #withNewTransaction(Map, Closure) */ - public T withTransaction(Closure callable) + public T withTransaction(Closure callable) /** * Executes the closure within the context of a new transaction @@ -445,7 +443,7 @@ interface GormStaticOperations { * @see #withTransaction(Map, Closure) * @see #withNewTransaction(Map, Closure) */ - public T withNewTransaction(Closure callable) + public T withNewTransaction(Closure callable) /** * Executes the closure within the context of a transaction which is @@ -465,12 +463,11 @@ interface GormStaticOperations { * @param transactionProperties properties to configure the transaction properties * @param callable The closure to call * @return The result of the closure execution - * @see org.springframework.transaction.support.DefaultTransactionDefinition - * @see #withNewTransaction(Closure) + * @see org.springframework.transaction.support.DefaultTransactionDefinition* @see #withNewTransaction(Closure) * @see #withNewTransaction(Map, Closure) * @see #withTransaction(Closure) */ - public T withTransaction(Map transactionProperties, Closure callable) + public T withTransaction(Map transactionProperties, Closure callable) /** * Executes the closure within the context of a new transaction which is @@ -492,12 +489,11 @@ interface GormStaticOperations { * @param transactionProperties properties to configure the transaction properties * @param callable The closure to call * @return The result of the closure execution - * @see org.springframework.transaction.support.DefaultTransactionDefinition - * @see #withNewTransaction(Closure) + * @see org.springframework.transaction.support.DefaultTransactionDefinition* @see #withNewTransaction(Closure) * @see #withTransaction(Closure) * @see #withTransaction(Map, Closure) */ - public T withNewTransaction(Map transactionProperties, Closure callable) + public T withNewTransaction(Map transactionProperties, Closure callable) /** * Executes the closure within the context of a transaction for the given {@link org.springframework.transaction.TransactionDefinition} @@ -510,14 +506,13 @@ interface GormStaticOperations { /** * Creates and binds a new session for the scope of the given closure */ - public T withNewSession(Closure callable) + public T withNewSession(Closure callable) /** * Creates and binds a new session for the scope of the given closure */ public T withStatelessSession(Closure callable) - /** * Executes a query for the given String * @@ -569,7 +564,7 @@ interface GormStaticOperations { * @return A list of results * */ - List executeQuery(CharSequence query, Object...params) + List executeQuery(CharSequence query, Object... params) /** * Executes a query for the given String @@ -636,7 +631,7 @@ interface GormStaticOperations { * @return The number of entities updated * */ - Integer executeUpdate(CharSequence query, Object...params) + Integer executeUpdate(CharSequence query, Object... params) /** * Executes an update for the given String @@ -772,7 +767,6 @@ interface GormStaticOperations { */ List findAll(CharSequence query, Collection params, Map args) - /** * Execute the closure with the given tenantId * @@ -782,7 +776,6 @@ interface GormStaticOperations { */ def T withTenant(Serializable tenantId, Closure callable) - /** * Execute the closure for each tenant * diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/dirty/checking/DirtyCheck.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/dirty/checking/DirtyCheck.groovy index ae340a91a5d..c7b4a3788b0 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/dirty/checking/DirtyCheck.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/dirty/checking/DirtyCheck.groovy @@ -34,6 +34,6 @@ import java.lang.annotation.Target @Retention(RetentionPolicy.RUNTIME) @Target([ElementType.TYPE]) @GroovyASTTransformationClass("org.grails.compiler.gorm.DirtyCheckTransformation") -public @interface DirtyCheck { +@interface DirtyCheck { } \ No newline at end of file diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/CurrentTenant.java b/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/CurrentTenant.java index 6b955d8d50a..d5df1359668 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/CurrentTenant.java +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/CurrentTenant.java @@ -22,7 +22,12 @@ import org.grails.datastore.gorm.transform.GormASTTransformationClass; import org.grails.datastore.mapping.core.connections.ConnectionSourcesProvider; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** *

An AST transformation that makes a particular class or method applicable to the tenant id returned by the passed closure. For example:

@@ -36,8 +41,8 @@ * } * * - * @since 6.1 * @author Graeme Rocher + * @since 6.1 */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @@ -46,6 +51,7 @@ @GroovyASTTransformationClass("org.grails.datastore.gorm.transform.OrderedGormTransformation") @GormASTTransformationClass("org.grails.datastore.gorm.multitenancy.transform.TenantTransform") public @interface CurrentTenant { + /** * If you are using multiple GORM implementations and wish to create a transaction for a specific implementation then use this. For example {@code @Transactional(forDatastore=HibernateDatastore) } * diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/Tenant.java b/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/Tenant.java index 63a64422f39..11143b642f9 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/Tenant.java +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/Tenant.java @@ -22,7 +22,12 @@ import org.grails.datastore.gorm.transform.GormASTTransformationClass; import org.grails.datastore.mapping.core.connections.ConnectionSourcesProvider; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** *

An AST transformation that makes a particular class or method applicable to the tenant id returned by the passed closure. For example:

@@ -36,8 +41,8 @@ * } * * - * @since 6.1 * @author Graeme Rocher + * @since 6.1 */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @@ -46,6 +51,7 @@ @GroovyASTTransformationClass("org.grails.datastore.gorm.transform.OrderedGormTransformation") @GormASTTransformationClass("org.grails.datastore.gorm.multitenancy.transform.TenantTransform") public @interface Tenant { + /** * The tenant resolver * diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/Tenants.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/Tenants.groovy index d52d0eb0bb1..3972370d360 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/Tenants.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/Tenants.groovy @@ -39,6 +39,7 @@ import org.grails.datastore.mapping.multitenancy.TenantResolver @CompileStatic @Slf4j class Tenants { + /** * Execute the given closure for each tenant. * @@ -67,11 +68,10 @@ class Tenants { */ static Serializable currentId() { Datastore datastore = GormEnhancer.findSingleDatastore() - if(datastore instanceof MultiTenantCapableDatastore) { - MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore)datastore + if (datastore instanceof MultiTenantCapableDatastore) { + MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore) datastore return currentId(multiTenantCapableDatastore) - } - else { + } else { throw new UnsupportedOperationException("Datastore implementation does not support multi-tenancy") } } @@ -102,21 +102,19 @@ class Tenants { */ static Serializable currentId(Class datastoreClass) { Datastore datastore = GormEnhancer.findDatastoreByType(datastoreClass) - if(datastore instanceof MultiTenantCapableDatastore) { - MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore)datastore + if (datastore instanceof MultiTenantCapableDatastore) { + MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore) datastore def tenantId = CurrentTenant.get() - if(tenantId != null) { + if (tenantId != null) { log.debug "Found tenant id [$tenantId] bound to thread local" return tenantId - } - else { + } else { TenantResolver tenantResolver = multiTenantCapableDatastore.getTenantResolver() def tenantIdentifier = tenantResolver.resolveTenantIdentifier() log.debug "Resolved tenant id [$tenantIdentifier] from resolver [${tenantResolver.getClass().simpleName}]" return tenantIdentifier } - } - else { + } else { throw new UnsupportedOperationException("Datastore implementation does not support multi-tenancy") } } @@ -130,8 +128,8 @@ class Tenants { */ static T withoutId(Closure callable) { Datastore datastore = GormEnhancer.findSingleDatastore() - if(datastore instanceof MultiTenantCapableDatastore) { - MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore)datastore + if (datastore instanceof MultiTenantCapableDatastore) { + MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore) datastore return withoutId(multiTenantCapableDatastore, callable) } else { throw new UnsupportedOperationException("Datastore implementation does not support multi-tenancy") @@ -147,11 +145,10 @@ class Tenants { static T withCurrent(Closure callable) { Serializable tenantIdentifier = currentId() Datastore datastore = GormEnhancer.findSingleDatastore() - if(datastore instanceof MultiTenantCapableDatastore) { - MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore)datastore + if (datastore instanceof MultiTenantCapableDatastore) { + MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore) datastore return withId(multiTenantCapableDatastore, tenantIdentifier, callable) - } - else { + } else { throw new UnsupportedOperationException("Datastore implementation does not support multi-tenancy") } } @@ -166,11 +163,10 @@ class Tenants { static T withCurrent(Class datastoreClass, Closure callable) { Serializable tenantIdentifier = currentId(datastoreClass) Datastore datastore = GormEnhancer.findDatastoreByType(datastoreClass) - if(datastore instanceof MultiTenantCapableDatastore) { - MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore)datastore + if (datastore instanceof MultiTenantCapableDatastore) { + MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore) datastore return withId(multiTenantCapableDatastore, tenantIdentifier, callable) - } - else { + } else { throw new UnsupportedOperationException("Datastore implementation does not support multi-tenancy") } } @@ -183,11 +179,10 @@ class Tenants { */ static T withId(Serializable tenantId, Closure callable) { Datastore datastore = GormEnhancer.findSingleDatastore() - if(datastore instanceof MultiTenantCapableDatastore) { - MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore)datastore + if (datastore instanceof MultiTenantCapableDatastore) { + MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore) datastore return withId(multiTenantCapableDatastore, tenantId, callable) - } - else { + } else { throw new UnsupportedOperationException("Datastore implementation does not support multi-tenancy") } } @@ -199,11 +194,10 @@ class Tenants { */ static T withId(Class datastoreClass, Serializable tenantId, Closure callable) { Datastore datastore = GormEnhancer.findDatastoreByType(datastoreClass) - if(datastore instanceof MultiTenantCapableDatastore) { - MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore)datastore + if (datastore instanceof MultiTenantCapableDatastore) { + MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore) datastore return withId(multiTenantCapableDatastore, tenantId, callable) - } - else { + } else { throw new UnsupportedOperationException("Datastore implementation does not support multi-tenancy") } } @@ -217,7 +211,7 @@ class Tenants { return CurrentTenant.withoutTenant { if (multiTenantCapableDatastore.getMultiTenancyMode().isSharedConnection()) { def i = callable.parameterTypes.length - if(i == 0 ) { + if (i == 0) { return callable.call() } else { return multiTenantCapableDatastore.withSession { session -> @@ -253,14 +247,13 @@ class Tenants { */ static T withId(MultiTenantCapableDatastore multiTenantCapableDatastore, Serializable tenantId, Closure callable) { return CurrentTenant.withTenant(tenantId) { - if(multiTenantCapableDatastore.getMultiTenancyMode().isSharedConnection()) { + if (multiTenantCapableDatastore.getMultiTenancyMode().isSharedConnection()) { def i = callable.parameterTypes.length - if(i == 2) { + if (i == 2) { return multiTenantCapableDatastore.withSession { session -> return callable.call(tenantId, session) } - } - else { + } else { switch (i) { case 0: return callable.call() @@ -272,8 +265,7 @@ class Tenants { throw new IllegalArgumentException("Provided closure accepts too many arguments") } } - } - else { + } else { return multiTenantCapableDatastore.withNewSession(tenantId) { session -> def i = callable.parameterTypes.length switch (i) { @@ -340,7 +332,7 @@ class Tenants { } @CompileStatic - protected static class CurrentTenant { + protected static class CurrentTenant { private static final ThreadLocal currentTenantThreadLocal = new ThreadLocal<>() @@ -376,16 +368,14 @@ class Tenants { set(tenantId) callable.call(tenantId) } finally { - if(previous == null) { + if (previous == null) { remove() - } - else { + } else { set(previous) } } } - /** * Execute without current tenant * diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/WithoutTenant.java b/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/WithoutTenant.java index 449347b82f4..5440b03cf53 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/WithoutTenant.java +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/multitenancy/WithoutTenant.java @@ -22,8 +22,12 @@ import org.grails.datastore.gorm.transform.GormASTTransformationClass; import org.grails.datastore.mapping.core.connections.ConnectionSourcesProvider; -import java.lang.annotation.*; - +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** *

An AST transformation that makes a particular class or method execute without a tenant id. For example:

@@ -37,8 +41,8 @@ * } * * - * @since 6.1 * @author Graeme Rocher + * @since 6.1 */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @@ -47,6 +51,7 @@ @GroovyASTTransformationClass("org.grails.datastore.gorm.transform.OrderedGormTransformation") @GormASTTransformationClass("org.grails.datastore.gorm.multitenancy.transform.TenantTransform") public @interface WithoutTenant { + /** * If you are using multiple GORM implementations and wish to create a transaction for a specific implementation then use this. For example {@code @Transactional(forDatastore=HibernateDatastore) } * diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/services/Join.java b/grails-datamapping-core/src/main/groovy/grails/gorm/services/Join.java index 704494a16a2..fbba09e1159 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/services/Join.java +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/services/Join.java @@ -16,10 +16,10 @@ * specific language governing permissions and limitations * under the License. */ - package grails.gorm.services; import jakarta.persistence.criteria.JoinType; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -34,6 +34,7 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Join { + /** * @return The property name to join on */ diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/services/Query.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/services/Query.groovy index 0a307210be5..588cb4fd052 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/services/Query.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/services/Query.groovy @@ -33,5 +33,6 @@ import java.lang.annotation.Target @Retention(RetentionPolicy.SOURCE) @Target(ElementType.METHOD) @interface Query { + String value() } \ No newline at end of file diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/services/Service.java b/grails-datamapping-core/src/main/groovy/grails/gorm/services/Service.java index ee45e30c89d..ecd2b9a2c2b 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/services/Service.java +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/services/Service.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package grails.gorm.services; import org.codehaus.groovy.transform.GroovyASTTransformationClass; @@ -31,8 +30,8 @@ /** * Makes any class into a GORM {@link org.grails.datastore.mapping.services.Service} * - * @since 6.1 * @author Graeme Rocher + * @since 6.1 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/services/Where.java b/grails-datamapping-core/src/main/groovy/grails/gorm/services/Where.java index 638fb8927bf..55d567fd880 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/services/Where.java +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/services/Where.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package grails.gorm.services; import java.lang.annotation.ElementType; @@ -33,5 +32,6 @@ @Retention(RetentionPolicy.SOURCE) @Target(ElementType.METHOD) public @interface Where { + Class value(); } diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalDateConverter.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalDateConverter.groovy index 84ae6f88f1b..43606eb1a92 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalDateConverter.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalDateConverter.groovy @@ -21,7 +21,12 @@ package grails.gorm.time import groovy.transform.CompileStatic -import java.time.* +import java.time.Instant +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.ZoneId +import java.time.ZoneOffset /** * A trait to convert a {@link LocalDate} to and from a long diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/GrailsTransactionAttribute.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/GrailsTransactionAttribute.groovy index 5dd521d22f2..eb57a4e2d7f 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/GrailsTransactionAttribute.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/GrailsTransactionAttribute.groovy @@ -26,8 +26,6 @@ import org.springframework.transaction.interceptor.NoRollbackRuleAttribute import org.springframework.transaction.interceptor.RollbackRuleAttribute import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute - - /** * Used to configure a {@link GrailsTransactionTemplate} * @@ -38,10 +36,11 @@ import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute @InheritConstructors @Slf4j class GrailsTransactionAttribute extends RuleBasedTransactionAttribute { + private static final long serialVersionUID = 1L; private boolean inheritRollbackOnly = true; - public GrailsTransactionAttribute(org.springframework.transaction.interceptor.TransactionAttribute other) { + GrailsTransactionAttribute(org.springframework.transaction.interceptor.TransactionAttribute other) { super(); propagationBehavior = other.propagationBehavior isolationLevel = other.isolationLevel @@ -50,7 +49,7 @@ class GrailsTransactionAttribute extends RuleBasedTransactionAttribute { name = other.name } - public GrailsTransactionAttribute(TransactionDefinition other) { + GrailsTransactionAttribute(TransactionDefinition other) { super(); propagationBehavior = other.propagationBehavior isolationLevel = other.isolationLevel @@ -59,18 +58,18 @@ class GrailsTransactionAttribute extends RuleBasedTransactionAttribute { name = other.name } - public GrailsTransactionAttribute(GrailsTransactionAttribute other) { - this((RuleBasedTransactionAttribute)other); + GrailsTransactionAttribute(GrailsTransactionAttribute other) { + this((RuleBasedTransactionAttribute) other); } - public GrailsTransactionAttribute(RuleBasedTransactionAttribute other) { + GrailsTransactionAttribute(RuleBasedTransactionAttribute other) { super(other) - if(other instanceof GrailsTransactionAttribute) { - this.inheritRollbackOnly = ((GrailsTransactionAttribute)other).inheritRollbackOnly + if (other instanceof GrailsTransactionAttribute) { + this.inheritRollbackOnly = ((GrailsTransactionAttribute) other).inheritRollbackOnly } } - public boolean isInheritRollbackOnly() { + boolean isInheritRollbackOnly() { return inheritRollbackOnly; } @@ -95,7 +94,7 @@ class GrailsTransactionAttribute extends RuleBasedTransactionAttribute { } if (log.isTraceEnabled()) { - log.trace("Winning rollback rule is: $winner" ); + log.trace("Winning rollback rule is: $winner"); } // User superclass behavior (rollback on unchecked) if no rule matches. @@ -109,7 +108,7 @@ class GrailsTransactionAttribute extends RuleBasedTransactionAttribute { return !(winner instanceof NoRollbackRuleAttribute) } - public void setInheritRollbackOnly(boolean inheritRollbackOnly) { + void setInheritRollbackOnly(boolean inheritRollbackOnly) { this.inheritRollbackOnly = inheritRollbackOnly; } } diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/GrailsTransactionTemplate.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/GrailsTransactionTemplate.groovy index cb0f2fae0cc..8705cfe2977 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/GrailsTransactionTemplate.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/GrailsTransactionTemplate.groovy @@ -50,11 +50,11 @@ class GrailsTransactionTemplate { } GrailsTransactionTemplate(PlatformTransactionManager transactionManager, TransactionDefinition transactionDefinition) { - this(transactionManager, transactionDefinition instanceof TransactionAttribute ? (TransactionAttribute)transactionDefinition : new GrailsTransactionAttribute(transactionDefinition)); + this(transactionManager, transactionDefinition instanceof TransactionAttribute ? (TransactionAttribute) transactionDefinition : new GrailsTransactionAttribute(transactionDefinition)); } GrailsTransactionTemplate(PlatformTransactionManager transactionManager, TransactionAttribute transactionAttribute) { - this(transactionManager, transactionAttribute instanceof CustomizableRollbackTransactionAttribute ? (CustomizableRollbackTransactionAttribute)transactionAttribute : new CustomizableRollbackTransactionAttribute(transactionAttribute)); + this(transactionManager, transactionAttribute instanceof CustomizableRollbackTransactionAttribute ? (CustomizableRollbackTransactionAttribute) transactionAttribute : new CustomizableRollbackTransactionAttribute(transactionAttribute)); } GrailsTransactionTemplate(PlatformTransactionManager transactionManager, CustomizableRollbackTransactionAttribute transactionAttribute) { @@ -65,6 +65,7 @@ class GrailsTransactionTemplate { public T executeAndRollback(@ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure action) throws TransactionException { try { Object result = transactionTemplate.execute(new TransactionCallback() { + Object doInTransaction(TransactionStatus status) { try { return action.call(status) @@ -91,6 +92,7 @@ class GrailsTransactionTemplate { public T execute(@ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure action) throws TransactionException { try { Object result = transactionTemplate.execute(new TransactionCallback() { + Object doInTransaction(TransactionStatus status) { try { return action.call(status) @@ -107,10 +109,10 @@ class GrailsTransactionTemplate { } } finally { boolean inheritRollbackOnly = true - if(transactionAttribute instanceof CustomizableRollbackTransactionAttribute) { + if (transactionAttribute instanceof CustomizableRollbackTransactionAttribute) { inheritRollbackOnly = transactionAttribute.isInheritRollbackOnly() } - if(inheritRollbackOnly && status.isRollbackOnly()) { + if (inheritRollbackOnly && status.isRollbackOnly()) { status.setRollbackOnly() } } @@ -120,7 +122,7 @@ class GrailsTransactionTemplate { if (result instanceof ThrowableHolder) { throw result.getThrowable() } else { - return (T)result + return (T) result } } catch (ThrowableHolderException e) { diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/NotTransactional.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/NotTransactional.groovy index 9e2fc53c135..853efc13355 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/NotTransactional.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/NotTransactional.groovy @@ -17,14 +17,14 @@ * under the License. */ -package grails.gorm.transactions; +package grails.gorm.transactions -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import java.lang.annotation.Documented +import java.lang.annotation.ElementType +import java.lang.annotation.Inherited +import java.lang.annotation.Retention +import java.lang.annotation.RetentionPolicy +import java.lang.annotation.Target /** * diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/ReadOnly.java b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/ReadOnly.java index 9a9dc5e4039..11d94a3c3d8 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/ReadOnly.java +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/ReadOnly.java @@ -26,13 +26,18 @@ import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Define a read-only transaction * - * @since 6.1 * @author Graeme Rocher + * @since 6.1 */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @@ -41,6 +46,7 @@ @GroovyASTTransformationClass("org.grails.datastore.gorm.transform.OrderedGormTransformation") @GormASTTransformationClass("org.grails.datastore.gorm.transactions.transform.TransactionalTransform") public @interface ReadOnly { + /** * A qualifier value for the specified transaction. *

May be used to determine the target transaction manager, @@ -53,6 +59,7 @@ /** * The transaction propagation type. * Defaults to {@link org.springframework.transaction.annotation.Propagation#REQUIRED}. + * * @see org.springframework.transaction.interceptor.TransactionAttribute#getPropagationBehavior() */ Propagation propagation() default Propagation.REQUIRED; @@ -60,6 +67,7 @@ /** * The transaction isolation level. * Defaults to {@link org.springframework.transaction.annotation.Isolation#DEFAULT}. + * * @see org.springframework.transaction.interceptor.TransactionAttribute#getIsolationLevel() */ Isolation isolation() default Isolation.DEFAULT; @@ -67,6 +75,7 @@ /** * The timeout for this transaction. * Defaults to the default timeout of the underlying transaction system. + * * @see org.springframework.transaction.interceptor.TransactionAttribute#getTimeout() */ int timeout() default TransactionDefinition.TIMEOUT_DEFAULT; @@ -118,10 +127,9 @@ */ String[] noRollbackForClassName() default {}; - /** * In Spring, when there are nested transaction calls, the execution of the outermost callback will throw UnexpectedRollbackException if TransactionStatus.setRollbackOnly() was called in a nested transaction callback. - * + *

* This feature will make the setRollbackOnly state get inherited to parent level transaction template calls and therefore prevent UnexpectedRollbackException. * The default value is true. * diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/Rollback.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/Rollback.groovy index c695a446b4a..1310ace3d11 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/Rollback.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/Rollback.groovy @@ -20,7 +20,6 @@ package grails.gorm.transactions import org.codehaus.groovy.transform.GroovyASTTransformationClass -import org.grails.datastore.gorm.transactions.transform.RollbackTransform import org.grails.datastore.gorm.transform.GormASTTransformationClass import java.lang.annotation.Documented diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/TransactionService.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/TransactionService.groovy index 8aa0039df5a..40087e4106c 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/TransactionService.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/TransactionService.groovy @@ -37,7 +37,7 @@ interface TransactionService { * @param callable The callable * @return The result */ - public T withTransaction(@ClosureParams(value=SimpleType.class, options="org.springframework.transaction.TransactionStatus") Closure callable) + public T withTransaction(@ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) /** * Executes the given callable within the context of a transaction that is automatically rolled back with the default attributes @@ -45,14 +45,14 @@ interface TransactionService { * @param callable The callable * @return The result */ - public T withRollback(@ClosureParams(value=SimpleType.class, options="org.springframework.transaction.TransactionStatus") Closure callable) + public T withRollback(@ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) /** * Executes the given callable within the context of a new transaction with the default attributes * * @param callable The callable * @return The result */ - public T withNewTransaction(@ClosureParams(value=SimpleType.class, options="org.springframework.transaction.TransactionStatus") Closure callable) + public T withNewTransaction(@ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) /** * Executes the given callable within the context of a transaction with the given definition @@ -61,7 +61,7 @@ interface TransactionService { * @param callable The callable The callable * @return The result of the callable */ - public T withTransaction(TransactionDefinition definition, @ClosureParams(value=SimpleType.class, options="org.springframework.transaction.TransactionStatus") Closure callable) + public T withTransaction(TransactionDefinition definition, @ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) /** * Executes the given callable within the context of a transaction with the given definition @@ -70,7 +70,7 @@ interface TransactionService { * @param callable The callable The callable * @return The result of the callable */ - public T withTransaction(Map definition, @ClosureParams(value=SimpleType.class, options="org.springframework.transaction.TransactionStatus") Closure callable) + public T withTransaction(Map definition, @ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) /** * Executes the given callable within the context of a transaction that is automatically rolled back with the default attributes @@ -79,7 +79,7 @@ interface TransactionService { * @param callable The callable * @return The result */ - public T withRollback(TransactionDefinition definition, @ClosureParams(value=SimpleType.class, options="org.springframework.transaction.TransactionStatus") Closure callable) + public T withRollback(TransactionDefinition definition, @ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) /** * Executes the given callable within the context of a new transaction with the default attributes * @@ -87,5 +87,5 @@ interface TransactionService { * @param callable The callable * @return The result */ - public T withNewTransaction(TransactionDefinition definition, @ClosureParams(value=SimpleType.class, options="org.springframework.transaction.TransactionStatus") Closure callable) + public T withNewTransaction(TransactionDefinition definition, @ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) } \ No newline at end of file diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/Transactional.java b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/Transactional.java index b72009cbeb0..dd530a9fcc8 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/Transactional.java +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/transactions/Transactional.java @@ -48,10 +48,9 @@ *

For specific information about the semantics of this annotation's attributes, * consider the {@link org.springframework.transaction.TransactionDefinition} and * {@link org.springframework.transaction.interceptor.TransactionAttribute} javadocs. - + * * @author Graeme Rocher * @author Juergen Hoeller - * * @since 6.1 */ @Target({ElementType.METHOD, ElementType.TYPE}) @@ -74,6 +73,7 @@ /** * The transaction propagation type. * Defaults to {@link org.springframework.transaction.annotation.Propagation#REQUIRED}. + * * @see org.springframework.transaction.interceptor.TransactionAttribute#getPropagationBehavior() */ Propagation propagation() default Propagation.REQUIRED; @@ -81,6 +81,7 @@ /** * The transaction isolation level. * Defaults to {@link org.springframework.transaction.annotation.Isolation#DEFAULT}. + * * @see org.springframework.transaction.interceptor.TransactionAttribute#getIsolationLevel() */ Isolation isolation() default Isolation.DEFAULT; @@ -88,6 +89,7 @@ /** * The timeout for this transaction. * Defaults to the default timeout of the underlying transaction system. + * * @see org.springframework.transaction.interceptor.TransactionAttribute#getTimeout() */ int timeout() default TransactionDefinition.TIMEOUT_DEFAULT; @@ -99,6 +101,7 @@ * it will not necessarily cause failure of write access attempts. * A transaction manager which cannot interpret the read-only hint will * not throw an exception when asked for a read-only transaction. + * * @see org.springframework.transaction.interceptor.TransactionAttribute#isReadOnly() */ boolean readOnly() default false; @@ -150,10 +153,9 @@ */ String[] noRollbackForClassName() default {}; - /** * In Spring, when there are nested transaction calls, the execution of the outermost callback will throw UnexpectedRollbackException if TransactionStatus.setRollbackOnly() was called in a nested transaction callback. - * + *

* This feature will make the setRollbackOnly state get inherited to parent level transaction template calls and therefore prevent UnexpectedRollbackException. * The default value is true. * @@ -172,4 +174,4 @@ */ String connection() default ConnectionSource.DEFAULT; -} \ No newline at end of file +} diff --git a/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy index e414a48475f..2d4bc8c491c 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy @@ -23,7 +23,15 @@ import grails.gorm.dirty.checking.DirtyCheck import grails.gorm.dirty.checking.DirtyCheckedProperty import groovy.transform.CompilationUnitAware import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.* +import org.codehaus.groovy.ast.AnnotationNode +import org.codehaus.groovy.ast.ClassHelper +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.FieldNode +import org.codehaus.groovy.ast.GenericsType +import org.codehaus.groovy.ast.MethodNode +import org.codehaus.groovy.ast.Parameter +import org.codehaus.groovy.ast.PropertyNode +import org.codehaus.groovy.ast.Variable import org.codehaus.groovy.ast.expr.ConstantExpression import org.codehaus.groovy.ast.expr.ListExpression import org.codehaus.groovy.ast.expr.MethodCallExpression @@ -43,9 +51,25 @@ import org.springframework.validation.annotation.Validated import java.lang.reflect.Modifier -import static java.lang.reflect.Modifier.* -import static org.codehaus.groovy.ast.tools.GeneralUtils.* -import static org.grails.datastore.mapping.reflect.AstUtils.* +import static java.lang.reflect.Modifier.PUBLIC +import static java.lang.reflect.Modifier.isFinal +import static java.lang.reflect.Modifier.isTransient +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS +import static org.codehaus.groovy.ast.tools.GeneralUtils.block +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX +import static org.codehaus.groovy.ast.tools.GeneralUtils.param +import static org.codehaus.groovy.ast.tools.GeneralUtils.params +import static org.codehaus.groovy.ast.tools.GeneralUtils.propX +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX +import static org.grails.datastore.mapping.reflect.AstUtils.OBJECT_CLASS_NODE +import static org.grails.datastore.mapping.reflect.AstUtils.ZERO_PARAMETERS +import static org.grails.datastore.mapping.reflect.AstUtils.addAnnotationIfNecessary +import static org.grails.datastore.mapping.reflect.AstUtils.hasAnnotation +import static org.grails.datastore.mapping.reflect.AstUtils.isDomainClass /** * @@ -57,6 +81,7 @@ import static org.grails.datastore.mapping.reflect.AstUtils.* */ @CompileStatic class DirtyCheckingTransformer implements CompilationUnitAware { + private static final String VOID = "void"; private static final Class[] EMPTY_JAVA_CLASS_ARRAY = []; private static final Class[] OBJECT_CLASS_ARG = [Object.class]; @@ -69,19 +94,17 @@ class DirtyCheckingTransformer implements CompilationUnitAware { public static final AnnotationNode DIRTY_CHECKED_PROPERTY_ANNOTATION_NODE = new AnnotationNode(DIRTY_CHECKED_PROPERTY_CLASS_NODE) static { - if(ClassUtils.isPresent("jakarta.validation.Constraint")) { + if (ClassUtils.isPresent("jakarta.validation.Constraint")) { try { VALIDATION_CONSTRAINT_NODE = ClassHelper.make(Class.forName("jakarta.validation.Constraint")) } catch (Throwable e) { VALIDATION_CONSTRAINT_NODE = null } - } - else { + } else { VALIDATION_CONSTRAINT_NODE = null } } - protected CompilationUnit compilationUnit void setCompilationUnit(CompilationUnit compilationUnit) { @@ -97,7 +120,6 @@ class DirtyCheckingTransformer implements CompilationUnitAware { } final MethodNode markDirtyMethodNode = changeTrackableClassNode.getMethod(METHOD_NAME_MARK_DIRTY, new Parameter(ClassHelper.STRING_TYPE, "propertyName"), new Parameter(ClassHelper.OBJECT_TYPE, "newValue")) - ClassNode superClass = classNode.getSuperClass() boolean shouldWeave = superClass.equals(OBJECT_CLASS_NODE) @@ -105,22 +127,22 @@ class DirtyCheckingTransformer implements CompilationUnitAware { if (traitToInject != DirtyCheckable) { dirtyCheckableTrait.setSuperClass(new ClassNode(DirtyCheckable).getPlainNodeReference()) } - - while(!shouldWeave) { - if(isDomainClass(superClass) || !superClass.getAnnotations(DIRTY_CHECK_CLASS_NODE).isEmpty()) { + + while (!shouldWeave) { + if (isDomainClass(superClass) || !superClass.getAnnotations(DIRTY_CHECK_CLASS_NODE).isEmpty()) { break } superClass = superClass.getSuperClass() - if(superClass == null || superClass.equals(OBJECT_CLASS_NODE)) { + if (superClass == null || superClass.equals(OBJECT_CLASS_NODE)) { shouldWeave = true break } } - if(shouldWeave ) { + if (shouldWeave) { classNode.addInterface(dirtyCheckableTrait) - if(compilationUnit != null) { + if (compilationUnit != null) { org.codehaus.groovy.transform.trait.TraitComposer.doExtendTraits(classNode, source, compilationUnit); } @@ -137,7 +159,7 @@ class DirtyCheckingTransformer implements CompilationUnitAware { for (MethodNode mn in classNode.methods) { final methodName = mn.name - if(!mn.isPublic() || mn.isStatic() || mn.isSynthetic() || mn.isAbstract()) continue + if (!mn.isPublic() || mn.isStatic() || mn.isSynthetic() || mn.isAbstract()) continue if (isSetter(methodName, mn)) { String propertyName = NameUtils.getPropertyNameForGetterOrSetter(methodName) @@ -148,7 +170,7 @@ class DirtyCheckingTransformer implements CompilationUnitAware { // if there are any jakarta.validation constraints present def annotationNodes = mn.annotations - if(!isJavaValidateable && isAnnotatedWithJavaValidationApi(annotationNodes)) { + if (!isJavaValidateable && isAnnotatedWithJavaValidationApi(annotationNodes)) { addAnnotationIfNecessary(classNode, Validated) isJavaValidateable = true } @@ -162,13 +184,12 @@ class DirtyCheckingTransformer implements CompilationUnitAware { for (PropertyNode pn in propertyNodes) { final propertyName = pn.name if (!pn.isStatic() && pn.isPublic() && !NameUtils.isConfigurational(propertyName)) { - if(isTransient(pn.modifiers) || isDefinedInTransientsNode(propertyName, transientPropertyNode) || isFinal(pn.modifiers)) continue + if (isTransient(pn.modifiers) || isDefinedInTransientsNode(propertyName, transientPropertyNode) || isFinal(pn.modifiers)) continue // don't dirty check id or version - if(propertyName == GormProperties.IDENTITY) { + if (propertyName == GormProperties.IDENTITY) { continue - } - else if(propertyName == GormProperties.VERSION) { + } else if (propertyName == GormProperties.VERSION) { hasVersion = true continue } @@ -176,15 +197,14 @@ class DirtyCheckingTransformer implements CompilationUnitAware { final GetterAndSetter getterAndSetter = gettersAndSetters[propertyName] final FieldNode propertyField = pn.getField() final List allAnnotationNodes = pn.annotations + propertyField.annotations - if(getterAndSetter?.getter != null) { + if (getterAndSetter?.getter != null) { allAnnotationNodes.addAll(getterAndSetter.getter.annotations) } - - if(hasAnnotation(allAnnotationNodes, GormEntityTransformation.JPA_ID_ANNOTATION_NODE)) { - if(!propertyName.equals(GormProperties.IDENTITY) ) { + if (hasAnnotation(allAnnotationNodes, GormEntityTransformation.JPA_ID_ANNOTATION_NODE)) { + if (!propertyName.equals(GormProperties.IDENTITY)) { // if the property is a JPA @Id but the property name is not id add a transient getter to retrieve the id called getId - if(classNode.getField(GormProperties.IDENTITY) == null && gettersAndSetters[GormProperties.IDENTITY] == null) { + if (classNode.getField(GormProperties.IDENTITY) == null && gettersAndSetters[GormProperties.IDENTITY] == null) { def getIdMethod = new MethodNode( "getId", Modifier.PUBLIC, @@ -201,10 +221,10 @@ class DirtyCheckingTransformer implements CompilationUnitAware { // skip dirty checking for JPA @Id continue } - if(hasAnnotation( allAnnotationNodes, GormEntityTransformation.JPA_VERSION_ANNOTATION_NODE)) { + if (hasAnnotation(allAnnotationNodes, GormEntityTransformation.JPA_VERSION_ANNOTATION_NODE)) { hasVersion = true // if the property is a JPA @Version but the property name is not version add a transient getter to retrieve the version called getVersion - if(classNode.getField(GormProperties.VERSION) == null && gettersAndSetters[GormProperties.VERSION] == null) { + if (classNode.getField(GormProperties.VERSION) == null && gettersAndSetters[GormProperties.VERSION] == null) { def getVersionMethod = new MethodNode( "getVersion", Modifier.PUBLIC, @@ -221,14 +241,13 @@ class DirtyCheckingTransformer implements CompilationUnitAware { } // if there is no explicit getter and setter then one will be generated by Groovy, so we must add these to track changes - if(getterAndSetter == null) { + if (getterAndSetter == null) { - if(!isJavaValidateable && isAnnotatedWithJavaValidationApi(allAnnotationNodes)) { + if (!isJavaValidateable && isAnnotatedWithJavaValidationApi(allAnnotationNodes)) { addAnnotationIfNecessary(classNode, Validated) isJavaValidateable = true } - // first add the getter ClassNode returnType = resolvePropertyReturnType(pn, classNode) boolean booleanProperty = ClassHelper.boolean_TYPE.getName().equals(returnType.getName()) || ClassHelper.Boolean_TYPE.getName().equals(returnType.getName()) @@ -236,7 +255,7 @@ class DirtyCheckingTransformer implements CompilationUnitAware { String getterName = NameUtils.getGetterName(propertyName, false) MethodNode getter = classNode.getMethod(getterName, ZERO_PARAMETERS) - if(getter == null) { + if (getter == null) { getter = classNode.addMethod(getterName, PUBLIC, returnType, ZERO_PARAMETERS, null, returnS(varX(fieldName))) @@ -244,7 +263,7 @@ class DirtyCheckingTransformer implements CompilationUnitAware { staticCompilationVisitor.visitMethod( getter ) - if(booleanProperty) { + if (booleanProperty) { classNode.addMethod(NameUtils.getGetterName(propertyName, true), PUBLIC, returnType, ZERO_PARAMETERS, null, returnS(varX(fieldName))) } } @@ -252,31 +271,27 @@ class DirtyCheckingTransformer implements CompilationUnitAware { // now add the setter that tracks changes. Each setters becomes: // void setFoo(String foo) { markDirty("foo", foo); this.foo = foo } addDirtyCheckingSetter(classNode, propertyName, fieldName, returnType, markDirtyMethodNode, staticCompilationVisitor) - } - else if(getterAndSetter.hasBoth()) { + } else if (getterAndSetter.hasBoth()) { // if both a setter and getter are present, we get hold of the setter and weave the markDirty method call into it weaveIntoExistingSetter(propertyName, getterAndSetter, markDirtyMethodNode) gettersAndSetters.remove(propertyName) - } - else { - if(getterAndSetter.setter != null) { + } else { + if (getterAndSetter.setter != null) { weaveIntoExistingSetter(propertyName, getterAndSetter, markDirtyMethodNode) // there isn't both a getter and a setter then this is not a candidate for persistence, so we eliminate it from change tracking gettersAndSetters.remove(propertyName) - } - else if(getterAndSetter.getter != null) { + } else if (getterAndSetter.getter != null) { String fieldName = propertyField.getName() ClassNode returnType = resolvePropertyReturnType(pn, classNode) addDirtyCheckingSetter(classNode, propertyName, fieldName, returnType, markDirtyMethodNode, staticCompilationVisitor) - } - else { + } else { gettersAndSetters.remove(propertyName) } } } } - if(!hasVersion && ClassUtils.isPresent("grails.artefact.Artefact") && !classNode.getAnnotations(GormEntityTransformation.JPA_ENTITY_CLASS_NODE).isEmpty()) { + if (!hasVersion && ClassUtils.isPresent("grails.artefact.Artefact") && !classNode.getAnnotations(GormEntityTransformation.JPA_ENTITY_CLASS_NODE).isEmpty()) { // if the entity is a JPA and has no version property then add a transient one as a stub, this is more to satisfy Grails def getVersionMethod = new MethodNode( "getVersion", @@ -292,7 +307,7 @@ class DirtyCheckingTransformer implements CompilationUnitAware { // We also need to search properties that are represented as getters with setters. This requires going through all the methods and finding getter/setter pairs that are public gettersAndSetters.each { String propertyName, GetterAndSetter getterAndSetter -> - if(!NameUtils.isConfigurational(propertyName) && getterAndSetter.hasBoth()) { + if (!NameUtils.isConfigurational(propertyName) && getterAndSetter.hasBoth()) { weaveIntoExistingSetter(propertyName, getterAndSetter, markDirtyMethodNode) } } @@ -351,7 +366,7 @@ class DirtyCheckingTransformer implements CompilationUnitAware { } void performInjection(SourceUnit source, GeneratorContext context, ClassNode classNode) { - if (classNode.annotations.any { AnnotationNode an -> an.classNode.name == 'grails.artefact.Artefact'}) return; + if (classNode.annotations.any { AnnotationNode an -> an.classNode.name == 'grails.artefact.Artefact' }) return; performInjectionOnAnnotatedClass(source, classNode) } @@ -368,15 +383,13 @@ class DirtyCheckingTransformer implements CompilationUnitAware { performInjectionOnAnnotatedClass(null, classNode) } - private static ClassNode alignReturnType(final ClassNode receiver, final ClassNode originalReturnType) { ClassNode copiedReturnType - if(originalReturnType.isGenericsPlaceHolder()) { + if (originalReturnType.isGenericsPlaceHolder()) { copiedReturnType = originalReturnType.getPlainNodeReference(); - copiedReturnType.setName( originalReturnType.getName() ) + copiedReturnType.setName(originalReturnType.getName()) copiedReturnType.setGenericsPlaceHolder(true) - } - else { + } else { copiedReturnType = originalReturnType.getPlainNodeReference(); } @@ -384,7 +397,7 @@ class DirtyCheckingTransformer implements CompilationUnitAware { if (genericTypes) { List newGenericTypes = [] - for(GenericsType gt in genericTypes) { + for (GenericsType gt in genericTypes) { ClassNode[] upperBounds = null if (gt.upperBounds) { upperBounds = gt.upperBounds.collect { ClassNode cn -> cn.plainNodeReference } as ClassNode[] @@ -395,27 +408,27 @@ class DirtyCheckingTransformer implements CompilationUnitAware { } return copiedReturnType } + protected void weaveIntoExistingSetter(String propertyName, GetterAndSetter getterAndSetter, MethodNode markDirtyMethodNode) { final MethodNode setterMethod = getterAndSetter.setter - if(setterMethod.annotations.any { AnnotationNode an -> an.classNode.name == 'grails.persistence.PersistenceMethod'} ) return + if (setterMethod.annotations.any { AnnotationNode an -> an.classNode.name == 'grails.persistence.PersistenceMethod' }) return - if(!setterMethod.getAnnotations(DIRTY_CHECKED_PROPERTY_CLASS_NODE)) { + if (!setterMethod.getAnnotations(DIRTY_CHECKED_PROPERTY_CLASS_NODE)) { setterMethod.addAnnotation(DIRTY_CHECKED_PROPERTY_ANNOTATION_NODE) - } - else { + } else { // already woven return } MethodNode getter = getterAndSetter.getter - if(getter != null && !getter.getAnnotations(DIRTY_CHECKED_PROPERTY_CLASS_NODE)) { + if (getter != null && !getter.getAnnotations(DIRTY_CHECKED_PROPERTY_CLASS_NODE)) { getter.addAnnotation(DIRTY_CHECKED_PROPERTY_ANNOTATION_NODE) } final currentBody = setterMethod.code final setterParameter = setterMethod.getParameters()[0] MethodCallExpression markDirtyMethodCall = createMarkDirtyMethodCall(markDirtyMethodNode, propertyName, setterParameter) final newBody = block( - stmt( markDirtyMethodCall ), - currentBody + stmt(markDirtyMethodCall), + currentBody ) setterMethod.code = newBody } @@ -436,8 +449,6 @@ class DirtyCheckingTransformer implements CompilationUnitAware { return getterAndSetter } - - private boolean isSetter(String methodName, MethodNode declaredMethod) { return declaredMethod.getParameters().length == 1 && ReflectionUtils.isSetter(methodName, OBJECT_CLASS_ARG); } @@ -452,6 +463,7 @@ class DirtyCheckingTransformer implements CompilationUnitAware { @CompileStatic class GetterAndSetter { + MethodNode getter MethodNode setter diff --git a/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/GlobalJpaEntityTransform.groovy b/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/GlobalJpaEntityTransform.groovy index d66e0410a4f..855c63daa90 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/GlobalJpaEntityTransform.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/GlobalJpaEntityTransform.groovy @@ -21,6 +21,7 @@ package org.grails.compiler.gorm import groovy.transform.CompilationUnitAware import groovy.transform.CompileStatic +import jakarta.persistence.Entity import org.apache.grails.common.compiler.GroovyTransformOrder import org.codehaus.groovy.ast.ASTNode import org.codehaus.groovy.ast.ClassHelper @@ -32,8 +33,6 @@ import org.codehaus.groovy.control.SourceUnit import org.codehaus.groovy.transform.ASTTransformation import org.codehaus.groovy.transform.AbstractASTTransformation import org.codehaus.groovy.transform.GroovyASTTransformation - -import jakarta.persistence.Entity import org.codehaus.groovy.transform.TransformWithPriority /** @@ -58,7 +57,7 @@ class GlobalJpaEntityTransform extends AbstractASTTransformation implements ASTT } void visitClass(ClassNode classNode, SourceUnit source) { - if(hasAnnotation(classNode, ClassHelper.make(Entity))) { + if (hasAnnotation(classNode, ClassHelper.make(Entity))) { def jpaEntityTransformation = new JpaGormEntityTransformation() jpaEntityTransformation.compilationUnit = compilationUnit jpaEntityTransformation.visit(classNode, source) diff --git a/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/GormEntityTransformation.groovy b/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/GormEntityTransformation.groovy index a469c489c84..21c37125089 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/GormEntityTransformation.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/GormEntityTransformation.groovy @@ -23,6 +23,12 @@ import groovy.transform.CompilationUnitAware import groovy.transform.CompileStatic import groovy.transform.Memoized import groovy.transform.ToString +import jakarta.persistence.Embeddable +import jakarta.persistence.Id +import jakarta.persistence.ManyToMany +import jakarta.persistence.OneToMany +import jakarta.persistence.Transient +import jakarta.persistence.Version import org.apache.grails.common.compiler.GroovyTransformOrder import org.codehaus.groovy.ast.ASTNode import org.codehaus.groovy.ast.AnnotatedNode @@ -51,7 +57,6 @@ import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.ExpressionStatement import org.codehaus.groovy.ast.stmt.ReturnStatement import org.codehaus.groovy.ast.stmt.Statement -import org.codehaus.groovy.ast.tools.GeneralUtils import org.codehaus.groovy.control.CompilationUnit import org.codehaus.groovy.control.CompilePhase import org.codehaus.groovy.control.SourceUnit @@ -67,16 +72,15 @@ import org.grails.datastore.mapping.model.config.GormProperties import org.grails.datastore.mapping.reflect.AstUtils import org.grails.datastore.mapping.reflect.ClassUtils import org.grails.datastore.mapping.reflect.NameUtils -import static org.codehaus.groovy.ast.tools.GeneralUtils.* -import jakarta.persistence.Embeddable -import jakarta.persistence.Id -import jakarta.persistence.ManyToMany -import jakarta.persistence.OneToMany -import jakarta.persistence.Transient -import jakarta.persistence.Version + import java.lang.annotation.Annotation import java.lang.reflect.Modifier +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS /** * An AST transformation that adds the following features:

@@ -94,6 +98,7 @@ import java.lang.reflect.Modifier @CompileStatic @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) class GormEntityTransformation extends AbstractASTTransformation implements CompilationUnitAware, ASTTransformation, TransformWithPriority { + private static final ClassNode MY_TYPE = new ClassNode(Entity.class); protected static final ClassNode JPA_ENTITY_CLASS_NODE = ClassHelper.make(jakarta.persistence.Entity) public static final AnnotationNode JPA_ENTITY_ANNOTATION_NODE = new AnnotationNode(JPA_ENTITY_CLASS_NODE) @@ -200,7 +205,6 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp } } - def rxEntityClassNode = AstUtils.findInterface(classNode, "grails.gorm.rx.RxEntity") boolean isRxEntity = rxEntityClassNode != null @@ -244,7 +248,6 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp def dirtyCheckTransformer = new DirtyCheckingTransformer() dirtyCheckTransformer.performInjectionOnAnnotatedClass(sourceUnit, classNode, GormEntityDirtyCheckable) - // convert the methodMissing and propertyMissing implementations to $static_methodMissing and $static_propertyMissing for the static versions def methodMissingBody = new BlockStatement() def methodNameParam = new Parameter(ClassHelper.make(String), "name") @@ -258,7 +261,6 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp def methodMissingParameters = [methodNameParam, methodArgsParam] as Parameter[] classNode.addMethod('$static_methodMissing', Modifier.PUBLIC | Modifier.STATIC, AstUtils.OBJECT_CLASS_NODE, methodMissingParameters, null, methodMissingBody) - // $static_propertyMissing setter def propertyMissingSetBody = new BlockStatement() def propertyMissingSetNameParam = new Parameter(ClassHelper.make(String), "name") @@ -282,7 +284,6 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp def propertyMissingGetParameters = [propertyMissingGetNameParam] as Parameter[] classNode.addMethod('$static_propertyMissing', Modifier.PUBLIC | Modifier.STATIC, AstUtils.OBJECT_CLASS_NODE, propertyMissingGetParameters, null, propertyMissingGetBody) - // now process named query associations // see https://grails.github.io/grails-doc/latest/ref/Domain%20Classes/namedQueries.html @@ -380,7 +381,6 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp protected Class pickGormEntityTrait(ClassNode classNode, SourceUnit source) { def classLoader = getClass().classLoader - // first try the `mapWithValue` def mapWith = AstUtils.getPropertyFromHierarchy(classNode, GormProperties.MAPPING_STRATEGY) String mapWithValue = mapWith?.initialExpression?.text @@ -504,7 +504,6 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp } injectAssociationProperties(classNode, propertiesToAdd) - ListExpression listExpression = getOrCreateListProperty(classNode, GormProperties.TRANSIENT) for (PropertyNode pn in classNode.getProperties()) { def type = pn.getType() @@ -602,7 +601,6 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp addAssociationForKey(propertyName, properties, classNode, findPropertyType(mee.valueExpression)) } - } return properties; } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/JpaGormEntityTransformation.groovy b/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/JpaGormEntityTransformation.groovy index 38a43475346..f4c55968402 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/JpaGormEntityTransformation.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/JpaGormEntityTransformation.groovy @@ -19,19 +19,16 @@ package org.grails.compiler.gorm -import grails.gorm.annotation.Entity import grails.gorm.annotation.JpaEntity import groovy.transform.CompileStatic import org.apache.grails.common.compiler.GroovyTransformOrder import org.codehaus.groovy.ast.ASTNode import org.codehaus.groovy.ast.AnnotatedNode import org.codehaus.groovy.ast.AnnotationNode -import org.codehaus.groovy.ast.ClassHelper import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.control.CompilePhase import org.codehaus.groovy.control.SourceUnit import org.codehaus.groovy.transform.GroovyASTTransformation -import org.grails.datastore.mapping.reflect.AstUtils /** * Enhanced GORM entity annotated with JPA annotations @@ -42,6 +39,7 @@ import org.grails.datastore.mapping.reflect.AstUtils @CompileStatic @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) class JpaGormEntityTransformation extends GormEntityTransformation { + private static final ClassNode MY_TYPE = new ClassNode(JpaEntity.class); @Override @@ -64,7 +62,7 @@ class JpaGormEntityTransformation extends GormEntityTransformation { @Override void visit(ClassNode classNode, SourceUnit sourceUnit) { - if(!hasAnnotation(classNode, JPA_ENTITY_CLASS_NODE)) { + if (!hasAnnotation(classNode, JPA_ENTITY_CLASS_NODE)) { classNode.addAnnotation(JPA_ENTITY_ANNOTATION_NODE) } super.visit(classNode, sourceUnit) diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/AbstractDatastoreApi.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/AbstractDatastoreApi.groovy index 90c1d3ef88e..077b4000e10 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/AbstractDatastoreApi.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/AbstractDatastoreApi.groovy @@ -18,8 +18,7 @@ */ package org.grails.datastore.gorm -import groovy.transform.CompileStatic; - +import groovy.transform.CompileStatic import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.core.DatastoreUtils import org.grails.datastore.mapping.core.SessionCallback @@ -38,21 +37,21 @@ abstract class AbstractDatastoreApi { } protected T execute(SessionCallback callback) { - if(datastore == null) { + if (datastore == null) { throw new IllegalStateException("Cannot execute session callback with null datastore") } DatastoreUtils.execute datastore, callback } protected void execute(VoidSessionCallback callback) { - if(datastore == null) { + if (datastore == null) { throw new IllegalStateException("Cannot execute session callback with null datastore") } DatastoreUtils.execute datastore, callback } Datastore getDatastore() { - if(datastore == null) { + if (datastore == null) { throw new IllegalStateException("No datastore configured in stateless mode") } return datastore diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/AbstractGormApi.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/AbstractGormApi.groovy index a613ba251f8..f42ac4d4b12 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/AbstractGormApi.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/AbstractGormApi.groovy @@ -20,43 +20,40 @@ package org.grails.datastore.gorm import groovy.transform.CompileDynamic import groovy.transform.CompileStatic -import groovy.transform.TypeChecked -import groovy.transform.TypeCheckingMode +import org.grails.datastore.gorm.utils.ReflectionUtils +import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.model.MappingContext +import org.grails.datastore.mapping.model.PersistentEntity import java.lang.reflect.Method import java.lang.reflect.Modifier -import org.grails.datastore.gorm.utils.ReflectionUtils -import org.grails.datastore.mapping.core.Datastore -import org.grails.datastore.mapping.model.PersistentEntity - /** * Abstract GORM API provider. * * @author Graeme Rocher - * @param the entity/domain class + * @param the entity/domain class * @since 1.0 */ @CompileStatic abstract class AbstractGormApi extends AbstractDatastoreApi { static final List EXCLUDES = [ - 'setProperty', - 'getProperty', - 'getMetaClass', - 'setMetaClass', - 'invokeMethod', - 'getMethods', - 'getExtendedMethods', - 'wait', - 'equals', - 'toString', - 'hashCode', - 'getClass', - 'notify', - 'notifyAll', - 'setTransactionManager' + 'setProperty', + 'getProperty', + 'getMetaClass', + 'setMetaClass', + 'invokeMethod', + 'getMethods', + 'getExtendedMethods', + 'wait', + 'equals', + 'toString', + 'hashCode', + 'getClass', + 'notify', + 'notifyAll', + 'setTransactionManager' ] protected Class persistentClass @@ -86,7 +83,7 @@ abstract class AbstractGormApi extends AbstractDatastoreApi { } methods.addAll methodsToAdd if (clazz != GormStaticApi.class && clazz != GormInstanceApi && clazz != GormValidationApi && clazz != AbstractGormApi) { - def extendedMethodsToAdd = methodsToAdd.findAll { Method m -> !ReflectionUtils.isMethodOverriddenFromParent(m)} + def extendedMethodsToAdd = methodsToAdd.findAll { Method m -> !ReflectionUtils.isMethodOverriddenFromParent(m) } extendedMethods.addAll extendedMethodsToAdd } clazz = clazz.getSuperclass() @@ -95,14 +92,14 @@ abstract class AbstractGormApi extends AbstractDatastoreApi { } List getMethods() { - if(methods == null) { + if (methods == null) { initializeMethods(getClass()) } return methods } List getExtendedMethods() { - if(extendedMethods == null) { + if (extendedMethods == null) { initializeMethods(getClass()) } return extendedMethods diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/CurrentTenant.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/CurrentTenant.groovy index d2d2257816a..7ef39f31818 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/CurrentTenant.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/CurrentTenant.groovy @@ -30,7 +30,7 @@ import groovy.transform.PackageScope */ @PackageScope @CompileStatic -class CurrentTenant { +class CurrentTenant { private static final ThreadLocal currentTenantThreadLocal = new ThreadLocal<>() diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEnhancer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEnhancer.groovy index 9adea3a65e4..287628e23eb 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEnhancer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEnhancer.groovy @@ -22,7 +22,15 @@ import groovy.util.logging.Slf4j import org.codehaus.groovy.reflection.CachedMethod import org.codehaus.groovy.runtime.metaclass.ClosureStaticMetaMethod import org.codehaus.groovy.runtime.metaclass.MethodSelectionException -import org.grails.datastore.gorm.finders.* +import org.grails.datastore.gorm.finders.CountByFinder +import org.grails.datastore.gorm.finders.FindAllByBooleanFinder +import org.grails.datastore.gorm.finders.FindAllByFinder +import org.grails.datastore.gorm.finders.FindByBooleanFinder +import org.grails.datastore.gorm.finders.FindByFinder +import org.grails.datastore.gorm.finders.FindOrCreateByFinder +import org.grails.datastore.gorm.finders.FindOrSaveByFinder +import org.grails.datastore.gorm.finders.FinderMethod +import org.grails.datastore.gorm.finders.ListOrderByFinder import org.grails.datastore.gorm.internal.InstanceMethodInvokingClosure import org.grails.datastore.gorm.internal.StaticMethodInvokingClosure import org.grails.datastore.gorm.query.GormQueryOperations @@ -91,7 +99,6 @@ class GormEnhancer implements Closeable { */ final boolean dynamicEnhance - GormEnhancer(Datastore datastore) { this(datastore, null) } @@ -114,13 +121,13 @@ class GormEnhancer implements Closeable { this.markDirty = markDirty == null ? true : markDirty this.transactionManager = transactionManager this.dynamicEnhance = false - if(datastore != null) { + if (datastore != null) { registerConstraints(datastore) } NAMED_QUERIES.clear() DATASTORES_BY_TYPE.put(datastore.getClass(), datastore) - for(entity in datastore.mappingContext.persistentEntities) { + for (entity in datastore.mappingContext.persistentEntities) { registerEntity(entity) } } @@ -136,7 +143,7 @@ class GormEnhancer implements Closeable { def cls = entity.javaClass List qualifiers = allQualifiers(this.datastore, entity) - if(!qualifiers.contains(ConnectionSource.DEFAULT)) { + if (!qualifiers.contains(ConnectionSource.DEFAULT)) { def firstQualifier = qualifiers.first() def staticApi = getStaticApi(cls, firstQualifier) def name = entity.name @@ -171,13 +178,13 @@ class GormEnhancer implements Closeable { List allQualifiers(Datastore datastore, PersistentEntity entity) { List qualifiers = new ArrayList<>() qualifiers.addAll ConnectionSourcesSupport.getConnectionSourceNames(entity) - if((MultiTenant.isAssignableFrom(entity.javaClass) || qualifiers.contains(ConnectionSource.ALL)) && (datastore instanceof ConnectionSourcesProvider)) { + if ((MultiTenant.isAssignableFrom(entity.javaClass) || qualifiers.contains(ConnectionSource.ALL)) && (datastore instanceof ConnectionSourcesProvider)) { qualifiers.clear() qualifiers.add(ConnectionSource.DEFAULT) Iterable allConnectionSources = ((ConnectionSourcesProvider) datastore).getConnectionSources().allConnectionSources Collection allConnectionSourceNames = allConnectionSources.findAll() { ConnectionSource connectionSource -> connectionSource.name != ConnectionSource.DEFAULT } - .collect() { ((ConnectionSource)it).name } + .collect() { ((ConnectionSource) it).name } qualifiers.addAll allConnectionSourceNames } return qualifiers @@ -214,26 +221,25 @@ class GormEnhancer implements Closeable { static GormQueryOperations createNamedQuery(Class entity, String queryName, Object... args) { def className = entity.getName() def namedQueries = NAMED_QUERIES.get(className) - if(namedQueries == null) { + if (namedQueries == null) { synchronized (NAMED_QUERIES) { namedQueries = NAMED_QUERIES.get(className) - if(namedQueries == null) { + if (namedQueries == null) { ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity) Closure closure = cpf.getStaticPropertyValue(GormProperties.NAMED_QUERIES, Closure.class) - if(closure != null) { - closure = (Closure)closure.clone() + if (closure != null) { + closure = (Closure) closure.clone() def evaluator = new NamedQueriesBuilder() namedQueries = evaluator.evaluate(closure) NAMED_QUERIES.put(className, namedQueries) - } - else { + } else { NAMED_QUERIES.put(className, Collections.emptyMap()) return null } } - } - } + } + } return buildNamedCriteriaProxy(entity, namedQueries, queryName, args) } @@ -257,24 +263,21 @@ class GormEnhancer implements Closeable { * @return */ protected static String findTenantId(Class entity) { - if(MultiTenant.isAssignableFrom(entity)) { + if (MultiTenant.isAssignableFrom(entity)) { Datastore defaultDatastore = findDatastore(entity, ConnectionSource.DEFAULT) - if((defaultDatastore instanceof MultiTenantCapableDatastore)) { + if ((defaultDatastore instanceof MultiTenantCapableDatastore)) { - MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore)defaultDatastore - if(multiTenantCapableDatastore.getMultiTenancyMode() == MultiTenancySettings.MultiTenancyMode.DATABASE) { - return Tenants.currentId( multiTenantCapableDatastore ) - } - else { + MultiTenantCapableDatastore multiTenantCapableDatastore = (MultiTenantCapableDatastore) defaultDatastore + if (multiTenantCapableDatastore.getMultiTenancyMode() == MultiTenancySettings.MultiTenancyMode.DATABASE) { + return Tenants.currentId(multiTenantCapableDatastore) + } else { return ConnectionSource.DEFAULT } - } - else { + } else { log.debug("Return default tenant id for non-multitenant capable datastore") return ConnectionSource.DEFAULT } - } - else { + } else { log.debug "Returning default tenant id for non-multitenant class [$entity]" return ConnectionSource.DEFAULT } @@ -292,7 +295,7 @@ class GormEnhancer implements Closeable { static GormStaticApi findStaticApi(Class entity, String qualifier = findTenantId(entity)) { String className = NameUtils.getClassName(entity) def staticApi = STATIC_APIS.get(qualifier)?.get(className) - if(staticApi == null) { + if (staticApi == null) { throw stateException(entity) } return staticApi @@ -309,7 +312,7 @@ class GormEnhancer implements Closeable { */ static GormInstanceApi findInstanceApi(Class entity, String qualifier = findTenantId(entity)) { def instanceApi = INSTANCE_APIS.get(qualifier)?.get(NameUtils.getClassName(entity)) - if(instanceApi == null) { + if (instanceApi == null) { throw stateException(entity) } return instanceApi @@ -326,7 +329,7 @@ class GormEnhancer implements Closeable { */ static GormValidationApi findValidationApi(Class entity, String qualifier = findTenantId(entity)) { def instanceApi = VALIDATION_APIS.get(qualifier)?.get(NameUtils.getClassName(entity)) - if(instanceApi == null) { + if (instanceApi == null) { throw stateException(entity) } return instanceApi @@ -343,7 +346,7 @@ class GormEnhancer implements Closeable { */ static Datastore findDatastore(Class entity, String qualifier = findTenantId(entity)) { def datastore = DATASTORES.get(qualifier)?.get(entity.name) - if(datastore == null) { + if (datastore == null) { throw stateException(entity) } return datastore @@ -359,7 +362,7 @@ class GormEnhancer implements Closeable { */ static Datastore findDatastoreByType(Class datastoreType) { Datastore datastore = DATASTORES_BY_TYPE.get(datastoreType) - if(datastore == null) { + if (datastore == null) { throw new IllegalStateException("No GORM implementation configured for type [$datastoreType]. Ensure GORM has been initialized correctly") } return datastore @@ -372,13 +375,11 @@ class GormEnhancer implements Closeable { */ static Datastore findSingleDatastore() { Collection allDatastores = DATASTORES_BY_TYPE.values() - if(allDatastores.isEmpty()) { + if (allDatastores.isEmpty()) { throw new IllegalStateException("No GORM implementations configured. Ensure GORM has been initialized correctly") - } - else if(allDatastores.size() > 1) { + } else if (allDatastores.size() > 1) { throw new IllegalStateException("More than one GORM implementation is configured. Specific the datastore type!") - } - else { + } else { return allDatastores.first() } } @@ -433,12 +434,12 @@ class GormEnhancer implements Closeable { removeConstraints() DATASTORES_BY_TYPE.clear() def registry = GroovySystem.metaClassRegistry - for(entity in datastore.mappingContext.persistentEntities) { + for (entity in datastore.mappingContext.persistentEntities) { List qualifiers = allQualifiers(datastore, entity) def cls = entity.javaClass def className = cls.name - for(q in qualifiers) { + for (q in qualifiers) { NAMED_QUERIES.remove(className) STATIC_APIS.get(q)?.remove(className) INSTANCE_APIS.get(q)?.remove(className) @@ -470,7 +471,7 @@ class GormEnhancer implements Closeable { try { String className = "org.apache.groovy.grails.validation.ConstrainedProperty" ClassLoader classLoader = getClass().getClassLoader() - if(ClassUtils.isPresent(className, classLoader)) { + if (ClassUtils.isPresent(className, classLoader)) { classLoader.loadClass(className).removeConstraint('unique') } } catch (Throwable e) { @@ -482,7 +483,7 @@ class GormEnhancer implements Closeable { try { String className = "org.grails.datastore.gorm.support.ConstraintRegistrar" ClassLoader classLoader = getClass().getClassLoader() - if(ClassUtils.isPresent(className, classLoader)) { + if (ClassUtils.isPresent(className, classLoader)) { classLoader.loadClass(className).newInstance(datastore) } } catch (Throwable e) { @@ -505,9 +506,9 @@ class GormEnhancer implements Closeable { */ @CompileStatic void enhance(boolean onlyExtendedMethods = false) { - if(dynamicEnhance) { + if (dynamicEnhance) { for (PersistentEntity e in datastore.mappingContext.persistentEntities) { - if(e.external && !includeExternal) continue + if (e.external && !includeExternal) continue enhance e, onlyExtendedMethods } } @@ -523,7 +524,7 @@ class GormEnhancer implements Closeable { void enhance(PersistentEntity e, boolean onlyExtendedMethods = false) { registerEntity(e) - if(!(GroovyObject.isAssignableFrom(e.javaClass) ) || dynamicEnhance) { + if (!(GroovyObject.isAssignableFrom(e.javaClass)) || dynamicEnhance) { addInstanceMethods(e, onlyExtendedMethods) addStaticMethods(e, onlyExtendedMethods) @@ -542,7 +543,7 @@ class GormEnhancer implements Closeable { def parameterTypes = method.parameterTypes if (parameterTypes != null) { boolean realMethodExists = doesRealMethodExist(mc, methodName, parameterTypes, true) - if(!realMethodExists) { + if (!realMethodExists) { registerStaticMethod(mc, methodName, parameterTypes, staticApiProvider) } } @@ -560,8 +561,6 @@ class GormEnhancer implements Closeable { !entity.isExternal() } - - @CompileDynamic protected List> getInstanceMethodApiProviders(Class cls) { [getInstanceApi(cls), getValidationApi(cls)] @@ -582,7 +581,7 @@ class GormEnhancer implements Closeable { boolean realMethodExists = doesRealMethodExist(mc, methodName, parameterTypes, false) - if(!realMethodExists) { + if (!realMethodExists) { registerInstanceMethod(cls, mc, apiProvider, methodName, parameterTypes) } } @@ -596,9 +595,10 @@ class GormEnhancer implements Closeable { def pt = parameterTypes // Hack to workaround http://jira.codehaus.org/browse/GROOVY-4720 final closureMethod = new ClosureStaticMetaMethod(methodName, cls, tooCall, pt) { - @Override - int getModifiers() { Modifier.PUBLIC } - } + + @Override + int getModifiers() { Modifier.PUBLIC } + } mc.registerInstanceMethod(closureMethod) } @@ -607,13 +607,13 @@ class GormEnhancer implements Closeable { boolean realMethodExists = false try { MetaMethod existingMethod = mc.pickMethod(methodName, parameterTypes) - if(existingMethod && existingMethod.isStatic()==staticScope && isRealMethod(existingMethod) && parameterTypes.length==existingMethod.parameterTypes.length) { + if (existingMethod && existingMethod.isStatic() == staticScope && isRealMethod(existingMethod) && parameterTypes.length == existingMethod.parameterTypes.length) { realMethodExists = true } } catch (MethodSelectionException mse) { // the metamethod already exists with multiple signatures, must check if the exact method exists realMethodExists = mc.methods.contains { MetaMethod existingMethod -> - existingMethod.name == methodName && existingMethod.isStatic()==staticScope && isRealMethod(existingMethod) && ((!parameterTypes && !existingMethod.parameterTypes) || parameterTypes==existingMethod.parameterTypes) + existingMethod.name == methodName && existingMethod.isStatic() == staticScope && isRealMethod(existingMethod) && ((!parameterTypes && !existingMethod.parameterTypes) || parameterTypes == existingMethod.parameterTypes) } } return realMethodExists diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy index 2c73f46f568..eafac8745ab 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy @@ -21,6 +21,7 @@ package org.grails.datastore.gorm import grails.gorm.DetachedCriteria import groovy.transform.CompileDynamic import groovy.transform.CompileStatic +import jakarta.persistence.Transient import org.grails.datastore.gorm.finders.FinderMethod import org.grails.datastore.gorm.query.GormQueryOperations import org.grails.datastore.mapping.dirty.checking.DirtyCheckable @@ -36,8 +37,6 @@ import org.grails.datastore.mapping.query.api.Criteria import org.grails.datastore.mapping.reflect.EntityReflector import org.springframework.transaction.TransactionDefinition -import jakarta.persistence.Transient - /** * * A trait that turns any class into a GORM entity @@ -49,7 +48,6 @@ import jakarta.persistence.Transient @CompileStatic trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi { - /** * Allow access to datasource by name * @@ -263,15 +261,14 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi getNamedQuery(String queryName, Object...args) { + static GormQueryOperations getNamedQuery(String queryName, Object... args) { GormEnhancer.createNamedQuery(this, queryName, args) } private GormInstanceApi currentGormInstanceApi() { - (GormInstanceApi)GormEnhancer.findInstanceApi(getClass()) + (GormInstanceApi) GormEnhancer.findInstanceApi(getClass()) } private static GormStaticApi currentGormStaticApi() { - (GormStaticApi)GormEnhancer.findStaticApi(this) + (GormStaticApi) GormEnhancer.findStaticApi(this) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntityApi.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntityApi.groovy index 8768b56631e..c6fdedc68d6 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntityApi.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntityApi.groovy @@ -25,9 +25,10 @@ package org.grails.datastore.gorm * @author Graeme Rocher * @since 5.0.5 * - * @param The entity type + * @param The entity type */ trait GormEntityApi { + /** * Proxy aware instanceOf implementation. */ diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntityDirtyCheckable.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntityDirtyCheckable.groovy index fdbd91796b4..34a16ca93a2 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntityDirtyCheckable.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntityDirtyCheckable.groovy @@ -19,14 +19,12 @@ package org.grails.datastore.gorm import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j +import jakarta.annotation.Generated import org.grails.datastore.mapping.config.Property import org.grails.datastore.mapping.dirty.checking.DirtyCheckable import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.model.PersistentProperty -import jakarta.annotation.Generated - /** * * Special trait meant only for GORM entities to override default behaviour of DirtyCheckable. @@ -36,19 +34,19 @@ import jakarta.annotation.Generated */ @CompileStatic trait GormEntityDirtyCheckable extends DirtyCheckable { - + @Override @Generated boolean hasChanged(String propertyName) { PersistentEntity entity = currentGormInstanceApi().persistentEntity - + PersistentProperty persistentProperty = entity.getPropertyByName(propertyName) if (!persistentProperty) { // Not persistent property, transient. We don't track changes for transients return false } - - Property propertyMapping = persistentProperty.getMapping().getMappedForm() + + Property propertyMapping = persistentProperty.getMapping().getMappedForm() if (propertyMapping.derived) { // Derived property cannot be changed, ex. sql formula return false diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormInstanceApi.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormInstanceApi.groovy index aade41b2898..c1c1cfab511 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormInstanceApi.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormInstanceApi.groovy @@ -20,16 +20,15 @@ package org.grails.datastore.gorm import grails.gorm.api.GormInstanceOperations import groovy.transform.CompileStatic - import org.codehaus.groovy.runtime.InvokerHelper -import org.grails.datastore.mapping.core.connections.ConnectionSource -import org.grails.datastore.mapping.core.connections.ConnectionSources -import org.grails.datastore.mapping.core.connections.ConnectionSourcesProvider -import org.grails.datastore.mapping.dirty.checking.DirtyCheckingSupport import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.core.Session import org.grails.datastore.mapping.core.SessionCallback +import org.grails.datastore.mapping.core.connections.ConnectionSource +import org.grails.datastore.mapping.core.connections.ConnectionSources +import org.grails.datastore.mapping.core.connections.ConnectionSourcesProvider import org.grails.datastore.mapping.dirty.checking.DirtyCheckable +import org.grails.datastore.mapping.dirty.checking.DirtyCheckingSupport import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.mapping.proxy.EntityProxy import org.grails.datastore.mapping.reflect.EntityReflector @@ -39,7 +38,7 @@ import org.grails.datastore.mapping.validation.ValidationException * Instance methods of the GORM API. * * @author Graeme Rocher - * @param the entity/domain class + * @param the entity/domain class */ @CompileStatic class GormInstanceApi extends AbstractGormApi implements GormInstanceOperations { @@ -68,7 +67,7 @@ class GormInstanceApi extends AbstractGormApi implements GormInstanceOpera */ boolean instanceOf(D o, Class cls) { if (o instanceof EntityProxy) { - o = (D)((EntityProxy)o).getTarget() + o = (D) ((EntityProxy) o).getTarget() } return o in cls } @@ -190,22 +189,21 @@ class GormInstanceApi extends AbstractGormApi implements GormInstanceOpera */ Serializable ident(D instance) { PersistentProperty identity = persistentEntity.getIdentity() - if(identity != null) { - return (Serializable)instance[identity.name] - } - else { + if (identity != null) { + return (Serializable) instance[identity.name] + } else { PersistentProperty[] idProperties = persistentEntity.getCompositeIdentity() - if(idProperties != null) { + if (idProperties != null) { EntityReflector entityReflector = persistentEntity.getReflector() def idInstance = persistentEntity.newInstance() - if(idInstance instanceof Serializable) { - for(prop in idProperties) { + if (idInstance instanceof Serializable) { + for (prop in idProperties) { String propertName = prop.name entityReflector.setProperty( idInstance, propertName, entityReflector.getProperty(instance, propertName) ) } - return (Serializable)idInstance + return (Serializable) idInstance } } } @@ -272,8 +270,8 @@ class GormInstanceApi extends AbstractGormApi implements GormInstanceOpera * @return true if the field is dirty */ boolean isDirty(D instance, String fieldName) { - if(instance instanceof DirtyCheckable) { - return ((DirtyCheckable)instance).hasChanged(fieldName) + if (instance instanceof DirtyCheckable) { + return ((DirtyCheckable) instance).hasChanged(fieldName) } return true } @@ -285,8 +283,8 @@ class GormInstanceApi extends AbstractGormApi implements GormInstanceOpera * @return true if it is dirty */ boolean isDirty(D instance) { - if(instance instanceof DirtyCheckable) { - return ((DirtyCheckable)instance).hasChanged() || DirtyCheckingSupport.areAssociationsDirty(persistentEntity, instance) + if (instance instanceof DirtyCheckable) { + return ((DirtyCheckable) instance).hasChanged() || DirtyCheckingSupport.areAssociationsDirty(persistentEntity, instance) } return true } @@ -298,8 +296,8 @@ class GormInstanceApi extends AbstractGormApi implements GormInstanceOpera * @return A list of property names that are dirty */ List getDirtyPropertyNames(D instance) { - if(instance instanceof DirtyCheckable) { - return ((DirtyCheckable)instance).listDirtyPropertyNames() + if (instance instanceof DirtyCheckable) { + return ((DirtyCheckable) instance).listDirtyPropertyNames() } return [] } @@ -311,8 +309,8 @@ class GormInstanceApi extends AbstractGormApi implements GormInstanceOpera * @return The original persisted value */ Object getPersistentValue(D instance, String fieldName) { - if(instance instanceof DirtyCheckable) { - return ((DirtyCheckable)instance).getOriginalValue(fieldName) + if (instance instanceof DirtyCheckable) { + return ((DirtyCheckable) instance).getOriginalValue(fieldName) } return null } @@ -321,27 +319,25 @@ class GormInstanceApi extends AbstractGormApi implements GormInstanceOpera boolean hasErrors = false boolean validate = params?.containsKey("validate") ? params.validate : true boolean shouldFlush = params?.flush ? params.flush : false - if(instance instanceof GormValidateable) { + if (instance instanceof GormValidateable) { def validateable = (GormValidateable) instance if (validate) { validateable.skipValidation(false) - if(datastore instanceof ConnectionSourcesProvider) { + if (datastore instanceof ConnectionSourcesProvider) { ConnectionSources connectionSources = ((ConnectionSourcesProvider) datastore).connectionSources String connectionSourceName = connectionSources.defaultConnectionSource.name - if(connectionSourceName != ConnectionSource.DEFAULT) { - GormValidationApi validationApi = GormEnhancer.findValidationApi((Class)instance.getClass(), connectionSourceName) - hasErrors = !validationApi.validate((D)instance, params) - } - else { + if (connectionSourceName != ConnectionSource.DEFAULT) { + GormValidationApi validationApi = GormEnhancer.findValidationApi((Class) instance.getClass(), connectionSourceName) + hasErrors = !validationApi.validate((D) instance, params) + } else { hasErrors = !validateable.validate(params) } - } - else { + } else { hasErrors = !validateable.validate(params) } // don't revalidate - if(shouldFlush) { + if (shouldFlush) { validateable.skipValidation(true) } @@ -360,9 +356,8 @@ class GormInstanceApi extends AbstractGormApi implements GormInstanceOpera } if (isInsert) { session.insert(instance) - } - else { - if(instance instanceof DirtyCheckable && markDirty) { + } else { + if (instance instanceof DirtyCheckable && markDirty) { // since this is an explicit call to save() we mark the instance as dirty to ensure it happens instance.markDirty() } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormStaticApi.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormStaticApi.groovy index 2f147443fa3..8412a4344a6 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormStaticApi.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormStaticApi.groovy @@ -28,7 +28,6 @@ import grails.gorm.transactions.GrailsTransactionTemplate import groovy.transform.CompileDynamic import groovy.transform.CompileStatic import groovy.transform.TypeCheckingMode - import org.codehaus.groovy.runtime.InvokerHelper import org.grails.datastore.gorm.finders.DynamicFinder import org.grails.datastore.gorm.finders.FinderMethod @@ -61,7 +60,7 @@ import org.springframework.util.Assert * Static methods of the GORM API. * * @author Graeme Rocher - * @param the entity/domain class + * @param the entity/domain class */ @CompileStatic class GormStaticApi extends AbstractGormApi implements GormAllOperations { @@ -82,14 +81,13 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations defaultConnectionSource = connectionSources.defaultConnectionSource qualifier = defaultConnectionSource.name multiTenancyMode = defaultConnectionSource.settings.multiTenancy.mode - } - else { + } else { connectionSources = null multiTenancyMode = MultiTenancyMode.NONE } @@ -113,10 +111,9 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations extends AbstractGormApi implements GormAllOperations f.isMethodMatch(methodName) } if (!method) { - if(args && args[-1] instanceof Closure) { + if (args && args[-1] instanceof Closure) { NamedCriteriaProxy proxy = GormEnhancer.createNamedQuery(persistentClass, methodName) - if(proxy != null) { + if (proxy != null) { return proxy.call(args) - } - else { + } else { throw new MissingMethodException(methodName, persistentClass, args) } - } - else { + } else { throw new MissingMethodException(methodName, persistentClass, args) } } // if the class is multi tenant, don't cache the method because the tenant will need to be resolved // for each method call - if(!MultiTenant.isAssignableFrom(persistentClass)) { + if (!MultiTenant.isAssignableFrom(persistentClass)) { def mc = persistentClass.getMetaClass() // register the method invocation for next time mc.static."$methodName" = { Object[] varArgs -> - // FYI... This is relevant to http://jira.grails.org/browse/GRAILS-3463 and may - // become problematic if http://jira.codehaus.org/browse/GROOVY-5876 is addressed... + // FYI... This is relevant to GRAILS-3463 and may + // become problematic if GROOVY-5876 is addressed... final argumentsForMethod - if(varArgs == null) { + if (varArgs == null) { argumentsForMethod = [null] as Object[] } // if the argument component type is not an Object then we have an array passed that is the actual argument - else if(varArgs.getClass().componentType != Object) { + else if (varArgs.getClass().componentType != Object) { // so we wrap it in an object array argumentsForMethod = [varArgs] as Object[] - } - else { + } else { - if(varArgs.length == 1 && varArgs[0].getClass().isArray()) { + if (varArgs.length == 1 && varArgs[0].getClass().isArray()) { argumentsForMethod = varArgs[0] } else { @@ -213,7 +207,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations whereAny(Closure callable) { - (DetachedCriteria)new DetachedCriteria(persistentClass).or(callable) + (DetachedCriteria) new DetachedCriteria(persistentClass).or(callable) } /** @@ -256,7 +250,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations saveAll(Object... objectsToSave) { - (List)execute({ Session session -> + (List) execute({ Session session -> session.persist Arrays.asList(objectsToSave) } as SessionCallback) } @@ -267,7 +261,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations saveAll(Iterable objectsToSave) { - (List)execute({ Session session -> + (List) execute({ Session session -> session.persist objectsToSave } as SessionCallback) } @@ -289,7 +283,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations session.delete Arrays.asList(objectsToDelete) - if(params?.flush) { + if (params?.flush) { session.flush() } } as SessionCallback) @@ -312,7 +306,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations session.delete objectToDelete - if(params?.flush) { + if (params?.flush) { session.flush() } } as SessionCallback) @@ -328,7 +322,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations extends AbstractGormApi implements GormAllOperations - session.retrieve((Class)persistentClass, id) + (D) execute({ Session session -> + session.retrieve((Class) persistentClass, id) } as SessionCallback) } @@ -352,8 +346,8 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations - session.retrieve((Class)persistentClass, id) + (D) execute({ Session session -> + session.retrieve((Class) persistentClass, id) } as SessionCallback) } @@ -361,8 +355,8 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations - session.proxy((Class)persistentClass, id) + (D) execute({ Session session -> + session.proxy((Class) persistentClass, id) } as SessionCallback) } @@ -388,7 +382,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations getAll(Serializable... ids) { - (List)execute ({ Session session -> + (List) execute({ Session session -> session.retrieveAll(persistentClass, ids.flatten()) } as SessionCallback) } @@ -413,7 +407,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations InvokerHelper.invokeMethod(createCriteria(), 'call', callable) - } as SessionCallback ) + } as SessionCallback) } /** @@ -429,16 +423,15 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations InvokerHelper.invokeMethod(criteriaBuilder, 'get', callable) - } as SessionCallback ) + } as SessionCallback) - } - else { + } else { execute({ Session session -> InvokerHelper.invokeMethod(criteriaBuilder, 'list', callable) - } as SessionCallback ) + } as SessionCallback) } } @@ -449,8 +442,8 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations - session.lock((Class)persistentClass, id) + (D) execute({ Session session -> + session.lock((Class) persistentClass, id) } as SessionCallback) } @@ -466,7 +459,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations extends AbstractGormApi implements GormAllOperations + execute({ Session session -> session.persist(d) return d } as SessionCallback) @@ -555,7 +548,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations + (Integer) execute({ Session session -> def q = session.createQuery(persistentClass) q.projections().count() @@ -593,7 +586,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations list(Map params) { - (List)execute ({ Session session -> + (List) execute({ Session session -> Query q = session.createQuery(persistentClass) DynamicFinder.populateArgumentsForCriteria(persistentClass, q, params) if (params?.max) { @@ -609,7 +602,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations list() { - (List)execute ({ Session session -> + (List) execute({ Session session -> session.createQuery(persistentClass).list() } as SessionCallback) } @@ -753,11 +746,11 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations findAllWhere(Map queryMap, Map args) { - (List)execute ({ Session session -> + (List) execute({ Session session -> Query q = session.createQuery(persistentClass) Map processedQueryMap = [:] - queryMap.each{ key, value -> processedQueryMap[key.toString()] = value } + queryMap.each { key, value -> processedQueryMap[key.toString()] = value } q.allEq(processedQueryMap) DynamicFinder.populateArgumentsForCriteria persistentClass, q, args @@ -814,7 +807,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations processedQueryMap = [:] - queryMap.each{ key, value -> processedQueryMap[key.toString()] = value } + queryMap.each { key, value -> processedQueryMap[key.toString()] = value } q.allEq(processedQueryMap) } DynamicFinder.populateArgumentsForCriteria persistentClass, q, args @@ -850,8 +843,8 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations T withSession(Closure callable) { - execute ({ Session session -> + public T withSession(Closure callable) { + execute({ Session session -> callable.call session } as SessionCallback) } @@ -862,8 +855,8 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations T withDatastoreSession(Closure callable) { - execute ({ Session session -> + public T withDatastoreSession(Closure callable) { + execute({ Session session -> callable.call session } as SessionCallback) } @@ -884,38 +877,33 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations T withTenant(Serializable tenantId, Closure callable) { - if(multiTenancyMode == MultiTenancyMode.DATABASE) { - Tenants.withId((Class)GormEnhancer.findDatastore(persistentClass, tenantId.toString()).getClass(), tenantId, callable) - } - else if(multiTenancyMode.isSharedConnection()) { - Tenants.withId((Class)GormEnhancer.findDatastore(persistentClass, ConnectionSource.DEFAULT).getClass(), tenantId, callable) - } - else { + if (multiTenancyMode == MultiTenancyMode.DATABASE) { + Tenants.withId((Class) GormEnhancer.findDatastore(persistentClass, tenantId.toString()).getClass(), tenantId, callable) + } else if (multiTenancyMode.isSharedConnection()) { + Tenants.withId((Class) GormEnhancer.findDatastore(persistentClass, ConnectionSource.DEFAULT).getClass(), tenantId, callable) + } else { throw new UnsupportedOperationException("Method not supported in multi tenancy mode $multiTenancyMode") } } @Override GormAllOperations eachTenant(Closure callable) { - if(multiTenancyMode != MultiTenancyMode.NONE) { + if (multiTenancyMode != MultiTenancyMode.NONE) { Tenants.eachTenant callable return this - } - else { + } else { throw new UnsupportedOperationException("Method not supported in multi tenancy mode $multiTenancyMode") } } @Override GormAllOperations withTenant(Serializable tenantId) { - if(multiTenancyMode == MultiTenancyMode.DATABASE) { + if (multiTenancyMode == MultiTenancyMode.DATABASE) { return GormEnhancer.findStaticApi(persistentClass, tenantId.toString()) - } - else if(multiTenancyMode.isSharedConnection()) { + } else if (multiTenancyMode.isSharedConnection()) { def staticApi = GormEnhancer.findStaticApi(persistentClass, ConnectionSource.DEFAULT) return new TenantDelegatingGormOperations(datastore, tenantId, staticApi) - } - else { + } else { throw new UnsupportedOperationException("Method not supported in multi tenancy mode $multiTenancyMode") } } @@ -928,7 +916,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations T withNewTransaction(Closure callable) { + public T withNewTransaction(Closure callable) { withTransaction([propagationBehavior: TransactionDefinition.PROPAGATION_REQUIRES_NEW], callable) } @@ -950,15 +938,14 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations T withTransaction(Map transactionProperties, Closure callable) { + public T withTransaction(Map transactionProperties, Closure callable) { def transactionDefinition = new DefaultTransactionDefinition() transactionProperties.each { k, v -> - if(v instanceof CharSequence && !(v instanceof String)) { + if (v instanceof CharSequence && !(v instanceof String)) { v = v.toString() } try { @@ -991,8 +978,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations extends AbstractGormApi implements GormAllOperations T withStatelessSession(Closure callable) { - if(datastore instanceof StatelessDatastore) { + public T withStatelessSession(Closure callable) { + if (datastore instanceof StatelessDatastore) { def session = datastore.connectStateless() try { DatastoreUtils.bindNewSession session @@ -1046,8 +1032,7 @@ class GormStaticApi extends AbstractGormApi implements GormAllOperations extends AbstractGormApi implements GormAllOperations extends AbstractGormApi implements GormAllOperations extends AbstractGormApi implements GormAllOperations the entity/domain class + * @param the entity/domain class * @since 1.0 */ @CompileStatic @@ -73,10 +72,10 @@ class GormValidationApi extends AbstractGormApi { Validator getValidator() { if (!internalValidator) { - if(persistentEntity instanceof ValidatorProvider) { - internalValidator = ((ValidatorProvider)persistentEntity).validator + if (persistentEntity instanceof ValidatorProvider) { + internalValidator = ((ValidatorProvider) persistentEntity).validator } - if(!internalValidator) { + if (!internalValidator) { internalValidator = mappingContext.getEntityValidator(persistentEntity) } } @@ -96,7 +95,7 @@ class GormValidationApi extends AbstractGormApi { deepValidate = ClassUtils.getBooleanFromMap(ARGUMENT_DEEP_VALIDATE, arguments) } - if(hasDatastore) { + if (hasDatastore) { currentSession = datastore.currentSession previousFlushMode = currentSession.flushMode currentSession.setFlushMode(FlushModeType.COMMIT) @@ -106,7 +105,7 @@ class GormValidationApi extends AbstractGormApi { fireEvent(instance, fields) Validator validator = getValidator() - if(validator == null) { + if (validator == null) { return true } @@ -116,7 +115,7 @@ class GormValidationApi extends AbstractGormApi { for (error in errors.allErrors) { if (error instanceof FieldError) { - if (((FieldError)error).bindingFailure) { + if (((FieldError) error).bindingFailure) { localErrors.addError error } } else { @@ -125,7 +124,7 @@ class GormValidationApi extends AbstractGormApi { } if (validator instanceof CascadingValidator) { - ((CascadingValidator)validator).validate instance, localErrors, deepValidate + ((CascadingValidator) validator).validate instance, localErrors, deepValidate } else if (validator instanceof org.grails.datastore.gorm.validation.CascadingValidator) { ((org.grails.datastore.gorm.validation.CascadingValidator) validator).validate instance, localErrors, deepValidate } else { @@ -140,7 +139,7 @@ class GormValidationApi extends AbstractGormApi { return !getErrors(instance).hasErrors() } finally { - if(previousFlushMode != null) { + if (previousFlushMode != null) { currentSession.setFlushMode(previousFlushMode) } } @@ -154,7 +153,7 @@ class GormValidationApi extends AbstractGormApi { * @return True if the instance is valid */ boolean validate(D instance, Map arguments) { - doValidate instance, arguments, (List)null + doValidate instance, arguments, (List) null } /** @@ -165,7 +164,7 @@ class GormValidationApi extends AbstractGormApi { * @return True if the instance is valid */ boolean validate(D instance, List fields) { - doValidate instance, (Map)null, fields + doValidate instance, (Map) null, fields } private ValidationErrors filterErrors(ValidationErrors errors, Set validatedFields, Object target) { @@ -176,7 +175,7 @@ class GormValidationApi extends AbstractGormApi { for (ObjectError error : errors.getAllErrors()) { if (error instanceof FieldError) { - FieldError fieldError = (FieldError)error + FieldError fieldError = (FieldError) error if (!validatedFields.contains(fieldError.getField())) continue } @@ -208,27 +207,25 @@ class GormValidationApi extends AbstractGormApi { * @return True if the instance is valid */ boolean validate(D instance) { - doValidate instance, (Map)null, (List)null + doValidate instance, (Map) null, (List) null } - /** * Obtains the errors for an instance * @param instance The instance to obtain errors for * @return The {@link Errors} instance */ Errors getErrors(D instance) { - if(instance instanceof GormValidateable) { - GormValidateable gv = (GormValidateable)instance + if (instance instanceof GormValidateable) { + GormValidateable gv = (GormValidateable) instance def errors = gv.errors if (errors == null) { errors = resetErrors(instance) } return errors - } - else { + } else { - Errors errors = (Errors)datastore.currentSession.getAttribute(instance, GormProperties.ERRORS) + Errors errors = (Errors) datastore.currentSession.getAttribute(instance, GormProperties.ERRORS) if (errors == null) { errors = resetErrors(instance) } @@ -248,11 +245,10 @@ class GormValidationApi extends AbstractGormApi { * @param errors The errors */ void setErrors(D instance, Errors errors) { - if(instance instanceof GormValidateable) { + if (instance instanceof GormValidateable) { GormValidateable gv = (GormValidateable) instance gv.errors = errors - } - else { + } else { datastore.currentSession.setAttribute(instance, GormProperties.ERRORS, errors) } } @@ -271,12 +267,11 @@ class GormValidationApi extends AbstractGormApi { * @return True if errors exist */ boolean hasErrors(D instance) { - if(instance instanceof GormValidateable) { + if (instance instanceof GormValidateable) { GormValidateable gv = (GormValidateable) instance return gv.hasErrors() - } - else { - Errors errors = (Errors)datastore.currentSession.getAttribute(instance, GormProperties.ERRORS) + } else { + Errors errors = (Errors) datastore.currentSession.getAttribute(instance, GormProperties.ERRORS) errors?.hasErrors() } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/bootstrap/AbstractDatastoreInitializer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/bootstrap/AbstractDatastoreInitializer.groovy index c7b391537c3..38883d321a7 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/bootstrap/AbstractDatastoreInitializer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/bootstrap/AbstractDatastoreInitializer.groovy @@ -38,7 +38,11 @@ import org.grails.datastore.mapping.services.ServiceDefinition import org.grails.datastore.mapping.services.SoftServiceLoader import org.grails.datastore.mapping.transactions.DatastoreTransactionManager import org.springframework.beans.factory.support.BeanDefinitionRegistry -import org.springframework.context.* +import org.springframework.context.ApplicationContext +import org.springframework.context.ApplicationEventPublisher +import org.springframework.context.ConfigurableApplicationContext +import org.springframework.context.MessageSource +import org.springframework.context.ResourceLoaderAware import org.springframework.context.support.GenericApplicationContext import org.springframework.context.support.StaticMessageSource import org.springframework.core.env.ConfigurableEnvironment @@ -60,13 +64,12 @@ import java.beans.Introspector * @since 3.0.3 */ @CompileStatic -abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ +abstract class AbstractDatastoreInitializer implements ResourceLoaderAware { public static final String TRANSACTION_MANAGER_BEAN = 'transactionManager' public static final String ENTITY_CLASS_RESOURCE_PATTERN = "/**/*.class" public static final String OSIV_CLASS_NAME = 'org.grails.datastore.mapping.web.support.OpenSessionInViewInterceptor' - PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver() Collection persistentClasses = [] Collection packages = [] @@ -84,6 +87,7 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ this(packages) this.classLoader = classLoader ?: Thread.currentThread().contextClassLoader } + AbstractDatastoreInitializer(String... packages) { this.packages = packages.toList() } @@ -101,11 +105,11 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ this.persistentClasses = persistentClasses } - AbstractDatastoreInitializer(PropertyResolver configuration, Class...persistentClasses) { + AbstractDatastoreInitializer(PropertyResolver configuration, Class... persistentClasses) { this(configuration, Arrays.asList(persistentClasses)) } - AbstractDatastoreInitializer(PropertyResolver configuration, String...packages) { + AbstractDatastoreInitializer(PropertyResolver configuration, String... packages) { this.configuration = configuration this.packages = Arrays.asList(packages) } @@ -127,13 +131,11 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ */ ApplicationEventPublisher findEventPublisher(BeanDefinitionRegistry beanDefinitionRegistry) { ApplicationEventPublisher eventPublisher - if(beanDefinitionRegistry instanceof ConfigurableApplicationContext){ - eventPublisher = new ConfigurableApplicationContextEventPublisher((ConfigurableApplicationContext)beanDefinitionRegistry) - } - else if(resourcePatternResolver.resourceLoader instanceof ConfigurableApplicationContext) { - eventPublisher = new ConfigurableApplicationContextEventPublisher((ConfigurableApplicationContext)resourcePatternResolver.resourceLoader) - } - else { + if (beanDefinitionRegistry instanceof ConfigurableApplicationContext) { + eventPublisher = new ConfigurableApplicationContextEventPublisher((ConfigurableApplicationContext) beanDefinitionRegistry) + } else if (resourcePatternResolver.resourceLoader instanceof ConfigurableApplicationContext) { + eventPublisher = new ConfigurableApplicationContextEventPublisher((ConfigurableApplicationContext) resourcePatternResolver.resourceLoader) + } else { eventPublisher = new DefaultApplicationEventPublisher() } return eventPublisher @@ -146,13 +148,11 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ */ MessageSource findMessageSource(BeanDefinitionRegistry beanDefinitionRegistry) { MessageSource messageSource - if(beanDefinitionRegistry instanceof MessageSource){ - messageSource = (MessageSource)beanDefinitionRegistry - } - else if(resourcePatternResolver.resourceLoader instanceof MessageSource) { - messageSource = (MessageSource)resourcePatternResolver.resourceLoader - } - else { + if (beanDefinitionRegistry instanceof MessageSource) { + messageSource = (MessageSource) beanDefinitionRegistry + } else if (resourcePatternResolver.resourceLoader instanceof MessageSource) { + messageSource = (MessageSource) resourcePatternResolver.resourceLoader + } else { messageSource = new StaticMessageSource() } return messageSource @@ -195,9 +195,8 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ scanUsingPattern(pattern, readerFactory) } - def entityNames = AstUtils.getKnownEntityNames() - if(entityNames) { + if (entityNames) { // only works at development time for (entityName in entityNames) { try { @@ -206,10 +205,9 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ // ignore } } - } - else { + } else { // try the default package in case of a script without recursing into subpackages - String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "*.class" + String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "*.class" scanUsingPattern(pattern, readerFactory) } } @@ -234,7 +232,7 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ @CompileStatic void configureForBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) { - if(configuration instanceof ConfigurableEnvironment && beanDefinitionRegistry instanceof ConfigurableApplicationContext) { + if (configuration instanceof ConfigurableEnvironment && beanDefinitionRegistry instanceof ConfigurableApplicationContext) { def env = (ConfigurableEnvironment) configuration def conversionService = ((ConfigurableApplicationContext) beanDefinitionRegistry).getEnvironment().getConversionService() @@ -246,13 +244,11 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ scanForPersistentClasses() - if( GroovyBeanReaderInit.isAvailable() ) { + if (GroovyBeanReaderInit.isAvailable()) { GroovyBeanReaderInit.registerBeans(beanDefinitionRegistry, getBeanDefinitions(beanDefinitionRegistry)) - } - else if (GrailsBeanBuilderInit.isAvailable() ) { + } else if (GrailsBeanBuilderInit.isAvailable()) { GrailsBeanBuilderInit.registerBeans(beanDefinitionRegistry, getBeanDefinitions(beanDefinitionRegistry)) - } - else { + } else { throw new IllegalStateException("Neither Spring 4.0+ nor grails-spring dependency found on classpath to enable GORM configuration. If you are using an earlier version of Spring please add the grails-spring dependency to your classpath.") } } @@ -262,7 +258,6 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ return {} } - protected Collection collectMappedClasses(String datastoreType) { def classes = !secondaryDatastore ? persistentClasses : persistentClasses.findAll() { Class cls -> isMappedClass(datastoreType, cls) @@ -274,7 +269,6 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ datastoreType.equals(ClassPropertyFetcher.getStaticPropertyValue(cls, GormProperties.MAPPING_STRATEGY, String)) } - abstract public Closure getBeanDefinitions(BeanDefinitionRegistry beanDefinitionRegistry) /** @@ -287,7 +281,7 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ */ @CompileDynamic Closure getAdditionalBeansConfiguration(BeanDefinitionRegistry registry, String type) { - {-> + { -> "${type}TransactionManager"(DatastoreTransactionManager) { datastore = ref("${type}Datastore") } @@ -301,7 +295,6 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ "${type}PersistenceContextInterceptorAggregator"(PersistenceContextInterceptorAggregator) - def classLoader = Thread.currentThread().contextClassLoader if (registry.containsBeanDefinition('dispatcherServlet') && ClassUtils.isPresent(OSIV_CLASS_NAME, classLoader)) { String interceptorName = "${type}OpenSessionInViewInterceptor" @@ -310,13 +303,13 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ } } loadDataServices(null) - .each {serviceName, serviceClass-> - "$serviceName"(DatastoreServiceMethodInvokingFactoryBean, serviceClass) { - targetObject = ref("${type}Datastore") - targetMethod = 'getService' - arguments = [serviceClass] - } - } + .each { serviceName, serviceClass -> + "$serviceName"(DatastoreServiceMethodInvokingFactoryBean, serviceClass) { + targetObject = ref("${type}Datastore") + targetMethod = 'getService' + arguments = [serviceClass] + } + } } } @@ -324,7 +317,7 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ protected Map> loadDataServices(String secondaryDatastore = null) { Map> services = [:] final SoftServiceLoader softServiceLoader = SoftServiceLoader.load(Service) - for (ServiceDefinition serviceDefinition: softServiceLoader) { + for (ServiceDefinition serviceDefinition : softServiceLoader) { if (serviceDefinition.isPresent()) { final Class clazz = serviceDefinition.getType() final Class serviceClass = loadServiceClass(clazz) @@ -367,7 +360,7 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ @CompileStatic protected Class getGrailsApplicationClass() { ClassLoader cl = getClass().getClassLoader() - if(ClassUtils.isPresent("grails.core.DefaultGrailsApplication", cl)) { + if (ClassUtils.isPresent("grails.core.DefaultGrailsApplication", cl)) { return ClassUtils.forName("grails.core.DefaultGrailsApplication", cl) } throw new IllegalStateException("No version of Grails found on classpath") @@ -376,7 +369,7 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ protected boolean isGrailsPresent() { ClassLoader cl = getClass().getClassLoader() - if(ClassUtils.isPresent("grails.core.DefaultGrailsApplication", cl)) { + if (ClassUtils.isPresent("grails.core.DefaultGrailsApplication", cl)) { return true } return false @@ -389,6 +382,7 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ @CompileDynamic static class GroovyBeanReaderInit { + static boolean isAvailable() { try { Thread.currentThread().contextClassLoader.loadClass('org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader') @@ -397,6 +391,7 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ return false } } + static void registerBeans(BeanDefinitionRegistry registry, Closure beanDefinitions) { def classLoader = Thread.currentThread().contextClassLoader def beanReader = classLoader.loadClass('org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader').newInstance(registry) @@ -406,6 +401,7 @@ abstract class AbstractDatastoreInitializer implements ResourceLoaderAware{ @CompileDynamic static class GrailsBeanBuilderInit { + static boolean isAvailable() { try { Thread.currentThread().contextClassLoader.loadClass('grails.spring.BeanBuilder') diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/bootstrap/support/InstanceFactoryBean.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/bootstrap/support/InstanceFactoryBean.java index ebc362ac5af..1f66bf6ecf4 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/bootstrap/support/InstanceFactoryBean.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/bootstrap/support/InstanceFactoryBean.java @@ -22,12 +22,13 @@ /** * Simple singleton instance implementation of Spring's FactoryBean interface - * + *

* mainly useful in unit tests * */ public class InstanceFactoryBean implements FactoryBean { + T object; Class objectType; @@ -55,7 +56,6 @@ public T getObject() { return object; } - public void setObject(T object) { this.object = object; } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/bootstrap/support/ServiceRegistryFactoryBean.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/bootstrap/support/ServiceRegistryFactoryBean.groovy index 2aacd11e46c..fce9efcec05 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/bootstrap/support/ServiceRegistryFactoryBean.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/bootstrap/support/ServiceRegistryFactoryBean.groovy @@ -28,13 +28,8 @@ import org.springframework.beans.BeansException import org.springframework.beans.factory.BeanFactory import org.springframework.beans.factory.BeanFactoryAware import org.springframework.beans.factory.FactoryBean -import org.springframework.beans.factory.InitializingBean import org.springframework.beans.factory.config.AutowireCapableBeanFactory -import org.springframework.beans.factory.config.ConfigurableBeanFactory import org.springframework.beans.factory.config.ConfigurableListableBeanFactory -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware -import org.springframework.context.ConfigurableApplicationContext import java.beans.Introspector @@ -44,6 +39,7 @@ import java.beans.Introspector */ @CompileStatic class ServiceRegistryFactoryBean implements FactoryBean, BeanFactoryAware { + final Datastore datastore ServiceRegistryFactoryBean(Datastore datastore) { @@ -67,27 +63,26 @@ class ServiceRegistryFactoryBean implements FactoryBean, BeanFa @Override void setBeanFactory(BeanFactory beanFactory) throws BeansException { - if(beanFactory instanceof ConfigurableListableBeanFactory) { - AutowireCapableBeanFactory autowireCapableBeanFactory = beanFactory instanceof AutowireCapableBeanFactory ? (AutowireCapableBeanFactory)beanFactory : null - ConfigurableListableBeanFactory configurableListableBeanFactory = (ConfigurableListableBeanFactory)beanFactory + if (beanFactory instanceof ConfigurableListableBeanFactory) { + AutowireCapableBeanFactory autowireCapableBeanFactory = beanFactory instanceof AutowireCapableBeanFactory ? (AutowireCapableBeanFactory) beanFactory : null + ConfigurableListableBeanFactory configurableListableBeanFactory = (ConfigurableListableBeanFactory) beanFactory - for(org.grails.datastore.mapping.services.Service service in datastore.services) { + for (org.grails.datastore.mapping.services.Service service in datastore.services) { def serviceClass = service.getClass() Service ann = serviceClass.getAnnotation(Service) String serviceName = ann?.name() - if(serviceName == null) { + if (serviceName == null) { serviceName = Introspector.decapitalize(serviceClass.simpleName) } - if(!configurableListableBeanFactory.containsBean(serviceName)) { + if (!configurableListableBeanFactory.containsBean(serviceName)) { autowireCapableBeanFactory?.autowireBean(service) service.setDatastore(datastore) configurableListableBeanFactory.registerSingleton(serviceName, service) - } - else { - String root = Introspector.decapitalize( datastore.getClass().simpleName - 'Datastore' ) + } else { + String root = Introspector.decapitalize(datastore.getClass().simpleName - 'Datastore') serviceName = "${root}${NameUtils.capitalize(serviceName)}" - if(!configurableListableBeanFactory.containsBean(serviceName)) { + if (!configurableListableBeanFactory.containsBean(serviceName)) { autowireCapableBeanFactory?.autowireBean(service) service.setDatastore(datastore) configurableListableBeanFactory.registerSingleton(serviceName, service) diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/AutoTimestampEventListener.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/AutoTimestampEventListener.java index bdf25e622d8..4607c44f1d7 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/AutoTimestampEventListener.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/AutoTimestampEventListener.java @@ -25,7 +25,11 @@ import org.grails.datastore.mapping.config.Settings; import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.event.*; +import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; +import org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener; +import org.grails.datastore.mapping.engine.event.EventType; +import org.grails.datastore.mapping.engine.event.PreInsertEvent; +import org.grails.datastore.mapping.engine.event.PreUpdateEvent; import org.grails.datastore.mapping.model.ClassMapping; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; @@ -34,7 +38,14 @@ import org.springframework.context.ApplicationEvent; import java.lang.reflect.Field; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; @@ -46,12 +57,14 @@ */ public class AutoTimestampEventListener extends AbstractPersistenceEventListener implements MappingContext.Listener { + public static final String DATE_CREATED_PROPERTY = "dateCreated"; + public static final String LAST_UPDATED_PROPERTY = "lastUpdated"; + + //CHECKSTYLE:OFF // if false, will not set timestamp on insert event if value is not null @Value("${" + Settings.SETTING_AUTO_TIMESTAMP_INSERT_OVERWRITE + ":true}") public boolean insertOverwrite = true; - - public static final String DATE_CREATED_PROPERTY = "dateCreated"; - public static final String LAST_UPDATED_PROPERTY = "lastUpdated"; + //CHECKSTYLE:ON protected Map>> entitiesWithDateCreated = new ConcurrentHashMap<>(); protected Map>> entitiesWithLastUpdated = new ConcurrentHashMap<>(); @@ -82,7 +95,9 @@ protected void initForMappingContext(MappingContext mappingContext) { @Override protected void onPersistenceEvent(final AbstractPersistenceEvent event) { - if (event.getEntity() == null) return; + if (event.getEntity() == null) { + return; + } if (event.getEventType() == EventType.PreInsert) { beforeInsert(event.getEntity(), event.getEntityAccess()); @@ -93,7 +108,7 @@ protected void onPersistenceEvent(final AbstractPersistenceEvent event) { public boolean supportsEventType(Class eventType) { return PreInsertEvent.class.isAssignableFrom(eventType) || - PreUpdateEvent.class.isAssignableFrom(eventType); + PreUpdateEvent.class.isAssignableFrom(eventType); } public boolean beforeInsert(PersistentEntity entity, EntityAccess ea) { @@ -198,10 +213,9 @@ protected void storeDateCreatedAndLastUpdatedInfo(PersistentEntity persistentEnt protected void storeTimestampAvailability(Map>> timestampAvailabilityMap, PersistentEntity persistentEntity, PersistentProperty property) { if (property != null && timestampProvider.supportsCreating(property.getType())) { Optional> timestampProperties = timestampAvailabilityMap.computeIfAbsent(persistentEntity.getName(), k -> Optional.of(new HashSet<>())); - if(timestampProperties.isPresent()) { + if (timestampProperties.isPresent()) { timestampProperties.get().add(property.getName()); - } - else { + } else { throw new IllegalStateException("Timestamp properties for entity [" + persistentEntity.getName() + "] have been disabled. Cannot add property [" + property.getName() + "]"); } } @@ -219,14 +233,14 @@ public void setTimestampProvider(TimestampProvider timestampProvider) { this.timestampProvider = timestampProvider; } - private void processAllEntries(final Set>>> entries, final Runnable runnable) { + private void processAllEntries(final Set>>> entries, final Runnable runnable) { Map>> originalValues = new LinkedHashMap<>(); - for (Map.Entry>> entry: entries) { + for (Map.Entry>> entry : entries) { originalValues.put(entry.getKey(), entry.getValue()); entry.setValue(Optional.empty()); } runnable.run(); - for (Map.Entry>> entry: entries) { + for (Map.Entry>> entry : entries) { entry.setValue(originalValues.get(entry.getKey())); } } @@ -234,10 +248,10 @@ private void processAllEntries(final Set> private void processEntries(final List classes, Map>> entities, final Runnable runnable) { Set>>> entries = new HashSet<>(); final List classNames = new ArrayList<>(classes.size()); - for (Class clazz: classes) { + for (Class clazz : classes) { classNames.add(clazz.getName()); } - for (Map.Entry>> entry: entities.entrySet()) { + for (Map.Entry>> entry : entities.entrySet()) { if (classNames.contains(entry.getKey())) { entries.add(entry); } @@ -247,30 +261,30 @@ private void processEntries(final List classes, Map classes, final Runnable runnable) { + public void withoutLastUpdated(final List classes, final Runnable runnable) { processEntries(classes, entitiesWithLastUpdated, runnable); } /** * Temporarily disables the last updated processing only on the provided class during the execution of the runnable * - * @param clazz Which class to disable the last updated processing for + * @param clazz Which class to disable the last updated processing for * @param runnable The code to execute while the last updated listener is disabled */ - public void withoutLastUpdated(final Class clazz, final Runnable runnable) { + public void withoutLastUpdated(final Class clazz, final Runnable runnable) { ArrayList list = new ArrayList<>(1); list.add(clazz); withoutLastUpdated(list, runnable); @@ -281,27 +295,27 @@ public void withoutLastUpdated(final Class clazz, final Runnable runnable) { * * @param runnable The code to execute while the date created listener is disabled */ - public void withoutDateCreated(final Runnable runnable) { + public void withoutDateCreated(final Runnable runnable) { processAllEntries(entitiesWithDateCreated.entrySet(), runnable); } /** * Temporarily disables the date created processing only on the provided classes during the execution of the runnable * - * @param classes Which classes to disable the date created processing for + * @param classes Which classes to disable the date created processing for * @param runnable The code to execute while the date created listener is disabled */ - public void withoutDateCreated(final List classes, final Runnable runnable) { + public void withoutDateCreated(final List classes, final Runnable runnable) { processEntries(classes, entitiesWithDateCreated, runnable); } /** * Temporarily disables the date created processing only on the provided class during the execution of the runnable * - * @param clazz Which class to disable the date created processing for + * @param clazz Which class to disable the date created processing for * @param runnable The code to execute while the date created listener is disabled */ - public void withoutDateCreated(final Class clazz, final Runnable runnable) { + public void withoutDateCreated(final Class clazz, final Runnable runnable) { ArrayList list = new ArrayList<>(1); list.add(clazz); withoutDateCreated(list, runnable); @@ -312,27 +326,27 @@ public void withoutDateCreated(final Class clazz, final Runnable runnable) { * * @param runnable The code to execute while the timestamp listeners are disabled */ - public void withoutTimestamps(final Runnable runnable) { + public void withoutTimestamps(final Runnable runnable) { withoutDateCreated(() -> withoutLastUpdated(runnable)); } /** * Temporarily disables the timestamp processing only on the provided classes during the execution of the runnable * - * @param classes Which classes to disable the timestamp processing for + * @param classes Which classes to disable the timestamp processing for * @param runnable The code to execute while the timestamp listeners are disabled */ - public void withoutTimestamps(final List classes, final Runnable runnable) { + public void withoutTimestamps(final List classes, final Runnable runnable) { withoutDateCreated(classes, () -> withoutLastUpdated(classes, runnable)); } /** * Temporarily disables the timestamp processing during the execution of the runnable * - * @param clazz Which class to disable the timestamp processing for + * @param clazz Which class to disable the timestamp processing for * @param runnable The code to execute while the timestamp listeners are disabled */ - public void withoutTimestamps(final Class clazz, final Runnable runnable) { + public void withoutTimestamps(final Class clazz, final Runnable runnable) { withoutDateCreated(clazz, () -> withoutLastUpdated(clazz, runnable)); } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/DefaultApplicationEventPublisher.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/DefaultApplicationEventPublisher.groovy index 99681514320..60a820f486a 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/DefaultApplicationEventPublisher.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/DefaultApplicationEventPublisher.groovy @@ -35,15 +35,15 @@ import org.springframework.context.event.SmartApplicationListener class DefaultApplicationEventPublisher implements ConfigurableApplicationEventPublisher { private List applicationListeners = [] + @Override void publishEvent(ApplicationEvent event) { - for(listener in applicationListeners) { - if(listener instanceof SmartApplicationListener) { + for (listener in applicationListeners) { + if (listener instanceof SmartApplicationListener) { SmartApplicationListener smartApplicationListener = (SmartApplicationListener) listener - if( !smartApplicationListener.supportsEventType((Class)event.getClass()) ) { + if (!smartApplicationListener.supportsEventType((Class) event.getClass())) { continue - } - else if(!smartApplicationListener.supportsSourceType(event.source.getClass())) { + } else if (!smartApplicationListener.supportsSourceType(event.source.getClass())) { continue } } @@ -53,14 +53,13 @@ class DefaultApplicationEventPublisher implements ConfigurableApplicationEventPu @Override void publishEvent(Object event) { - for(listener in applicationListeners) { + for (listener in applicationListeners) { def eventObject = new PayloadApplicationEvent(this, event) - if(listener instanceof SmartApplicationListener) { + if (listener instanceof SmartApplicationListener) { SmartApplicationListener smartApplicationListener = (SmartApplicationListener) listener - if( !smartApplicationListener.supportsEventType((Class)eventObject.getClass()) ) { + if (!smartApplicationListener.supportsEventType((Class) eventObject.getClass())) { continue - } - else if(!smartApplicationListener.supportsSourceType(eventObject.source.getClass())) { + } else if (!smartApplicationListener.supportsSourceType(eventObject.source.getClass())) { continue } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/DomainEventListener.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/DomainEventListener.java index 13371dc5ae7..694bdad8569 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/DomainEventListener.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/events/DomainEventListener.java @@ -18,19 +18,20 @@ */ package org.grails.datastore.gorm.events; -import java.lang.reflect.Method; -import java.sql.Timestamp; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.connections.ConnectionSourcesProvider; import org.grails.datastore.mapping.dirty.checking.DirtyCheckable; import org.grails.datastore.mapping.engine.EntityAccess; -import org.grails.datastore.mapping.engine.event.*; +import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; +import org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener; +import org.grails.datastore.mapping.engine.event.PostDeleteEvent; +import org.grails.datastore.mapping.engine.event.PostInsertEvent; +import org.grails.datastore.mapping.engine.event.PostLoadEvent; +import org.grails.datastore.mapping.engine.event.PostUpdateEvent; +import org.grails.datastore.mapping.engine.event.PreDeleteEvent; +import org.grails.datastore.mapping.engine.event.PreInsertEvent; +import org.grails.datastore.mapping.engine.event.PreLoadEvent; +import org.grails.datastore.mapping.engine.event.PreUpdateEvent; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.config.GormProperties; @@ -39,6 +40,14 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.util.ReflectionUtils; +import java.lang.reflect.Method; +import java.sql.Timestamp; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + /** * An event listener that provides support for GORM domain events. * @@ -46,25 +55,24 @@ * @since 1.0 */ public class DomainEventListener extends AbstractPersistenceEventListener - implements MappingContext.Listener { - - private Map> entityEvents = new ConcurrentHashMap>(); + implements MappingContext.Listener { @SuppressWarnings("rawtypes") public static final Class[] ZERO_PARAMS = {}; - public static final String EVENT_BEFORE_INSERT = "beforeInsert"; + public static final String EVENT_BEFORE_INSERT = "beforeInsert"; private static final String EVENT_BEFORE_UPDATE = "beforeUpdate"; private static final String EVENT_BEFORE_DELETE = "beforeDelete"; - private static final String EVENT_BEFORE_LOAD = "beforeLoad"; - private static final String EVENT_AFTER_INSERT = "afterInsert"; - private static final String EVENT_AFTER_UPDATE = "afterUpdate"; - private static final String EVENT_AFTER_DELETE = "afterDelete"; - private static final String EVENT_AFTER_LOAD = "afterLoad"; + private static final String EVENT_BEFORE_LOAD = "beforeLoad"; + private static final String EVENT_AFTER_INSERT = "afterInsert"; + private static final String EVENT_AFTER_UPDATE = "afterUpdate"; + private static final String EVENT_AFTER_DELETE = "afterDelete"; + private static final String EVENT_AFTER_LOAD = "afterLoad"; private static final List REFRESH_EVENTS = Arrays.asList( EVENT_BEFORE_INSERT, EVENT_BEFORE_UPDATE, EVENT_BEFORE_DELETE); private final boolean autowireEntities; + private final Map> entityEvents = new ConcurrentHashMap>(); public DomainEventListener(final Datastore datastore) { super(datastore); @@ -74,15 +82,13 @@ public DomainEventListener(final Datastore datastore) { } datastore.getMappingContext().addMappingContextListener(this); - if(datastore instanceof ConnectionSourcesProvider) { - autowireEntities = ((ConnectionSourcesProvider)datastore).getConnectionSources().getDefaultConnectionSource().getSettings().isAutowire(); - } - else { + if (datastore instanceof ConnectionSourcesProvider) { + autowireEntities = ((ConnectionSourcesProvider) datastore).getConnectionSources().getDefaultConnectionSource().getSettings().isAutowire(); + } else { autowireEntities = false; } } - protected DomainEventListener(ConnectionSourcesProvider connectionSourcesProvider, final MappingContext mappingContext) { super(null); @@ -93,12 +99,11 @@ protected DomainEventListener(ConnectionSourcesProvider connectionSourcesProvide mappingContext.addMappingContextListener(this); } - @Override protected void onPersistenceEvent(final AbstractPersistenceEvent event) { - switch(event.getEventType()) { + switch (event.getEventType()) { case PreInsert: - if( !beforeInsert(event.getEntity(), event.getEntityAccess(), (PreInsertEvent) event) ) { + if (!beforeInsert(event.getEntity(), event.getEntityAccess(), (PreInsertEvent) event)) { event.cancel(); } break; @@ -106,7 +111,7 @@ protected void onPersistenceEvent(final AbstractPersistenceEvent event) { afterInsert(event.getEntity(), event.getEntityAccess(), (PostInsertEvent) event); break; case PreUpdate: - if( !beforeUpdate(event.getEntity(), event.getEntityAccess(), (PreUpdateEvent) event) ) { + if (!beforeUpdate(event.getEntity(), event.getEntityAccess(), (PreUpdateEvent) event)) { event.cancel(); } break; @@ -114,7 +119,7 @@ protected void onPersistenceEvent(final AbstractPersistenceEvent event) { afterUpdate(event.getEntity(), event.getEntityAccess(), (PostUpdateEvent) event); break; case PreDelete: - if( ! beforeDelete(event.getEntity(), event.getEntityAccess(), (PreDeleteEvent) event) ) { + if (!beforeDelete(event.getEntity(), event.getEntityAccess(), (PreDeleteEvent) event)) { event.cancel(); } break; @@ -149,24 +154,21 @@ public boolean beforeInsert(final PersistentEntity entity, final EntityAccess ea if (entity.isVersioned()) { try { setVersion(ea); - } - catch (RuntimeException e) { + } catch (RuntimeException e) { // TODO } } return invokeEvent(EVENT_BEFORE_INSERT, entity, ea, event); - } + } protected void setVersion(final EntityAccess ea) { final Class versionType = ea.getPersistentEntity().getVersion().getType(); if (Number.class.isAssignableFrom(versionType)) { ea.setProperty(GormProperties.VERSION, 0); - } - else if (Timestamp.class.isAssignableFrom(versionType)) { + } else if (Timestamp.class.isAssignableFrom(versionType)) { ea.setProperty(GormProperties.VERSION, new Timestamp(System.currentTimeMillis())); - } - else if (Date.class.isAssignableFrom(versionType)) { + } else if (Date.class.isAssignableFrom(versionType)) { ea.setProperty(GormProperties.VERSION, new Date()); } } @@ -177,7 +179,7 @@ public boolean beforeUpdate(final PersistentEntity entity, final EntityAccess ea public boolean beforeUpdate(final PersistentEntity entity, final EntityAccess ea, PreUpdateEvent event) { return invokeEvent(EVENT_BEFORE_UPDATE, entity, ea, event); - } + } public boolean beforeDelete(final PersistentEntity entity, final EntityAccess ea) { return invokeEvent(EVENT_BEFORE_DELETE, entity, ea, null); @@ -185,7 +187,7 @@ public boolean beforeDelete(final PersistentEntity entity, final EntityAccess ea public boolean beforeDelete(final PersistentEntity entity, final EntityAccess ea, PreDeleteEvent event) { return invokeEvent(EVENT_BEFORE_DELETE, entity, ea, event); - } + } public void beforeLoad(final PersistentEntity entity, final EntityAccess ea) { beforeLoad(entity, ea, null); @@ -201,7 +203,7 @@ public void afterDelete(final PersistentEntity entity, final EntityAccess ea) { public void afterDelete(final PersistentEntity entity, final EntityAccess ea, PostDeleteEvent event) { invokeEvent(EVENT_AFTER_DELETE, entity, ea, event); - } + } public void afterInsert(final PersistentEntity entity, final EntityAccess ea) { afterInsert(entity, ea, null); @@ -214,7 +216,7 @@ public void afterInsert(final PersistentEntity entity, final EntityAccess ea, Po private void activateDirtyChecking(EntityAccess ea) { Object e = ea.getEntity(); - if(e instanceof DirtyCheckable) { + if (e instanceof DirtyCheckable) { ((DirtyCheckable) e).trackChanges(); } } @@ -234,7 +236,7 @@ public void afterLoad(final PersistentEntity entity, final EntityAccess ea) { public void afterLoad(final PersistentEntity entity, final EntityAccess ea, PostLoadEvent event) { activateDirtyChecking(ea); - if (autowireEntities || ( entity != null && entity.getMapping().getMappedForm().isAutowire() )) { + if (autowireEntities || (entity != null && entity.getMapping().getMappedForm().isAutowire())) { autowireBeanProperties(ea.getEntity()); } invokeEvent(EVENT_AFTER_LOAD, entity, ea, event); @@ -242,7 +244,7 @@ public void afterLoad(final PersistentEntity entity, final EntityAccess ea, Post protected void autowireBeanProperties(final Object entity) { ConfigurableApplicationContext applicationContext = datastore.getApplicationContext(); - if(applicationContext != null) { + if (applicationContext != null) { applicationContext.getAutowireCapableBeanFactory().autowireBeanProperties( entity, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false); } @@ -250,8 +252,9 @@ protected void autowireBeanProperties(final Object entity) { /** * {@inheritDoc} + * * @see org.grails.datastore.mapping.model.MappingContext.Listener#persistentEntityAdded( - * org.grails.datastore.mapping.model.PersistentEntity) + *org.grails.datastore.mapping.model.PersistentEntity) */ public void persistentEntityAdded(PersistentEntity entity) { createEventCaches(entity); @@ -259,8 +262,9 @@ public void persistentEntityAdded(PersistentEntity entity) { /** * {@inheritDoc} + * * @see org.springframework.context.event.SmartApplicationListener#supportsEventType( - * java.lang.Class) + *java.lang.Class) */ public boolean supportsEventType(Class eventType) { return AbstractPersistenceEvent.class.isAssignableFrom(eventType); @@ -277,23 +281,20 @@ private boolean invokeEvent(String eventName, PersistentEntity entity, EntityAcc return true; } - final Object result; - if(ea != null) { + if (ea != null) { final Object o = ea.getEntity(); if (eventMethod.getParameterTypes().length == 1) { result = ReflectionUtils.invokeMethod(eventMethod, o, event); - } - else { + } else { result = ReflectionUtils.invokeMethod(eventMethod, o); } - } - else { + } else { result = null; } - boolean booleanResult = (result instanceof Boolean) ? (Boolean)result : true; + boolean booleanResult = (result instanceof Boolean) ? (Boolean) result : true; if (booleanResult && REFRESH_EVENTS.contains(eventName)) { ea.refresh(); } @@ -308,11 +309,11 @@ private void createEventCaches(PersistentEntity entity) { findAndCacheEvent(EVENT_BEFORE_INSERT, javaClass, events); findAndCacheEvent(EVENT_BEFORE_UPDATE, javaClass, events); findAndCacheEvent(EVENT_BEFORE_DELETE, javaClass, events); - findAndCacheEvent(EVENT_BEFORE_LOAD, javaClass, events); - findAndCacheEvent(EVENT_AFTER_INSERT, javaClass, events); - findAndCacheEvent(EVENT_AFTER_UPDATE, javaClass, events); - findAndCacheEvent(EVENT_AFTER_DELETE, javaClass, events); - findAndCacheEvent(EVENT_AFTER_LOAD, javaClass, events); + findAndCacheEvent(EVENT_BEFORE_LOAD, javaClass, events); + findAndCacheEvent(EVENT_AFTER_INSERT, javaClass, events); + findAndCacheEvent(EVENT_AFTER_UPDATE, javaClass, events); + findAndCacheEvent(EVENT_AFTER_DELETE, javaClass, events); + findAndCacheEvent(EVENT_AFTER_LOAD, javaClass, events); } private void findAndCacheEvent(String event, Class javaClass, Map events) { diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFindByFinder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFindByFinder.java index aab25a7d63a..397690907bb 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFindByFinder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFindByFinder.java @@ -16,21 +16,21 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.finders; -import java.util.regex.Pattern; - import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.core.SessionCallback; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.query.Query; +import java.util.regex.Pattern; + public abstract class AbstractFindByFinder extends DynamicFinder { + public static final String OPERATOR_OR = "Or"; public static final String OPERATOR_AND = "And"; - public static final String[] OPERATORS = { OPERATOR_AND, OPERATOR_OR }; + public static final String[] OPERATORS = {OPERATOR_AND, OPERATOR_OR}; protected AbstractFindByFinder(Pattern pattern, Datastore datastore) { super(pattern, OPERATORS, datastore); @@ -81,8 +81,7 @@ protected Query buildQuery(DynamicFinderInvocation invocation, Class clazz, Q for (MethodExpression expression : invocation.getExpressions()) { query.add(disjunction, expression.createCriterion()); } - } - else { + } else { for (MethodExpression expression : invocation.getExpressions()) { query.add(expression.createCriterion()); } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFinder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFinder.java index 5c0347d891f..40d5cb613d0 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFinder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/AbstractFinder.java @@ -20,7 +20,6 @@ import grails.gorm.CriteriaBuilder; import groovy.lang.Closure; - import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.DatastoreUtils; import org.grails.datastore.mapping.core.SessionCallback; @@ -42,19 +41,17 @@ public AbstractFinder(final Datastore datastore) { } protected T execute(final SessionCallback callback) { - if(datastore != null) { + if (datastore != null) { return DatastoreUtils.execute(datastore, callback); - } - else { + } else { throw new IllegalStateException("Cannot execute session query in stateless mode"); } } protected void execute(final VoidSessionCallback callback) { - if(datastore != null) { + if (datastore != null) { DatastoreUtils.execute(datastore, callback); - } - else { + } else { throw new IllegalStateException("Cannot execute session query in stateless mode"); } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/CountByFinder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/CountByFinder.java index b07eefaf7a8..d74fc3564dc 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/CountByFinder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/CountByFinder.java @@ -18,14 +18,14 @@ */ package org.grails.datastore.gorm.finders; -import java.util.regex.Pattern; - import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.core.SessionCallback; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.query.Query; +import java.util.regex.Pattern; + /** * Supports counting objects. For example Book.countByTitle("The Stand") */ @@ -35,7 +35,7 @@ public class CountByFinder extends DynamicFinder implements QueryBuildingFinder private static final String OPERATOR_AND = "And"; private static final Pattern METHOD_PATTERN = Pattern.compile("(countBy)(\\w+)"); - private static final String[] OPERATORS = { OPERATOR_AND, OPERATOR_OR }; + private static final String[] OPERATORS = {OPERATOR_AND, OPERATOR_OR}; public CountByFinder(final Datastore datastore) { super(METHOD_PATTERN, OPERATORS, datastore); @@ -76,10 +76,9 @@ protected Query buildQuery(DynamicFinderInvocation invocation, Class clazz, Q for (MethodExpression expression : invocation.getExpressions()) { q.add(disjunction, expression.createCriterion()); } - } - else { + } else { for (MethodExpression expression : invocation.getExpressions()) { - q.add( expression.createCriterion() ); + q.add(expression.createCriterion()); } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/DynamicFinder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/DynamicFinder.java index 17bd93ca0bf..0f2154cf908 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/DynamicFinder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/DynamicFinder.java @@ -17,15 +17,8 @@ import grails.gorm.DetachedCriteria; import groovy.lang.Closure; import groovy.lang.MissingMethodException; - -import java.lang.reflect.Constructor; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import jakarta.persistence.FetchType; import jakarta.persistence.criteria.JoinType; - import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.grails.datastore.gorm.finders.MethodExpression.Between; import org.grails.datastore.gorm.finders.MethodExpression.Equal; @@ -33,7 +26,6 @@ import org.grails.datastore.gorm.finders.MethodExpression.GreaterThanEquals; import org.grails.datastore.gorm.finders.MethodExpression.Ilike; import org.grails.datastore.gorm.finders.MethodExpression.InList; -import org.grails.datastore.gorm.finders.MethodExpression.NotInList; import org.grails.datastore.gorm.finders.MethodExpression.InRange; import org.grails.datastore.gorm.finders.MethodExpression.IsEmpty; import org.grails.datastore.gorm.finders.MethodExpression.IsNotEmpty; @@ -43,6 +35,7 @@ import org.grails.datastore.gorm.finders.MethodExpression.LessThanEquals; import org.grails.datastore.gorm.finders.MethodExpression.Like; import org.grails.datastore.gorm.finders.MethodExpression.NotEqual; +import org.grails.datastore.gorm.finders.MethodExpression.NotInList; import org.grails.datastore.gorm.finders.MethodExpression.Rlike; import org.grails.datastore.gorm.query.criteria.AbstractDetachedCriteria; import org.grails.datastore.mapping.core.Datastore; @@ -57,6 +50,16 @@ import org.springframework.core.convert.ConversionException; import org.springframework.core.convert.ConversionService; import org.springframework.util.StringUtils; + +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * Abstract base class for dynamic finders. * @@ -80,40 +83,39 @@ public abstract class DynamicFinder extends AbstractFinder implements QueryBuild public static final String ARGUMENT_IGNORE_CASE = "ignoreCase"; public static final String ARGUMENT_CACHE = "cache"; public static final String ARGUMENT_LOCK = "lock"; - protected Pattern pattern; private static final String OPERATOR_OR = "Or"; private static final String OPERATOR_AND = "And"; private static final String[] DEFAULT_OPERATORS = {OPERATOR_AND, OPERATOR_OR}; - private Pattern[] operatorPatterns; - private String[] operators; - private static Pattern methodExpressinPattern; - - private static final Pattern[] defaultOperationPatterns; + private static final Pattern[] DEFAULT_OPERATION_PATTERNS; private static final Object[] EMPTY_OBJECT_ARRAY = {}; - private static final String NOT = "Not"; - private static final Map methodExpressions = new LinkedHashMap(); + private static final Map METHOD_EXPRESSIONS = new LinkedHashMap(); + protected final MappingContext mappingContext; + protected Pattern pattern; + + private Pattern[] operatorPatterns; + private String[] operators; static { - defaultOperationPatterns = new Pattern[2]; + DEFAULT_OPERATION_PATTERNS = new Pattern[2]; for (int i = 0; i < DEFAULT_OPERATORS.length; i++) { String defaultOperator = DEFAULT_OPERATORS[i]; - defaultOperationPatterns[i] = Pattern.compile("(\\w+)(" + defaultOperator + ")(\\p{Upper})(\\w+)"); + DEFAULT_OPERATION_PATTERNS[i] = Pattern.compile("(\\w+)(" + defaultOperator + ")(\\p{Upper})(\\w+)"); } // populate the default method expressions try { Class[] classes = { - Equal.class, NotEqual.class, NotInList.class, InList.class, InRange.class, Between.class, Like.class, Ilike.class, Rlike.class, - GreaterThanEquals.class, LessThanEquals.class, GreaterThan.class, - LessThan.class, IsNull.class, IsNotNull.class, IsEmpty.class, - IsEmpty.class, IsNotEmpty.class }; - Class[] constructorParamTypes = { Class.class, String.class }; + Equal.class, NotEqual.class, NotInList.class, InList.class, InRange.class, Between.class, Like.class, Ilike.class, Rlike.class, + GreaterThanEquals.class, LessThanEquals.class, GreaterThan.class, + LessThan.class, IsNull.class, IsNotNull.class, IsEmpty.class, + IsEmpty.class, IsNotEmpty.class}; + Class[] constructorParamTypes = {Class.class, String.class}; for (Class c : classes) { - methodExpressions.put(c.getSimpleName(), c.getConstructor(constructorParamTypes)); + METHOD_EXPRESSIONS.put(c.getSimpleName(), c.getConstructor(constructorParamTypes)); } } catch (SecurityException e) { // ignore @@ -150,7 +152,7 @@ protected DynamicFinder(final Pattern pattern, final String[] operators, final M */ public static void registerNewMethodExpression(Class methodExpression) { try { - methodExpressions.put(methodExpression.getSimpleName(), methodExpression.getConstructor( + METHOD_EXPRESSIONS.put(methodExpression.getSimpleName(), methodExpression.getConstructor( Class.class, String.class)); resetMethodExpressionPattern(); } catch (SecurityException e) { @@ -167,15 +169,15 @@ public static void registerNewMethodExpression(Class methodExpression) { /** * Builds a match specification that can be used to establish information about a dynamic finder compilation for the purposes of compilation etc. * - * @param prefix The dynamic finder prefix. For example 'findBy' - * @param methodName The full method name + * @param prefix The dynamic finder prefix. For example 'findBy' + * @param methodName The full method name * @param parameterCount The number of parameters * @return The match specification */ public static MatchSpec buildMatchSpec(String prefix, String methodName, int parameterCount) { - String methodPattern = "("+prefix+")([A-Z]\\w*)"; + String methodPattern = "(" + prefix + ")([A-Z]\\w*)"; Matcher matcher = Pattern.compile(methodPattern).matcher(methodName); - if(matcher.find()) { + if (matcher.find()) { int totalRequiredArguments = 0; List expressions = new ArrayList<>(); if (matcher.groupCount() == 2) { @@ -184,7 +186,7 @@ public static MatchSpec buildMatchSpec(String prefix, String methodName, int par boolean containsOperator = false; String[] queryParameters; for (int i = 0; i < DEFAULT_OPERATORS.length; i++) { - Matcher currentMatcher = defaultOperationPatterns[i].matcher(querySequence); + Matcher currentMatcher = DEFAULT_OPERATION_PATTERNS[i].matcher(querySequence); if (currentMatcher.find()) { containsOperator = true; operatorInUse = DEFAULT_OPERATORS[i]; @@ -204,10 +206,10 @@ public static MatchSpec buildMatchSpec(String prefix, String methodName, int par // otherwise there is only one expression if (!containsOperator && querySequence != null) { - MethodExpression solo =findMethodExpression(querySequence); + MethodExpression solo = findMethodExpression(querySequence); final int requiredArguments = solo.getArgumentsRequired(); - if (requiredArguments > parameterCount) { + if (requiredArguments > parameterCount) { return null; } @@ -219,9 +221,8 @@ public static MatchSpec buildMatchSpec(String prefix, String methodName, int par // return null if (totalRequiredArguments > parameterCount) { return null; - } - else { - return new MatchSpec(methodName,prefix, querySequence, totalRequiredArguments, expressions); + } else { + return new MatchSpec(methodName, prefix, querySequence, totalRequiredArguments, expressions); } } } @@ -239,6 +240,7 @@ public void setPattern(String pattern) { /** * Checks whether the given method is a match + * * @param methodName The method name * @return True if it is */ @@ -246,7 +248,6 @@ public boolean isMethodMatch(String methodName) { return pattern.matcher(methodName.subSequence(0, methodName.length())).find(); } - public Object invoke(final Class clazz, String methodName, Closure additionalCriteria, Object[] arguments) { DynamicFinderInvocation invocation = createFinderInvocation(clazz, methodName, additionalCriteria, arguments); return doInvokeInternal(invocation); @@ -254,20 +255,21 @@ public Object invoke(final Class clazz, String methodName, Closure additionalCri public Object invoke(final Class clazz, String methodName, DetachedCriteria detachedCriteria, Object[] arguments) { DynamicFinderInvocation invocation = createFinderInvocation(clazz, methodName, null, arguments); - if (detachedCriteria != null ) { + if (detachedCriteria != null) { invocation.setDetachedCriteria(detachedCriteria); } return doInvokeInternal(invocation); } public DynamicFinderInvocation createFinderInvocation(Class clazz, String methodName, - Closure additionalCriteria, Object[] arguments) { + Closure additionalCriteria, Object[] arguments) { List expressions = new ArrayList(); - if (arguments == null) arguments = EMPTY_OBJECT_ARRAY; - else { + if (arguments == null) { + arguments = EMPTY_OBJECT_ARRAY; + } else { Object[] tmp = new Object[arguments.length]; - System.arraycopy(arguments,0,tmp, 0, arguments.length); + System.arraycopy(arguments, 0, tmp, 0, arguments.length); arguments = tmp; } Matcher match = pattern.matcher(methodName); @@ -284,8 +286,7 @@ public DynamicFinderInvocation createFinderInvocation(Class clazz, String method if (booleanProperty == null) { booleanProperty = match.group(6); querySequence = null; - } - else { + } else { querySequence = match.group(5); } Boolean arg = Boolean.TRUE; @@ -296,8 +297,7 @@ public DynamicFinderInvocation createFinderInvocation(Class clazz, String method MethodExpression booleanExpression = findMethodExpression(clazz, booleanProperty); booleanExpression.setArguments(new Object[]{arg}); expressions.add(booleanExpression); - } - else { + } else { querySequence = match.group(2); } // if it contains operator and split @@ -346,11 +346,11 @@ public DynamicFinderInvocation createFinderInvocation(Class clazz, String method } // otherwise there is only one expression if (!containsOperator && querySequence != null) { - MethodExpression solo =findMethodExpression(clazz,querySequence); + MethodExpression solo = findMethodExpression(clazz, querySequence); final int requiredArguments = solo.getArgumentsRequired(); - if (requiredArguments > arguments.length) { - throw new MissingMethodException(methodName,clazz,arguments); + if (requiredArguments > arguments.length) { + throw new MissingMethodException(methodName, clazz, arguments); } totalRequiredArguments += requiredArguments; @@ -371,13 +371,13 @@ public DynamicFinderInvocation createFinderInvocation(Class clazz, String method // if the total of all the arguments necessary does not equal the number of arguments // throw exception if (totalRequiredArguments > arguments.length) { - throw new MissingMethodException(methodName,clazz,arguments); + throw new MissingMethodException(methodName, clazz, arguments); } // calculate the remaining arguments Object[] remainingArguments = new Object[arguments.length - totalRequiredArguments]; if (remainingArguments.length > 0) { - for (int i = 0, j = totalRequiredArguments; i < remainingArguments.length; i++,j++) { + for (int i = 0, j = totalRequiredArguments; i < remainingArguments.length; i++, j++) { remainingArguments[i] = arguments[j]; } } @@ -387,32 +387,32 @@ public DynamicFinderInvocation createFinderInvocation(Class clazz, String method } public Object invoke(final Class clazz, String methodName, Object[] arguments) { - return invoke(clazz, methodName, (Closure)null, arguments); + return invoke(clazz, methodName, (Closure) null, arguments); } /** * Populates arguments for the given query form the given map - * @param query The query + * + * @param query The query * @param argMap The query arguments */ public static void populateArgumentsForCriteria(BuildableCriteria query, Map argMap) { if (argMap == null) { return; } - String orderParam = (String)argMap.get(ARGUMENT_ORDER); + String orderParam = (String) argMap.get(ARGUMENT_ORDER); Object fetchObj = argMap.get(ARGUMENT_FETCH); if (fetchObj instanceof Map) { - Map fetch = (Map)fetchObj; + Map fetch = (Map) fetchObj; for (Object o : fetch.keySet()) { String associationName = (String) o; Object fetchValue = fetch.get(associationName); - if(fetchValue instanceof FetchType) { - FetchType fetchType = (FetchType)fetchValue; + if (fetchValue instanceof FetchType) { + FetchType fetchType = (FetchType) fetchValue; handleFetchType(query, associationName, fetchType); - } - else if(fetchValue instanceof JoinType) { - JoinType joinType = (JoinType)fetchValue; + } else if (fetchValue instanceof JoinType) { + JoinType joinType = (JoinType) fetchValue; query.join(associationName, joinType); } else { FetchType fetchType = getFetchMode(fetchValue); @@ -421,30 +421,28 @@ else if(fetchValue instanceof JoinType) { } } - if(argMap.containsKey(ARGUMENT_CACHE)) { + if (argMap.containsKey(ARGUMENT_CACHE)) { query.cache(ClassUtils.getBooleanFromMap(ARGUMENT_CACHE, argMap)); } Object sortObject = argMap.get(ARGUMENT_SORT); boolean ignoreCase = !argMap.containsKey(ARGUMENT_IGNORE_CASE) || ClassUtils.getBooleanFromMap(ARGUMENT_IGNORE_CASE, argMap); - if (sortObject != null) { - if(sortObject instanceof CharSequence) { + if (sortObject instanceof CharSequence) { final String sort = sortObject.toString(); final Query.Order order = ORDER_DESC.equalsIgnoreCase(orderParam) ? Query.Order.desc(sort) : Query.Order.asc(sort); - if(ignoreCase) { + if (ignoreCase) { order.ignoreCase(); } query.order(order); - } - else if(sortObject instanceof Map) { - Map sortMap = (Map)sortObject; + } else if (sortObject instanceof Map) { + Map sortMap = (Map) sortObject; for (Object key : sortMap.keySet()) { Object value = sortMap.get(key); String sort = key.toString(); final Query.Order order = ORDER_DESC.equalsIgnoreCase(orderParam) ? Query.Order.desc(sort) : Query.Order.asc(sort); - if(ignoreCase) { + if (ignoreCase) { order.ignoreCase(); } query.order(order); @@ -453,15 +451,15 @@ else if(sortObject instanceof Map) { } } - if (query instanceof QueryArgumentsAware) { - ((QueryArgumentsAware)query).setArguments(argMap); + ((QueryArgumentsAware) query).setArguments(argMap); } } /** * Populates arguments for the given query form the given map - * @param query The query + * + * @param query The query * @param argMap The query arguments */ //TODO: Change {code}Class{code} to {class} once GROOVY-9460 is fixed. @@ -479,20 +477,19 @@ public static void populateArgumentsForCriteria(Class targetCl if (argMap.containsKey(ARGUMENT_OFFSET)) { offsetParam = conversionService.convert(argMap.get(ARGUMENT_OFFSET), Integer.class); } - String orderParam = (String)argMap.get(ARGUMENT_ORDER); + String orderParam = (String) argMap.get(ARGUMENT_ORDER); Object fetchObj = argMap.get(ARGUMENT_FETCH); if (fetchObj instanceof Map) { - Map fetch = (Map)fetchObj; + Map fetch = (Map) fetchObj; for (Object o : fetch.keySet()) { String associationName = (String) o; Object fetchValue = fetch.get(associationName); - if(fetchValue instanceof FetchType) { - FetchType fetchType = (FetchType)fetchValue; + if (fetchValue instanceof FetchType) { + FetchType fetchType = (FetchType) fetchValue; handleFetchType(query, associationName, fetchType); - } - else if(fetchValue instanceof JoinType) { - JoinType joinType = (JoinType)fetchValue; + } else if (fetchValue instanceof JoinType) { + JoinType joinType = (JoinType) fetchValue; query.join(associationName, joinType); } else { FetchType fetchType = getFetchMode(fetchValue); @@ -501,10 +498,10 @@ else if(fetchValue instanceof JoinType) { } } - if(argMap.containsKey(ARGUMENT_CACHE)) { + if (argMap.containsKey(ARGUMENT_CACHE)) { query.cache(ClassUtils.getBooleanFromMap(ARGUMENT_CACHE, argMap)); } - if(argMap.containsKey(ARGUMENT_LOCK)) { + if (argMap.containsKey(ARGUMENT_LOCK)) { query.lock(ClassUtils.getBooleanFromMap(ARGUMENT_LOCK, argMap)); } @@ -520,27 +517,27 @@ else if(fetchValue instanceof JoinType) { boolean ignoreCase = !argMap.containsKey(ARGUMENT_IGNORE_CASE) || ClassUtils.getBooleanFromMap(ARGUMENT_IGNORE_CASE, argMap); if (sortObject != null) { - if(sortObject instanceof CharSequence) { + if (sortObject instanceof CharSequence) { final String sort = sortObject.toString(); final String order = ORDER_DESC.equalsIgnoreCase(orderParam) ? ORDER_DESC : ORDER_ASC; addSimpleSort(query, sort, order, ignoreCase); - } - else if(sortObject instanceof Map) { - Map sortMap = (Map)sortObject; + } else if (sortObject instanceof Map) { + Map sortMap = (Map) sortObject; applySortForMap(query, sortMap, ignoreCase); } } if (query instanceof QueryArgumentsAware) { - ((QueryArgumentsAware)query).setArguments(argMap); + ((QueryArgumentsAware) query).setArguments(argMap); } } /** * Applies sorting logic to the given query from the given map - * @param query The query - * @param sortMap The sort map + * + * @param query The query + * @param sortMap The sort map * @param ignoreCase Whether toi ignore case */ public static void applySortForMap(Query query, Map sortMap, boolean ignoreCase) { @@ -573,7 +570,7 @@ public static FetchType getFetchMode(Object object) { /** * Applies the given detached criteria to the given query * - * @param query The query + * @param query The query * @param detachedCriteria The detached criteria */ public static void applyDetachedCriteria(Query query, AbstractDetachedCriteria detachedCriteria) { @@ -581,18 +578,21 @@ public static void applyDetachedCriteria(Query query, AbstractDetachedCriteria d Map fetchStrategies = detachedCriteria.getFetchStrategies(); for (Map.Entry entry : fetchStrategies.entrySet()) { String property = entry.getKey(); - switch(entry.getValue()) { + switch (entry.getValue()) { case EAGER: JoinType joinType = (JoinType) detachedCriteria.getJoinTypes().get(property); - if(joinType != null) { + if (joinType != null) { query.join(property, joinType); - } - else { + } else { query.join(property); } break; case LAZY: query.select(property); + break; + default: + // do nothing + break; } } List criteria = detachedCriteria.getCriteria(); @@ -612,14 +612,16 @@ public static void applyDetachedCriteria(Query query, AbstractDetachedCriteria d protected abstract Object doInvokeInternal(DynamicFinderInvocation invocation); - private static void handleFetchType(Query q, String associationName, FetchType fetchType) { - switch(fetchType) { + switch (fetchType) { case LAZY: q.select(associationName); break; case EAGER: q.join(associationName); + break; + default: + // do nothing } } @@ -639,8 +641,8 @@ private static MethodExpression findMethodExpressionInternal(final Class clazz, String clause = methodExpressionClass.getSimpleName(); if (matcher.find()) { clause = matcher.group(1); - methodExpressionConstructor = methodExpressions.get(clause); - if(methodExpressionConstructor != null) { + methodExpressionConstructor = METHOD_EXPRESSIONS.get(clause); + if (methodExpressionConstructor != null) { methodExpressionClass = methodExpressionConstructor.getDeclaringClass(); } } @@ -658,7 +660,7 @@ private static MethodExpression findMethodExpressionInternal(final Class clazz, } propertyName = NameUtils.decapitalizeFirstChar(propertyName); - if(methodExpressionConstructor != null) { + if (methodExpressionConstructor != null) { try { me = (MethodExpression) methodExpressionConstructor.newInstance(clazz, propertyName); } catch (Exception e) { @@ -668,7 +670,7 @@ private static MethodExpression findMethodExpressionInternal(final Class clazz, if (me == null) { me = new Equal(clazz, propertyName); } - if(negation) { + if (negation) { final MethodExpression finalMe = me; return new MethodExpression(clazz, propertyName) { @Override @@ -696,17 +698,20 @@ public Object[] getArguments() { } private static void handleFetchType(BuildableCriteria q, String associationName, FetchType fetchType) { - switch(fetchType) { + switch (fetchType) { case LAZY: q.select(associationName); break; case EAGER: q.join(associationName); + break; + default: + // do nothing } } private static void resetMethodExpressionPattern() { - String expressionPattern = DefaultGroovyMethods.join((Iterable)methodExpressions.keySet(), "|"); + String expressionPattern = DefaultGroovyMethods.join((Iterable) METHOD_EXPRESSIONS.keySet(), "|"); methodExpressinPattern = Pattern.compile("\\p{Upper}[\\p{Lower}\\d]+(" + expressionPattern + ")"); } @@ -714,12 +719,13 @@ private static void addSimpleSort(Query q, String sort, String order, boolean ig Query.Order o; if (ORDER_DESC.equalsIgnoreCase(order)) { o = Query.Order.desc(sort); - } - else { + } else { o = Query.Order.asc(sort); } - if(ignoreCase) o = o.ignoreCase(); + if (ignoreCase) { + o = o.ignoreCase(); + } q.order(o); } @@ -736,18 +742,16 @@ protected void configureQueryWithArguments(Class clazz, Query query, Object[] ar return; } - Map argMap = (Map)arguments[0]; + Map argMap = (Map) arguments[0]; populateArgumentsForCriteria(clazz, query, argMap); } - private static String calcPropertyName(String queryParameter, String clause) { String propName; if (clause != null && !clause.equals(Equal.class.getSimpleName())) { int i = queryParameter.indexOf(clause); - propName = queryParameter.substring(0,i); - } - else { + propName = queryParameter.substring(0, i); + } else { propName = queryParameter; } @@ -760,7 +764,7 @@ private static String calcPropertyName(String queryParameter, String clause) { * and returned of type IsNull. * * @param expression expression to initialize - * @param arguments arguments to the expression + * @param arguments arguments to the expression * @return the initialized expression */ private MethodExpression getInitializedExpression(MethodExpression expression, Object[] arguments) { @@ -772,5 +776,4 @@ private MethodExpression getInitializedExpression(MethodExpression expression, O return expression; } - } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByBooleanFinder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByBooleanFinder.java index b4ee31bf69d..d30a834d671 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByBooleanFinder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByBooleanFinder.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.finders; import org.grails.datastore.mapping.core.Datastore; @@ -26,18 +25,20 @@ * The "findAll<booleanProperty>By*" static persistent method. This method allows querying for * instances of grails domain classes based on a boolean property and any other arbitrary * properties. - * + *

* eg. * Account.findAllActiveByHolder("Joe Blogs"); // Where class "Account" has a properties called "active" and "holder" * Account.findAllActiveByHolderAndBranch("Joe Blogs", "London"); // Where class "Account" has a properties called "active', "holder" and "branch" - * + *

* In both of those queries, the query will only select Account objects where active=true. * * @author Jeff Brown * @author Graeme Rocher */ -public class FindAllByBooleanFinder extends FindAllByFinder{ +public class FindAllByBooleanFinder extends FindAllByFinder { + public static final String METHOD_PATTERN = "(findAll)((\\w+)(By)([A-Z]\\w*)|(\\w+))"; + public FindAllByBooleanFinder(Datastore datastore) { super(datastore); setPattern(METHOD_PATTERN); diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByFinder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByFinder.java index abdeabe4abe..a4896af8c70 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByFinder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindAllByFinder.java @@ -18,14 +18,14 @@ */ package org.grails.datastore.gorm.finders; -import java.util.regex.Pattern; - import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.core.SessionCallback; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.query.Query; +import java.util.regex.Pattern; + /** * Finder used to return multiple results. Eg. Book.findAllBy..(..) */ @@ -34,7 +34,7 @@ public class FindAllByFinder extends DynamicFinder { private static final String OPERATOR_OR = "Or"; private static final String OPERATOR_AND = "And"; private static final String METHOD_PATTERN = "(findAllBy)([A-Z]\\w*)"; - private static final String[] OPERATORS = { OPERATOR_AND, OPERATOR_OR }; + private static final String[] OPERATORS = {OPERATOR_AND, OPERATOR_OR}; public FindAllByFinder(final Datastore datastore) { super(Pattern.compile(METHOD_PATTERN), OPERATORS, datastore); @@ -84,10 +84,9 @@ protected Query buildQuery(DynamicFinderInvocation invocation, Class clazz, Q for (MethodExpression expression : invocation.getExpressions()) { query.add(disjunction, expression.createCriterion()); } - } - else { + } else { for (MethodExpression expression : invocation.getExpressions()) { - query.add( expression.createCriterion() ); + query.add(expression.createCriterion()); } } query.projections().distinct(); diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindByBooleanFinder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindByBooleanFinder.java index 023f016e802..61caad08a3c 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindByBooleanFinder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindByBooleanFinder.java @@ -22,7 +22,7 @@ import org.grails.datastore.mapping.model.MappingContext; /** - * + * *

The "find<booleanProperty>By*" static persistent method. This method allows querying for * instances of grails domain classes based on a boolean property and any other arbitrary * properties. This method returns the first result of the query.

@@ -40,7 +40,8 @@ * @author Graeme Rocher * @author Jeff Brown */ -public class FindByBooleanFinder extends FindByFinder{ +public class FindByBooleanFinder extends FindByFinder { + public static final String METHOD_PATTERN = "(find)((\\w+)(By)([A-Z]\\w*)|(\\w++))"; public FindByBooleanFinder(Datastore datastore) { diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindByFinder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindByFinder.java index 5e8ee5cf614..19659433418 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindByFinder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindByFinder.java @@ -18,11 +18,11 @@ */ package org.grails.datastore.gorm.finders; -import java.util.regex.Pattern; - import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.model.MappingContext; +import java.util.regex.Pattern; + /** * Finder used to return a single result */ diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindOrCreateByFinder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindOrCreateByFinder.java index aaa7647bae9..dd6d999c788 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindOrCreateByFinder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindOrCreateByFinder.java @@ -21,16 +21,15 @@ import groovy.lang.GroovySystem; import groovy.lang.MetaClass; import groovy.lang.MissingMethodException; +import org.grails.datastore.mapping.core.Datastore; +import org.grails.datastore.mapping.model.MappingContext; +import org.springframework.core.convert.ConversionException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.model.MappingContext; -import org.springframework.core.convert.ConversionException; - /** * Finder used to return a single result */ @@ -46,7 +45,6 @@ public FindOrCreateByFinder(final Datastore datastore) { this(METHOD_PATTERN, datastore); } - public FindOrCreateByFinder(MappingContext mappingContext) { super(Pattern.compile(METHOD_PATTERN), mappingContext); } @@ -55,7 +53,6 @@ public FindOrCreateByFinder(final String methodPattern, MappingContext mappingCo super(Pattern.compile(methodPattern), mappingContext); } - @Override @SuppressWarnings({"rawtypes", "unchecked"}) protected Object doInvokeInternal(final DynamicFinderInvocation invocation) { diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindOrSaveByFinder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindOrSaveByFinder.java index 2459b1a3b31..04039d4940b 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindOrSaveByFinder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FindOrSaveByFinder.java @@ -21,14 +21,13 @@ import groovy.lang.GroovySystem; import groovy.lang.MetaClass; import groovy.lang.MissingMethodException; +import org.grails.datastore.mapping.core.Datastore; +import org.grails.datastore.mapping.model.MappingContext; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.model.MappingContext; - public class FindOrSaveByFinder extends FindOrCreateByFinder { public static final String METHOD_PATTERN = "(findOrSaveBy)([A-Z]\\w*)"; diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FinderMethod.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FinderMethod.java index 015216fca74..779be5026a7 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FinderMethod.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/FinderMethod.java @@ -33,25 +33,28 @@ public interface FinderMethod { /** * Invokes the method - * @param clazz The class + * + * @param clazz The class * @param methodName The method name - * @param arguments The arguments + * @param arguments The arguments * @return The return value */ Object invoke(Class clazz, String methodName, Object[] arguments); /** * Invokes the method - * @param clazz The class - * @param methodName The method name + * + * @param clazz The class + * @param methodName The method name * @param additionalCriteria additional criteria closure - * @param arguments The arguments + * @param arguments The arguments * @return The return value */ Object invoke(Class clazz, String methodName, Closure additionalCriteria, Object[] arguments); /** * Whether the given method name matches this finder + * * @param methodName The method name * @return true if it does */ diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/ListOrderByFinder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/ListOrderByFinder.java index 6bc095db804..8316216a178 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/ListOrderByFinder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/ListOrderByFinder.java @@ -19,21 +19,20 @@ package org.grails.datastore.gorm.finders; import groovy.lang.Closure; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.core.SessionCallback; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.reflect.NameUtils; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * The "listOrderBy*" static persistent method. Allows ordered listing of instances based on their properties. - * + *

* eg. * Account.listOrderByHolder(); * Account.listOrderByHolder(max); // max results @@ -41,6 +40,7 @@ * @author Graeme Rocher */ public class ListOrderByFinder extends AbstractFinder { + private static final Pattern METHOD_PATTERN = Pattern.compile("(listOrderBy)(\\w+)"); private Pattern pattern = METHOD_PATTERN; @@ -73,15 +73,15 @@ public Object doInSession(final Session session) { boolean ascending = true; if (arguments.length > 0 && (arguments[0] instanceof Map)) { - final Map args = new LinkedHashMap( (Map) arguments[0] ); + final Map args = new LinkedHashMap((Map) arguments[0]); final Object order = args.remove(DynamicFinder.ARGUMENT_ORDER); - if(order != null && "desc".equalsIgnoreCase(order.toString())) { + if (order != null && "desc".equalsIgnoreCase(order.toString())) { ascending = false; } DynamicFinder.populateArgumentsForCriteria(clazz, q, args); } - q.order( ascending ? Query.Order.asc(propertyName) : Query.Order.desc(propertyName)); + q.order(ascending ? Query.Order.asc(propertyName) : Query.Order.desc(propertyName)); q.projections().distinct(); return invokeQuery(q); } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/MatchSpec.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/MatchSpec.groovy index 8c73f0ff5ba..ea2b9bf9b48 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/MatchSpec.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/MatchSpec.groovy @@ -20,7 +20,6 @@ package org.grails.datastore.gorm.finders import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.expr.MethodCallExpression /** * A match spec details a matched finder diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/MethodExpression.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/MethodExpression.java index 549d7dae76d..bdeaf0dcd6c 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/MethodExpression.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/MethodExpression.java @@ -19,9 +19,6 @@ package org.grails.datastore.gorm.finders; import groovy.lang.Range; - -import java.util.*; - import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.query.Query; @@ -31,8 +28,14 @@ import org.springframework.core.convert.TypeDescriptor; import org.springframework.util.Assert; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + /** - * Method expression used to evaluate a dynamic finder. + * Method expression used to evaluate a dynamic finder. */ public abstract class MethodExpression { @@ -40,13 +43,11 @@ public abstract class MethodExpression { protected Object[] arguments; protected int argumentsRequired = 1; /** - * @deprecated Do not use + * @deprecated Do not use */ @Deprecated protected Class targetClass; - public abstract Query.Criterion createCriterion(); - protected MethodExpression(Class targetClass, String propertyName) { this.propertyName = propertyName; } @@ -55,6 +56,8 @@ protected MethodExpression(String propertyName) { this.propertyName = propertyName; } + public abstract Query.Criterion createCriterion(); + public int getArgumentsRequired() { return argumentsRequired; } @@ -75,10 +78,10 @@ public void convertArguments(PersistentEntity persistentEntity) { Object arg = arguments[i]; if (arg != null && !type.isAssignableFrom(arg.getClass())) { // Add special handling for GStringImpl - if(arg instanceof CharSequence && arg.getClass() != String.class) { + if (arg instanceof CharSequence && arg.getClass() != String.class) { arg = arg.toString(); arguments[i] = arg; - if(type.isAssignableFrom(arg.getClass())) { + if (type.isAssignableFrom(arg.getClass())) { break; } } @@ -87,7 +90,7 @@ public void convertArguments(PersistentEntity persistentEntity) { // skip converting argument to collection/array type if argument is correct instance of element type break; } - if(conversionService.canConvert(arg.getClass(), type)) { + if (conversionService.canConvert(arg.getClass(), type)) { arguments[i] = conversionService.convert(arg, type); } } @@ -107,7 +110,33 @@ public String getPropertyName() { return propertyName; } + private static void convertArgumentsForProp(PersistentEntity persistentEntity, PersistentProperty prop, String propertyName, Object[] arguments, ConversionService conversionService) { + if (prop == null) { + if (propertyName.equals(persistentEntity.getIdentity().getName())) { + prop = persistentEntity.getIdentity(); + } + } + if (prop != null) { + Class type = prop.getType(); + Collection collection = (Collection) arguments[0]; + List converted; + if (collection == null) { + converted = Collections.emptyList(); + } else { + converted = new ArrayList<>(collection.size()); + for (Object o : collection) { + if (o != null && !type.isAssignableFrom(o.getClass())) { + o = conversionService.convert(o, type); + } + converted.add(o); + } + } + arguments[0] = converted; + } + } + public static class GreaterThan extends MethodExpression { + public GreaterThan(Class targetClass, String propertyName) { super(targetClass, propertyName); } @@ -123,6 +152,7 @@ public Query.Criterion createCriterion() { } public static class GreaterThanEquals extends MethodExpression { + public GreaterThanEquals(Class targetClass, String propertyName) { super(targetClass, propertyName); } @@ -138,6 +168,7 @@ public Query.Criterion createCriterion() { } public static class LessThan extends MethodExpression { + public LessThan(Class targetClass, String propertyName) { super(targetClass, propertyName); } @@ -153,6 +184,7 @@ public Query.Criterion createCriterion() { } public static class LessThanEquals extends MethodExpression { + public LessThanEquals(Class targetClass, String propertyName) { super(targetClass, propertyName); } @@ -168,6 +200,7 @@ public Query.Criterion createCriterion() { } public static class Like extends MethodExpression { + public Like(Class targetClass, String propertyName) { super(targetClass, propertyName); } @@ -183,6 +216,7 @@ public Query.Criterion createCriterion() { } public static class Ilike extends MethodExpression { + public Ilike(Class targetClass, String propertyName) { super(targetClass, propertyName); } @@ -198,6 +232,7 @@ public Query.Criterion createCriterion() { } public static class Rlike extends MethodExpression { + public Rlike(Class targetClass, String propertyName) { super(targetClass, propertyName); } @@ -213,6 +248,7 @@ public Query.Criterion createCriterion() { } public static class NotInList extends MethodExpression { + public NotInList(Class targetClass, String propertyName) { super(targetClass, propertyName); } @@ -234,7 +270,7 @@ public void setArguments(Object[] arguments) { "Only a collection of elements is supported in an 'in' query"); Object arg = arguments[0]; - Assert.isTrue( (arg instanceof Collection) || arg == null, "Only a collection of elements is supported in an 'in' query"); + Assert.isTrue((arg instanceof Collection) || arg == null, "Only a collection of elements is supported in an 'in' query"); super.setArguments(arguments); } @@ -256,6 +292,7 @@ public static class InList extends MethodExpression { public InList(Class targetClass, String propertyName) { super(targetClass, propertyName); } + public InList(String propertyName) { super(propertyName); } @@ -268,10 +305,10 @@ public Query.Criterion createCriterion() { @Override public void setArguments(Object[] arguments) { Assert.isTrue(arguments.length > 0, - "Only a collection of elements is supported in an 'in' query"); + "Only a collection of elements is supported in an 'in' query"); Object arg = arguments[0]; - Assert.isTrue( (arg instanceof Collection) || arg == null, "Only a collection of elements is supported in an 'in' query"); + Assert.isTrue((arg instanceof Collection) || arg == null, "Only a collection of elements is supported in an 'in' query"); super.setArguments(arguments); } @@ -286,12 +323,14 @@ public void convertArguments(PersistentEntity persistentEntity) { } } + public static class Between extends MethodExpression { public Between(Class targetClass, String propertyName) { super(targetClass, propertyName); argumentsRequired = 2; } + public Between(String propertyName) { super(propertyName); argumentsRequired = 2; @@ -306,18 +345,20 @@ public Query.Criterion createCriterion() { public void setArguments(Object[] arguments) { Assert.isTrue(arguments.length > 1, "A 'between' query requires at least two arguments"); Assert.isTrue(arguments[0] instanceof Comparable && arguments[1] instanceof Comparable, - "A 'between' query requires that both arguments are comparable"); + "A 'between' query requires that both arguments are comparable"); super.setArguments(arguments); } } + public static class InRange extends MethodExpression { public InRange(Class targetClass, String propertyName) { super(targetClass, propertyName); argumentsRequired = 1; } + public InRange(String propertyName) { super(propertyName); argumentsRequired = 1; @@ -344,12 +385,14 @@ public void setArguments(Object[] arguments) { } } + public static class IsNull extends MethodExpression { public IsNull(Class targetClass, String propertyName) { super(targetClass, propertyName); argumentsRequired = 0; } + public IsNull(String propertyName) { super(propertyName); argumentsRequired = 0; @@ -361,6 +404,7 @@ public Criterion createCriterion() { } } + public static class IsNotNull extends MethodExpression { public IsNotNull(Class targetClass, String propertyName) { @@ -379,12 +423,14 @@ public Criterion createCriterion() { } } + public static class IsEmpty extends MethodExpression { public IsEmpty(Class targetClass, String propertyName) { super(targetClass, propertyName); argumentsRequired = 0; } + public IsEmpty(String propertyName) { super(propertyName); argumentsRequired = 0; @@ -396,6 +442,7 @@ public Criterion createCriterion() { } } + public static class IsNotEmpty extends MethodExpression { public IsNotEmpty(Class targetClass, String propertyName) { @@ -413,13 +460,14 @@ public Criterion createCriterion() { return Restrictions.isNotEmpty(propertyName); } - } + public static class Equal extends MethodExpression { public Equal(Class targetClass, String propertyName) { super(targetClass, propertyName); } + public Equal(String propertyName) { super(propertyName); } @@ -435,11 +483,13 @@ public Query.Criterion createCriterion() { } } + public static class NotEqual extends MethodExpression { public NotEqual(Class targetClass, String propertyName) { super(targetClass, propertyName); } + public NotEqual(String propertyName) { super(propertyName); } @@ -455,29 +505,4 @@ public Query.Criterion createCriterion() { } } - private static void convertArgumentsForProp(PersistentEntity persistentEntity, PersistentProperty prop, String propertyName, Object[] arguments, ConversionService conversionService) { - if (prop == null) { - if (propertyName.equals(persistentEntity.getIdentity().getName())) { - prop = persistentEntity.getIdentity(); - } - } - if (prop != null) { - Class type = prop.getType(); - Collection collection = (Collection) arguments[0]; - List converted; - if(collection == null) { - converted = Collections.emptyList(); - } - else { - converted = new ArrayList<>(collection.size()); - for (Object o : collection) { - if (o != null && !type.isAssignableFrom(o.getClass())) { - o = conversionService.convert(o, type); - } - converted.add(o); - } - } - arguments[0] = converted; - } - } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/QueryBuildingFinder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/QueryBuildingFinder.java index 1806a1e93f2..b2554710a8a 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/QueryBuildingFinder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/QueryBuildingFinder.java @@ -31,8 +31,9 @@ public interface QueryBuildingFinder { /** * Build a query from an invocation + * * @param invocation The invocation - * @param session an active session + * @param session an active session * @return The query */ Query buildQuery(DynamicFinderInvocation invocation, Session session); diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/InstanceMethodInvokingClosure.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/InstanceMethodInvokingClosure.groovy index b5fe4a8df04..bcf0edfdf1f 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/InstanceMethodInvokingClosure.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/InstanceMethodInvokingClosure.groovy @@ -16,13 +16,13 @@ package org.grails.datastore.gorm.internal import groovy.transform.CompileStatic - /** * Not public API. Used by GormEnhancer */ @SuppressWarnings("rawtypes") @CompileStatic class InstanceMethodInvokingClosure extends MethodInvokingClosure { + InstanceMethodInvokingClosure(apiDelegate, Class persistentClass, String methodName, Class[] parameterTypes) { super(apiDelegate, methodName, parameterTypes) List params = parameterTypes.toList() @@ -36,13 +36,12 @@ class InstanceMethodInvokingClosure extends MethodInvokingClosure { Object call(Object[] args) { def delegateArg = Collections.singletonList(delegate).toArray() Object[] arguments - if(args) { + if (args) { def argList = [] argList.add(delegate) argList.addAll(Arrays.asList(args)) arguments = argList.toArray() - } - else { + } else { arguments = delegateArg } metaMethod.invoke(apiDelegate, arguments) diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/MethodInvokingClosure.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/MethodInvokingClosure.groovy index dfdadad7bc8..9c2519ecec8 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/MethodInvokingClosure.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/MethodInvokingClosure.groovy @@ -15,7 +15,6 @@ package org.grails.datastore.gorm.internal import groovy.transform.CompileStatic - import org.codehaus.groovy.runtime.metaclass.MethodSelectionException /** @@ -24,11 +23,12 @@ import org.codehaus.groovy.runtime.metaclass.MethodSelectionException @SuppressWarnings("rawtypes") @CompileStatic abstract class MethodInvokingClosure extends Closure { + protected String methodName protected apiDelegate protected Class[] parameterTypes protected MetaMethod metaMethod - + MethodInvokingClosure(apiDelegate, String methodName, Class[] parameterTypes) { super(apiDelegate, apiDelegate) this.apiDelegate = apiDelegate @@ -50,11 +50,11 @@ abstract class MethodInvokingClosure extends Closure { int getMaximumNumberOfParameters() { parameterTypes.length } - + /** * Utility method for choosing matching metamethod, handles MethodSelectionException - * - * + * + * * @param theMetaClass * @param methodName * @param parameterTypes @@ -67,7 +67,7 @@ abstract class MethodInvokingClosure extends Closure { } catch (MethodSelectionException mse) { // the metamethod already exists with multiple signatures, pick the most specific return theMetaClass.methods.find { MetaMethod existingMethod -> - existingMethod.name == methodName && existingMethod.isStatic()==staticScope && ((!parameterTypes && !existingMethod.parameterTypes) || parameterTypes==existingMethod.parameterTypes) + existingMethod.name == methodName && existingMethod.isStatic() == staticScope && ((!parameterTypes && !existingMethod.parameterTypes) || parameterTypes == existingMethod.parameterTypes) } } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/RuntimeSupport.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/RuntimeSupport.groovy index b7347b276ef..3dfb1f2a265 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/RuntimeSupport.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/RuntimeSupport.groovy @@ -41,15 +41,15 @@ class RuntimeSupport { * @return */ static Datastore findDefaultDatastore(Datastore[] datastores) { - for(Datastore d in datastores) { - if( d instanceof ConnectionSourcesProvider) { - ConnectionSourcesProvider provider = (ConnectionSourcesProvider)d - if(ConnectionSource.DEFAULT == provider.getConnectionSources().defaultConnectionSource.name) { + for (Datastore d in datastores) { + if (d instanceof ConnectionSourcesProvider) { + ConnectionSourcesProvider provider = (ConnectionSourcesProvider) d + if (ConnectionSource.DEFAULT == provider.getConnectionSources().defaultConnectionSource.name) { return d } } } - if(datastores) { + if (datastores) { return datastores[0] } throw new DatastoreConfigurationException("No default datastore configured") diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/StaticMethodInvokingClosure.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/StaticMethodInvokingClosure.groovy index 2ee3485ea86..40d3d2b9efa 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/StaticMethodInvokingClosure.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/internal/StaticMethodInvokingClosure.groovy @@ -22,11 +22,12 @@ import groovy.transform.CompileStatic @SuppressWarnings("rawtypes") @CompileStatic class StaticMethodInvokingClosure extends MethodInvokingClosure { + StaticMethodInvokingClosure(apiDelegate, String methodName, Class[] parameterTypes) { super(apiDelegate, methodName, parameterTypes) super.metaMethod = pickMetaMethod(apiDelegate.getMetaClass(), methodName, parameterTypes, true) } - + @Override Object call(Object[] args) { metaMethod.invoke(apiDelegate, args) diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/DataSourceBuilder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/DataSourceBuilder.java index b7d6d0d9f08..65049dd17f3 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/DataSourceBuilder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/DataSourceBuilder.java @@ -18,24 +18,22 @@ */ package org.grails.datastore.gorm.jdbc; +import org.grails.datastore.mapping.core.exceptions.ConfigurationException; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.util.ClassUtils; +import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.Properties; -import javax.sql.DataSource; - -import org.grails.datastore.mapping.core.exceptions.ConfigurationException; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.jdbc.datasource.DriverManagerDataSource; -import org.springframework.util.ClassUtils; - /** * NOTE: Forked from Spring Boot logic to avoid hard dependency on Boot. - * + *

* Convenience class for building a {@link DataSource} with common implementations and * properties. If Tomcat, HikariCP or Commons DBCP are on the classpath one of them will * be selected (in that order with Tomcat first). In the interest of a uniform interface, @@ -46,12 +44,11 @@ * * @author Dave Syer * @author Graeme Rocher - * * @since 1.1.0 */ public class DataSourceBuilder { - private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] { + private static final String[] DATA_SOURCE_TYPE_NAMES = new String[]{ "org.apache.tomcat.jdbc.pool.DataSource", "com.zaxxer.hikari.HikariDataSource", "org.apache.commons.dbcp.BasicDataSource", @@ -66,6 +63,10 @@ public class DataSourceBuilder { private boolean pooled = true; private boolean readOnly = false; + public DataSourceBuilder(ClassLoader classLoader) { + this.classLoader = classLoader; + } + public static DataSourceBuilder create() { return new DataSourceBuilder(null); } @@ -74,10 +75,6 @@ public static DataSourceBuilder create(ClassLoader classLoader) { return new DataSourceBuilder(classLoader); } - public DataSourceBuilder(ClassLoader classLoader) { - this.classLoader = classLoader; - } - public DataSource build() { Class type = getType(); DataSource result = BeanUtils.instantiateClass(type); @@ -97,7 +94,7 @@ private void maybeGetDriverClassName() { } private void bind(DataSource result) { - if(properties.containsKey("dbProperties")) { + if (properties.containsKey("dbProperties")) { coerceDbProperties(); } MutablePropertyValues properties = new MutablePropertyValues(this.properties); @@ -105,7 +102,7 @@ private void bind(DataSource result) { .withAlias("username", "user").bind(properties); } - public DataSourceBuilder properties( Map properties) { + public DataSourceBuilder properties(Map properties) { this.properties.putAll(properties); return this; } @@ -113,12 +110,12 @@ public DataSourceBuilder properties( Map properties) { private void coerceDbProperties() { Map propertiesMap = this.properties; Object dbPropertiesObject = propertiesMap.get("dbProperties"); - if(dbPropertiesObject instanceof Map) { + if (dbPropertiesObject instanceof Map) { Map dbProperties = (Map) dbPropertiesObject; Properties properties = new Properties(); for (Object key : dbProperties.keySet()) { Object value = dbProperties.get(key); - if(value != null) { + if (value != null) { properties.put(key.toString(), value.toString()); } } @@ -156,12 +153,10 @@ public Class findType() { if (this.type != null) { return this.type; - } - else if(!pooled) { - if(this.readOnly) { + } else if (!pooled) { + if (this.readOnly) { return ReadOnlyDriverManagerDataSource.class; - } - else { + } else { return org.springframework.jdbc.datasource.DriverManagerDataSource.class; } } @@ -170,8 +165,7 @@ else if(!pooled) { try { return (Class) ClassUtils.forName(name, this.classLoader); - } - catch (Exception ex) { + } catch (Exception ex) { // Swallow and continue } } @@ -203,4 +197,4 @@ protected Connection getConnectionFromDriverManager(final String url, final Prop return connection; } } -} \ No newline at end of file +} diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/DatabaseDriver.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/DatabaseDriver.java index 7c449e4c1f0..df8480091c7 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/DatabaseDriver.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/DatabaseDriver.java @@ -18,8 +18,6 @@ */ package org.grails.datastore.gorm.jdbc; - - import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -109,7 +107,6 @@ public enum DatabaseDriver { FIREBIRD("Firebird", "org.firebirdsql.jdbc.FBDriver", "org.firebirdsql.pool.FBConnectionPoolDataSource", "SELECT 1 FROM RDB$DATABASE") { - @Override protected boolean matchProductName(String productName) { return super.matchProductName(productName) @@ -122,7 +119,6 @@ protected boolean matchProductName(String productName) { */ DB2("DB2", "com.ibm.db2.jcc.DB2Driver", "com.ibm.db2.jcc.DB2XADataSource", "SELECT 1 FROM SYSIBM.SYSDUMMY1") { - @Override protected boolean matchProductName(String productName) { return super.matchProductName(productName) @@ -136,7 +132,6 @@ protected boolean matchProductName(String productName) { DB2_AS400("DB2 UDB for AS/400", "com.ibm.as400.access.AS400JDBCDriver", "com.ibm.as400.access.AS400JDBCXADataSource", "SELECT 1 FROM SYSIBM.SYSDUMMY1") { - @Override protected boolean matchProductName(String productName) { return super.matchProductName(productName) @@ -185,6 +180,7 @@ protected boolean matchProductName(String productName) { /** * Return the driver class name. + * * @return the class name or {@code null} */ public String getDriverClassName() { @@ -193,6 +189,7 @@ public String getDriverClassName() { /** * Return the XA driver source class name. + * * @return the class name or {@code null} */ public String getXaDataSourceClassName() { @@ -201,6 +198,7 @@ public String getXaDataSourceClassName() { /** * Return the validation query. + * * @return the validation query or {@code null} */ public String getValidationQuery() { @@ -209,6 +207,7 @@ public String getValidationQuery() { /** * Find a {@link DatabaseDriver} for the given URL. + * * @param url JDBC URL * @return the database driver or {@link #UNKNOWN} if not found */ @@ -228,6 +227,7 @@ public static DatabaseDriver fromJdbcUrl(String url) { /** * Find a {@link DatabaseDriver} for the given product name. + * * @param productName product name * @return the database driver or {@link #UNKNOWN} if not found */ @@ -241,5 +241,4 @@ public static DatabaseDriver fromProductName(String productName) { } return UNKNOWN; } - -} \ No newline at end of file +} diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/MultiTenantConnection.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/MultiTenantConnection.groovy index e76ba509ea7..6fbce2cc831 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/MultiTenantConnection.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/MultiTenantConnection.groovy @@ -22,7 +22,6 @@ package org.grails.datastore.gorm.jdbc import groovy.transform.CompileStatic import org.grails.datastore.gorm.jdbc.schema.SchemaHandler -import javax.sql.DataSource import java.sql.Connection import java.sql.SQLException @@ -35,7 +34,8 @@ import java.sql.SQLException @CompileStatic class MultiTenantConnection implements Connection { - final @Delegate Connection target + final @Delegate + Connection target final SchemaHandler schemaHandler MultiTenantConnection(Connection target, SchemaHandler schemaHandler) { @@ -46,7 +46,7 @@ class MultiTenantConnection implements Connection { @Override void close() throws SQLException { try { - if(!isClosed()) { + if (!isClosed()) { schemaHandler.useDefaultSchema(this) } } finally { diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/MultiTenantDataSource.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/MultiTenantDataSource.groovy index b1d57796d7b..a89ea9e06bc 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/MultiTenantDataSource.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/MultiTenantDataSource.groovy @@ -34,7 +34,8 @@ import javax.sql.DataSource @EqualsAndHashCode(includes = ['tenantId']) class MultiTenantDataSource implements DataSource { - final @Delegate DataSource target + final @Delegate + DataSource target final String tenantId MultiTenantDataSource(DataSource target, String tenantId) { diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/OriginCapablePropertyValue.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/OriginCapablePropertyValue.java index 58e414bfe17..bcf5d39d338 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/OriginCapablePropertyValue.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/OriginCapablePropertyValue.java @@ -60,5 +60,4 @@ static PropertyOrigin getOrigin(PropertyValue propertyValue) { } return new OriginCapablePropertyValue(propertyValue).getOrigin(); } - -} \ No newline at end of file +} diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/PropertyOrigin.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/PropertyOrigin.java index 679d5c9f46f..013e2689731 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/PropertyOrigin.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/PropertyOrigin.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.jdbc; import org.springframework.core.env.PropertySource; @@ -46,5 +45,4 @@ public PropertySource getSource() { public String getName() { return this.name; } - -} \ No newline at end of file +} diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/RelaxedConversionService.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/RelaxedConversionService.java index 7dfbf9a55eb..9b425691db9 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/RelaxedConversionService.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/RelaxedConversionService.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.jdbc; import org.springframework.core.convert.ConversionFailedException; @@ -47,6 +46,7 @@ class RelaxedConversionService implements ConversionService { /** * Create a new {@link RelaxedConversionService} instance. + * * @param conversionService and option root conversion service */ RelaxedConversionService(ConversionService conversionService) { @@ -86,8 +86,7 @@ public Object convert(Object source, TypeDescriptor sourceType, if (this.conversionService != null) { try { return this.conversionService.convert(source, sourceType, targetType); - } - catch (ConversionFailedException ex) { + } catch (ConversionFailedException ex) { // Ignore and try the additional converters } } @@ -98,7 +97,7 @@ public Object convert(Object source, TypeDescriptor sourceType, * Clone of Spring's package private StringToEnumConverterFactory, but ignoring the * case of the source. */ - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) private static class StringToEnumIgnoringCaseConverterFactory implements ConverterFactory { @@ -128,7 +127,7 @@ public T convert(String source) { return null; } source = source.trim(); - for (T candidate : (Set)EnumSet.allOf(this.enumType)) { + for (T candidate : (Set) EnumSet.allOf(this.enumType)) { RelaxedNames names = new RelaxedNames( candidate.name().replace("_", "-").toLowerCase()); for (String name : names) { @@ -149,9 +148,10 @@ public T convert(String source) { } private class StringToCharArrayConverter implements Converter { + @Override public char[] convert(String source) { return source.toCharArray(); } } -} \ No newline at end of file +} diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/RelaxedDataBinder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/RelaxedDataBinder.java index d399dcf50e4..22d2f4a0361 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/RelaxedDataBinder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/RelaxedDataBinder.java @@ -16,17 +16,29 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.jdbc; -import org.springframework.beans.*; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.beans.InvalidPropertyException; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.PropertyValue; import org.springframework.core.convert.TypeDescriptor; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; import org.springframework.validation.DataBinder; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; /** * Binder implementation that allows caller to bind to maps and also allows property names @@ -51,6 +63,7 @@ class RelaxedDataBinder extends DataBinder { /** * Create a new {@link RelaxedDataBinder} instance. + * * @param target the target into which properties are bound */ RelaxedDataBinder(Object target) { @@ -59,7 +72,8 @@ class RelaxedDataBinder extends DataBinder { /** * Add aliases to the {@link DataBinder}. - * @param name the property name to alias + * + * @param name the property name to alias * @param alias aliases for the property names * @return this instance */ @@ -80,8 +94,9 @@ protected void doBind(MutablePropertyValues propertyValues) { * map keys. Also creates new maps for properties of map type that are null (assuming * all maps are potentially nested). The standard bracket {@code[...]} dereferencing * is also accepted. + * * @param propertyValues the property values - * @param target the target object + * @param target the target object * @return modified property values */ private MutablePropertyValues modifyProperties(MutablePropertyValues propertyValues, @@ -122,6 +137,7 @@ private List getSortedPropertyNames(MutablePropertyValues propertyValues * significant for other property names (it shouldn't be but who knows what people * might be relying on, e.g. HSQL has a JDBCXADataSource where "databaseName" is a * synonym for "url"). + * * @param names the names to sort */ private void sortPropertyNames(List names) { @@ -156,7 +172,7 @@ private MutablePropertyValues getPropertyValuesForNamePrefix( for (PropertyValue value : propertyValues.getPropertyValues()) { String name = value.getName(); for (String prefix : new RelaxedNames(stripLastDot(this.namePrefix))) { - for (String separator : new String[] { ".", "_" }) { + for (String separator : new String[]{".", "_"}) { String candidate = (StringUtils.hasLength(prefix) ? prefix + separator : prefix); if (name.startsWith(candidate)) { @@ -198,8 +214,9 @@ private PropertyValue modifyProperty(BeanWrapper target, *

  • Fuzzy matching can be employed for bean property names
  • *
  • Period separators can be used instead of indexing ([...]) for map keys
  • * + * * @param wrapper a bean wrapper for the object to bind - * @param path the bean path to bind + * @param path the bean path to bind * @return a transformed path with correct bean wrapper syntax */ private String normalizePath(BeanWrapper wrapper, String path) { @@ -226,19 +243,16 @@ private String initializePath(BeanWrapper wrapper, BeanPath path, int index) { } path.mapIndex(index); extendMapIfNecessary(wrapper, path, index); - } - else if (descriptor.isCollection()) { + } else if (descriptor.isCollection()) { extendCollectionIfNecessary(wrapper, path, index); - } - else if (descriptor.getType().equals(Object.class)) { + } else if (descriptor.getType().equals(Object.class)) { if (isBlanked(wrapper, name, path.name(index))) { path.collapseKeys(index); } path.mapIndex(index); if (path.isLastNode(index)) { wrapper.setPropertyValue(path.toString(), BLANK); - } - else { + } else { String next = path.prefix(index + 1); if (wrapper.getPropertyValue(next) == null) { wrapper.setPropertyValue(next, new LinkedHashMap()); @@ -361,8 +375,7 @@ private String resolvePropertyName(BeanWrapper target, String prefix, String nam if (target.getPropertyType(joinString(prefix, candidate)) != null) { return candidate; } - } - catch (InvalidPropertyException ex) { + } catch (InvalidPropertyException ex) { // swallow and continue } } @@ -462,8 +475,7 @@ private String extractIndexedPaths(String path, List nodes) { String sub = current.substring(startRef + 1, endRef); if (sub.matches("[0-9]+")) { nodes.add(new ArrayIndexNode(sub)); - } - else { + } else { nodes.add(new MapIndexNode(sub)); } } @@ -589,6 +601,5 @@ public String toString() { } } - } -} \ No newline at end of file +} diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/RelaxedNames.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/RelaxedNames.java index 017074556d6..6e909523933 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/RelaxedNames.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/RelaxedNames.java @@ -16,19 +16,16 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.jdbc; import org.springframework.util.StringUtils; - import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; - /** * Generates relaxed name variations from a given source. * @@ -49,8 +46,9 @@ final class RelaxedNames implements Iterable { /** * Create a new {@link RelaxedNames} instance. + * * @param name the source name. For the maximum number of variations specify the name - * using dashed notation (e.g. {@literal my-property-name} + * using dashed notation (e.g. {@literal my-property-name} */ RelaxedNames(String name) { this.name = (name == null ? "" : name); @@ -192,7 +190,7 @@ private static String separatedToCamelCase(String value, builder.append( builder.length() == 0 ? field : StringUtils.capitalize(field)); } - for (String suffix : new String[] { "_", "-", "." }) { + for (String suffix : new String[]{"_", "-", "."}) { if (value.endsWith(suffix)) { builder.append(suffix); } @@ -201,6 +199,4 @@ private static String separatedToCamelCase(String value, } } - - -} \ No newline at end of file +} diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/CachedDataSourceConnectionSourceFactory.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/CachedDataSourceConnectionSourceFactory.java index 92456d2ef6e..8b5c2f8165f 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/CachedDataSourceConnectionSourceFactory.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/CachedDataSourceConnectionSourceFactory.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.jdbc.connections; import org.grails.datastore.mapping.core.connections.ConnectionSource; @@ -33,14 +32,14 @@ * @since 6.1.7 */ public class CachedDataSourceConnectionSourceFactory extends DataSourceConnectionSourceFactory { + private final Map> dataSources = new LinkedHashMap<>(); @Override public ConnectionSource create(String name, PropertyResolver configuration) { - if(dataSources.containsKey(name)) { + if (dataSources.containsKey(name)) { return dataSources.get(name); - } - else { + } else { ConnectionSource connectionSource = super.create(name, configuration); dataSources.put(name, connectionSource); return connectionSource; @@ -49,10 +48,9 @@ public ConnectionSource create(String name, Prop @Override public ConnectionSource create(String name, DataSourceSettings settings) { - if(dataSources.containsKey(name)) { + if (dataSources.containsKey(name)) { return dataSources.get(name); - } - else { + } else { ConnectionSource connectionSource = super.create(name, settings); dataSources.put(name, connectionSource); return connectionSource; diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceConnectionSource.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceConnectionSource.java index 911bc3f266f..c5e95f87e04 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceConnectionSource.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceConnectionSource.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.jdbc.connections; import org.grails.datastore.mapping.core.connections.DefaultConnectionSource; @@ -36,6 +35,7 @@ * @since 6.0 */ public class DataSourceConnectionSource extends DefaultConnectionSource { + private static final Logger LOG = LoggerFactory.getLogger(DataSourceConnectionSource.class); public DataSourceConnectionSource(String name, DataSource source, DataSourceSettings settings) { @@ -45,7 +45,7 @@ public DataSourceConnectionSource(String name, DataSource source, DataSourceSett @Override public void close() throws IOException { super.close(); - if(!closed) { + if (!closed) { DataSource source = getSource(); Method closeMethod = ReflectionUtils.findMethod(source.getClass(), "close"); @@ -55,7 +55,7 @@ public void close() throws IOException { closeMethod = ReflectionUtils.findMethod(source.getClass(), "close"); } - if(closeMethod != null) { + if (closeMethod != null) { try { ReflectionUtils.invokeMethod(closeMethod, source); this.closed = true; diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceConnectionSourceFactory.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceConnectionSourceFactory.java index d471157a5f1..2df5422a6ff 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceConnectionSourceFactory.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceConnectionSourceFactory.java @@ -16,12 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.jdbc.connections; -import org.grails.datastore.mapping.config.Settings; -import org.grails.datastore.mapping.core.connections.*; import org.grails.datastore.gorm.jdbc.DataSourceBuilder; +import org.grails.datastore.mapping.config.Settings; +import org.grails.datastore.mapping.core.connections.AbstractConnectionSourceFactory; +import org.grails.datastore.mapping.core.connections.ConnectionSource; +import org.grails.datastore.mapping.core.connections.ConnectionSourceSettings; +import org.grails.datastore.mapping.core.connections.DefaultConnectionSource; import org.grails.datastore.mapping.core.exceptions.ConfigurationException; import org.springframework.core.env.PropertyResolver; import org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy; @@ -35,27 +37,26 @@ import java.util.Map; /** - * A {@link ConnectionSourceFactory} for creating JDBC {@link DataSource} connections + * A {@link org.grails.datastore.mapping.core.connections.ConnectionSourceFactory} for creating JDBC {@link javax.sql.DataSource} connections * * @author Graeme Rocher * @since 6.0 */ public class DataSourceConnectionSourceFactory extends AbstractConnectionSourceFactory { + @Override protected DataSourceSettings buildSettings(String name, PropertyResolver configuration, F fallbackSettings, boolean isDefaultDataSource) { String configurationPrefix = isDefaultDataSource ? Settings.SETTING_DATASOURCE : Settings.SETTING_DATASOURCES + '.' + name; DataSourceSettingsBuilder builder; - if(isDefaultDataSource) { + if (isDefaultDataSource) { String qualified = Settings.SETTING_DATASOURCES + '.' + Settings.SETTING_DATASOURCE; Map config = configuration.getProperty(qualified, Map.class, Collections.emptyMap()); - if(!config.isEmpty()) { + if (!config.isEmpty()) { builder = new DataSourceSettingsBuilder(configuration, qualified); - } - else { + } else { builder = new DataSourceSettingsBuilder(configuration, configurationPrefix); } - } - else { + } else { builder = new DataSourceSettingsBuilder(configuration, configurationPrefix); } @@ -66,7 +67,7 @@ protected DataSourceSettings buildSettings( public ConnectionSource create(String name, DataSourceSettings settings) { DataSource dataSource; - if(settings.getJndiName() != null && !settings.getJndiName().isEmpty()) { + if (settings.getJndiName() != null && !settings.getJndiName().isEmpty()) { JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean(); jndiObjectFactoryBean.setExpectedType(DataSource.class); jndiObjectFactoryBean.setJndiName(settings.getJndiName()); @@ -75,11 +76,10 @@ public ConnectionSource create(String name, Data } catch (NamingException e) { throw new ConfigurationException("Unable to configure JNDI data source: " + e.getMessage(), e); } - dataSource = (DataSource)jndiObjectFactoryBean.getObject(); + dataSource = (DataSource) jndiObjectFactoryBean.getObject(); dataSource = proxy(dataSource, settings); return new DefaultConnectionSource<>(name, dataSource, settings); - } - else { + } else { DataSourceBuilder dataSourceBuilder = new DataSourceBuilder(getClass().getClassLoader()); dataSourceBuilder.setPooled(settings.isPooled()); @@ -91,15 +91,15 @@ public ConnectionSource create(String name, Data String url = settings.getUrl(); Class type = settings.getType(); - if(properties != null && !properties.isEmpty()) { + if (properties != null && !properties.isEmpty()) { dataSourceBuilder.properties(settings.toProperties()); } dataSourceBuilder.url(url); - if(driverClassName != null) { + if (driverClassName != null) { dataSourceBuilder.driverClassName(driverClassName); } - if(username != null && password != null) { + if (username != null && password != null) { dataSourceBuilder.username(username); dataSourceBuilder.password(password); } @@ -115,10 +115,10 @@ public ConnectionSource create(String name, Data } protected DataSource proxy(DataSource dataSource, DataSourceSettings settings) { - if(settings.isLazy()) { + if (settings.isLazy()) { dataSource = new LazyConnectionDataSourceProxy(dataSource); } - if(settings.isTransactionAware()) { + if (settings.isTransactionAware()) { dataSource = new TransactionAwareDataSourceProxy(dataSource); } return dataSource; diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceSettings.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceSettings.groovy index c4b11aeeeed..ea528776edf 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceSettings.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceSettings.groovy @@ -125,7 +125,7 @@ class DataSourceSettings extends ConnectionSourceSettings { props.put("hibernate.hbm2ddl.auto", dbCreate) props.put("hibernate.show_sql", String.valueOf(logSql)) props.put("hibernate.format_sql", String.valueOf(formatSql)) - if(dialect != null) { + if (dialect != null) { props.put("hibernate.dialect", dialect.name) } return props @@ -135,20 +135,20 @@ class DataSourceSettings extends ConnectionSourceSettings { * @return Convert to datasource properties */ @CompileStatic - Map toProperties() { - Map properties = new LinkedHashMap<>() + Map toProperties() { + Map properties = new LinkedHashMap<>() properties.putAll(this.properties) properties.put("url", url) - if(driverClassName) { + if (driverClassName) { properties.put("driverClassName", driverClassName) } - if(username) { + if (username) { properties.put("username", username) } - if(password) { + if (password) { properties.put("username", password) } - if(readOnly) { + if (readOnly) { properties.put("defaultReadOnly", String.valueOf(readOnly)) } return properties diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceSettingsBuilder.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceSettingsBuilder.groovy index a71e080ebf0..b757ec5e86b 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceSettingsBuilder.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/DataSourceSettingsBuilder.groovy @@ -32,6 +32,7 @@ import org.springframework.core.env.PropertyResolver */ @CompileStatic class DataSourceSettingsBuilder extends ConfigurationBuilder { + DataSourceSettingsBuilder(PropertyResolver propertyResolver, String configurationPrefix = Settings.SETTING_DATASOURCE, Object fallBackSettings = null) { super(propertyResolver, configurationPrefix, fallBackSettings) } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/SpringDataSourceConnectionSourceFactory.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/SpringDataSourceConnectionSourceFactory.java index d12c2ced887..7c2aaef74c4 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/SpringDataSourceConnectionSourceFactory.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/connections/SpringDataSourceConnectionSourceFactory.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.jdbc.connections; import org.grails.datastore.mapping.config.Settings; @@ -35,6 +34,7 @@ * @since 6.0 */ public class SpringDataSourceConnectionSourceFactory extends DataSourceConnectionSourceFactory implements ApplicationContextAware { + private ApplicationContext applicationContext; @Override diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/schema/DefaultSchemaHandler.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/schema/DefaultSchemaHandler.groovy index e946bb30b98..e031bddd5a9 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/schema/DefaultSchemaHandler.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/jdbc/schema/DefaultSchemaHandler.groovy @@ -82,7 +82,7 @@ class DefaultSchemaHandler implements SchemaHandler { try { connection = dataSource.getConnection() ResultSet schemas = connection.getMetaData().getSchemas() - while(schemas.next()) { + while (schemas.next()) { schemaNames.add(schemas.getString("TABLE_SCHEM")) } } finally { diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/multitenancy/MultiTenantEventListener.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/multitenancy/MultiTenantEventListener.java index 5e397c828c7..fba0fabb6fe 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/multitenancy/MultiTenantEventListener.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/multitenancy/MultiTenantEventListener.java @@ -16,14 +16,17 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.multitenancy; import grails.gorm.multitenancy.Tenants; import org.grails.datastore.gorm.GormEnhancer; import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.connections.ConnectionSource; -import org.grails.datastore.mapping.engine.event.*; +import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent; +import org.grails.datastore.mapping.engine.event.PersistenceEventListener; +import org.grails.datastore.mapping.engine.event.PreInsertEvent; +import org.grails.datastore.mapping.engine.event.PreUpdateEvent; +import org.grails.datastore.mapping.engine.event.ValidationEvent; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.types.TenantId; import org.grails.datastore.mapping.multitenancy.MultiTenantCapableDatastore; @@ -43,8 +46,9 @@ * @since 6.0 */ public class MultiTenantEventListener implements PersistenceEventListener { - protected final Datastore datastore; + public static final List> SUPPORTED_EVENTS = Arrays.asList(PreQueryEvent.class, ValidationEvent.class, PreInsertEvent.class, PreUpdateEvent.class); + protected final Datastore datastore; public MultiTenantEventListener(Datastore datastore) { this.datastore = datastore; @@ -63,58 +67,55 @@ public boolean supportsSourceType(Class sourceType) { @Override public void onApplicationEvent(ApplicationEvent event) { Class eventClass = event.getClass(); - if(supportsEventType(eventClass)) { + if (supportsEventType(eventClass)) { Datastore datastore = (Datastore) event.getSource(); - if(event instanceof PreQueryEvent) { + if (event instanceof PreQueryEvent) { PreQueryEvent preQueryEvent = (PreQueryEvent) event; Query query = preQueryEvent.getQuery(); PersistentEntity entity = query.getEntity(); - if(entity.isMultiTenant()) { - if(datastore == null) { + if (entity.isMultiTenant()) { + if (datastore == null) { datastore = GormEnhancer.findDatastore(entity.getJavaClass()); } - if(supportsSourceType(datastore.getClass()) && this.datastore.equals(datastore)) { + if (supportsSourceType(datastore.getClass()) && this.datastore.equals(datastore)) { TenantId tenantId = entity.getTenantId(); - if(tenantId != null) { + if (tenantId != null) { Serializable currentId; - if(datastore instanceof MultiTenantCapableDatastore) { + if (datastore instanceof MultiTenantCapableDatastore) { currentId = Tenants.currentId((MultiTenantCapableDatastore) datastore); - } - else { + } else { currentId = Tenants.currentId(datastore.getClass()); } - query.eq(tenantId.getName(), currentId ); + query.eq(tenantId.getName(), currentId); } } } - } - else if((event instanceof ValidationEvent) || (event instanceof PreInsertEvent) || (event instanceof PreUpdateEvent)) { + } else if ((event instanceof ValidationEvent) || (event instanceof PreInsertEvent) || (event instanceof PreUpdateEvent)) { AbstractPersistenceEvent preInsertEvent = (AbstractPersistenceEvent) event; PersistentEntity entity = preInsertEvent.getEntity(); - if(entity.isMultiTenant()) { + if (entity.isMultiTenant()) { TenantId tenantId = entity.getTenantId(); - if(datastore == null) { + if (datastore == null) { datastore = GormEnhancer.findDatastore(entity.getJavaClass()); } - if(supportsSourceType(datastore.getClass()) && this.datastore.equals(datastore)) { + if (supportsSourceType(datastore.getClass()) && this.datastore.equals(datastore)) { Serializable currentId; - if(datastore instanceof MultiTenantCapableDatastore) { + if (datastore instanceof MultiTenantCapableDatastore) { currentId = Tenants.currentId((MultiTenantCapableDatastore) datastore); - } - else { + } else { currentId = Tenants.currentId(datastore.getClass()); } - if(currentId != null) { + if (currentId != null) { try { - if(currentId == ConnectionSource.DEFAULT) { + if (currentId == ConnectionSource.DEFAULT) { currentId = (Serializable) preInsertEvent.getEntityAccess().getProperty(tenantId.getName()); } preInsertEvent.getEntityAccess().setProperty(tenantId.getName(), currentId); } catch (Exception e) { - throw new TenantException("Could not assigned tenant id ["+currentId+"] to property ["+tenantId+"], probably due to a type mismatch. You should return a type from the tenant resolver that matches the property type of the tenant id!: " + e.getMessage(), e); + throw new TenantException("Could not assigned tenant id [" + currentId + "] to property [" + tenantId + "], probably due to a type mismatch. You should return a type from the tenant resolver that matches the property type of the tenant id!: " + e.getMessage(), e); } } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/multitenancy/TenantDelegatingGormOperations.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/multitenancy/TenantDelegatingGormOperations.groovy index 158c8113e05..769cc337326 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/multitenancy/TenantDelegatingGormOperations.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/multitenancy/TenantDelegatingGormOperations.groovy @@ -38,6 +38,7 @@ import org.springframework.transaction.TransactionDefinition */ @CompileStatic class TenantDelegatingGormOperations implements GormAllOperations { + final Datastore datastore final Serializable tenantId final GormAllOperations allOperations @@ -50,119 +51,119 @@ class TenantDelegatingGormOperations implements GormAllOperations { @Override def propertyMissing(D instance, String name) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.propertyMissing(instance, name) } } @Override boolean instanceOf(D instance, Class cls) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.instanceOf(instance, cls) } } @Override D lock(D instance) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.lock(instance) } } @Override def T mutex(D instance, Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.mutex(instance, callable) } } @Override D refresh(D instance) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.refresh(instance) } } @Override D save(D instance) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.save(instance) } } @Override D insert(D instance) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.insert(instance) } } @Override D insert(D instance, Map params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.insert(instance, params) } } @Override D merge(D instance, Map params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.merge(instance, params) } } @Override D save(D instance, boolean validate) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.save(instance, validate) } } @Override D save(D instance, Map params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.save(instance, params) } } @Override Serializable ident(D instance) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.ident(instance) } } @Override D attach(D instance) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.attach(instance) } } @Override boolean isAttached(D instance) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.isAttached(instance) } } @Override void discard(D instance) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.discard(instance) } } @Override void delete(D instance) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.delete(instance) } } @Override void delete(D instance, Map params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.save(instance, params) } } @@ -179,70 +180,70 @@ class TenantDelegatingGormOperations implements GormAllOperations { @Override DetachedCriteria where(Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.where(callable) } } @Override DetachedCriteria whereLazy(Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.whereLazy(callable) } } @Override DetachedCriteria whereAny(Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.whereAny(callable) } } @Override List findAll(Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAll(callable) } } @Override List findAll(Map args, Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAll(args, callable) } } @Override D find(Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.find(callable) } } @Override List saveAll(Object... objectsToSave) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.saveAll(objectsToSave) } } @Override List saveAll(Iterable objectsToSave) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.saveAll(objectsToSave) } } @Override void deleteAll(Object... objectsToDelete) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.deleteAll(objectsToDelete) } } @Override void deleteAll(Iterable objectsToDelete) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.deleteAll(objectsToDelete) } } @@ -254,497 +255,497 @@ class TenantDelegatingGormOperations implements GormAllOperations { @Override D get(Serializable id) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.get(id) } } @Override D read(Serializable id) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.read(id) } } @Override D load(Serializable id) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.load(id) } } @Override D proxy(Serializable id) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.proxy(id) } } @Override List getAll(Iterable ids) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.getAll(ids) } } @Override List getAll(Serializable... ids) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.getAll(ids) } } @Override List getAll() { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.getAll() } } @Override BuildableCriteria createCriteria() { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.createCriteria() } } @Override def T withCriteria(@DelegatesTo(Criteria) Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.withCriteria callable } } @Override def T withCriteria(Map builderArgs, @DelegatesTo(Criteria) Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.withCriteria builderArgs, callable } } @Override D lock(Serializable id) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.lock(id) } } @Override D merge(D d) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.merge(d) } } @Override Integer count() { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.count() } } @Override Integer getCount() { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.getCount() } } @Override boolean exists(Serializable id) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.exists(id) } } @Override List list(Map params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.list(params) } } @Override List list() { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.list() } } @Override List findAll(Map params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAll(params) } } @Override List findAll() { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAll() } } @Override List findAll(D example) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAll(example) } } @Override List findAll(D example, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAll(example, args) } } @Override D first() { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.first() } } @Override D first(String propertyName) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.first(propertyName) } } @Override D first(Map queryParams) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.first(queryParams) } } @Override D last() { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.last() } } @Override D last(String propertyName) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.last(propertyName) } } @Override Object methodMissing(String methodName, Object arg) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.methodMissing(methodName, arg) } } @Override Object propertyMissing(String property) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.propertyMissing(property) } } @Override void propertyMissing(String property, Object value) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.propertyMissing(property, value) } } @Override D last(Map queryParams) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.last(queryParams) } } @Override List findAllWhere(Map queryMap) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAllWhere(queryMap) } } @Override List findAllWhere(Map queryMap, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAllWhere(queryMap, args) } } @Override D find(D example) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.find(example) } } @Override D find(D example, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.find(example, args) } } @Override D findWhere(Map queryMap) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findWhere(queryMap) } } @Override D findWhere(Map queryMap, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findWhere(queryMap, args) } } @Override D findOrCreateWhere(Map queryMap) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findOrCreateWhere(queryMap) } } @Override D findOrSaveWhere(Map queryMap) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findOrSaveWhere(queryMap) } } @Override def T withSession(Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.withSession callable } } @Override def T withDatastoreSession(Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.withDatastoreSession callable } } @Override def T withTransaction(Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.withTransaction callable } } @Override def T withNewTransaction(Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.withNewTransaction callable } } @Override def T withTransaction(Map transactionProperties, Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.withTransaction transactionProperties, callable } } @Override def T withNewTransaction(Map transactionProperties, Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.withNewTransaction transactionProperties, callable } } @Override def T withTransaction(TransactionDefinition definition, Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.withTransaction definition, callable } } @Override def T withNewSession(Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.withNewSession callable } } @Override def T withStatelessSession(Closure callable) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.withStatelessSession callable } } @Override List executeQuery(CharSequence query) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.executeQuery(query) } } @Override List executeQuery(CharSequence query, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.executeQuery(query, args) } } @Override List executeQuery(CharSequence query, Map params, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.executeQuery(query, params, args) } } @Override List executeQuery(CharSequence query, Collection params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.executeQuery(query, params) } } @Override List executeQuery(CharSequence query, Object... params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.executeQuery(query, params) } } @Override List executeQuery(CharSequence query, Collection params, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.executeQuery(query, params, args) } } @Override Integer executeUpdate(CharSequence query) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.executeUpdate(query) } } @Override Integer executeUpdate(CharSequence query, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.executeUpdate(query, args) } } @Override Integer executeUpdate(CharSequence query, Map params, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.executeUpdate(query, params, args) } } @Override Integer executeUpdate(CharSequence query, Collection params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.executeUpdate(query, params) } } @Override Integer executeUpdate(CharSequence query, Object... params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.executeUpdate(query, params) } } @Override Integer executeUpdate(CharSequence query, Collection params, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.executeUpdate(query, params, args) } } @Override D find(CharSequence query) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.find(query) } } @Override D find(CharSequence query, Map params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.find(query, params) } } @Override D find(CharSequence query, Map params, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.find(query, params, args) } } @Override D find(CharSequence query, Collection params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.find(query, params) } } @Override D find(CharSequence query, Object[] params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.find(query, params) } } @Override D find(CharSequence query, Collection params, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.find(query, params, args) } } @Override List findAll(CharSequence query) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAll(query) } } @Override List findAll(CharSequence query, Map params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAll(query, params) } } @Override List findAll(CharSequence query, Map params, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAll(query, params, args) } } @Override List findAll(CharSequence query, Collection params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAll(query, params) } } @Override List findAll(CharSequence query, Object[] params) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAll(query, params) } } @Override List findAll(CharSequence query, Collection params, Map args) { - Tenants.withId((Class)datastore.getClass(), tenantId) { + Tenants.withId((Class) datastore.getClass(), tenantId) { allOperations.findAll(query, params, args) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/multitenancy/transform/TenantTransform.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/multitenancy/transform/TenantTransform.groovy index f7fca8a9108..20a04713e4f 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/multitenancy/transform/TenantTransform.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/multitenancy/transform/TenantTransform.groovy @@ -24,7 +24,12 @@ import grails.gorm.multitenancy.TenantService import grails.gorm.multitenancy.WithoutTenant import groovy.transform.CompileStatic import org.apache.grails.common.compiler.GroovyTransformOrder -import org.codehaus.groovy.ast.* +import org.codehaus.groovy.ast.AnnotatedNode +import org.codehaus.groovy.ast.AnnotationNode +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.MethodNode +import org.codehaus.groovy.ast.Parameter +import org.codehaus.groovy.ast.VariableScope import org.codehaus.groovy.ast.expr.ClassExpression import org.codehaus.groovy.ast.expr.ClosureExpression import org.codehaus.groovy.ast.expr.Expression @@ -34,7 +39,6 @@ import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.control.CompilePhase import org.codehaus.groovy.control.SourceUnit import org.codehaus.groovy.transform.GroovyASTTransformation -import org.grails.datastore.gorm.transactions.transform.TransactionalTransform import org.grails.datastore.gorm.transform.AbstractDatastoreMethodDecoratingTransformation import org.grails.datastore.mapping.multitenancy.exceptions.TenantNotFoundException import org.grails.datastore.mapping.reflect.AstUtils @@ -42,7 +46,20 @@ import org.grails.datastore.mapping.services.ServiceRegistry import static org.codehaus.groovy.ast.ClassHelper.CLOSURE_TYPE import static org.codehaus.groovy.ast.ClassHelper.make -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS +import static org.codehaus.groovy.ast.tools.GeneralUtils.castX +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.equalsNullX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS +import static org.codehaus.groovy.ast.tools.GeneralUtils.param +import static org.codehaus.groovy.ast.tools.GeneralUtils.params +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt +import static org.codehaus.groovy.ast.tools.GeneralUtils.throwS +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.callD import static org.grails.datastore.mapping.reflect.AstUtils.copyParameters import static org.grails.datastore.mapping.reflect.AstUtils.varThis @@ -56,14 +73,15 @@ import static org.grails.datastore.mapping.reflect.AstUtils.varThis @CompileStatic @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) class TenantTransform extends AbstractDatastoreMethodDecoratingTransformation { + private static final Object APPLIED_MARKER = new Object() private static final ClassExpression CURRENT_TENANT_ANNOTATION_TYPE_EXPR = classX(CurrentTenant) private static final ClassExpression TENANT_ANNOTATION_TYPE_EXPR = classX(Tenant) private static final ClassExpression WITHOUT_TENANT_ANNOTATION_TYPE_EXPR = classX(WithoutTenant) public static final ClassNode TENANT_ANNOTATION_TYPE = TENANT_ANNOTATION_TYPE_EXPR.getType() - public static final ClassNode CURRENT_TENANT_ANNOTATION_TYPE = CURRENT_TENANT_ANNOTATION_TYPE_EXPR.getType() - public static final ClassNode WITHOUT_TENANT_ANNOTATION_TYPE = WITHOUT_TENANT_ANNOTATION_TYPE_EXPR.getType() + public static final ClassNode CURRENT_TENANT_ANNOTATION_TYPE = CURRENT_TENANT_ANNOTATION_TYPE_EXPR.getType() + public static final ClassNode WITHOUT_TENANT_ANNOTATION_TYPE = WITHOUT_TENANT_ANNOTATION_TYPE_EXPR.getType() public static final String RENAMED_METHOD_PREFIX = '$mt__' public static final String VAR_TENANT_ID = "tenantId" @@ -80,9 +98,9 @@ class TenantTransform extends AbstractDatastoreMethodDecoratingTransformation { ClassNode tenantServiceClassNode = make(TenantService) VariableScope variableScope = methodNode.getVariableScope() VariableExpression tenantServiceVar = varX('$tenantService', tenantServiceClassNode) - variableScope.putDeclaredVariable( tenantServiceVar ) + variableScope.putDeclaredVariable(tenantServiceVar) newMethodBody.addStatement( - declS(tenantServiceVar, callD(ServiceRegistry, "targetDatastore", "getService", classX(tenantServiceClassNode) ) ) + declS(tenantServiceVar, callD(ServiceRegistry, "targetDatastore", "getService", classX(tenantServiceClassNode))) ) ClassNode serializableClassNode = make(Serializable) @@ -94,44 +112,42 @@ class TenantTransform extends AbstractDatastoreMethodDecoratingTransformation { } else { // must be @Tenant Expression annValue = annotationNode.getMember("value") - if(annValue instanceof ClosureExpression) { + if (annValue instanceof ClosureExpression) { VariableExpression closureVar = varX('$tenantResolver', CLOSURE_TYPE) VariableExpression tenantIdVar = varX('$tenantId', serializableClassNode) tenantIdVar.setClosureSharedVariable(true) - variableScope.putDeclaredVariable( closureVar ) - variableScope.putReferencedLocalVariable( tenantIdVar ) - variableScope.putDeclaredVariable( tenantIdVar ) + variableScope.putDeclaredVariable(closureVar) + variableScope.putReferencedLocalVariable(tenantIdVar) + variableScope.putDeclaredVariable(tenantIdVar) // Generates: // Closure $tenantResolver = ... // $tenantResolver = $tenantResolver.clone() // $tenantResolver.setDelegate(this) // Serializable $tenantId = (Serializable)$tenantResolver.call() // if($tenantId == null) throw new TenantNotFoundException(..) - newMethodBody.addStatement declS( closureVar, annValue) - newMethodBody.addStatement assignS( closureVar, callD( closureVar, "clone")) - newMethodBody.addStatement stmt( callD( closureVar, "setDelegate", varThis() ) ) - newMethodBody.addStatement declS( tenantIdVar, castX( serializableClassNode, callD( closureVar, "call") )) - newMethodBody.addStatement ifS( equalsNullX(tenantIdVar), - throwS( ctorX( make(TenantNotFoundException), constX("Tenant id resolved from @Tenant is null")) ) + newMethodBody.addStatement declS(closureVar, annValue) + newMethodBody.addStatement assignS(closureVar, callD(closureVar, "clone")) + newMethodBody.addStatement stmt(callD(closureVar, "setDelegate", varThis())) + newMethodBody.addStatement declS(tenantIdVar, castX(serializableClassNode, callD(closureVar, "call"))) + newMethodBody.addStatement ifS(equalsNullX(tenantIdVar), + throwS(ctorX(make(TenantNotFoundException), constX("Tenant id resolved from @Tenant is null"))) ) - return makeDelegatingClosureCall( tenantServiceVar, "withId", args(tenantIdVar), params( param(serializableClassNode, VAR_TENANT_ID)), originalMethodCallExpr, variableScope) - } - else { + return makeDelegatingClosureCall(tenantServiceVar, "withId", args(tenantIdVar), params(param(serializableClassNode, VAR_TENANT_ID)), originalMethodCallExpr, variableScope) + } else { addError("@Tenant value should be a closure", annotationNode) - return makeDelegatingClosureCall( tenantServiceVar, "withCurrent", params( param(serializableClassNode, VAR_TENANT_ID)), originalMethodCallExpr, variableScope) + return makeDelegatingClosureCall(tenantServiceVar, "withCurrent", params(param(serializableClassNode, VAR_TENANT_ID)), originalMethodCallExpr, variableScope) } } } @Override protected Parameter[] prepareNewMethodParameters(MethodNode methodNode, Map genericsSpec, ClassNode classNode = null) { - if(methodNode.getAnnotations(WITHOUT_TENANT_ANNOTATION_TYPE).isEmpty() && (!classNode || classNode.getAnnotations(WITHOUT_TENANT_ANNOTATION_TYPE).isEmpty())) { + if (methodNode.getAnnotations(WITHOUT_TENANT_ANNOTATION_TYPE).isEmpty() && (!classNode || classNode.getAnnotations(WITHOUT_TENANT_ANNOTATION_TYPE).isEmpty())) { final Parameter tenantIdParameter = param(make(Serializable), VAR_TENANT_ID) Parameter[] parameters = methodNode.getParameters() Parameter[] newParameters = parameters.length > 0 ? (copyParameters(((parameters as List) + [tenantIdParameter]) as Parameter[], genericsSpec)) : [tenantIdParameter] as Parameter[] return newParameters - } - else { + } else { return copyParameters(methodNode.getParameters()) } } @@ -160,19 +176,18 @@ class TenantTransform extends AbstractDatastoreMethodDecoratingTransformation { */ static boolean hasTenantAnnotation(AnnotatedNode node) { ClassNode classNode - if(node instanceof MethodNode) { - if(AstUtils.findAnnotation(node, WithoutTenant)) { + if (node instanceof MethodNode) { + if (AstUtils.findAnnotation(node, WithoutTenant)) { return false } - classNode = ((MethodNode)node).getDeclaringClass() - } - else if(node instanceof ClassNode) { - classNode = ((ClassNode)node) + classNode = ((MethodNode) node).getDeclaringClass() + } else if (node instanceof ClassNode) { + classNode = ((ClassNode) node) } - if(classNode != null) { + if (classNode != null) { - for(ann in [CurrentTenant, Tenant]) { - if(AstUtils.findAnnotation(classNode, ann) || AstUtils.findAnnotation(node, ann)) { + for (ann in [CurrentTenant, Tenant]) { + if (AstUtils.findAnnotation(classNode, ann) || AstUtils.findAnnotation(node, ann)) { return true } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/plugin/support/PersistenceContextInterceptorAggregator.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/plugin/support/PersistenceContextInterceptorAggregator.groovy index 305ab3f02ac..eb5161ac74c 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/plugin/support/PersistenceContextInterceptorAggregator.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/plugin/support/PersistenceContextInterceptorAggregator.groovy @@ -30,11 +30,12 @@ import org.springframework.core.Ordered import org.springframework.util.ClassUtils import java.util.regex.Pattern + /** * BeanDefinitionRegistryPostProcessor that replaces multiple discovered PersistenceContextInterceptor beans with * a single aggregating instance. The previous multiple PersistenceContextInterceptor beans will be removed from * the context and re-added as inner beans of the new AggregatePersistenceContextInterceptor bean. - * + * * PersistenceContextInterceptor beans are discovered by the bean name. The default pattern used for matching * the beans is ^.*[pP]ersistenceInterceptor$ * @@ -43,6 +44,7 @@ import java.util.regex.Pattern */ @CompileStatic class PersistenceContextInterceptorAggregator implements BeanDefinitionRegistryPostProcessor, Ordered { + Pattern persistenceInterceptorBeanNamePattern = ~/^.*[pP]ersistenceInterceptor$/ String aggregatorBeanName = 'persistenceInterceptor' Class aggregatorBeanClass = ClassUtils.forName("org.grails.datastore.gorm.support.AggregatePersistenceContextInterceptor", Thread.currentThread().contextClassLoader) @@ -54,12 +56,12 @@ class PersistenceContextInterceptorAggregator implements BeanDefinitionRegistryP protected createAggregatePersistenceContextInterceptorOnDemand(BeanDefinitionRegistry registry) { Collection persistenceInterceptorBeanNames = findPersistenceInterceptorBeanNames(registry) - if(persistenceInterceptorBeanNames.size() > 1) { + if (persistenceInterceptorBeanNames.size() > 1) { ManagedList interceptorBeans = moveInterceptorBeansToManagedList(registry, persistenceInterceptorBeanNames) registry.registerBeanDefinition(aggregatorBeanName, createAggregateBeanDefinition(interceptorBeans)) } } - + protected Collection findPersistenceInterceptorBeanNames(BeanDefinitionRegistry registry) { // assume that all persistenceInterceptor beans match the defined pattern // checking for type (class) would require instantiating classes @@ -86,6 +88,6 @@ class PersistenceContextInterceptorAggregator implements BeanDefinitionRegistryP } void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { - + } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/proxy/GroovyProxyFactory.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/proxy/GroovyProxyFactory.groovy index d980c806bc3..e6edea83de2 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/proxy/GroovyProxyFactory.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/proxy/GroovyProxyFactory.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.gorm.proxy import groovy.transform.CompileStatic - import org.codehaus.groovy.runtime.HandleMetaClass import org.grails.datastore.mapping.core.Session import org.grails.datastore.mapping.engine.AssociationQueryExecutor @@ -35,6 +34,7 @@ import org.grails.datastore.mapping.reflect.ClassPropertyFetcher */ @CompileStatic class GroovyProxyFactory implements ProxyFactory { + /** * Check our object has the correct meta class to be a proxy of this type. * @param object The object. @@ -48,7 +48,7 @@ class GroovyProxyFactory implements ProxyFactory { @Override @Override public Class getProxiedClass(Object o) { - if(isProxy(o)) { + if (isProxy(o)) { return o.getClass().getSuperclass() } return o.getClass() @@ -60,11 +60,11 @@ class GroovyProxyFactory implements ProxyFactory { } protected ProxyInstanceMetaClass getProxyInstanceMetaClass(object) { - if(object == null) { + if (object == null) { return null } - MetaClass mc = unwrapHandleMetaClass(object instanceof GroovyObject ? ((GroovyObject)object).getMetaClass() : object.metaClass) - mc instanceof ProxyInstanceMetaClass ? (ProxyInstanceMetaClass)mc : null + MetaClass mc = unwrapHandleMetaClass(object instanceof GroovyObject ? ((GroovyObject) object).getMetaClass() : object.metaClass) + mc instanceof ProxyInstanceMetaClass ? (ProxyInstanceMetaClass) mc : null } @Override @@ -85,7 +85,7 @@ class GroovyProxyFactory implements ProxyFactory { /** * Creates a proxy * - * @param The type of the proxy to create + * @param The type of the proxy to create * @param session The session instance * @param type The type of the proxy to create * @param key The key to proxy @@ -98,9 +98,9 @@ class GroovyProxyFactory implements ProxyFactory { persister.setObjectIdentifier(proxy, key) MetaClass metaClass = new ProxyInstanceMetaClass(resolveTargetMetaClass(proxy, type), session, key) - if(proxy instanceof GroovyObject) { + if (proxy instanceof GroovyObject) { // direct assignment of MetaClass to GroovyObject - ((GroovyObject)proxy).setMetaClass(metaClass) + ((GroovyObject) proxy).setMetaClass(metaClass) } else { // call DefaultGroovyMethods.setMetaClass proxy.metaClass = metaClass @@ -116,9 +116,9 @@ class GroovyProxyFactory implements ProxyFactory { protected MetaClass resolveTargetMetaClass(T proxy, Class type) { unwrapHandleMetaClass(proxy.getMetaClass()) } - + private MetaClass unwrapHandleMetaClass(MetaClass metaClass) { - (metaClass instanceof HandleMetaClass) ? ((HandleMetaClass)metaClass).getAdaptee() : metaClass + (metaClass instanceof HandleMetaClass) ? ((HandleMetaClass) metaClass).getAdaptee() : metaClass } @Override diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/proxy/ProxyInstanceMetaClass.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/proxy/ProxyInstanceMetaClass.java index 99c6d565c6a..1eea2a5bd06 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/proxy/ProxyInstanceMetaClass.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/proxy/ProxyInstanceMetaClass.java @@ -20,12 +20,11 @@ import groovy.lang.DelegatingMetaClass; import groovy.lang.MetaClass; - -import java.io.Serializable; - import org.grails.datastore.mapping.core.Session; import org.springframework.dao.DataIntegrityViolationException; +import java.io.Serializable; + /** * Per-instance metaclass to use for proxied GORM domain objects. It auto-retrieves the associated entity when * fields, properties or methods are called (other than those supported by the proxy). The methods and properties @@ -39,9 +38,11 @@ *
  • target/getTarget() - resolve performed
  • *
  • initialize() - resolve performed
  • * + * * @author Tom Widmer */ public class ProxyInstanceMetaClass extends DelegatingMetaClass { + /** * Session to fetch from, if we need to. */ @@ -63,6 +64,7 @@ public ProxyInstanceMetaClass(MetaClass delegate, Session session, Serializable /** * Load the target from the DB. + * * @return target. */ public Object getProxyTarget() { @@ -80,7 +82,8 @@ public Object getProxyTarget() { /** * Handle method calls on our proxy. - * @param o The proxy. + * + * @param o The proxy. * @param methodName * @param arguments * @return @@ -101,7 +104,7 @@ public Object invokeMethod(Object o, String methodName, Object[] arguments) { } else if (methodName.equals("getClass") || methodName.equals("getDomainClass")) { // return correct class only if loaded, otherwise hope for the best resolveTarget = isProxyInitiated(); - } else if (methodName.equals("setMetaClass") && arguments.length == 1 && (arguments[0]==null || arguments[0] instanceof MetaClass)) { + } else if (methodName.equals("setMetaClass") && arguments.length == 1 && (arguments[0] == null || arguments[0] instanceof MetaClass)) { resolveTarget = false; } return delegate.invokeMethod(resolveTarget ? getProxyTarget() : o, methodName, arguments); @@ -138,9 +141,9 @@ public Object getProperty(Object object, String property) { @Override public void setProperty(Object object, String property, Object newValue) { boolean resolveTarget = true; - if(property.equals("metaClass") && (newValue == null || newValue instanceof MetaClass)) { + if (property.equals("metaClass") && (newValue == null || newValue instanceof MetaClass)) { resolveTarget = false; - } + } delegate.setProperty(resolveTarget ? getProxyTarget() : object, property, newValue); } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/AbstractResultList.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/AbstractResultList.java index d47e5f3dc9d..c094f78379d 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/AbstractResultList.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/AbstractResultList.java @@ -19,7 +19,11 @@ package org.grails.datastore.gorm.query; import java.io.Closeable; -import java.util.*; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; /** * An abstract result list for initializing objects lazily from a cursor @@ -28,12 +32,13 @@ * @since 5.0 */ public abstract class AbstractResultList extends AbstractList implements Closeable { + protected int offset = 0; protected final List initializedObjects; - private int internalIndex; - private Integer size; protected boolean initialized = false; protected Iterator cursor; + private int internalIndex; + private Integer size; public AbstractResultList(int offset, Iterator cursor) { this(offset, -1, cursor); @@ -42,7 +47,7 @@ public AbstractResultList(int offset, Iterator cursor) { public AbstractResultList(int offset, Integer size, Iterator cursor) { this.offset = offset; boolean hasSize = size != null && size > -1; - if(hasSize) { + if (hasSize) { this.size = size; } this.cursor = cursor; @@ -54,9 +59,10 @@ public Iterator getCursor() { return cursor; } - protected void initializeFully() { - if (initialized) return; + if (initialized) { + return; + } while (cursor.hasNext()) { convertObject(); @@ -64,13 +70,11 @@ protected void initializeFully() { initialized = true; } - @Override public boolean isEmpty() { if (initialized) { return initializedObjects.isEmpty(); - } - else { + } else { return initializedObjects.isEmpty() && !cursor.hasNext(); } } @@ -87,8 +91,7 @@ public Object get(int index) { Object o = convertObject(); if (index == internalIndex) { return o; - } - else if(index < initializedSize) { + } else if (index < initializedSize) { return initializedObjects.get(index); } @@ -100,7 +103,7 @@ else if(index < initializedSize) { protected Object convertObject() { final Object next = convertObject(nextDecoded()); - if(!cursor.hasNext()) { + if (!cursor.hasNext()) { initialized = true; } initializedObjects.add(next); @@ -152,21 +155,20 @@ public ListIterator listIterator(int index) { @Override public Iterator iterator() { if (initialized || !initializedObjects.isEmpty()) { - if(!initialized) { + if (!initialized) { initializeFully(); } return initializedObjects.iterator(); } - return new Iterator() { int iteratorIndex = 0; Object current; + public boolean hasNext() { - if(iteratorIndex < internalIndex) { + if (iteratorIndex < internalIndex) { return true; - } - else if(!initialized) { + } else if (!initialized) { boolean hasMore = cursor.hasNext(); if (!hasMore) { @@ -179,10 +181,9 @@ else if(!initialized) { @SuppressWarnings("unchecked") public Object next() { - if(iteratorIndex < internalIndex) { + if (iteratorIndex < internalIndex) { current = initializedObjects.get(iteratorIndex); - } - else { + } else { current = convertObject(); } try { @@ -193,7 +194,7 @@ public Object next() { } public void remove() { - if(current != null) { + if (current != null) { initializedObjects.remove(current); } } @@ -204,13 +205,11 @@ public void remove() { public int size() { if (initialized) { return initializedObjects.size(); - } - else if (this.size == null) { + } else if (this.size == null) { initializeFully(); this.size = initializedObjects.size(); } return size; } - } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/GormQueryOperations.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/GormQueryOperations.groovy index 4417c5d1cd7..a648c19b6b4 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/GormQueryOperations.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/GormQueryOperations.groovy @@ -18,8 +18,6 @@ */ package org.grails.datastore.gorm.query - - /** * Interface defining all typical query GORM operations on class * @@ -31,7 +29,7 @@ interface GormQueryOperations { /** * Synonym for #get */ - T find(Map args , Closure additionalCriteria) + T find(Map args, Closure additionalCriteria) /** * Synonym for #get @@ -88,7 +86,7 @@ interface GormQueryOperations { * @param additionalCriteria The additional criteria * @return A list of matching instances */ - List list(Map args , Closure additionalCriteria) + List list(Map args, Closure additionalCriteria) /** * Counts the number of records returned by the query diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/NamedCriteriaProxy.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/NamedCriteriaProxy.groovy index 0d8aea23fd0..7849e2bd0e8 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/NamedCriteriaProxy.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/NamedCriteriaProxy.groovy @@ -23,13 +23,6 @@ import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.gorm.finders.DynamicFinder import org.grails.datastore.gorm.finders.FinderMethod import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.query.api.BuildableCriteria -import org.grails.datastore.mapping.reflect.NameUtils -import org.springframework.util.ReflectionUtils - -import java.lang.reflect.Modifier - - /** * Handles named queries @@ -51,9 +44,8 @@ class NamedCriteriaProxy implements GormQueryOperations { private previousInChain private queryBuilder - NamedCriteriaProxy(Closure criteriaClosure, PersistentEntity entity, List finders) { - this.criteriaClosure = (Closure)criteriaClosure.clone() + this.criteriaClosure = (Closure) criteriaClosure.clone() this.criteriaClosure.delegate = this this.entity = entity this.finders = finders @@ -66,38 +58,36 @@ class NamedCriteriaProxy implements GormQueryOperations { def call(Object[] params) { if (params && params[-1] instanceof Closure) { - Closure additionalCriteriaClosure = (Closure)params[-1] + Closure additionalCriteriaClosure = (Closure) params[-1] params = params.length > 1 ? params[0..-2] : [:] if (params) { if (params[-1] instanceof Map) { if (params.length > 1) { namedCriteriaParams = params[0..-2] as Object[] } - return list((Map)params[-1], additionalCriteriaClosure) + return list((Map) params[-1], additionalCriteriaClosure) } else { namedCriteriaParams = params return list(Collections.emptyMap(), additionalCriteriaClosure) } - } - else { + } else { return list(Collections.emptyMap(), additionalCriteriaClosure) } - } - else { + } else { namedCriteriaParams = params this } } D get(Serializable id) { - id = (Serializable)entity.mappingContext.conversionService.convert(id, entity.identity.type) + id = (Serializable) entity.mappingContext.conversionService.convert(id, entity.identity.type) def getClosure = { queryBuilder = delegate invokeCriteriaClosure() eq 'id', id uniqueResult = true } - return entity.javaClass.createCriteria().get(getClosure) + return entity.javaClass.createCriteria().get(getClosure) } @Override @@ -116,7 +106,7 @@ class NamedCriteriaProxy implements GormQueryOperations { @Override D get(Map paramsMap = Collections.emptyMap(), Closure additionalCriteria = null) { def conversionService = entity.mappingContext.conversionService - return (D) entity.javaClass.createCriteria().get( { + return (D) entity.javaClass.createCriteria().get({ queryBuilder = delegate maxResults 1 uniqueResult = true @@ -124,10 +114,9 @@ class NamedCriteriaProxy implements GormQueryOperations { if (paramsMap && queryBuilder instanceof CriteriaBuilder) { DynamicFinder.populateArgumentsForCriteria(entity.javaClass, queryBuilder.query, paramsMap) } - } ) + }) } - List list(Closure additionalCriteria) { list(Collections.emptyMap(), additionalCriteria) } @@ -139,10 +128,9 @@ class NamedCriteriaProxy implements GormQueryOperations { queryBuilder = delegate invokeCriteriaClosure(additionalCriteria) } - if(paramsMap.isEmpty()) { + if (paramsMap.isEmpty()) { return entity.javaClass.createCriteria().list(callable) - } - else { + } else { return entity.javaClass.createCriteria().list(paramsMap, callable) } } @@ -180,16 +168,15 @@ class NamedCriteriaProxy implements GormQueryOperations { entity.javaClass.createCriteria().count(countClosure) } - Number count(Closure additionalCriteria ) { + Number count(Closure additionalCriteria) { count(Collections.emptyMap(), additionalCriteria) } - D findWhere(Map params) { def queryClosure = { queryBuilder = delegate invokeCriteriaClosure() - params.each {key, val -> + params.each { key, val -> eq key, val } maxResults 1 @@ -202,7 +189,7 @@ class NamedCriteriaProxy implements GormQueryOperations { def queryClosure = { queryBuilder = delegate invokeCriteriaClosure() - params.each {key, val -> + params.each { key, val -> eq key, val } } @@ -226,7 +213,7 @@ class NamedCriteriaProxy implements GormQueryOperations { def methodMissing(String methodName, args) { def javaClass = entity.javaClass - FinderMethod method = finders.find { FinderMethod f -> f.isMethodMatch(methodName) } + FinderMethod method = finders.find { FinderMethod f -> f.isMethodMatch(methodName) } if (method) { def preparedClosure = getPreparedCriteriaClosure() @@ -235,15 +222,13 @@ class NamedCriteriaProxy implements GormQueryOperations { if (queryBuilder == null) { NamedCriteriaProxy nextInChain = GormEnhancer.createNamedQuery(javaClass, methodName) - if(nextInChain != null) { + if (nextInChain != null) { nextInChain.previousInChain = this return nextInChain.call(args) - } - else { + } else { throw new MissingMethodException(methodName, javaClass, args) } - } - else { + } else { try { return queryBuilder."${methodName}"(*args) @@ -259,8 +244,7 @@ class NamedCriteriaProxy implements GormQueryOperations { nestedCriteria.delegate = this nestedCriteria(*args) return this - } - else { + } else { throw mme } } @@ -293,5 +277,4 @@ class NamedCriteriaProxy implements GormQueryOperations { return c } - } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/NamedQueriesBuilder.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/NamedQueriesBuilder.groovy index 3b8dde59f58..adbf3624d56 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/NamedQueriesBuilder.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/NamedQueriesBuilder.groovy @@ -20,9 +20,7 @@ package org.grails.datastore.gorm.query import groovy.transform.CompileStatic -import org.grails.datastore.gorm.finders.FinderMethod -import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.reflect.NameUtils + /** * Handles creation of named queries * @@ -36,7 +34,7 @@ class NamedQueriesBuilder { @CompileStatic Map evaluate(Closure namedQueriesClosure) { - Closure closure = (Closure)namedQueriesClosure.clone() + Closure closure = (Closure) namedQueriesClosure.clone() closure.resolveStrategy = Closure.DELEGATE_ONLY closure.delegate = this closure.call() @@ -46,7 +44,7 @@ class NamedQueriesBuilder { def methodMissing(String name, args) { if (args && args[0] instanceof Closure && !initialized) { - Closure criteriaClosure = (Closure)args[0] + Closure criteriaClosure = (Closure) args[0] namedQueries.put(name, criteriaClosure) return null diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/criteria/AbstractCriteriaBuilder.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/criteria/AbstractCriteriaBuilder.java index 6ebd22a57ff..e4ac8a6faf0 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/criteria/AbstractCriteriaBuilder.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/criteria/AbstractCriteriaBuilder.java @@ -16,12 +16,16 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.query.criteria; import grails.gorm.CriteriaBuilder; import grails.gorm.DetachedCriteria; -import groovy.lang.*; +import groovy.lang.Closure; +import groovy.lang.GroovyObjectSupport; +import groovy.lang.GroovySystem; +import groovy.lang.MetaMethod; +import groovy.lang.MetaObjectProtocol; +import groovy.lang.MissingMethodException; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; @@ -35,7 +39,11 @@ import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.springframework.util.Assert; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; /** * Abstract criteria builder implementation @@ -44,6 +52,7 @@ * @since 6.0 */ public abstract class AbstractCriteriaBuilder extends GroovyObjectSupport implements Criteria, ProjectionList { + public static final String ORDER_DESCENDING = "desc"; public static final String ORDER_ASCENDING = "asc"; @@ -56,14 +65,13 @@ public abstract class AbstractCriteriaBuilder extends GroovyObjectSupport implem protected Query query; protected boolean uniqueResult = false; protected boolean paginationEnabledList; - protected List orderEntries = new ArrayList(); - protected MetaObjectProtocol queryMetaClass; - protected Query.ProjectionList projectionList; + protected List orderEntries = new ArrayList(); + protected MetaObjectProtocol queryMetaClass; + protected Query.ProjectionList projectionList; protected PersistentEntity persistentEntity; protected boolean readOnly; private List logicalExpressionStack = new ArrayList(); - public AbstractCriteriaBuilder(final Class targetClass, QueryCreator queryCreator, final MappingContext mappingContext) { Assert.notNull(targetClass, "Argument [targetClass] cannot be null"); Assert.notNull(mappingContext, "Argument [session] cannot be null"); @@ -79,47 +87,46 @@ public AbstractCriteriaBuilder(final Class targetClass, QueryCreator queryCreato this.queryCreator = queryCreator; } - - public Class getTargetClass() { return this.targetClass; } public void setUniqueResult(boolean uniqueResult) { this.uniqueResult = uniqueResult; - } + } @Override - public Criteria cache(boolean cache) { - query.cache(cache); - return this; - } + public Criteria cache(boolean cache) { + query.cache(cache); + return this; + } @Override - public Criteria readOnly(boolean readOnly) { - this.readOnly = readOnly; - return this; - } + public Criteria readOnly(boolean readOnly) { + this.readOnly = readOnly; + return this; + } public Criteria join(String property) { - query.join(property); - return this; - } + query.join(property); + return this; + } public Criteria select(String property) { - query.select(property); - return this; - } + query.select(property); + return this; + } public Query.ProjectionList id() { - if (projectionList != null) { - projectionList.id(); - } - return projectionList; + if (projectionList != null) { + projectionList.id(); + } + return projectionList; } /** * Count the number of records returned + * * @return The project list */ @@ -147,7 +154,6 @@ public ProjectionList countDistinct(String property) { * Defines a group by projection for datastores that support it * * @param property The property name - * * @return The projection list */ @Override @@ -185,6 +191,7 @@ public ProjectionList distinct(String property) { /** * Count the number of records returned + * * @return The project list */ public ProjectionList rowCount() { @@ -193,6 +200,7 @@ public ProjectionList rowCount() { /** * A projection that obtains the value of a property of an entity + * * @param name The name of the property * @return The projection list */ @@ -249,20 +257,19 @@ public ProjectionList max(String name) { * @return The PropertyProjection instance */ public ProjectionList avg(String name) { - if (projectionList != null) { - projectionList.avg(name); - } - return projectionList; + if (projectionList != null) { + projectionList.avg(name); + } + return projectionList; } @Override public Object invokeMethod(String name, Object obj) { - Object[] args = obj.getClass().isArray() ? (Object[])obj : new Object[]{obj}; + Object[] args = obj.getClass().isArray() ? (Object[]) obj : new Object[]{obj}; ensureQueryIsInitialized(); if (isCriteriaConstructionMethod(name, args)) { - uniqueResult = false; invokeClosureNode(args[0]); @@ -270,8 +277,7 @@ public Object invokeMethod(String name, Object obj) { Object result; if (!uniqueResult) { result = invokeList(); - } - else { + } else { result = query.singleResult(); } query = null; @@ -308,8 +314,7 @@ public Object invokeMethod(String name, Object obj) { logicalExpressionStack = new ArrayList(); invokeClosureNode(args[0]); return query; - } - finally { + } finally { logicalExpressionStack = previousLogicalExpressionStack; persistentEntity = previousEntity; @@ -398,9 +403,8 @@ public Criteria isNotNull(String propertyName) { /** * Creates an "equals" Criterion based on the specified property name and value. * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria eq(String propertyName, Object propertyValue) { @@ -413,16 +417,14 @@ public Criteria eq(String propertyName, Object propertyValue) { * Apply an "equals" constraint to each property in the key set of a Map * * @param propertyValues a map from property names to values - * * @return Criterion - * * @see Query.Conjunction */ @Override public Criteria allEq(Map propertyValues) { Query.Conjunction conjunction = new Query.Conjunction(); for (String property : propertyValues.keySet()) { - conjunction.add( Restrictions.eq(property, propertyValues.get(property))); + conjunction.add(Restrictions.eq(property, propertyValues.get(property))); } addToCriteria(conjunction); return this; @@ -431,9 +433,8 @@ public Criteria allEq(Map propertyValues) { /** * Creates a subquery criterion that ensures the given property is equal to all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria eqAll(String propertyName, Closure propertyValue) { @@ -448,9 +449,8 @@ private QueryableCriteria buildQueryableCriteria(Closure queryClosure) { /** * Creates a subquery criterion that ensures the given property is greater than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria gtAll(String propertyName, Closure propertyValue) { @@ -460,9 +460,8 @@ public Criteria gtAll(String propertyName, Closure propertyValue) { /** * Creates a subquery criterion that ensures the given property is less than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria ltAll(String propertyName, Closure propertyValue) { @@ -472,9 +471,8 @@ public Criteria ltAll(String propertyName, Closure propertyValue) { /** * Creates a subquery criterion that ensures the given property is greater than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria geAll(String propertyName, Closure propertyValue) { @@ -484,9 +482,8 @@ public Criteria geAll(String propertyName, Closure propertyValue) { /** * Creates a subquery criterion that ensures the given property is less than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria leAll(String propertyName, Closure propertyValue) { @@ -496,9 +493,8 @@ public Criteria leAll(String propertyName, Closure propertyValue) { /** * Creates a subquery criterion that ensures the given property is equal to all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria eqAll(String propertyName, QueryableCriteria propertyValue) { @@ -510,9 +506,8 @@ public Criteria eqAll(String propertyName, QueryableCriteria propertyValue) { /** * Creates a subquery criterion that ensures the given property is greater than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria gtAll(String propertyName, QueryableCriteria propertyValue) { @@ -606,9 +601,8 @@ public Criteria notIn(String propertyName, Closure subquery) { /** * Creates a subquery criterion that ensures the given property is less than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria ltAll(String propertyName, QueryableCriteria propertyValue) { @@ -620,9 +614,8 @@ public Criteria ltAll(String propertyName, QueryableCriteria propertyValue) { /** * Creates a subquery criterion that ensures the given property is greater than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria geAll(String propertyName, QueryableCriteria propertyValue) { @@ -634,9 +627,8 @@ public Criteria geAll(String propertyName, QueryableCriteria propertyValue) { /** * Creates a subquery criterion that ensures the given property is less than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria leAll(String propertyName, QueryableCriteria propertyValue) { @@ -649,7 +641,6 @@ public Criteria leAll(String propertyName, QueryableCriteria propertyValue) { * Creates an "equals" Criterion based on the specified property name and value. * * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria idEq(Object propertyValue) { @@ -660,9 +651,8 @@ public Criteria idEq(Object propertyValue) { /** * Creates a "not equals" Criterion based on the specified property name and value. * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria ne(String propertyName, Object propertyValue) { @@ -675,9 +665,8 @@ public Criteria ne(String propertyName, Object propertyValue) { * Restricts the results by the given property value range (inclusive) * * @param propertyName The property name - * - * @param start The start of the range - * @param finish The end of the range + * @param start The start of the range + * @param finish The end of the range * @return A Criterion instance */ public Criteria between(String propertyName, Object start, Object finish) { @@ -688,8 +677,9 @@ public Criteria between(String propertyName, Object start, Object finish) { /** * Used to restrict a value to be greater than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The Criterion instance */ public Criteria gte(String property, Object value) { @@ -700,8 +690,9 @@ public Criteria gte(String property, Object value) { /** * Used to restrict a value to be greater than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The Criterion instance */ public Criteria ge(String property, Object value) { @@ -711,8 +702,9 @@ public Criteria ge(String property, Object value) { /** * Used to restrict a value to be greater than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The Criterion instance */ public Criteria gt(String property, Object value) { @@ -723,8 +715,9 @@ public Criteria gt(String property, Object value) { /** * Used to restrict a value to be less than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The Criterion instance */ public Criteria lte(String property, Object value) { @@ -735,8 +728,9 @@ public Criteria lte(String property, Object value) { /** * Used to restrict a value to be less than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The Criterion instance */ public Criteria le(String property, Object value) { @@ -746,8 +740,9 @@ public Criteria le(String property, Object value) { /** * Used to restrict a value to be less than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The Criterion instance */ public Criteria lt(String property, Object value) { @@ -759,9 +754,8 @@ public Criteria lt(String property, Object value) { /** * Creates an like Criterion based on the specified property name and value. * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria like(String propertyName, Object propertyValue) { @@ -774,9 +768,8 @@ public Criteria like(String propertyName, Object propertyValue) { /** * Creates an ilike Criterion based on the specified property name and value. Unlike a like condition, ilike is case insensitive * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria ilike(String propertyName, Object propertyValue) { @@ -789,9 +782,8 @@ public Criteria ilike(String propertyName, Object propertyValue) { /** * Creates an rlike Criterion based on the specified property name and value. * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return A Criterion instance */ public Criteria rlike(String propertyName, Object propertyValue) { @@ -805,8 +797,7 @@ public Criteria rlike(String propertyName, Object propertyValue) { * Creates an "in" Criterion based on the specified property name and list of values. * * @param propertyName The property name - * @param values The values - * + * @param values The values * @return A Criterion instance */ public Criteria in(String propertyName, Collection values) { @@ -820,8 +811,7 @@ public Criteria in(String propertyName, Collection values) { * Creates an "in" Criterion based on the specified property name and list of values. * * @param propertyName The property name - * @param values The values - * + * @param values The values * @return A Criterion instance */ public Criteria inList(String propertyName, Collection values) { @@ -833,8 +823,7 @@ public Criteria inList(String propertyName, Collection values) { * Creates an "in" Criterion based on the specified property name and list of values. * * @param propertyName The property name - * @param values The values - * + * @param values The values * @return A Criterion instance */ public Criteria inList(String propertyName, Object[] values) { @@ -845,8 +834,7 @@ public Criteria inList(String propertyName, Object[] values) { * Creates an "in" Criterion based on the specified property name and list of values. * * @param propertyName The property name - * @param values The values - * + * @param values The values * @return A Criterion instance */ public Criteria in(String propertyName, Object[] values) { @@ -986,8 +974,7 @@ public Criteria order(String propertyName) { Query.Order o = Query.Order.asc(propertyName); if (paginationEnabledList) { orderEntries.add(o); - } - else { + } else { query.order(o); } return this; @@ -1003,8 +990,7 @@ public Criteria order(String propertyName) { public Criteria order(Query.Order o) { if (paginationEnabledList) { orderEntries.add(o); - } - else { + } else { query.order(o); } return this; @@ -1014,29 +1000,28 @@ public Criteria order(Query.Order o) { * Orders by the specified property name and direction * * @param propertyName The property name to order by - * @param direction Either "asc" for ascending or "desc" for descending - * + * @param direction Either "asc" for ascending or "desc" for descending * @return A Order instance */ public Criteria order(String propertyName, String direction) { Query.Order o; if (direction.equals(CriteriaBuilder.ORDER_DESCENDING)) { o = Query.Order.desc(propertyName); - } - else { + } else { o = Query.Order.asc(propertyName); } if (paginationEnabledList) { orderEntries.add(o); - } - else { + } else { query.order(o); } return this; } protected void validatePropertyName(String propertyName, String methodName) { - if (persistentEntity == null) return; + if (persistentEntity == null) { + return; + } if (propertyName == null) { throw new IllegalArgumentException("Cannot use [" + methodName + "] restriction with null property name"); @@ -1053,12 +1038,12 @@ protected void validatePropertyName(String propertyName, String methodName) { } protected void ensureQueryIsInitialized() { - if(query == null) { - query = queryCreator.createQuery(targetClass); - } - if(queryMetaClass == null) { - queryMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(query.getClass()); - } + if (query == null) { + query = queryCreator.createQuery(targetClass); + } + if (queryMetaClass == null) { + queryMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(query.getClass()); + } } private boolean isCriteriaConstructionMethod(String name, Object[] args) { @@ -1069,7 +1054,7 @@ private boolean isCriteriaConstructionMethod(String name, Object[] args) { protected void invokeClosureNode(Object args) { if (args instanceof Closure) { - Closure callable = (Closure)args; + Closure callable = (Closure) args; callable.setDelegate(this); callable.setResolveStrategy(Closure.DELEGATE_FIRST); callable.call(); @@ -1083,16 +1068,16 @@ private void handleJunction(Query.Junction junction, Closure callable) { invokeClosureNode(callable); } } finally { - Query.Junction logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); + Query.Junction logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size() - 1); addToCriteria(logicalExpression); } } /* - * adds and returns the given criterion to the currently active criteria set. - * this might be either the root criteria or a currently open - * LogicalExpression. - */ + * adds and returns the given criterion to the currently active criteria set. + * this might be either the root criteria or a currently open + * LogicalExpression. + */ protected Query.Criterion addToCriteria(Query.Criterion c) { if (c instanceof Query.PropertyCriterion) { Query.PropertyCriterion pc = (Query.PropertyCriterion) c; @@ -1104,8 +1089,7 @@ protected Query.Criterion addToCriteria(Query.Criterion c) { } if (!logicalExpressionStack.isEmpty()) { logicalExpressionStack.get(logicalExpressionStack.size() - 1).add(c); - } - else { + } else { if (query == null) { ensureQueryIsInitialized(); } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/criteria/AbstractDetachedCriteria.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/criteria/AbstractDetachedCriteria.groovy index 7fdb442884a..23a29b6e64d 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/criteria/AbstractDetachedCriteria.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/criteria/AbstractDetachedCriteria.groovy @@ -22,6 +22,8 @@ package org.grails.datastore.gorm.query.criteria import groovy.transform.CompileDynamic import groovy.transform.CompileStatic import groovy.transform.TypeCheckingMode +import jakarta.persistence.FetchType +import jakarta.persistence.criteria.JoinType import org.grails.datastore.gorm.finders.DynamicFinder import org.grails.datastore.gorm.finders.FinderMethod import org.grails.datastore.mapping.core.connections.ConnectionSource @@ -35,9 +37,6 @@ import org.grails.datastore.mapping.query.api.Criteria import org.grails.datastore.mapping.query.api.ProjectionList import org.grails.datastore.mapping.query.api.QueryableCriteria -import jakarta.persistence.FetchType -import jakarta.persistence.criteria.JoinType - /** * Abstract super class for DetachedCriteria implementations * @@ -64,10 +63,8 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { protected String connectionName = ConnectionSource.DEFAULT protected Map associationCriteriaMap = [:] - ProjectionList projectionList = new DetachedProjections(projections) - /** * Constructs a DetachedCriteria instance target the given class and alias for the name * @param targetClass The target class @@ -82,14 +79,14 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * @return Obtain the fetch strategies for each property */ Map getFetchStrategies() { - return Collections.unmodifiableMap( fetchStrategies ) + return Collections.unmodifiableMap(fetchStrategies) } /** * @return Obtain the join types */ Map getJoinTypes() { - return Collections.unmodifiableMap( joinTypes ) + return Collections.unmodifiableMap(joinTypes) } /** * @return The root alias to be used for the query @@ -118,34 +115,31 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { Criteria createAlias(String associationPath, String alias) { initialiseIfNecessary(targetClass) PersistentProperty prop - if(associationPath.contains('.')) { + if (associationPath.contains('.')) { def tokens = associationPath.split(/\./) def entity = this.persistentEntity - for(t in tokens) { + for (t in tokens) { prop = entity.getPropertyByName(t) if (!(prop instanceof Association)) { throw new IllegalArgumentException("Argument [$associationPath] is not an association") - } - else { - entity = ((Association)prop).associatedEntity + } else { + entity = ((Association) prop).associatedEntity } } - } - else { + } else { prop = persistentEntity.getPropertyByName(associationPath) } if (!(prop instanceof Association)) { throw new IllegalArgumentException("Argument [$associationPath] is not an association") } - Association a = (Association)prop + Association a = (Association) prop DetachedAssociationCriteria associationCriteria = associationCriteriaMap[associationPath] - if(associationCriteria == null) { + if (associationCriteria == null) { associationCriteria = new DetachedAssociationCriteria(a.associatedEntity.javaClass, a, associationPath, alias) associationCriteriaMap[associationPath] = associationCriteria add associationCriteria - } - else { + } else { associationCriteria.setAlias(alias) } return associationCriteria @@ -162,7 +156,6 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { return this } - /** * Specifies whether a join query should be used (if join queries are supported by the underlying datastore) * @@ -188,7 +181,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { } T getPersistentClass() { - (T)getPersistentEntity().getJavaClass() + (T) getPersistentEntity().getJavaClass() } PersistentEntity getPersistentEntity() { @@ -214,13 +207,12 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { applyLazyCriteria() if (criterion instanceof Query.PropertyCriterion) { if (criterion.value instanceof Closure) { - criterion.value = buildQueryableCriteria((Closure)criterion.value) + criterion.value = buildQueryableCriteria((Closure) criterion.value) } } - if (junctions) { + if (junctions) { junctions[-1].add criterion - } - else { + } else { criteria << criterion } } @@ -235,7 +227,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * Evaluate projections within the context of the given closure * * @param callable The callable - * @return The projection list + * @return The projection list */ Criteria projections(@DelegatesTo(ProjectionList) Closure callable) { callable.delegate = projectionList @@ -357,7 +349,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { protected List convertArgumentList(Collection argList) { List convertedList = new ArrayList(argList.size()); for (Object item : argList) { - if(item instanceof CharSequence) { + if (item instanceof CharSequence) { item = item.toString(); } convertedList.add(item); @@ -424,7 +416,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * @see Criteria */ Criteria eqProperty(String propertyName, String otherPropertyName) { - add Restrictions.eqProperty(propertyName,otherPropertyName) + add Restrictions.eqProperty(propertyName, otherPropertyName) return this } @@ -432,7 +424,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * @see Criteria#neProperty(java.lang.String, java.lang.String) */ Criteria neProperty(String propertyName, String otherPropertyName) { - add Restrictions.neProperty(propertyName,otherPropertyName) + add Restrictions.neProperty(propertyName, otherPropertyName) return this } @@ -453,7 +445,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * @see Criteria */ Criteria gtProperty(String propertyName, String otherPropertyName) { - add Restrictions.gtProperty(propertyName,otherPropertyName) + add Restrictions.gtProperty(propertyName, otherPropertyName) return this } @@ -461,7 +453,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * @see Criteria */ Criteria geProperty(String propertyName, String otherPropertyName) { - add Restrictions.geProperty(propertyName,otherPropertyName) + add Restrictions.geProperty(propertyName, otherPropertyName) return this } @@ -469,7 +461,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * @see Criteria */ Criteria ltProperty(String propertyName, String otherPropertyName) { - add Restrictions.ltProperty(propertyName,otherPropertyName) + add Restrictions.ltProperty(propertyName, otherPropertyName) return this } @@ -477,7 +469,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * @see Criteria */ Criteria leProperty(String propertyName, String otherPropertyName) { - add Restrictions.leProperty(propertyName,otherPropertyName) + add Restrictions.leProperty(propertyName, otherPropertyName) return this } @@ -543,7 +535,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * @see Criteria */ Criteria eq(String propertyName, Object propertyValue) { - add Restrictions.eq(propertyName,propertyValue) + add Restrictions.eq(propertyName, propertyValue) return this } @@ -559,7 +551,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * @see Criteria */ Criteria ne(String propertyName, Object propertyValue) { - add Restrictions.ne(propertyName,propertyValue) + add Restrictions.ne(propertyName, propertyValue) return this } @@ -575,7 +567,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * @see Criteria */ Criteria gte(String property, Object value) { - add Restrictions.gte(property,value) + add Restrictions.gte(property, value) return this } @@ -590,7 +582,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * @see Criteria */ Criteria gt(String property, Object value) { - add Restrictions.gt(property,value) + add Restrictions.gt(property, value) return this } @@ -606,14 +598,14 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * @see Criteria */ Criteria le(String property, Object value) { - lte(property,value) + lte(property, value) } /** * @see Criteria */ Criteria lt(String property, Object value) { - add Restrictions.lt(property,value) + add Restrictions.lt(property, value) return this } @@ -621,7 +613,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { * @see Criteria */ Criteria like(String propertyName, Object propertyValue) { - add Restrictions.like(propertyName,propertyValue.toString()) + add Restrictions.like(propertyName, propertyValue.toString()) return this } @@ -827,7 +819,6 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { return newQuery.build(additionalQuery) } - /** * Enable the builder syntax for constructing Criteria * @@ -856,7 +847,6 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { return newCriteria } - /** * Create a return a new DetachedCriteria that uses the given connection * @@ -1011,7 +1001,6 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { return newCriteria } - def propertyMissing(String name) { final entity = getPersistentEntity() final p = entity.getPropertyByName(name) @@ -1046,7 +1035,7 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { def method = dynamicFinders.find { FinderMethod f -> f.isMethodMatch(methodName) } if (method != null) { applyLazyCriteria() - return method.invoke(targetClass, methodName,this, args) + return method.invoke(targetClass, methodName, this, args) } if (!args) { @@ -1058,7 +1047,6 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { throw new MissingMethodException(methodName, AbstractDetachedCriteria, args) } - def alias = args[0] instanceof CharSequence ? args[0].toString() : null def existing = associationCriteriaMap[methodName] @@ -1069,16 +1057,14 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { associationCriteriaMap[methodName] = associationCriteria add associationCriteria - - def lastArg = args[-1] - if(lastArg instanceof Closure) { + if (lastArg instanceof Closure) { Closure callable = lastArg callable.resolveStrategy = Closure.DELEGATE_FIRST Closure parentCallable = callable - while(parentCallable.delegate instanceof Closure) { - parentCallable = (Closure)parentCallable.delegate + while (parentCallable.delegate instanceof Closure) { + parentCallable = (Closure) parentCallable.delegate } def previous = parentCallable.delegate @@ -1092,7 +1078,6 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { } } - protected void handleJunction(Closure callable) { try { callable.delegate = this @@ -1106,7 +1091,6 @@ abstract class AbstractDetachedCriteria implements Criteria, Cloneable { protected abstract QueryableCriteria buildQueryableCriteria(Closure queryClosure) - protected void applyLazyCriteria() { if (lazyQuery == null) { return diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/criteria/DetachedAssociationCriteria.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/criteria/DetachedAssociationCriteria.groovy index 623508d45ba..5f22629cef2 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/criteria/DetachedAssociationCriteria.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/criteria/DetachedAssociationCriteria.groovy @@ -20,7 +20,6 @@ package org.grails.datastore.gorm.query.criteria import grails.gorm.DetachedCriteria - import org.grails.datastore.mapping.model.types.Association import org.grails.datastore.mapping.query.Query.Criterion import org.grails.datastore.mapping.query.api.AssociationCriteria diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/ApplyDetachedCriteriaTransform.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/ApplyDetachedCriteriaTransform.java index 7e4537c5103..9f46846f45f 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/ApplyDetachedCriteriaTransform.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/ApplyDetachedCriteriaTransform.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.query.transform; import org.codehaus.groovy.transform.GroovyASTTransformationClass; @@ -32,5 +31,6 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) @GroovyASTTransformationClass("org.grails.datastore.gorm.query.transform.DetachedCriteriaASTTransformation") -public @interface ApplyDetachedCriteriaTransform { +public @interface ApplyDetachedCriteriaTransform { + } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaASTTransformation.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaASTTransformation.java index 5ff73e536b7..7d691bb7110 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaASTTransformation.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaASTTransformation.java @@ -31,7 +31,7 @@ /** * Transforms regular Groovy-style finders into detached criteria */ -@GroovyASTTransformation(phase= CompilePhase.CANONICALIZATION) +@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) public class DetachedCriteriaASTTransformation implements ASTTransformation, TransformWithPriority { /** diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaTransformer.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaTransformer.java index 4f21cfa00ed..73fee43c829 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaTransformer.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/DetachedCriteriaTransformer.java @@ -19,9 +19,44 @@ package org.grails.datastore.gorm.query.transform; import grails.gorm.DetachedCriteria; -import org.codehaus.groovy.ast.*; -import org.codehaus.groovy.ast.expr.*; -import org.codehaus.groovy.ast.stmt.*; +import org.codehaus.groovy.ast.ASTNode; +import org.codehaus.groovy.ast.ClassCodeVisitorSupport; +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.FieldNode; +import org.codehaus.groovy.ast.GenericsType; +import org.codehaus.groovy.ast.MethodNode; +import org.codehaus.groovy.ast.Parameter; +import org.codehaus.groovy.ast.Variable; +import org.codehaus.groovy.ast.VariableScope; +import org.codehaus.groovy.ast.expr.ArgumentListExpression; +import org.codehaus.groovy.ast.expr.BinaryExpression; +import org.codehaus.groovy.ast.expr.BitwiseNegationExpression; +import org.codehaus.groovy.ast.expr.CastExpression; +import org.codehaus.groovy.ast.expr.ClassExpression; +import org.codehaus.groovy.ast.expr.ClosureExpression; +import org.codehaus.groovy.ast.expr.ConstantExpression; +import org.codehaus.groovy.ast.expr.ConstructorCallExpression; +import org.codehaus.groovy.ast.expr.DeclarationExpression; +import org.codehaus.groovy.ast.expr.Expression; +import org.codehaus.groovy.ast.expr.GStringExpression; +import org.codehaus.groovy.ast.expr.MethodCallExpression; +import org.codehaus.groovy.ast.expr.NotExpression; +import org.codehaus.groovy.ast.expr.PropertyExpression; +import org.codehaus.groovy.ast.expr.RangeExpression; +import org.codehaus.groovy.ast.expr.StaticMethodCallExpression; +import org.codehaus.groovy.ast.expr.VariableExpression; +import org.codehaus.groovy.ast.stmt.BlockStatement; +import org.codehaus.groovy.ast.stmt.CaseStatement; +import org.codehaus.groovy.ast.stmt.CatchStatement; +import org.codehaus.groovy.ast.stmt.ExpressionStatement; +import org.codehaus.groovy.ast.stmt.ForStatement; +import org.codehaus.groovy.ast.stmt.IfStatement; +import org.codehaus.groovy.ast.stmt.ReturnStatement; +import org.codehaus.groovy.ast.stmt.Statement; +import org.codehaus.groovy.ast.stmt.SwitchStatement; +import org.codehaus.groovy.ast.stmt.TryCatchStatement; +import org.codehaus.groovy.ast.stmt.WhileStatement; import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.control.messages.LocatedMessage; import org.codehaus.groovy.syntax.Token; @@ -33,7 +68,15 @@ import java.io.PrintWriter; import java.io.StringWriter; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * ClassCodeVisitorSupport that transforms where methods into detached criteria queries @@ -44,8 +87,6 @@ @SuppressWarnings("unchecked") public class DetachedCriteriaTransformer extends ClassCodeVisitorSupport { - private static final Class[] EMPTY_JAVA_CLASS_ARRAY = {}; - private static final Object TRANSFORMED_MARKER = new Object(); public static final String AND_OPERATOR = "&"; public static final String OR_OPERATOR = "|"; public static final ClassNode DETACHED_CRITERIA_CLASS_NODE = ClassHelper.make(DetachedCriteria.class); @@ -54,10 +95,9 @@ public class DetachedCriteriaTransformer extends ClassCodeVisitorSupport { public static final String EQUALS_OPERATOR = "=="; public static final String IS_NULL_CRITERION = "isNull"; public static final ConstantExpression WHERE_LAZY = new ConstantExpression("whereLazy"); - - private SourceUnit sourceUnit; + private static final Object TRANSFORMED_MARKER = new Object(); + private static final Class[] EMPTY_JAVA_CLASS_ARRAY = {}; private static final Set CANDIDATE_METHODS = newSet("where", "whereLazy", "whereAny", "findAll", "find"); - private static final Set SUPPORTED_FUNCTIONS = newSet( "lower", "upper", "trim", "length", "second", "hour", "minute", "day", "month", "year"); @@ -73,7 +113,6 @@ public class DetachedCriteriaTransformer extends ClassCodeVisitorSupport { "=~", "ilike", "in", "inList"); - private static final Map METHOD_TO_SUBQUERY_MAP = (Map) newMap( "eq", "eqAll", "gt", "gtAll", @@ -115,12 +154,12 @@ public class DetachedCriteriaTransformer extends ClassCodeVisitorSupport { "sum", "sum", "property", "property", "count", "countDistinct"); - protected Map detachedCriteriaVariables = new HashMap(); protected Map aliases = new HashMap(); protected Map staticDetachedCriteriaVariables = new HashMap(); protected Set aliasExpressions = new HashSet(); protected ClassNode currentClassNode; + private SourceUnit sourceUnit; public DetachedCriteriaTransformer(SourceUnit sourceUnit) { this.sourceUnit = sourceUnit; @@ -319,18 +358,17 @@ public void visitMethodCallExpression(MethodCallExpression call) { this.currentClassNode = varType; visitMethodCall(varType, arguments); } else if (var.isThisExpression() && - currentClassNode != null && - isCandidateWhereMethod(method.getText(), arguments)) { + currentClassNode != null && + isCandidateWhereMethod(method.getText(), arguments)) { if (AstUtils.isDomainClass(currentClassNode)) { visitMethodCall(this.currentClassNode, arguments); call.setMethod(WHERE_LAZY); } - } - else { + } else { varType = var.getType(); - if(varType != null && varType.getName().equals(DETACHED_CRITERIA_CLASS_NODE.getName()) && isCandidateWhereMethod(method, arguments)) { + if (varType != null && varType.getName().equals(DETACHED_CRITERIA_CLASS_NODE.getName()) && isCandidateWhereMethod(method, arguments)) { GenericsType[] genericsTypes = varType.getGenericsTypes(); - if(genericsTypes != null && genericsTypes.length == 1) { + if (genericsTypes != null && genericsTypes.length == 1) { this.currentClassNode = genericsTypes[0].getType(); visitMethodCallOnDetachedCriteria(this.currentClassNode, (ArgumentListExpression) arguments); } @@ -346,23 +384,22 @@ public void visitMethodCallExpression(MethodCallExpression call) { visitMethodCall(classNode, arguments); } } - } else if(objectExpression instanceof MethodCallExpression) { - MethodCallExpression mce = (MethodCallExpression)objectExpression; + } else if (objectExpression instanceof MethodCallExpression) { + MethodCallExpression mce = (MethodCallExpression) objectExpression; MethodNode methodTarget = mce.getMethodTarget(); String methodName = mce.getMethodAsString(); Expression targetObject = mce.getObjectExpression(); ClassNode targetType = null; - if(targetObject instanceof ClassExpression) { - targetType = ((ClassExpression)targetObject).getType(); - } - else if(targetObject instanceof VariableExpression) { - targetType = ((VariableExpression)targetObject).getType(); + if (targetObject instanceof ClassExpression) { + targetType = ((ClassExpression) targetObject).getType(); + } else if (targetObject instanceof VariableExpression) { + targetType = ((VariableExpression) targetObject).getType(); } - if(targetType != null && AstUtils.isDomainClass(targetType) && isCandidateWhereMethod(method, arguments)) { + if (targetType != null && AstUtils.isDomainClass(targetType) && isCandidateWhereMethod(method, arguments)) { List methods = targetType.getMethods(methodName); for (MethodNode methodNode : methods) { - if(methodNode.getReturnType().equals(DETACHED_CRITERIA_CLASS_NODE)) { + if (methodNode.getReturnType().equals(DETACHED_CRITERIA_CLASS_NODE)) { visitMethodCall(targetType, arguments); } } @@ -389,7 +426,7 @@ private ClassExpression getTargetClassExpresssion(Expression objectExpression) { } else if (objectExpression instanceof VariableExpression) { VariableExpression ve = (VariableExpression) objectExpression; if (ve.isThisExpression() && - AstUtils.isDomainClass(this.currentClassNode)) { + AstUtils.isDomainClass(this.currentClassNode)) { return new ClassExpression(this.currentClassNode); } } @@ -480,7 +517,9 @@ public void visitStaticMethodCallExpression(StaticMethodCallExpression call) { } public void transformClosureExpression(ClassNode classNode, ClosureExpression closureExpression) { - if (closureExpression.getNodeMetaData(TRANSFORMED_MARKER) != null) return; + if (closureExpression.getNodeMetaData(TRANSFORMED_MARKER) != null) { + return; + } ClassNode previousClassNode = this.currentClassNode; try { this.currentClassNode = classNode; @@ -505,7 +544,6 @@ public void transformClosureExpression(ClassNode classNode, ClosureExpression cl } } - private void addBlockStatementToNewQuery(BlockStatement blockStatement, BlockStatement newCode, boolean addAll, List propertyNames, VariableScope variableScope) { List statements = blockStatement.getStatements(); for (Statement statement : statements) { @@ -521,12 +559,12 @@ private void addStatementToNewQuery(Statement statement, BlockStatement newCode, Expression expression = es.getExpression(); if (expression instanceof DeclarationExpression) { - DeclarationExpression de = (DeclarationExpression)expression; + DeclarationExpression de = (DeclarationExpression) expression; Expression leftExpression = de.getLeftExpression(); Expression rightExpression = de.getRightExpression(); - if((leftExpression instanceof VariableExpression) && (rightExpression instanceof ClassExpression)) { + if ((leftExpression instanceof VariableExpression) && (rightExpression instanceof ClassExpression)) { ClassExpression classExpression = (ClassExpression) rightExpression; - if(currentClassNode.equals(classExpression.getType())) { + if (currentClassNode.equals(classExpression.getType())) { ArgumentListExpression arguments = new ArgumentListExpression(); String aliasName = leftExpression.getText(); aliases.put(aliasName, currentClassNode); @@ -535,10 +573,9 @@ private void addStatementToNewQuery(Statement statement, BlockStatement newCode, newCode.addStatement(new ExpressionStatement(setAliasMethodCall)); } newCode.addStatement(es); - } - else if((leftExpression instanceof VariableExpression) && (rightExpression instanceof VariableExpression)) { + } else if ((leftExpression instanceof VariableExpression) && (rightExpression instanceof VariableExpression)) { String referencedProperty = rightExpression.getText(); - if(propertyNames.contains(referencedProperty)) { + if (propertyNames.contains(referencedProperty)) { ArgumentListExpression arguments = new ArgumentListExpression(); arguments.addExpression(new ConstantExpression(referencedProperty)); String aliasName = leftExpression.getText(); @@ -548,8 +585,7 @@ else if((leftExpression instanceof VariableExpression) && (rightExpression insta newCode.addStatement(new ExpressionStatement(createAliasMethodCall)); } newCode.addStatement(es); - } - else { + } else { newCode.addStatement(es); } } else if (expression instanceof BinaryExpression) { @@ -631,10 +667,9 @@ else if((leftExpression instanceof VariableExpression) && (rightExpression insta newCode.addStatement(tcs); } else if (statement instanceof ReturnStatement) { ReturnStatement rs = (ReturnStatement) statement; - addStatementToNewQuery(new ExpressionStatement(rs.getExpression()), newCode, addAll, propertyNames,variableScope); + addStatementToNewQuery(new ExpressionStatement(rs.getExpression()), newCode, addAll, propertyNames, variableScope); - } - else { + } else { newCode.addStatement(statement); } } @@ -695,8 +730,7 @@ private void handleAssociationMethodCallExpression(BlockStatement newCode, Metho currentClassNode = existing; } } - } - else { + } else { newCode.addStatement(new ExpressionStatement(methodCall)); } // else { @@ -734,7 +768,6 @@ private ClassNode getPropertyType(String prop) { return AstPropertyResolveUtils.getPropertyType(classNode, prop); } - private boolean isAssociationMethodCall(List propertyNames, String methodName, ArgumentListExpression arguments) { return propertyNames.contains(methodName) && hasClosureArgument(arguments); } @@ -877,7 +910,9 @@ private void handleFunctionCall(BlockStatement newCode, String operator, Express } private void handleBinaryExpressionSide(Expression expressionSide, Expression oppositeSide, String operator, BlockStatement newCode, boolean addAll, List propertyNames, VariableScope variableScope) { - if(aliasExpressions.contains(expressionSide)) return; + if (aliasExpressions.contains(expressionSide)) { + return; + } if (expressionSide instanceof BinaryExpression) { addBinaryExpressionToNewBody(propertyNames, newCode, (BinaryExpression) expressionSide, addAll, variableScope); } else if (expressionSide instanceof NotExpression) { @@ -910,11 +945,10 @@ private void handleAssociationQueryViaPropertyExpression(PropertyExpression pe, String propertyName = ve.getName(); // handle trait - if(!(propertyName.equals("$self") && Traits.isTrait(objectExpression.getType()))) { + if (!(propertyName.equals("$self") && Traits.isTrait(objectExpression.getType()))) { associationMethodCalls.add(propertyName); } - Collections.reverse(associationMethodCalls); ClassNode currentType = currentClassNode; @@ -929,7 +963,9 @@ private void handleAssociationQueryViaPropertyExpression(PropertyExpression pe, ArgumentListExpression arguments = closureAndArguments.getArguments(); ClassNode type = getPropertyTypeFromGenerics(associationMethodCall, currentType); - if (type == null) break; + if (type == null) { + break; + } currentType = type; currentBody.addStatement(new ExpressionStatement(new MethodCallExpression(delegateExpression, associationMethodCall, arguments))); @@ -957,7 +993,7 @@ private void handleAssociationQueryViaPropertyExpression(PropertyExpression pe, } else if (objectExpression instanceof VariableExpression) { String propertyName = objectExpression.getText(); // handle trait - if(propertyName.equals("$self") && Traits.isTrait(objectExpression.getType())) { + if (propertyName.equals("$self") && Traits.isTrait(objectExpression.getType())) { propertyName = pe.getPropertyAsString(); } Object aliased = aliases.get(propertyName); @@ -967,9 +1003,9 @@ private void handleAssociationQueryViaPropertyExpression(PropertyExpression pe, ClassNode classNode = currentClassNode; ClassNode type = getPropertyTypeFromGenerics(actualPropertyName, classNode); - if(!AstUtils.isDomainClass(type)) { + if (!AstUtils.isDomainClass(type)) { - if(AstUtils.isGroovyType(type)) { + if (AstUtils.isGroovyType(type)) { // an embedded property List associationPropertyNames = AstPropertyResolveUtils.getPropertyNames(type); boolean hasNoProperties = associationPropertyNames.isEmpty(); @@ -994,12 +1030,10 @@ private void handleAssociationQueryViaPropertyExpression(PropertyExpression pe, } newCode.addStatement(new ExpressionStatement(new MethodCallExpression(new VariableExpression("delegate"), actualPropertyName, arguments))); - } - else { + } else { addCriteriaCallMethodExpression(newCode, operator, pe, oppositeSide, associationProperty, Collections.emptyList(), false, variableScope); } - } - else { + } else { List associationPropertyNames = getPropertyNamesForAssociation(type); if (associationPropertyNames == null) { @@ -1027,11 +1061,11 @@ private void handleAssociationQueryViaPropertyExpression(PropertyExpression pe, } newCode.addStatement(new ExpressionStatement(new MethodCallExpression(new VariableExpression("delegate"), actualPropertyName, arguments))); } - } else if((aliased instanceof ClassNode) && (oppositeSide instanceof PropertyExpression)) { + } else if ((aliased instanceof ClassNode) && (oppositeSide instanceof PropertyExpression)) { String rootReference = pe.getText(); PropertyExpression oppositeProperty = (PropertyExpression) oppositeSide; String targetObject = oppositeProperty.getObjectExpression().getText(); - if(aliases.containsKey(targetObject)) { + if (aliases.containsKey(targetObject)) { String methodToCall = PROPERTY_COMPARISON_OPERATOR_TO_CRITERIA_METHOD_MAP.get(operator); ArgumentListExpression args = new ArgumentListExpression(); args.addExpression(new ConstantExpression(rootReference)); @@ -1045,7 +1079,6 @@ private void handleAssociationQueryViaPropertyExpression(PropertyExpression pe, } } - private ClassNode getPropertyTypeFromGenerics(String propertyName, ClassNode classNode) { ClassNode type = AstPropertyResolveUtils.getPropertyType(classNode, propertyName); if (type != null && !AstUtils.isDomainClass(type)) { @@ -1106,8 +1139,8 @@ private void addCriteriaCall(BlockStatement newCode, String operator, Expression } } } else if (aggregateFunctionName != null) { - if((methodTarget instanceof VariableExpression) && - ((VariableExpression)methodTarget).isThisExpression()) { + if ((methodTarget instanceof VariableExpression) && + ((VariableExpression) methodTarget).isThisExpression()) { Expression arguments = aggregateMethodCall.getArguments(); if (arguments instanceof ArgumentListExpression) { ArgumentListExpression argList = (ArgumentListExpression) arguments; @@ -1213,24 +1246,22 @@ private void addCriteriaCall(BlockStatement newCode, String operator, Expression arguments.addExpression(new ConstantExpression(propertyName)) .addExpression(rightExpression); } - } else if(rightExpression instanceof PropertyExpression) { + } else if (rightExpression instanceof PropertyExpression) { PropertyExpression pe = (PropertyExpression) rightExpression; String property = pe.getObjectExpression().getText(); - if((leftExpression instanceof PropertyExpression ) && aliases.containsKey(property)) { + if ((leftExpression instanceof PropertyExpression) && aliases.containsKey(property)) { aliasExpressions.add(pe); arguments = new ArgumentListExpression(); - arguments.addExpression(new ConstantExpression(((PropertyExpression)leftExpression).getPropertyAsString())); + arguments.addExpression(new ConstantExpression(((PropertyExpression) leftExpression).getPropertyAsString())); arguments.addExpression(new ConstantExpression(pe.getText())); methodToCall = PROPERTY_COMPARISON_OPERATOR_TO_CRITERIA_METHOD_MAP.get(operator); - } - else if((leftExpression instanceof VariableExpression) && aliases.containsKey(property)) { + } else if ((leftExpression instanceof VariableExpression) && aliases.containsKey(property)) { aliasExpressions.add(pe); arguments = new ArgumentListExpression(); - arguments.addExpression(new ConstantExpression(((VariableExpression)leftExpression).getName())); + arguments.addExpression(new ConstantExpression(((VariableExpression) leftExpression).getName())); arguments.addExpression(new ConstantExpression(pe.getText())); methodToCall = PROPERTY_COMPARISON_OPERATOR_TO_CRITERIA_METHOD_MAP.get(operator); - } - else { + } else { arguments = new ArgumentListExpression(); arguments.addExpression(new ConstantExpression(propertyName)) .addExpression(rightExpression); @@ -1257,7 +1288,32 @@ protected SourceUnit getSourceUnit() { return this.sourceUnit; } - private class ClosureAndArguments { + @SuppressWarnings("rawtypes") + private static Map newMap(Object... keysAndValues) { + if (keysAndValues == null) { + return Collections.emptyMap(); + } + if (keysAndValues.length % 2 == 1) { + throw new IllegalArgumentException("Must have an even number of keys and values"); + } + + Map map = new HashMap(); + for (int i = 0; i < keysAndValues.length; i += 2) { + map.put((K) keysAndValues[i], (V) keysAndValues[i + 1]); + } + return map; + } + + private static Set newSet(T... values) { + if (values == null) { + return Collections.emptySet(); + } + + return new HashSet(Arrays.asList(values)); + } + + private static final class ClosureAndArguments { + private BlockStatement currentBody; private ArgumentListExpression arguments; private ClosureExpression closureExpression; @@ -1291,28 +1347,4 @@ public ClosureExpression getClosureExpression() { return closureExpression; } } - - @SuppressWarnings("rawtypes") - private static Map newMap(Object... keysAndValues) { - if (keysAndValues == null) { - return Collections.emptyMap(); - } - if (keysAndValues.length % 2 == 1) { - throw new IllegalArgumentException("Must have an even number of keys and values"); - } - - Map map = new HashMap(); - for (int i = 0; i < keysAndValues.length; i += 2) { - map.put((K) keysAndValues[i], (V) keysAndValues[i + 1]); - } - return map; - } - - private static Set newSet(T... values) { - if (values == null) { - return Collections.emptySet(); - } - - return new HashSet(Arrays.asList(values)); - } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/GlobalDetachedCriteriaASTTransformation.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/GlobalDetachedCriteriaASTTransformation.java index da98de4e91e..bae72e6cf79 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/GlobalDetachedCriteriaASTTransformation.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/transform/GlobalDetachedCriteriaASTTransformation.java @@ -36,8 +36,9 @@ * @author Graeme Rocher * @since 1.0 */ -@GroovyASTTransformation(phase= CompilePhase.CANONICALIZATION) +@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) public class GlobalDetachedCriteriaASTTransformation implements ASTTransformation, TransformWithPriority { + /** * The method is invoked when an AST Transformation is active. For local transformations, it is invoked once * each time the local annotation is encountered. For global transformations, it is invoked once for every source diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributeHelper.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributeHelper.java index ab08e0db84d..0d3d76d15f4 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributeHelper.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributeHelper.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.schemaless; /** diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributes.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributes.groovy index 39188919278..bdbf5a6eb6b 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributes.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributes.groovy @@ -35,9 +35,9 @@ trait DynamicAttributes { private void putAtDynamic(String name, value) { def oldValue = dynamicAttributes.put(name, value) - if(oldValue != value) { - if(this instanceof DirtyCheckable) { - ((DirtyCheckable)this).markDirty(name, value, oldValue) + if (oldValue != value) { + if (this instanceof DirtyCheckable) { + ((DirtyCheckable) this).markDirty(name, value, oldValue) } } } @@ -49,9 +49,9 @@ trait DynamicAttributes { * @param value The value of the attribute */ void putAt(String name, value) { - if(this.hasProperty(name)) { + if (this.hasProperty(name)) { try { - ((GroovyObject)this).setProperty(name, value) + ((GroovyObject) this).setProperty(name, value) } catch (ReadOnlyPropertyException e) { putAtDynamic(name, value) } @@ -67,10 +67,9 @@ trait DynamicAttributes { * @return The value of the attribute */ def getAt(String name) { - if(this.hasProperty(name)) { - return ((GroovyObject)this).getProperty(name) - } - else { + if (this.hasProperty(name)) { + return ((GroovyObject) this).getProperty(name) + } else { dynamicAttributes.get(name) } } @@ -91,7 +90,7 @@ trait DynamicAttributes { * @return The dynamic attributes */ Map attributes(Map newAttributes) { - if(newAttributes != null) { + if (newAttributes != null) { this.dynamicAttributes.putAll(newAttributes) } return dynamicAttributes diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/DefaultTenantService.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/DefaultTenantService.groovy index d6123940cd7..9930358757f 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/DefaultTenantService.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/DefaultTenantService.groovy @@ -21,7 +21,6 @@ package org.grails.datastore.gorm.services import grails.gorm.multitenancy.TenantService import grails.gorm.multitenancy.Tenants import groovy.transform.CompileStatic -import org.grails.datastore.mapping.core.connections.ConnectionSource import org.grails.datastore.mapping.model.DatastoreConfigurationException import org.grails.datastore.mapping.multitenancy.MultiTenancySettings import org.grails.datastore.mapping.multitenancy.MultiTenantCapableDatastore @@ -46,10 +45,9 @@ class DefaultTenantService implements Service, TenantService { Serializable currentId() { MultiTenantCapableDatastore multiTenantCapableDatastore = multiTenantDatastore() def mode = multiTenantCapableDatastore.getMultiTenancyMode() - if(mode != MultiTenancySettings.MultiTenancyMode.NONE) { + if (mode != MultiTenancySettings.MultiTenancyMode.NONE) { return Tenants.currentId(multiTenantCapableDatastore) - } - else { + } else { throw new DatastoreConfigurationException("Current datastore [$datastore] is not configured for Multi-Tenancy") } } @@ -58,10 +56,9 @@ class DefaultTenantService implements Service, TenantService { def T withoutId(Closure callable) { MultiTenantCapableDatastore multiTenantCapableDatastore = multiTenantDatastore() def mode = multiTenantCapableDatastore.getMultiTenancyMode() - if(mode != MultiTenancySettings.MultiTenancyMode.NONE) { + if (mode != MultiTenancySettings.MultiTenancyMode.NONE) { return Tenants.withoutId(multiTenantCapableDatastore, callable) - } - else { + } else { throw new DatastoreConfigurationException("Current datastore [$datastore] is not configured for Multi-Tenancy") } } @@ -70,10 +67,9 @@ class DefaultTenantService implements Service, TenantService { def T withCurrent(Closure callable) { MultiTenantCapableDatastore multiTenantCapableDatastore = multiTenantDatastore() def mode = multiTenantCapableDatastore.getMultiTenancyMode() - if(mode != MultiTenancySettings.MultiTenancyMode.NONE) { + if (mode != MultiTenancySettings.MultiTenancyMode.NONE) { return Tenants.withId(multiTenantCapableDatastore, currentId(), callable) - } - else { + } else { throw new DatastoreConfigurationException("Current datastore [$datastore] is not configured for Multi-Tenancy") } } @@ -82,10 +78,9 @@ class DefaultTenantService implements Service, TenantService { def T withId(Serializable tenantId, Closure callable) { MultiTenantCapableDatastore multiTenantCapableDatastore = multiTenantDatastore() def mode = multiTenantCapableDatastore.getMultiTenancyMode() - if(mode != MultiTenancySettings.MultiTenancyMode.NONE) { + if (mode != MultiTenancySettings.MultiTenancyMode.NONE) { return Tenants.withId(multiTenantCapableDatastore, tenantId, callable) - } - else { + } else { throw new DatastoreConfigurationException("Current datastore [$datastore] is not configured for Multi-Tenancy") } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/DefaultTransactionService.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/DefaultTransactionService.groovy index c90809c62c8..4ce26eeb678 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/DefaultTransactionService.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/DefaultTransactionService.groovy @@ -18,8 +18,8 @@ */ package org.grails.datastore.gorm.services -import grails.gorm.transactions.TransactionService import grails.gorm.transactions.GrailsTransactionTemplate +import grails.gorm.transactions.TransactionService import groovy.transform.CompileDynamic import groovy.transform.CompileStatic import groovy.transform.stc.ClosureParams @@ -39,14 +39,14 @@ import org.springframework.transaction.TransactionSystemException */ @CompileStatic class DefaultTransactionService implements TransactionService, Service { + @Override def T withTransaction( @ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) { - if(datastore instanceof TransactionCapableDatastore) { - GrailsTransactionTemplate template = new GrailsTransactionTemplate(((TransactionCapableDatastore)datastore).transactionManager) + if (datastore instanceof TransactionCapableDatastore) { + GrailsTransactionTemplate template = new GrailsTransactionTemplate(((TransactionCapableDatastore) datastore).transactionManager) return template.execute(callable) - } - else { + } else { throw new TransactionSystemException("Datastore [$datastore] does not support transactions") } } @@ -54,11 +54,10 @@ class DefaultTransactionService implements TransactionService, Service { @Override def T withRollback( @ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) { - if(datastore instanceof TransactionCapableDatastore) { - GrailsTransactionTemplate template = new GrailsTransactionTemplate(((TransactionCapableDatastore)datastore).transactionManager) + if (datastore instanceof TransactionCapableDatastore) { + GrailsTransactionTemplate template = new GrailsTransactionTemplate(((TransactionCapableDatastore) datastore).transactionManager) return template.executeAndRollback(callable) - } - else { + } else { throw new TransactionSystemException("Datastore [$datastore] does not support transactions") } } @@ -66,13 +65,12 @@ class DefaultTransactionService implements TransactionService, Service { @Override def T withNewTransaction( @ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) { - if(datastore instanceof TransactionCapableDatastore) { + if (datastore instanceof TransactionCapableDatastore) { PlatformTransactionManager transactionManager = ((TransactionCapableDatastore) datastore).transactionManager def txDef = new CustomizableRollbackTransactionAttribute(propagationBehavior: TransactionDefinition.PROPAGATION_REQUIRES_NEW) GrailsTransactionTemplate template = new GrailsTransactionTemplate(transactionManager, txDef) return template.execute(callable) - } - else { + } else { throw new TransactionSystemException("Datastore [$datastore] does not support transactions") } } @@ -80,12 +78,11 @@ class DefaultTransactionService implements TransactionService, Service { @Override def T withTransaction(TransactionDefinition definition, @ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) { - if(datastore instanceof TransactionCapableDatastore) { + if (datastore instanceof TransactionCapableDatastore) { PlatformTransactionManager transactionManager = ((TransactionCapableDatastore) datastore).transactionManager GrailsTransactionTemplate template = new GrailsTransactionTemplate(transactionManager, definition) return template.execute(callable) - } - else { + } else { throw new TransactionSystemException("Datastore [$datastore] does not support transactions") } } @@ -93,13 +90,12 @@ class DefaultTransactionService implements TransactionService, Service { @Override def T withTransaction(Map definition, @ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) { - if(datastore instanceof TransactionCapableDatastore) { + if (datastore instanceof TransactionCapableDatastore) { PlatformTransactionManager transactionManager = ((TransactionCapableDatastore) datastore).transactionManager def txDef = newDefinition(definition) GrailsTransactionTemplate template = new GrailsTransactionTemplate(transactionManager, txDef) return template.execute(callable) - } - else { + } else { throw new TransactionSystemException("Datastore [$datastore] does not support transactions") } } @@ -112,12 +108,11 @@ class DefaultTransactionService implements TransactionService, Service { @Override def T withRollback(TransactionDefinition definition, @ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) { - if(datastore instanceof TransactionCapableDatastore) { + if (datastore instanceof TransactionCapableDatastore) { PlatformTransactionManager transactionManager = ((TransactionCapableDatastore) datastore).transactionManager GrailsTransactionTemplate template = new GrailsTransactionTemplate(transactionManager, definition) return template.executeAndRollback(callable) - } - else { + } else { throw new TransactionSystemException("Datastore [$datastore] does not support transactions") } @@ -126,14 +121,13 @@ class DefaultTransactionService implements TransactionService, Service { @Override def T withNewTransaction(TransactionDefinition definition, @ClosureParams(value = SimpleType.class, options = "org.springframework.transaction.TransactionStatus") Closure callable) { - if(datastore instanceof TransactionCapableDatastore) { + if (datastore instanceof TransactionCapableDatastore) { PlatformTransactionManager transactionManager = ((TransactionCapableDatastore) datastore).transactionManager def txDef = new CustomizableRollbackTransactionAttribute(definition) txDef.propagationBehavior = TransactionDefinition.PROPAGATION_REQUIRES_NEW GrailsTransactionTemplate template = new GrailsTransactionTemplate(transactionManager, txDef) return template.execute(callable) - } - else { + } else { throw new TransactionSystemException("Datastore [$datastore] does not support transactions") } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/Implemented.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/Implemented.groovy index 49ac7b0160b..f9aba31912f 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/Implemented.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/Implemented.groovy @@ -34,5 +34,6 @@ import java.lang.annotation.Target @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @interface Implemented { + Class by() } \ No newline at end of file diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractArrayOrIterableResultImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractArrayOrIterableResultImplementer.groovy index 6acb87b1e10..10985cd287f 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractArrayOrIterableResultImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractArrayOrIterableResultImplementer.groovy @@ -46,10 +46,10 @@ abstract class AbstractArrayOrIterableResultImplementer extends AbstractReadOper @Override final void doImplement(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, ClassNode targetClassNode) { - ClassNode returnType = (ClassNode)newMethodNode.getNodeMetaData(RETURN_TYPE) ?: abstractMethodNode.returnType + ClassNode returnType = (ClassNode) newMethodNode.getNodeMetaData(RETURN_TYPE) ?: abstractMethodNode.returnType boolean isArray = returnType.isArray() ClassNode domainClassForReturnType = resolveDomainClassForReturnType(domainClassNode, isArray, returnType) - if(AstUtils.isDomainClass(domainClassForReturnType)) { + if (AstUtils.isDomainClass(domainClassForReturnType)) { domainClassNode = domainClassForReturnType } doImplement(domainClassNode, targetClassNode, abstractMethodNode, newMethodNode, isArray) @@ -64,12 +64,11 @@ abstract class AbstractArrayOrIterableResultImplementer extends AbstractReadOper * @return The domain class type */ protected ClassNode resolveDomainClassForReturnType(ClassNode currentDomainClass, boolean isArray, ClassNode returnType) { - if(returnType.isArray()) { + if (returnType.isArray()) { return returnType.componentType - } - else { + } else { GenericsType[] genericTypes = returnType.genericsTypes - if(genericTypes) { + if (genericTypes) { return genericTypes[0].type } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractDetachedCriteriaServiceImplementor.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractDetachedCriteriaServiceImplementor.groovy index 8c657eb0955..5d43c98c2c8 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractDetachedCriteriaServiceImplementor.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractDetachedCriteriaServiceImplementor.groovy @@ -35,7 +35,15 @@ import org.codehaus.groovy.ast.stmt.BlockStatement import org.grails.datastore.mapping.model.config.GormProperties import org.grails.datastore.mapping.reflect.AstUtils -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX /** * An abstract implementer that builds a detached criteria query from the method arguments @@ -54,23 +62,22 @@ abstract class AbstractDetachedCriteriaServiceImplementor extends AbstractReadOp Parameter[] parameters = newMethodNode.parameters int parameterCount = parameters.length AnnotationNode joinAnnotation = AstUtils.findAnnotation(abstractMethodNode, Join) - if(lookupById() && joinAnnotation == null && parameterCount == 1 && parameters[0].name == GormProperties.IDENTITY) { + if (lookupById() && joinAnnotation == null && parameterCount == 1 && parameters[0].name == GormProperties.IDENTITY) { // optimize query by id - Expression byId = callX( classX(domainClassNode), "get", varX(parameters[0])) - implementById(domainClassNode,abstractMethodNode,newMethodNode, targetClassNode, body, byId) - } - else { + Expression byId = callX(classX(domainClassNode), "get", varX(parameters[0])) + implementById(domainClassNode, abstractMethodNode, newMethodNode, targetClassNode, body, byId) + } else { Expression argsExpression = AstUtils.ZERO_ARGUMENTS VariableExpression queryVar = varX('$query') // def query = new DetachedCriteria(Foo) body.addStatement( - declS(queryVar, ctorX(getDetachedCriteriaType(domainClassNode), args(classX(domainClassNode.plainNodeReference)))) + declS(queryVar, ctorX(getDetachedCriteriaType(domainClassNode), args(classX(domainClassNode.plainNodeReference)))) ) Expression connectionId = findConnectionId(newMethodNode) - if(connectionId != null) { + if (connectionId != null) { body.addStatement( - assignS(queryVar, callX(queryVar, "withConnection", connectionId)) + assignS(queryVar, callX(queryVar, "withConnection", connectionId)) ) } handleJoinAnnotation(joinAnnotation, body, queryVar) @@ -78,18 +85,17 @@ abstract class AbstractDetachedCriteriaServiceImplementor extends AbstractReadOp if (parameterCount > 0) { for (Parameter parameter in parameters) { String parameterName = parameter.name - if(parameterName == GormProperties.IDENTITY) { + if (parameterName == GormProperties.IDENTITY) { body.addStatement( - stmt( - callX(queryVar, "idEq", varX(parameter)) - ) + stmt( + callX(queryVar, "idEq", varX(parameter)) + ) ) - } - else if (isValidParameter(domainClassNode, parameter, parameterName)) { + } else if (isValidParameter(domainClassNode, parameter, parameterName)) { body.addStatement( - stmt( - callX(queryVar, "eq", args( constX(parameterName), varX(parameter) )) - ) + stmt( + callX(queryVar, "eq", args(constX(parameterName), varX(parameter))) + ) ) } else if (parameter.type == ClassHelper.MAP_TYPE && parameterName == 'args') { argsExpression = varX(parameter) diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractProjectionImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractProjectionImplementer.groovy index 958b64378f9..00b9e624da6 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractProjectionImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractProjectionImplementer.groovy @@ -62,13 +62,12 @@ abstract class AbstractProjectionImplementer extends AbstractDetachedCriteriaSer } protected boolean isValidPropertyType(ClassNode returnType, ClassNode propertyType) { - if(propertyType == null) return false + if (propertyType == null) return false else { returnType == propertyType || AstUtils.isSubclassOfOrImplementsInterface(returnType, propertyType) } } - @Override protected boolean lookupById() { return false @@ -79,11 +78,10 @@ abstract class AbstractProjectionImplementer extends AbstractDetachedCriteriaSer // no-op } - @Override void implementWithQuery(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, ClassNode targetClassNode, BlockStatement body, VariableExpression detachedCriteriaVar, Expression queryArgs) { - String propertyName = (String)abstractMethodNode.getNodeMetaData(RESOLVED_PROPERTY_NAME) - assert propertyName != null : "Bug in ${getClass().name} transform logic. Method implement should never be called before doesImplement(..) check" + String propertyName = (String) abstractMethodNode.getNodeMetaData(RESOLVED_PROPERTY_NAME) + assert propertyName != null: "Bug in ${getClass().name} transform logic. Method implement should never be called before doesImplement(..) check" body.addStatements([ assignS(detachedCriteriaVar, callX(detachedCriteriaVar, getProjectionName(), constX(propertyName))), diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractReadOperationImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractReadOperationImplementer.groovy index c9039574bf4..34345ae2adc 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractReadOperationImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractReadOperationImplementer.groovy @@ -53,13 +53,13 @@ abstract class AbstractReadOperationImplementer extends AbstractServiceImplement final void implement(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, ClassNode targetClassNode) { // copy any annotations from the abstract method copyClassAnnotations(abstractMethodNode, newMethodNode) - if(!TransactionalTransform.hasTransactionalAnnotation(targetClassNode) && !TransactionalTransform.hasTransactionalAnnotation(newMethodNode) && Modifier.isPublic(newMethodNode.modifiers)) { + if (!TransactionalTransform.hasTransactionalAnnotation(targetClassNode) && !TransactionalTransform.hasTransactionalAnnotation(newMethodNode) && Modifier.isPublic(newMethodNode.modifiers)) { // read-only transaction by default applyDefaultTransactionHandling(newMethodNode) } ClassNode domainClassFromSignature = resolveDomainClassFromSignature(domainClassNode, abstractMethodNode) - if(domainClassFromSignature != null && AstUtils.isDomainClass(domainClassFromSignature)) { + if (domainClassFromSignature != null && AstUtils.isDomainClass(domainClassFromSignature)) { domainClassNode = domainClassFromSignature } doImplement(domainClassNode, abstractMethodNode, newMethodNode, targetClassNode) @@ -88,7 +88,7 @@ abstract class AbstractReadOperationImplementer extends AbstractServiceImplement @Override void enhance(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, ClassNode targetClassNode) { - if(!TransactionalTransform.hasTransactionalAnnotation(newMethodNode) && Modifier.isPublic(newMethodNode.modifiers)) { + if (!TransactionalTransform.hasTransactionalAnnotation(newMethodNode) && Modifier.isPublic(newMethodNode.modifiers)) { // read-only transaction by default applyDefaultTransactionHandling(newMethodNode) } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractSaveImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractSaveImplementer.groovy index 4475811adbe..2c5e2ac25fd 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractSaveImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractSaveImplementer.groovy @@ -31,14 +31,14 @@ import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.Statement import org.grails.datastore.mapping.reflect.AstUtils +import static org.codehaus.groovy.ast.tools.GeneralUtils.args import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS -import static org.codehaus.groovy.ast.tools.GeneralUtils.propX -import static org.codehaus.groovy.ast.tools.GeneralUtils.varX +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX import static org.codehaus.groovy.ast.tools.GeneralUtils.declS -import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.propX import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS -import static org.codehaus.groovy.ast.tools.GeneralUtils.callX import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.namedArgs /** @@ -49,6 +49,7 @@ import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.namedAr */ @CompileStatic abstract class AbstractSaveImplementer extends AbstractWriteOperationImplementer { + protected Statement bindParametersAndSave(ClassNode domainClassNode, MethodNode abstractMethodNode, Parameter[] parameters, BlockStatement body, VariableExpression entityVar) { Expression argsExpression = null @@ -82,10 +83,9 @@ abstract class AbstractSaveImplementer extends AbstractWriteOperationImplementer } Expression connectionId = findConnectionId(abstractMethodNode) - if(connectionId != null) { + if (connectionId != null) { returnS(callX(buildInstanceApiLookup(domainClassNode, connectionId), "save", args(entityVar, saveArgs))) - } - else { + } else { return returnS(callX(entityVar, "save", saveArgs)) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractServiceImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractServiceImplementer.groovy index 9e8c619b8c8..1fde1e3b77d 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractServiceImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractServiceImplementer.groovy @@ -44,8 +44,12 @@ import org.grails.datastore.mapping.services.ServiceRegistry import org.grails.datastore.mapping.transactions.TransactionCapableDatastore import static org.codehaus.groovy.ast.ClassHelper.make -import static org.codehaus.groovy.ast.tools.GeneralUtils.* -import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.castX +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX +import static org.codehaus.groovy.ast.tools.GeneralUtils.propX +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX +import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.callD /** * Abstract implementation of the {@link ServiceImplementer} interface @@ -66,7 +70,7 @@ abstract class AbstractServiceImplementer implements PrefixedServiceImplementer, def alreadyImplemented = methodNode.getNodeMetaData(IMPLEMENTED) String prefix = resolvePrefix(methodNode) - if(!alreadyImplemented && prefix) { + if (!alreadyImplemented && prefix) { ClassNode returnType = methodNode.returnType return isCompatibleReturnType(domainClass, methodNode, returnType, prefix) } @@ -87,7 +91,6 @@ abstract class AbstractServiceImplementer implements PrefixedServiceImplementer, */ protected abstract boolean isCompatibleReturnType(ClassNode domainClass, MethodNode methodNode, ClassNode returnType, String prefix) - /** * Copies annotation from the abstract method to the implementation method * @@ -112,12 +115,11 @@ abstract class AbstractServiceImplementer implements PrefixedServiceImplementer, * @return True if it is */ protected boolean isValidParameter(ClassNode domainClassNode, Parameter parameter, String parameterName) { - if(GormProperties.IDENTITY.equals(parameterName)) { + if (GormProperties.IDENTITY.equals(parameterName)) { return true - } - else { + } else { ClassNode propertyType = AstPropertyResolveUtils.getPropertyType(domainClassNode, parameterName) - if(propertyType != null && (propertyType == parameter.type || AstUtils.isSubclassOf(parameter.type, propertyType.name))) { + if (propertyType != null && (propertyType == parameter.type || AstUtils.isSubclassOf(parameter.type, propertyType.name))) { return true } } @@ -135,41 +137,40 @@ abstract class AbstractServiceImplementer implements PrefixedServiceImplementer, * @return The datastore expression */ protected Expression transactionalDatastore() { - return castX( ClassHelper.make(TransactionCapableDatastore), propX(varX("this"), "targetDatastore")) + return castX(ClassHelper.make(TransactionCapableDatastore), propX(varX("this"), "targetDatastore")) } /** * @return The datastore expression */ protected Expression multiTenantDatastore() { - return castX( ClassHelper.make(MultiTenantCapableDatastore), propX(varX("this"), "targetDatastore")) + return castX(ClassHelper.make(MultiTenantCapableDatastore), propX(varX("this"), "targetDatastore")) } /** * @return The tenant service */ protected Expression tenantService() { - return callD(ServiceRegistry, "targetDatastore", "getService", classX(make(TenantService)) ) + return callD(ServiceRegistry, "targetDatastore", "getService", classX(make(TenantService))) } /** * @return The transaction service */ protected Expression transactionService() { - return callD(ServiceRegistry, "targetDatastore", "getService", classX(make(TransactionService)) ) + return callD(ServiceRegistry, "targetDatastore", "getService", classX(make(TransactionService))) } protected Expression findConnectionId(MethodNode methodNode) { - if(TenantTransform.hasTenantAnnotation(methodNode)) { + if (TenantTransform.hasTenantAnnotation(methodNode)) { return callD(classX(ClassHelper.make(MultiTenancySettings)), "resolveConnectionForTenantId", args( - propX(multiTenantDatastore(), "multiTenancyMode"), callD(tenantService(), "currentId") + propX(multiTenantDatastore(), "multiTenancyMode"), callD(tenantService(), "currentId") )) - } - else { + } else { AnnotationNode ann = TransactionalTransform.findTransactionalAnnotation(methodNode) Expression connectionId = ann?.getMember("connection") - if(connectionId == null) { - connectionId= ann?.getMember("value") + if (connectionId == null) { + connectionId = ann?.getMember("value") } return connectionId } @@ -177,7 +178,7 @@ abstract class AbstractServiceImplementer implements PrefixedServiceImplementer, protected Expression buildInstanceApiLookup(ClassNode domainClass, Expression connectionId) { return AstMethodDispatchUtils.callD( - classX(GormEnhancer), "findInstanceApi", args(classX(domainClass), connectionId) + classX(GormEnhancer), "findInstanceApi", args(classX(domainClass), connectionId) ) } @@ -189,20 +190,18 @@ abstract class AbstractServiceImplementer implements PrefixedServiceImplementer, protected Expression findInstanceApiForConnectionId(ClassNode domainClass, MethodNode methodNode) { Expression connectionId = findConnectionId(methodNode) - if(connectionId != null) { + if (connectionId != null) { return buildInstanceApiLookup(domainClass, connectionId) - } - else { + } else { return classX(domainClass.plainNodeReference) } } protected Expression findStaticApiForConnectionId(ClassNode domainClass, MethodNode methodNode) { Expression connectionId = findConnectionId(methodNode) - if(connectionId != null) { + if (connectionId != null) { return buildStaticApiLookup(domainClass, connectionId) - } - else { + } else { return classX(domainClass.plainNodeReference) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractStringQueryImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractStringQueryImplementer.groovy index 05378b35322..9692671b21c 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractStringQueryImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractStringQueryImplementer.groovy @@ -30,7 +30,6 @@ import org.codehaus.groovy.ast.expr.GStringExpression import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.Statement import org.codehaus.groovy.control.SourceUnit -import org.grails.datastore.gorm.services.ServiceImplementer import org.grails.datastore.gorm.services.transform.QueryStringTransformer import org.grails.datastore.mapping.reflect.AstUtils @@ -47,6 +46,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.constX */ @CompileStatic abstract class AbstractStringQueryImplementer extends AbstractReadOperationImplementer implements AnnotatedServiceImplementer { + @Override int getOrder() { return FindAllByImplementer.POSITION - 100 @@ -54,7 +54,7 @@ abstract class AbstractStringQueryImplementer extends AbstractReadOperationImple @Override boolean doesImplement(ClassNode domainClass, MethodNode methodNode) { - if( isAnnotated(domainClass, methodNode) ) { + if (isAnnotated(domainClass, methodNode)) { return isCompatibleReturnType(domainClass, methodNode, methodNode.returnType, methodNode.name) } return false @@ -70,18 +70,18 @@ abstract class AbstractStringQueryImplementer extends AbstractReadOperationImple AnnotationNode annotationNode = AstUtils.findAnnotation(abstractMethodNode, getAnnotationType()) Expression expr = annotationNode.getMember("value") VariableScope scope = newMethodNode.variableScope - if(expr instanceof GStringExpression) { - GStringExpression gstring = (GStringExpression)expr + if (expr instanceof GStringExpression) { + GStringExpression gstring = (GStringExpression) expr SourceUnit sourceUnit = abstractMethodNode.declaringClass.module.context QueryStringTransformer transformer = createQueryStringTransformer(sourceUnit, scope) Expression transformed = transformer.transformQuery(gstring) - BlockStatement body = (BlockStatement)newMethodNode.code + BlockStatement body = (BlockStatement) newMethodNode.code Expression argMap = findArgsExpression(newMethodNode) - if(argMap != null) { - transformed = args( transformed, argMap ) + if (argMap != null) { + transformed = args(transformed, argMap) } body.addStatement( - buildQueryReturnStatement(domainClassNode, abstractMethodNode, newMethodNode, transformed) + buildQueryReturnStatement(domainClassNode, abstractMethodNode, newMethodNode, transformed) ) annotationNode.setMember("value", constX(IMPLEMENTED)) } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWhereImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWhereImplementer.groovy index 371d649ea3c..52754fb21d0 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWhereImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWhereImplementer.groovy @@ -22,7 +22,10 @@ package org.grails.datastore.gorm.services.implementers import grails.gorm.DetachedCriteria import grails.gorm.services.Where import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.* +import org.codehaus.groovy.ast.AnnotationNode +import org.codehaus.groovy.ast.ClassHelper +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.MethodNode import org.codehaus.groovy.ast.expr.ClosureExpression import org.codehaus.groovy.ast.expr.Expression import org.codehaus.groovy.ast.expr.VariableExpression @@ -32,7 +35,14 @@ import org.codehaus.groovy.control.SourceUnit import org.grails.datastore.gorm.query.transform.DetachedCriteriaTransformer import org.grails.datastore.mapping.reflect.AstUtils -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX import static org.grails.datastore.mapping.reflect.AstUtils.processVariableScopes /** @@ -44,7 +54,6 @@ import static org.grails.datastore.mapping.reflect.AstUtils.processVariableScope @CompileStatic abstract class AbstractWhereImplementer extends AbstractReadOperationImplementer implements AnnotatedServiceImplementer { - public static final int POSITION = FindAllByImplementer.POSITION - 100 @Override @@ -59,7 +68,7 @@ abstract class AbstractWhereImplementer extends AbstractReadOperationImplementer @Override boolean doesImplement(ClassNode domainClass, MethodNode methodNode) { - if( isAnnotated(domainClass, methodNode) ) { + if (isAnnotated(domainClass, methodNode)) { return isCompatibleReturnType(domainClass, methodNode, methodNode.returnType, methodNode.name) } return false @@ -72,13 +81,13 @@ abstract class AbstractWhereImplementer extends AbstractReadOperationImplementer abstractMethodNode.annotations.remove(annotationNode) Expression expr = annotationNode.getMember("value") SourceUnit sourceUnit = abstractMethodNode.declaringClass.module.context - if(expr instanceof ClosureExpression) { + if (expr instanceof ClosureExpression) { ClosureExpression originalClosureExpression = (ClosureExpression) expr ClosureExpression closureExpression = AstUtils.makeClosureAwareOfArguments(newMethodNode, originalClosureExpression) DetachedCriteriaTransformer transformer = new DetachedCriteriaTransformer(sourceUnit) - transformer.transformClosureExpression( domainClassNode, closureExpression) + transformer.transformClosureExpression(domainClassNode, closureExpression) - BlockStatement body = (BlockStatement)newMethodNode.getCode() + BlockStatement body = (BlockStatement) newMethodNode.getCode() Expression argsExpression = findArgsExpression(newMethodNode) VariableExpression queryVar = varX('$query') @@ -88,7 +97,7 @@ abstract class AbstractWhereImplementer extends AbstractReadOperationImplementer ) Expression connectionId = findConnectionId(newMethodNode) - if(connectionId != null) { + if (connectionId != null) { body.addStatement( assignS(queryVar, callX(queryVar, "withConnection", connectionId)) ) @@ -98,16 +107,14 @@ abstract class AbstractWhereImplementer extends AbstractReadOperationImplementer ) Expression queryExpression = callX(queryVar, getQueryMethodToExecute(domainClassNode, newMethodNode), argsExpression != null ? argsExpression : AstUtils.ZERO_ARGUMENTS) body.addStatement( - buildReturnStatement(domainClassNode, abstractMethodNode, newMethodNode, queryExpression) + buildReturnStatement(domainClassNode, abstractMethodNode, newMethodNode, queryExpression) ) processVariableScopes(sourceUnit, targetClassNode, newMethodNode) - } - else { + } else { AstUtils.error(sourceUnit, annotationNode, "@Where value must be a closure") } } - protected ClassNode getDetachedCriteriaType(ClassNode domainClassNode) { ClassHelper.make(DetachedCriteria) } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWriteOperationImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWriteOperationImplementer.groovy index 6d2ee633a7f..5fa145a0894 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWriteOperationImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWriteOperationImplementer.groovy @@ -47,9 +47,9 @@ abstract class AbstractWriteOperationImplementer extends AbstractServiceImplemen final void implement(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, ClassNode targetClassNode) { // copy any annotations from the abstract method copyClassAnnotations(abstractMethodNode, newMethodNode) - if(!TransactionalTransform.hasTransactionalAnnotation(newMethodNode)) { + if (!TransactionalTransform.hasTransactionalAnnotation(newMethodNode)) { // read-only transaction by default - newMethodNode.addAnnotation( new AnnotationNode(TransactionalTransform.MY_TYPE) ) + newMethodNode.addAnnotation(new AnnotationNode(TransactionalTransform.MY_TYPE)) } doImplement(domainClassNode, abstractMethodNode, newMethodNode, targetClassNode) @@ -63,9 +63,9 @@ abstract class AbstractWriteOperationImplementer extends AbstractServiceImplemen @Override void enhance(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, ClassNode targetClassNode) { - if(!TransactionalTransform.hasTransactionalAnnotation(newMethodNode)) { + if (!TransactionalTransform.hasTransactionalAnnotation(newMethodNode)) { // read-only transaction by default - newMethodNode.addAnnotation( new AnnotationNode(TransactionalTransform.MY_TYPE) ) + newMethodNode.addAnnotation(new AnnotationNode(TransactionalTransform.MY_TYPE)) } } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AdaptedImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AdaptedImplementer.groovy index a74849e34fe..783c207f2d1 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AdaptedImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AdaptedImplementer.groovy @@ -28,5 +28,6 @@ import org.grails.datastore.gorm.services.ServiceImplementer * @since 6.1.1 */ interface AdaptedImplementer { + ServiceImplementer getAdapted() } \ No newline at end of file diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AnnotatedServiceImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AnnotatedServiceImplementer.groovy index 946539df44b..1265e3ce7c0 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AnnotatedServiceImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AnnotatedServiceImplementer.groovy @@ -25,7 +25,7 @@ import org.codehaus.groovy.ast.MethodNode /** * An annotated implementer * - * @param The annotation type + * @param The annotation type */ interface AnnotatedServiceImplementer extends PrefixedServiceImplementer { /** diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/CountByImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/CountByImplementer.groovy index aabb4166139..4eaeab191fa 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/CountByImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/CountByImplementer.groovy @@ -20,7 +20,6 @@ package org.grails.datastore.gorm.services.implementers import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.ClassHelper import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.MethodNode import org.grails.datastore.mapping.reflect.AstUtils @@ -33,8 +32,8 @@ import org.grails.datastore.mapping.reflect.AstUtils */ @CompileStatic class CountByImplementer extends FindAllByImplementer implements SingleResultServiceImplementer { - static final List HANDLED_PREFIXES = ['countBy'] + static final List HANDLED_PREFIXES = ['countBy'] @Override protected boolean isCompatibleReturnType(ClassNode domainClass, MethodNode methodNode, ClassNode returnType, String prefix) { diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/CountImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/CountImplementer.groovy index e8c96af4542..2927d76ae12 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/CountImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/CountImplementer.groovy @@ -20,11 +20,9 @@ package org.grails.datastore.gorm.services.implementers import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.ClassHelper import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.MethodNode import org.codehaus.groovy.ast.expr.Expression -import org.codehaus.groovy.ast.expr.MethodCallExpression import org.codehaus.groovy.ast.expr.VariableExpression import org.codehaus.groovy.ast.stmt.BlockStatement import org.grails.datastore.mapping.reflect.AstUtils @@ -41,6 +39,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS */ @CompileStatic class CountImplementer extends AbstractDetachedCriteriaServiceImplementor implements SingleResultServiceImplementer { + static final List HANDLED_PREFIXES = ['count'] @Override @@ -72,7 +71,7 @@ class CountImplementer extends AbstractDetachedCriteriaServiceImplementor implem void implementWithQuery(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, ClassNode targetClassNode, BlockStatement body, VariableExpression detachedCriteriaVar, Expression queryArgs) { Expression callCount = callX(detachedCriteriaVar, "count", queryArgs) body.addStatement( - returnS( castX(newMethodNode.returnType, callCount) ) + returnS(castX(newMethodNode.returnType, callCount)) ) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/CountWhereImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/CountWhereImplementer.groovy index 044cd6ad39c..4993d5b2a8f 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/CountWhereImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/CountWhereImplementer.groovy @@ -21,8 +21,6 @@ package org.grails.datastore.gorm.services.implementers import grails.gorm.services.Where import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.AnnotationNode -import org.codehaus.groovy.ast.ClassHelper import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.MethodNode import org.codehaus.groovy.ast.expr.Expression @@ -43,7 +41,7 @@ class CountWhereImplementer extends AbstractWhereImplementer implements Annotate @Override boolean doesImplement(ClassNode domainClass, MethodNode methodNode) { - if( isAnnotated(domainClass, methodNode) ) { + if (isAnnotated(domainClass, methodNode)) { return isCompatibleReturnType(domainClass, methodNode, methodNode.returnType, methodNode.name) } return false diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/DeleteImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/DeleteImplementer.groovy index 8d1e2469d8e..0c44b4f80fc 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/DeleteImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/DeleteImplementer.groovy @@ -29,11 +29,18 @@ import org.codehaus.groovy.ast.expr.MethodCallExpression import org.codehaus.groovy.ast.expr.VariableExpression import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.Statement -import org.grails.datastore.gorm.GormEntity import org.grails.datastore.gorm.transactions.transform.TransactionalTransform import org.grails.datastore.mapping.reflect.AstUtils -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.block +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS +import static org.codehaus.groovy.ast.tools.GeneralUtils.notNullX +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX /** * Implements "void delete(..)" @@ -42,11 +49,12 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.* */ @CompileStatic class DeleteImplementer extends AbstractDetachedCriteriaServiceImplementor implements SingleResultServiceImplementer { + static final List HANDLED_PREFIXES = ['delete', 'remove'] @Override boolean doesImplement(ClassNode domainClass, MethodNode methodNode) { - if(methodNode.parameters.length == 0) return false + if (methodNode.parameters.length == 0) return false else { return AstUtils.isDomainClass(domainClass) && super.doesImplement(domainClass, methodNode) } @@ -72,23 +80,23 @@ class DeleteImplementer extends AbstractDetachedCriteriaServiceImplementor imple boolean isVoidReturnType = ClassHelper.VOID_TYPE.equals(newMethodNode.returnType) VariableExpression obj = varX('$obj') Statement deleteStatement = stmt(callX(obj, "delete")) - if(!isVoidReturnType) { + if (!isVoidReturnType) { deleteStatement = block( - deleteStatement, - returnS(constX(1)) + deleteStatement, + returnS(constX(1)) ) } body.addStatements([ - declS(obj, byIdLookup), - ifS( - notNullX(obj), - deleteStatement - ) + declS(obj, byIdLookup), + ifS( + notNullX(obj), + deleteStatement + ) ]) - if(!isVoidReturnType) { + if (!isVoidReturnType) { body.addStatement( - returnS(constX(0)) + returnS(constX(0)) ) } } @@ -96,12 +104,12 @@ class DeleteImplementer extends AbstractDetachedCriteriaServiceImplementor imple @Override void implementWithQuery(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, ClassNode targetClassNode, BlockStatement body, VariableExpression detachedCriteriaVar, Expression queryArgs) { - MethodCallExpression deleteCall = callX(detachedCriteriaVar, "deleteAll" ) + MethodCallExpression deleteCall = callX(detachedCriteriaVar, "deleteAll") boolean isVoidReturnType = ClassHelper.VOID_TYPE.equals(newMethodNode.returnType) body.addStatements([ // return query.deleteAll() - isVoidReturnType ? stmt(deleteCall) : returnS( deleteCall ) + isVoidReturnType ? stmt(deleteCall) : returnS(deleteCall) ]) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/DeleteWhereImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/DeleteWhereImplementer.groovy index 2979e83292f..348ffbf1424 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/DeleteWhereImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/DeleteWhereImplementer.groovy @@ -49,7 +49,7 @@ class DeleteWhereImplementer extends AbstractWhereImplementer { @Override boolean doesImplement(ClassNode domainClass, MethodNode methodNode) { String prefix = handledPrefixes.find() { String it -> methodNode.name.startsWith(it) } - if(prefix != null) { + if (prefix != null) { return super.doesImplement(domainClass, methodNode) } return false @@ -68,11 +68,10 @@ class DeleteWhereImplementer extends AbstractWhereImplementer { @Override protected Statement buildReturnStatement(ClassNode domainClass, MethodNode abstractMethodNode, MethodNode methodNode, Expression queryExpression) { boolean isVoid = abstractMethodNode.returnType == ClassHelper.VOID_TYPE - if(isVoid) { + if (isVoid) { return GeneralUtils.stmt(queryExpression) - } - else { - return GeneralUtils.returnS( GeneralUtils.castX( abstractMethodNode.returnType, queryExpression) ) + } else { + return GeneralUtils.returnS(GeneralUtils.castX(abstractMethodNode.returnType, queryExpression)) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllByImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllByImplementer.groovy index 1c6c347862a..62032210814 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllByImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllByImplementer.groovy @@ -37,18 +37,18 @@ import org.grails.datastore.gorm.services.transform.ServiceTransformation import org.grails.datastore.mapping.core.Ordered import org.grails.datastore.mapping.reflect.AstUtils -import static org.codehaus.groovy.ast.tools.GeneralUtils.varX +import static org.codehaus.groovy.ast.ClassHelper.MAP_TYPE +import static org.codehaus.groovy.ast.tools.GeneralUtils.args import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.castX import static org.codehaus.groovy.ast.tools.GeneralUtils.constX -import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS -import static org.codehaus.groovy.ast.tools.GeneralUtils.args -import static org.codehaus.groovy.ast.tools.GeneralUtils.castX -import static org.codehaus.groovy.ast.ClassHelper.MAP_TYPE -import static org.grails.datastore.mapping.reflect.AstUtils.hasProperty +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX import static org.grails.datastore.mapping.reflect.AstUtils.error -import static org.grails.datastore.mapping.reflect.AstUtils.mapX import static org.grails.datastore.mapping.reflect.AstUtils.findAnnotation +import static org.grails.datastore.mapping.reflect.AstUtils.hasProperty +import static org.grails.datastore.mapping.reflect.AstUtils.mapX /** * Automatically implement services that find objects based an arguments @@ -58,7 +58,8 @@ import static org.grails.datastore.mapping.reflect.AstUtils.findAnnotation */ @CompileStatic class FindAllByImplementer extends AbstractArrayOrIterableResultImplementer implements Ordered, IterableServiceImplementer { - static final List HANDLED_PREFIXES = ['listBy','findBy', 'findAllBy'] + + static final List HANDLED_PREFIXES = ['listBy', 'findBy', 'findAllBy'] public static final int POSITION = -100 // position before FindAllImplementer @@ -69,11 +70,11 @@ class FindAllByImplementer extends AbstractArrayOrIterableResultImplementer impl @Override boolean doesImplement(ClassNode domainClass, MethodNode methodNode) { - if(super.doesImplement(domainClass, methodNode)) { + if (super.doesImplement(domainClass, methodNode)) { String methodName = methodNode.name int parameterCount = methodNode.parameters.length - for(String prefix in getHandledPrefixes()) { - if(methodName.startsWith(prefix) && buildMatchSpec(prefix, methodName, parameterCount) != null) { + for (String prefix in getHandledPrefixes()) { + if (methodName.startsWith(prefix) && buildMatchSpec(prefix, methodName, parameterCount) != null) { return true } } @@ -93,26 +94,25 @@ class FindAllByImplementer extends AbstractArrayOrIterableResultImplementer impl @Override void doImplement(ClassNode domainClassNode, ClassNode targetClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, boolean isArray) { - BlockStatement body = (BlockStatement)newMethodNode.getCode() + BlockStatement body = (BlockStatement) newMethodNode.getCode() ClassNode returnType = newMethodNode.returnType String methodName = newMethodNode.name Parameter[] parameters = newMethodNode.parameters int parameterCount = parameters.length MatchSpec matchSpec = null - for(String prefix in getHandledPrefixes()) { + for (String prefix in getHandledPrefixes()) { matchSpec = buildMatchSpec(prefix, methodName, parameterCount) - if(methodName.startsWith(prefix) && matchSpec != null) { + if (methodName.startsWith(prefix) && matchSpec != null) { break } } - if(matchSpec == null) { + if (matchSpec == null) { AstUtils.error(abstractMethodNode.declaringClass.module.context, abstractMethodNode, ServiceTransformation.NO_IMPLEMENTATIONS_MESSAGE) - } - else { + } else { // validate the properties - for(String propertyName in matchSpec.propertyNames) { - if(!hasProperty(domainClassNode, propertyName)) { + for (String propertyName in matchSpec.propertyNames) { + if (!hasProperty(domainClassNode, propertyName)) { error(abstractMethodNode.declaringClass.module.context, abstractMethodNode, "Cannot implement finder for non-existent property [$propertyName] of class [$domainClassNode.name]") } } @@ -122,9 +122,9 @@ class FindAllByImplementer extends AbstractArrayOrIterableResultImplementer impl String finderCallName = "${methodPrefix}${matchSpec.queryExpression}" ArgumentListExpression argList = buildArgs(parameters, abstractMethodNode, body) Expression findCall = callX(findStaticApiForConnectionId(domainClassNode, newMethodNode), finderCallName, argList) - if(isArray || ClassHelper.isNumberType(returnType)) { + if (isArray || ClassHelper.isNumberType(returnType)) { // handle array cast - findCall = castX( returnType.plainNodeReference, findCall) + findCall = castX(returnType.plainNodeReference, findCall) } body.addStatement( buildReturnStatement(domainClassNode, abstractMethodNode, newMethodNode, findCall) @@ -143,8 +143,7 @@ class FindAllByImplementer extends AbstractArrayOrIterableResultImplementer impl body.addStatement( stmt(callX(varX(parameters[-1]), "put", args(constX("fetch"), joinMap))) ) - } - else { + } else { argList.addExpression(mapX(fetch: joinMap)) } } else { @@ -157,11 +156,10 @@ class FindAllByImplementer extends AbstractArrayOrIterableResultImplementer impl protected Statement buildReturnStatement(ClassNode domainClass, MethodNode abstractMethodNode, MethodNode newMethodNode, Expression queryExpression) { returnS( - queryExpression + queryExpression ) } - protected String getDynamicFinderPrefix() { return "findAllBy" } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllImplementer.groovy index a5e853e2948..2db153f36eb 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllImplementer.groovy @@ -28,7 +28,9 @@ import org.grails.datastore.gorm.GormEntity import org.grails.datastore.mapping.core.Ordered import org.grails.datastore.mapping.reflect.AstUtils -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.castX +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS /** * Automatically implements {@link grails.gorm.services.Service} interface methods that start with "list" and @@ -60,10 +62,9 @@ class FindAllImplementer extends AbstractDetachedCriteriaServiceImplementor impl @Override protected ClassNode resolveDomainClassFromSignature(ClassNode currentDomainClassNode, MethodNode methodNode) { ClassNode returnType = methodNode.returnType - if(returnType.isArray()) { + if (returnType.isArray()) { return returnType.componentType - } - else { + } else { return returnType.genericsTypes[0].type } } @@ -75,13 +76,13 @@ class FindAllImplementer extends AbstractDetachedCriteriaServiceImplementor impl @Override void implementWithQuery(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, ClassNode targetClassNode, BlockStatement body, VariableExpression detachedCriteriaVar, Expression queryArgs) { - ClassNode returnType = (ClassNode)newMethodNode.getNodeMetaData(RETURN_TYPE) ?: newMethodNode.returnType + ClassNode returnType = (ClassNode) newMethodNode.getNodeMetaData(RETURN_TYPE) ?: newMethodNode.returnType Expression methodCall = callX(detachedCriteriaVar, "list", queryArgs) - if(returnType.isArray()) { + if (returnType.isArray()) { methodCall = castX(returnType.plainNodeReference, methodCall) } body.addStatement( - returnS(methodCall) + returnS(methodCall) ) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllInterfaceProjectionImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllInterfaceProjectionImplementer.groovy index 7a17d26fff0..48072c72890 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllInterfaceProjectionImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllInterfaceProjectionImplementer.groovy @@ -34,6 +34,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.castX */ @CompileStatic class FindAllInterfaceProjectionImplementer extends FindAllImplementer implements IterableInterfaceProjectionBuilder, IterableProjectionServiceImplementer { + @Override protected ClassNode resolveDomainClassFromSignature(ClassNode currentDomainClassNode, MethodNode methodNode) { return currentDomainClassNode @@ -46,14 +47,14 @@ class FindAllInterfaceProjectionImplementer extends FindAllImplementer implement @Override void implementWithQuery(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, ClassNode targetClassNode, BlockStatement body, VariableExpression detachedCriteriaVar, Expression queryArgs) { - ClassNode returnType = (ClassNode)newMethodNode.getNodeMetaData(RETURN_TYPE) ?: newMethodNode.returnType + ClassNode returnType = (ClassNode) newMethodNode.getNodeMetaData(RETURN_TYPE) ?: newMethodNode.returnType Expression methodCall = callX(detachedCriteriaVar, "list", queryArgs) - if(returnType.isArray()) { + if (returnType.isArray()) { methodCall = castX(returnType.plainNodeReference, methodCall) } body.addStatement( - buildInterfaceProjection(domainClassNode, abstractMethodNode, methodCall, queryArgs, newMethodNode) + buildInterfaceProjection(domainClassNode, abstractMethodNode, methodCall, queryArgs, newMethodNode) ) } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllPropertyProjectionImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllPropertyProjectionImplementer.groovy index 22b23e3be94..0eae8ec6c38 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllPropertyProjectionImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllPropertyProjectionImplementer.groovy @@ -35,14 +35,15 @@ import static org.grails.datastore.mapping.reflect.AstUtils.implementsInterface */ @CompileStatic class FindAllPropertyProjectionImplementer extends AbstractProjectionImplementer implements IterableProjectionServiceImplementer { + @Override boolean isCompatibleReturnType(ClassNode domainClass, MethodNode methodNode, ClassNode returnType, String prefix) { boolean isCompatibleReturnType = false String propertyName = establishPropertyName(methodNode, prefix, domainClass) - if(propertyName == null) return false + if (propertyName == null) return false ClassNode propertyType = AstPropertyResolveUtils.getPropertyType(domainClass, propertyName) - if(propertyType == null) return false + if (propertyType == null) return false if (returnType.name == Iterable.name || implementsInterface(returnType, Iterable.name)) { GenericsType[] genericsTypes = returnType.genericsTypes diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllStringQueryImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllStringQueryImplementer.groovy index c92be81a019..de894172892 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllStringQueryImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllStringQueryImplementer.groovy @@ -40,6 +40,7 @@ import static org.grails.datastore.mapping.reflect.AstUtils.implementsInterface */ @CompileStatic class FindAllStringQueryImplementer extends AbstractStringQueryImplementer implements IterableServiceImplementer { + @Override protected boolean isCompatibleReturnType(ClassNode domainClass, MethodNode methodNode, ClassNode returnType, String prefix) { boolean isCompatibleReturnType = false @@ -53,7 +54,7 @@ class FindAllStringQueryImplementer extends AbstractStringQueryImplementer imple @Override protected Statement buildQueryReturnStatement(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, Expression args) { - ClassNode returnType = (ClassNode)newMethodNode.getNodeMetaData(RETURN_TYPE) ?: abstractMethodNode.returnType + ClassNode returnType = (ClassNode) newMethodNode.getNodeMetaData(RETURN_TYPE) ?: abstractMethodNode.returnType String methodName = AstUtils.isIterableOrArrayOfDomainClasses(returnType) ? "findAll" : "executeQuery" Expression methodCall = callX(findStaticApiForConnectionId(domainClassNode, newMethodNode), methodName, args) methodCall = castX(returnType.plainNodeReference, methodCall) diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllWhereImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllWhereImplementer.groovy index 29171079532..82ea68bc86e 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllWhereImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAllWhereImplementer.groovy @@ -42,7 +42,7 @@ class FindAllWhereImplementer extends AbstractWhereImplementer implements Iterab @Override boolean doesImplement(ClassNode domainClass, MethodNode methodNode) { - if( isAnnotated(domainClass, methodNode )) { + if (isAnnotated(domainClass, methodNode)) { return isCompatibleReturnType(domainClass, methodNode, methodNode.returnType, methodNode.name) } return false @@ -61,10 +61,9 @@ class FindAllWhereImplementer extends AbstractWhereImplementer implements Iterab @Override protected ClassNode resolveDomainClassFromSignature(ClassNode currentDomainClassNode, MethodNode methodNode) { ClassNode returnType = methodNode.returnType - if(returnType.isArray()) { + if (returnType.isArray()) { return returnType.componentType - } - else { + } else { return returnType.genericsTypes[0].type } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAndDeleteImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAndDeleteImplementer.groovy index ce9a113ebf7..31689d09c1e 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAndDeleteImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindAndDeleteImplementer.groovy @@ -30,7 +30,14 @@ import org.codehaus.groovy.ast.stmt.Statement import org.grails.datastore.gorm.GormEntity import org.grails.datastore.gorm.transactions.transform.TransactionalTransform import org.grails.datastore.mapping.reflect.AstUtils -import static org.codehaus.groovy.ast.tools.GeneralUtils.* + +import static org.codehaus.groovy.ast.tools.GeneralUtils.block +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX + /** * An implementer that handles delete methods * @@ -42,10 +49,9 @@ class FindAndDeleteImplementer extends FindOneImplementer implements SingleResul @Override boolean doesImplement(ClassNode domainClass, MethodNode methodNode) { - if(methodNode.parameters.length == 0) { + if (methodNode.parameters.length == 0) { return false - } - else { + } else { return super.doesImplement(domainClass, methodNode) } } @@ -67,9 +73,9 @@ class FindAndDeleteImplementer extends FindOneImplementer implements SingleResul deleteCall.setSafe(true) // null safe block( - declS(var, queryMethodCall), - stmt(deleteCall), - returnS(var) + declS(var, queryMethodCall), + stmt(deleteCall), + returnS(var) ) } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneByImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneByImplementer.groovy index 55aa2714335..9dae24ac897 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneByImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneByImplementer.groovy @@ -29,7 +29,9 @@ import org.grails.datastore.gorm.GormEntity import org.grails.datastore.mapping.model.config.GormProperties import org.grails.datastore.mapping.reflect.AstUtils -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS + /** * Handles implementation for a finder that returns a single result * @@ -38,23 +40,23 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.* */ @CompileStatic class FindOneByImplementer extends FindAllByImplementer implements SingleResultServiceImplementer { - static final List HANDLED_PREFIXES = ['findBy','getBy', 'findOneBy'] + + static final List HANDLED_PREFIXES = ['findBy', 'getBy', 'findOneBy'] @Override void doImplement(ClassNode domainClassNode, ClassNode targetClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, boolean isArray) { - BlockStatement body = (BlockStatement)newMethodNode.getCode() + BlockStatement body = (BlockStatement) newMethodNode.getCode() Parameter[] parameters = newMethodNode.parameters - if(parameters.length == 1 && parameters[0].name == GormProperties.IDENTITY) { + if (parameters.length == 1 && parameters[0].name == GormProperties.IDENTITY) { // add a method that invokes get(id) ArgumentListExpression argList = buildArgs(parameters, abstractMethodNode, body) Expression queryMethodCall = callX(findStaticApiForConnectionId(domainClassNode, newMethodNode), "get", argList) body.addStatement( - returnS( - queryMethodCall - ) + returnS( + queryMethodCall + ) ) - } - else { + } else { super.doImplement(domainClassNode, targetClassNode, abstractMethodNode, newMethodNode, isArray) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneImplementer.groovy index 340567251f6..7e78f4eb4c1 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneImplementer.groovy @@ -28,7 +28,10 @@ import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.Statement import org.grails.datastore.gorm.GormEntity import org.grails.datastore.mapping.reflect.AstUtils -import static org.codehaus.groovy.ast.tools.GeneralUtils.* + +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS + /** * An implementer that implements logic for finding a single entity * @@ -37,7 +40,8 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.* */ @CompileStatic class FindOneImplementer extends AbstractDetachedCriteriaServiceImplementor implements SingleResultServiceImplementer { - static final List HANDLED_PREFIXES = ['retrieve','get', 'find', 'read'] + + static final List HANDLED_PREFIXES = ['retrieve', 'get', 'find', 'read'] @Override protected boolean isCompatibleReturnType(ClassNode domainClass, MethodNode methodNode, ClassNode returnType, String prefix) { @@ -57,7 +61,7 @@ class FindOneImplementer extends AbstractDetachedCriteriaServiceImplementor impl @Override void implementById(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, ClassNode targetClassNode, BlockStatement body, Expression byIdLookup) { body.addStatement( - buildReturnStatement(domainClassNode, abstractMethodNode, byIdLookup, null, newMethodNode) + buildReturnStatement(domainClassNode, abstractMethodNode, byIdLookup, null, newMethodNode) ) } @@ -66,7 +70,7 @@ class FindOneImplementer extends AbstractDetachedCriteriaServiceImplementor impl String findMethod = findMethodToInvoke(domainClassNode, newMethodNode) MethodCallExpression findCall = queryArgs != null ? callX(detachedCriteriaVar, findMethod, queryArgs) : callX(detachedCriteriaVar, findMethod) body.addStatement( - buildReturnStatement(domainClassNode, abstractMethodNode, findCall, queryArgs, newMethodNode) + buildReturnStatement(domainClassNode, abstractMethodNode, findCall, queryArgs, newMethodNode) ) } @@ -76,7 +80,7 @@ class FindOneImplementer extends AbstractDetachedCriteriaServiceImplementor impl protected Statement buildReturnStatement(ClassNode targetDomainClass, MethodNode abstractMethodNode, Expression queryMethodCall, Expression args, MethodNode newMethodNode) { returnS( - queryMethodCall + queryMethodCall ) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneInterfaceProjectionImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneInterfaceProjectionImplementer.groovy index c4d3c73112b..96c59638c98 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneInterfaceProjectionImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneInterfaceProjectionImplementer.groovy @@ -47,6 +47,6 @@ class FindOneInterfaceProjectionImplementer extends FindOneImplementer implement @Override protected Statement buildReturnStatement(ClassNode targetDomainClass, MethodNode abstractMethodNode, Expression queryMethodCall, Expression args, MethodNode newMethodNode) { - return buildInterfaceProjection(targetDomainClass, abstractMethodNode, queryMethodCall, args, newMethodNode) + return buildInterfaceProjection(targetDomainClass, abstractMethodNode, queryMethodCall, args, newMethodNode) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneInterfaceProjectionStringQueryImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneInterfaceProjectionStringQueryImplementer.groovy index cc0de822086..bbb5d6e0db0 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneInterfaceProjectionStringQueryImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneInterfaceProjectionStringQueryImplementer.groovy @@ -48,7 +48,7 @@ class FindOneInterfaceProjectionStringQueryImplementer extends FindOneStringQuer @Override protected Statement buildQueryReturnStatement(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, Expression queryArg) { - ReturnStatement rs = (ReturnStatement)super.buildQueryReturnStatement(domainClassNode, abstractMethodNode, newMethodNode, queryArg) + ReturnStatement rs = (ReturnStatement) super.buildQueryReturnStatement(domainClassNode, abstractMethodNode, newMethodNode, queryArg) return buildInterfaceProjection(domainClassNode, abstractMethodNode, rs.expression, queryArg, newMethodNode) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneInterfaceProjectionWhereImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneInterfaceProjectionWhereImplementer.groovy index 69a1ac8b1fa..af23fb93188 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneInterfaceProjectionWhereImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneInterfaceProjectionWhereImplementer.groovy @@ -48,7 +48,7 @@ class FindOneInterfaceProjectionWhereImplementer extends FindOneWhereImplementer @Override protected Statement buildReturnStatement(ClassNode domainClass, MethodNode abstractMethodNode, MethodNode newMethodNode, Expression queryExpression) { - ReturnStatement rs = (ReturnStatement)super.buildReturnStatement(domainClass, abstractMethodNode, newMethodNode, queryExpression) + ReturnStatement rs = (ReturnStatement) super.buildReturnStatement(domainClass, abstractMethodNode, newMethodNode, queryExpression) return buildInterfaceProjection(domainClass, abstractMethodNode, rs.expression, queryExpression, newMethodNode) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOnePropertyProjectionImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOnePropertyProjectionImplementer.groovy index 916764483e3..8691aeef93f 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOnePropertyProjectionImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOnePropertyProjectionImplementer.groovy @@ -22,15 +22,7 @@ package org.grails.datastore.gorm.services.implementers import groovy.transform.CompileStatic import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.MethodNode -import org.codehaus.groovy.ast.expr.Expression -import org.codehaus.groovy.ast.expr.VariableExpression -import org.codehaus.groovy.ast.stmt.BlockStatement import org.grails.datastore.gorm.transform.AstPropertyResolveUtils -import org.grails.datastore.mapping.reflect.AstUtils - -import java.beans.Introspector - -import static org.codehaus.groovy.ast.tools.GeneralUtils.* /** * Implements property projection by query @@ -41,13 +33,12 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.* @CompileStatic class FindOnePropertyProjectionImplementer extends AbstractProjectionImplementer implements SingleResultProjectionServiceImplementer { - @Override boolean isCompatibleReturnType(ClassNode domainClass, MethodNode methodNode, ClassNode returnType, String prefix) { String propertyName = establishPropertyName(methodNode, prefix, domainClass) - if(propertyName) { + if (propertyName) { ClassNode propertyType = AstPropertyResolveUtils.getPropertyType(domainClass, propertyName) - if(isValidPropertyType(resolveProjectionReturnType(returnType), propertyType)) { + if (isValidPropertyType(resolveProjectionReturnType(returnType), propertyType)) { return true } } @@ -63,7 +54,6 @@ class FindOnePropertyProjectionImplementer extends AbstractProjectionImplementer return returnType } - @Override Iterable getHandledPrefixes() { return FindOneImplementer.HANDLED_PREFIXES diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneStringQueryImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneStringQueryImplementer.groovy index a47f770a756..dcaa24cde1b 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneStringQueryImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneStringQueryImplementer.groovy @@ -19,17 +19,13 @@ package org.grails.datastore.gorm.services.implementers -import grails.gorm.services.Query import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.AnnotationNode import org.codehaus.groovy.ast.ClassHelper import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.MethodNode import org.codehaus.groovy.ast.expr.ConstantExpression import org.codehaus.groovy.ast.expr.Expression import org.codehaus.groovy.ast.expr.GStringExpression -import org.codehaus.groovy.ast.expr.MapEntryExpression -import org.codehaus.groovy.ast.expr.MapExpression import org.codehaus.groovy.ast.stmt.Statement import org.grails.datastore.gorm.GormEntity import org.grails.datastore.mapping.reflect.AstUtils @@ -47,49 +43,48 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS */ @CompileStatic class FindOneStringQueryImplementer extends AbstractStringQueryImplementer implements SingleResultServiceImplementer { + @Override protected Statement buildQueryReturnStatement(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, Expression queryArg) { - ClassNode returnType = (ClassNode)newMethodNode.getNodeMetaData(RETURN_TYPE) ?: abstractMethodNode.returnType + ClassNode returnType = (ClassNode) newMethodNode.getNodeMetaData(RETURN_TYPE) ?: abstractMethodNode.returnType String methodToExecute = getFindMethodToInvoke(domainClassNode, newMethodNode, returnType) - if(methodToExecute != "find") { - queryArg = args(queryArg, AstUtils.mapX(max:constX(1))) + if (methodToExecute != "find") { + queryArg = args(queryArg, AstUtils.mapX(max: constX(1))) } - Expression queryCall = callX( findStaticApiForConnectionId(domainClassNode, newMethodNode), + Expression queryCall = callX(findStaticApiForConnectionId(domainClassNode, newMethodNode), methodToExecute, queryArg) - if(!AstUtils.isDomainClass(returnType)) { + if (!AstUtils.isDomainClass(returnType)) { queryCall = callX(queryCall, "first") } returnS( - queryCall + queryCall ) } protected String getFindMethodToInvoke(ClassNode classNode, MethodNode methodNode, ClassNode returnType) { - if(AstUtils.isDomainClass(returnType)) { + if (AstUtils.isDomainClass(returnType)) { return "find" - } - else { + } else { return "executeQuery" } } @Override protected boolean isCompatibleReturnType(ClassNode domainClass, MethodNode methodNode, ClassNode returnType, String prefix) { - if(AstUtils.isDomainClass(returnType)) { + if (AstUtils.isDomainClass(returnType)) { return true - } - else if(!AstUtils.isSubclassOfOrImplementsInterface(returnType, Iterable.name) && !returnType.isArray() && !returnType.packageName?.startsWith("rx.")) { + } else if (!AstUtils.isSubclassOfOrImplementsInterface(returnType, Iterable.name) && !returnType.isArray() && !returnType.packageName?.startsWith("rx.")) { def queryAnnotation = AstUtils.findAnnotation(methodNode, getAnnotationType()) def query = queryAnnotation.getMember("value") - if(query instanceof GStringExpression) { - GStringExpression gstring = (GStringExpression)query + if (query instanceof GStringExpression) { + GStringExpression gstring = (GStringExpression) query List strings = gstring.strings ConstantExpression stem = strings.first() - if(stem.text.toLowerCase(Locale.ENGLISH).contains("select")) { + if (stem.text.toLowerCase(Locale.ENGLISH).contains("select")) { return returnType != ClassHelper.VOID_TYPE } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneWhereImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneWhereImplementer.groovy index 533458f73b3..8a58237d3c9 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneWhereImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/FindOneWhereImplementer.groovy @@ -28,7 +28,6 @@ import org.codehaus.groovy.ast.stmt.Statement import org.grails.datastore.gorm.GormEntity import org.grails.datastore.mapping.reflect.AstUtils -import static org.codehaus.groovy.ast.tools.GeneralUtils.castX import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS /** @@ -42,7 +41,7 @@ class FindOneWhereImplementer extends AbstractWhereImplementer implements Single @Override boolean doesImplement(ClassNode domainClass, MethodNode methodNode) { - if( isAnnotated(domainClass, methodNode )) { + if (isAnnotated(domainClass, methodNode)) { return isCompatibleReturnType(domainClass, methodNode, methodNode.returnType, methodNode.name) } return false diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/InterfaceProjectionBuilder.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/InterfaceProjectionBuilder.groovy index 93bddfde85d..a416a58d91a 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/InterfaceProjectionBuilder.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/InterfaceProjectionBuilder.groovy @@ -55,16 +55,15 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.varX trait InterfaceProjectionBuilder { boolean isInterfaceProjection(ClassNode domainClass, MethodNode methodNode, ClassNode returnType) { - if(returnType.isInterface() && !returnType.packageName?.startsWith("java.")) { + if (returnType.isInterface() && !returnType.packageName?.startsWith("java.")) { List interfacePropertyNames = AstPropertyResolveUtils.getPropertyNames(returnType) - for(prop in interfacePropertyNames) { + for (prop in interfacePropertyNames) { ClassNode existingType = AstPropertyResolveUtils.getPropertyType(domainClass, prop) ClassNode propertyType = AstPropertyResolveUtils.getPropertyType(returnType, prop) - if(existingType == null) { + if (existingType == null) { return false - } - else if(!AstUtils.isSubclassOfOrImplementsInterface(existingType, propertyType)) { + } else if (!AstUtils.isSubclassOfOrImplementsInterface(existingType, propertyType)) { return false } } @@ -76,8 +75,8 @@ trait InterfaceProjectionBuilder { MethodNode buildInterfaceImpl(ClassNode interfaceNode, ClassNode declaringClass, ClassNode targetDomainClass, MethodNode abstractMethodNode) { List getterNames = (List) AstPropertyResolveUtils.getPropertyNames(interfaceNode) .collect() { - new ConstantExpression(NameUtils.getGetterName(it)) - } + new ConstantExpression(NameUtils.getGetterName(it)) + } String innerClassName = "${declaringClass.name}\$${interfaceNode.nameWithoutPackage}" InnerClassNode innerClassNode = (InnerClassNode) declaringClass.innerClasses.find { InnerClassNode inner -> inner.name == innerClassName } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableInterfaceProjectionBuilder.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableInterfaceProjectionBuilder.groovy index cc9de16a382..49d35834d90 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableInterfaceProjectionBuilder.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableInterfaceProjectionBuilder.groovy @@ -24,10 +24,8 @@ import org.codehaus.groovy.ast.ClassHelper import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.MethodNode import org.codehaus.groovy.ast.Parameter -import org.codehaus.groovy.ast.VariableScope import org.codehaus.groovy.ast.expr.ClosureExpression import org.codehaus.groovy.ast.expr.Expression -import org.codehaus.groovy.ast.expr.MethodCallExpression import org.codehaus.groovy.ast.expr.VariableExpression import org.codehaus.groovy.ast.stmt.Statement import org.grails.datastore.gorm.services.ServiceImplementer @@ -35,7 +33,19 @@ import org.grails.datastore.gorm.transform.AstPropertyResolveUtils import org.grails.datastore.mapping.reflect.AstGenericsUtils import org.grails.datastore.mapping.reflect.AstUtils -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX +import static org.codehaus.groovy.ast.tools.GeneralUtils.block +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.castX +import static org.codehaus.groovy.ast.tools.GeneralUtils.closureX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.param +import static org.codehaus.groovy.ast.tools.GeneralUtils.params +import static org.codehaus.groovy.ast.tools.GeneralUtils.propX +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX /** * Projection builder for iterable results like lists and arrays @@ -44,7 +54,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.* * @since 6.1.1 */ @CompileStatic -trait IterableInterfaceProjectionBuilder extends InterfaceProjectionBuilder{ +trait IterableInterfaceProjectionBuilder extends InterfaceProjectionBuilder { /** * Is the method an interface projection @@ -55,19 +65,18 @@ trait IterableInterfaceProjectionBuilder extends InterfaceProjectionBuilder{ */ @Override boolean isInterfaceProjection(ClassNode domainClass, MethodNode methodNode, ClassNode returnType) { - if(AstUtils.isSubclassOfOrImplementsInterface(returnType, Iterable.name) || returnType.isArray()) { + if (AstUtils.isSubclassOfOrImplementsInterface(returnType, Iterable.name) || returnType.isArray()) { ClassNode genericType = AstGenericsUtils.resolveSingleGenericType(returnType) - if(genericType != null && genericType.isInterface() && !genericType.packageName?.startsWith("java.")) { + if (genericType != null && genericType.isInterface() && !genericType.packageName?.startsWith("java.")) { List interfacePropertyNames = AstPropertyResolveUtils.getPropertyNames(genericType) - for(prop in interfacePropertyNames) { + for (prop in interfacePropertyNames) { ClassNode existingType = AstPropertyResolveUtils.getPropertyType(domainClass, prop) ClassNode propertyType = AstPropertyResolveUtils.getPropertyType(genericType, prop) - if(existingType == null) { + if (existingType == null) { return false - } - else if(!AstUtils.isSubclassOfOrImplementsInterface(existingType, propertyType)) { + } else if (!AstUtils.isSubclassOfOrImplementsInterface(existingType, propertyType)) { return false } } @@ -81,7 +90,7 @@ trait IterableInterfaceProjectionBuilder extends InterfaceProjectionBuilder{ ClassNode declaringClass = newMethodNode.declaringClass ClassNode returnType = (ClassNode) newMethodNode.getNodeMetaData(ServiceImplementer.RETURN_TYPE) ?: abstractMethodNode.returnType ClassNode interfaceNode = AstGenericsUtils.resolveSingleGenericType(returnType) - if(!interfaceNode.isInterface()) { + if (!interfaceNode.isInterface()) { AstUtils.error(targetDomainClass.module.context, abstractMethodNode, "Cannot implement interface projection, [$interfaceNode.name] is not an interface!") } MethodNode methodTarget = buildInterfaceImpl(interfaceNode, declaringClass, targetDomainClass, abstractMethodNode) @@ -89,7 +98,7 @@ trait IterableInterfaceProjectionBuilder extends InterfaceProjectionBuilder{ VariableExpression delegateVar = varX('$delegate', innerClassNode) Parameter p = param(ClassHelper.OBJECT_TYPE, '$target') - Expression setTargetCall = assignX(propX(delegateVar, '$target'), castX(targetDomainClass, varX(p)) ) + Expression setTargetCall = assignX(propX(delegateVar, '$target'), castX(targetDomainClass, varX(p))) Statement closureBody = block( declS(delegateVar, ctorX(innerClassNode)), stmt(setTargetCall), @@ -101,9 +110,9 @@ trait IterableInterfaceProjectionBuilder extends InterfaceProjectionBuilder{ closureExpression.setVariableScope(variableScope) Expression collectCall = callX(queryMethodCall, "collect", closureExpression) - if(returnType.isArray()) { + if (returnType.isArray()) { // handle array cast - collectCall = castX( returnType.plainNodeReference, collectCall) + collectCall = castX(returnType.plainNodeReference, collectCall) } stmt(collectCall) diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableProjectionServiceImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableProjectionServiceImplementer.groovy index b1a2eb4f825..a3dddd58bb3 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableProjectionServiceImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableProjectionServiceImplementer.groovy @@ -29,7 +29,8 @@ import org.grails.datastore.gorm.GormEntity * @author Graeme Rocher * @since 6.1.1 */ -interface IterableProjectionServiceImplementer extends IterableServiceImplementer { +interface IterableProjectionServiceImplementer extends IterableServiceImplementer { + /** * Is the return type compatible with the projection query * diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableServiceImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableServiceImplementer.groovy index ab23c115eab..8b5117c4a37 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableServiceImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableServiceImplementer.groovy @@ -22,7 +22,7 @@ package org.grails.datastore.gorm.services.implementers /** * An implementer that returns an iterable or an array * - * @param The return type + * @param The return type */ interface IterableServiceImplementer extends PrefixedServiceImplementer { diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/PrefixedServiceImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/PrefixedServiceImplementer.groovy index 196c8affeaf..2a61d98330f 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/PrefixedServiceImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/PrefixedServiceImplementer.groovy @@ -26,6 +26,7 @@ import org.grails.datastore.gorm.services.ServiceImplementer * An implementer that uses a set of prefixes */ interface PrefixedServiceImplementer extends ServiceImplementer { + /** * @return The handled prefixes */ diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/QueryStringImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/QueryStringImplementer.groovy index 0c996c8d18a..6c2893531aa 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/QueryStringImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/QueryStringImplementer.groovy @@ -23,5 +23,4 @@ package org.grails.datastore.gorm.services.implementers * Created by graemerocher on 04/04/2017. */ interface QueryStringImplementer { - } \ No newline at end of file diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SaveImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SaveImplementer.groovy index cfaa33628ba..2f540d42c68 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SaveImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SaveImplementer.groovy @@ -28,7 +28,11 @@ import org.codehaus.groovy.ast.stmt.BlockStatement import org.grails.datastore.gorm.GormEntity import org.grails.datastore.mapping.reflect.AstUtils -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.namedArgs /** @@ -39,14 +43,14 @@ import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.namedAr */ @CompileStatic class SaveImplementer extends AbstractSaveImplementer implements SingleResultServiceImplementer { + static final List HANDLED_PREFIXES = ['save', 'store', 'persist'] @Override boolean doesImplement(ClassNode domainClass, MethodNode methodNode) { - if( methodNode.parameters.length == 0 ) { + if (methodNode.parameters.length == 0) { return false - } - else { + } else { return super.doesImplement(domainClass, methodNode) } } @@ -56,18 +60,17 @@ class SaveImplementer extends AbstractSaveImplementer implements SingleResultSer BlockStatement body = (BlockStatement) newMethodNode.getCode() Parameter[] parameters = newMethodNode.parameters int parameterCount = parameters.length - if(parameterCount == 1 && AstUtils.isDomainClass(parameters[0].type)) { + if (parameterCount == 1 && AstUtils.isDomainClass(parameters[0].type)) { body.addStatement( - returnS( callX( varX( parameters[0] ), "save", namedArgs(failOnError: ConstantExpression.TRUE) ) ) + returnS(callX(varX(parameters[0]), "save", namedArgs(failOnError: ConstantExpression.TRUE))) ) - } - else { + } else { VariableExpression entityVar = varX('$entity') body.addStatement( - declS(entityVar, ctorX(domainClassNode)) + declS(entityVar, ctorX(domainClassNode)) ) body.addStatement( - bindParametersAndSave(domainClassNode, abstractMethodNode, parameters, body, entityVar) + bindParametersAndSave(domainClassNode, abstractMethodNode, parameters, body, entityVar) ) } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultInterfaceProjectionBuilder.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultInterfaceProjectionBuilder.groovy index 81463660992..f2ff2dad9e9 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultInterfaceProjectionBuilder.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultInterfaceProjectionBuilder.groovy @@ -20,22 +20,23 @@ package org.grails.datastore.gorm.services.implementers import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.* -import org.codehaus.groovy.ast.expr.ConstantExpression +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.MethodNode import org.codehaus.groovy.ast.expr.Expression -import org.codehaus.groovy.ast.expr.ListExpression import org.codehaus.groovy.ast.expr.MethodCallExpression import org.codehaus.groovy.ast.expr.VariableExpression import org.codehaus.groovy.ast.stmt.Statement -import org.codehaus.groovy.transform.DelegateASTTransformation import org.grails.datastore.gorm.services.ServiceImplementer -import org.grails.datastore.gorm.transform.AstPropertyResolveUtils -import org.grails.datastore.mapping.reflect.AstUtils -import org.grails.datastore.mapping.reflect.NameUtils -import java.lang.reflect.Modifier - -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.block +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS +import static org.codehaus.groovy.ast.tools.GeneralUtils.notNullX +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX /** * Support trait for building interface projections @@ -48,23 +49,22 @@ trait SingleResultInterfaceProjectionBuilder extends InterfaceProjectionBuilder Statement buildInterfaceProjection(ClassNode targetDomainClass, MethodNode abstractMethodNode, Expression queryMethodCall, Expression args, MethodNode newMethodNode) { ClassNode declaringClass = newMethodNode.declaringClass - ClassNode interfaceNode = (ClassNode)newMethodNode.getNodeMetaData(ServiceImplementer.RETURN_TYPE) ?: abstractMethodNode.returnType + ClassNode interfaceNode = (ClassNode) newMethodNode.getNodeMetaData(ServiceImplementer.RETURN_TYPE) ?: abstractMethodNode.returnType MethodNode methodTarget = buildInterfaceImpl(interfaceNode, declaringClass, targetDomainClass, abstractMethodNode) ClassNode innerClassNode = methodTarget.getDeclaringClass() VariableExpression delegateVar = varX('$delegate', innerClassNode) VariableExpression targetVar = varX('$target', targetDomainClass) - MethodCallExpression setTargetCall = callX(delegateVar, '$setTarget', targetVar ) + MethodCallExpression setTargetCall = callX(delegateVar, '$setTarget', targetVar) setTargetCall.setMethodTarget(methodTarget) block( - declS(delegateVar, ctorX(innerClassNode)), - declS(targetVar, queryMethodCall), - ifS(notNullX(targetVar), block( - stmt(setTargetCall), - returnS(delegateVar) - )) + declS(delegateVar, ctorX(innerClassNode)), + declS(targetVar, queryMethodCall), + ifS(notNullX(targetVar), block( + stmt(setTargetCall), + returnS(delegateVar) + )) ) } - } \ No newline at end of file diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultServiceImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultServiceImplementer.groovy index e4705fe6dca..1032554f497 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultServiceImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultServiceImplementer.groovy @@ -22,7 +22,7 @@ package org.grails.datastore.gorm.services.implementers /** * An implementer that returns a single result * - * @param The return type + * @param The return type */ interface SingleResultServiceImplementer extends PrefixedServiceImplementer { diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/UpdateOneImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/UpdateOneImplementer.groovy index b5e15df2c07..c2de83d8f1a 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/UpdateOneImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/UpdateOneImplementer.groovy @@ -29,7 +29,14 @@ import org.codehaus.groovy.ast.stmt.Statement import org.grails.datastore.gorm.GormEntity import org.grails.datastore.mapping.model.config.GormProperties import org.grails.datastore.mapping.reflect.AstUtils -import static org.codehaus.groovy.ast.tools.GeneralUtils.* + +import static org.codehaus.groovy.ast.tools.GeneralUtils.block +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS +import static org.codehaus.groovy.ast.tools.GeneralUtils.notNullX +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX + /** * Implements an update operation that returns the updated domain class * @@ -38,19 +45,19 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.* */ @CompileStatic class UpdateOneImplementer extends AbstractSaveImplementer implements SingleResultServiceImplementer { + static final List HANDLED_PREFIXES = ['update'] @Override boolean doesImplement(ClassNode domainClass, MethodNode methodNode) { Parameter[] parameters = methodNode.parameters - if( parameters.length < 2 ) { + if (parameters.length < 2) { return false } // first parameter should be the id - else if(parameters[0].name != GormProperties.IDENTITY) { + else if (parameters[0].name != GormProperties.IDENTITY) { return false - } - else { + } else { return super.doesImplement(domainClass, methodNode) } } @@ -71,22 +78,22 @@ class UpdateOneImplementer extends AbstractSaveImplementer implements SingleResu StaticMethodCallExpression lookupCall = callX(domainClassNode, "get", varX(parameters[0])) VariableExpression entityVar = varX('$entity', domainClassNode) - BlockStatement body = (BlockStatement)newMethodNode.code + BlockStatement body = (BlockStatement) newMethodNode.code // def $entity = Foo.get(id) // if($entity != null) { // ... bind parameters // $entity.save() // } body.addStatement( - declS( entityVar, lookupCall) + declS(entityVar, lookupCall) ) BlockStatement ifBody = block() Statement saveStmt = bindParametersAndSave(domainClassNode, abstractMethodNode, parameters[1..-1] as Parameter[], ifBody, entityVar) ifBody.addStatement(saveStmt) body.addStatement( - ifS( notNullX(entityVar), - ifBody - ) + ifS(notNullX(entityVar), + ifBody + ) ) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/transform/QueryStringTransformer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/transform/QueryStringTransformer.groovy index 5ca309b7fe4..489e286b5cd 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/transform/QueryStringTransformer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/transform/QueryStringTransformer.groovy @@ -23,7 +23,16 @@ import groovy.transform.CompileStatic import org.codehaus.groovy.ast.ClassCodeExpressionTransformer import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.VariableScope -import org.codehaus.groovy.ast.expr.* +import org.codehaus.groovy.ast.expr.ClassExpression +import org.codehaus.groovy.ast.expr.ClosureExpression +import org.codehaus.groovy.ast.expr.ConstantExpression +import org.codehaus.groovy.ast.expr.DeclarationExpression +import org.codehaus.groovy.ast.expr.EmptyExpression +import org.codehaus.groovy.ast.expr.Expression +import org.codehaus.groovy.ast.expr.GStringExpression +import org.codehaus.groovy.ast.expr.MethodCallExpression +import org.codehaus.groovy.ast.expr.PropertyExpression +import org.codehaus.groovy.ast.expr.VariableExpression import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.ExpressionStatement import org.codehaus.groovy.ast.stmt.ReturnStatement @@ -56,44 +65,39 @@ class QueryStringTransformer extends ClassCodeExpressionTransformer { GStringExpression transformQuery(GStringExpression query) { Expression transformed = transform(query) transformed = transformPropertyExpressions(transformed) - GStringExpression transformedGString = (GStringExpression)transformed + GStringExpression transformedGString = (GStringExpression) transformed int i = 0 List newStrings = [] List newValues = [] ConstantExpression currentConstant List values = transformedGString.values - for(ConstantExpression exp in transformedGString.strings) { - if(i < values.size()) { + for (ConstantExpression exp in transformedGString.strings) { + if (i < values.size()) { Expression valueExpr = values[i++] - if(valueExpr instanceof ConstantExpression) { - ConstantExpression valueConstant = (ConstantExpression)valueExpr + if (valueExpr instanceof ConstantExpression) { + ConstantExpression valueConstant = (ConstantExpression) valueExpr String newConstant = exp.value.toString() + valueConstant.value.toString() - if(currentConstant != null) { - currentConstant = constX(currentConstant.value.toString() + newConstant ) - } - else { + if (currentConstant != null) { + currentConstant = constX(currentConstant.value.toString() + newConstant) + } else { currentConstant = constX(newConstant) } - } - else if(currentConstant != null) { + } else if (currentConstant != null) { currentConstant = constX(currentConstant.value.toString() + exp.text) newStrings.add(currentConstant) newValues.add(valueExpr) currentConstant = null - } - else { + } else { newStrings.add(exp) newValues.add(valueExpr) } - } - else { - if(currentConstant != null) { + } else { + if (currentConstant != null) { currentConstant = constX(currentConstant.value.toString() + exp.text) newStrings.add(currentConstant) currentConstant = null - } - else { + } else { newStrings.add(exp) } } @@ -104,38 +108,34 @@ class QueryStringTransformer extends ClassCodeExpressionTransformer { @Override Expression transform(Expression exp) { - if(exp instanceof ClassExpression) { + if (exp instanceof ClassExpression) { ClassNode type = ((ClassExpression) exp).type - if(AstUtils.isDomainClass(type)) { + if (AstUtils.isDomainClass(type)) { return constX(type.name) - } - else { + } else { AstUtils.error(sourceUnit, exp, "Invalid query class [$type.name]. Referenced classes in queries must be domain classes") } - } - else if(exp instanceof PropertyExpression) { + } else if (exp instanceof PropertyExpression) { return transformPropertyExpressions(exp) - } - else if(exp instanceof MethodCallExpression) { - MethodCallExpression mce = (MethodCallExpression)exp + } else if (exp instanceof MethodCallExpression) { + MethodCallExpression mce = (MethodCallExpression) exp Expression methodTarget = mce.objectExpression - if( methodTarget instanceof ClosureExpression && mce.methodAsString == 'call') { - ClosureExpression closureExpression = (ClosureExpression)methodTarget + if (methodTarget instanceof ClosureExpression && mce.methodAsString == 'call') { + ClosureExpression closureExpression = (ClosureExpression) methodTarget Statement body = closureExpression.code - if(body instanceof BlockStatement) { + if (body instanceof BlockStatement) { def statements = ((BlockStatement) body).statements - if(statements.size() == 1) { - for(stmt in statements) { - if(stmt instanceof ExpressionStatement) { - def stmtExpr = ((ExpressionStatement)stmt).expression - if(stmtExpr instanceof DeclarationExpression) { - return transformDeclarationExpression((DeclarationExpression)stmtExpr) + if (statements.size() == 1) { + for (stmt in statements) { + if (stmt instanceof ExpressionStatement) { + def stmtExpr = ((ExpressionStatement) stmt).expression + if (stmtExpr instanceof DeclarationExpression) { + return transformDeclarationExpression((DeclarationExpression) stmtExpr) } - } - else if(stmt instanceof ReturnStatement) { - def stmtExpr = ((ReturnStatement)stmt).expression - if(stmtExpr instanceof DeclarationExpression) { - return transformDeclarationExpression((DeclarationExpression)stmtExpr) + } else if (stmt instanceof ReturnStatement) { + def stmtExpr = ((ReturnStatement) stmt).expression + if (stmtExpr instanceof DeclarationExpression) { + return transformDeclarationExpression((DeclarationExpression) stmtExpr) } } } @@ -144,13 +144,12 @@ class QueryStringTransformer extends ClassCodeExpressionTransformer { } } - if(exp instanceof VariableExpression) { - VariableExpression var = (VariableExpression)exp + if (exp instanceof VariableExpression) { + VariableExpression var = (VariableExpression) exp def declared = variableScope.getDeclaredVariable(var.name) - if(declared != null) { + if (declared != null) { return varX(declared) - } - else if(declaredQueryTargets.containsKey(var.name)) { + } else if (declaredQueryTargets.containsKey(var.name)) { return constX(var.name) } } @@ -158,51 +157,46 @@ class QueryStringTransformer extends ClassCodeExpressionTransformer { } Expression transformDeclarationExpression(DeclarationExpression dec) { - if(dec.leftExpression instanceof VariableExpression && dec.rightExpression instanceof EmptyExpression) { - VariableExpression declaredVar = (VariableExpression)dec.leftExpression + if (dec.leftExpression instanceof VariableExpression && dec.rightExpression instanceof EmptyExpression) { + VariableExpression declaredVar = (VariableExpression) dec.leftExpression ClassNode variableType = declaredVar.type String variableName = declaredVar.name - if(AstUtils.isDomainClass(variableType)) { + if (AstUtils.isDomainClass(variableType)) { declaredQueryTargets.put(variableName, variableType) return constX(formatDomainClassVariable(variableType, variableName)) } - } - else if(dec.leftExpression instanceof VariableExpression && dec.rightExpression instanceof PropertyExpression) { - VariableExpression declaredVar = (VariableExpression)dec.leftExpression + } else if (dec.leftExpression instanceof VariableExpression && dec.rightExpression instanceof PropertyExpression) { + VariableExpression declaredVar = (VariableExpression) dec.leftExpression ClassNode variableType = declaredVar.type String variableName = declaredVar.name - if(AstUtils.isDomainClass(variableType)) { - PropertyExpression pe = (PropertyExpression)dec.rightExpression + if (AstUtils.isDomainClass(variableType)) { + PropertyExpression pe = (PropertyExpression) dec.rightExpression Expression obj = pe.objectExpression String currentProperty = pe.propertyAsString StringBuilder path = new StringBuilder() - if(obj instanceof VariableExpression) { - VariableExpression ve = (VariableExpression)obj + if (obj instanceof VariableExpression) { + VariableExpression ve = (VariableExpression) obj ClassNode declaredType = declaredQueryTargets.get(ve.name) - if(declaredType == null) { + if (declaredType == null) { AstUtils.error(sourceUnit, dec, "Invalid property path $path in query") - } - else { + } else { declaredQueryTargets.put(variableName, variableType) return constX(formatPropertyReference(ve, currentProperty, variableName)) } - } - else if(obj instanceof PropertyExpression) { + } else if (obj instanceof PropertyExpression) { List propertyPath = calculatePropertyPath(pe) ClassNode currentType = declaredQueryTargets.get(propertyPath[0]) - for(String pp in propertyPath[1..-1]) { - if(currentType == null) { + for (String pp in propertyPath[1..-1]) { + if (currentType == null) { AstUtils.error(sourceUnit, dec, "Invalid property path $path in query") - } - else { + } else { currentType = AstPropertyResolveUtils.getPropertyType(currentType, pp) } } - if(currentType != null) { + if (currentType != null) { declaredQueryTargets.put(variableName, currentType) return constX(formatPropertyPath(propertyPath, variableName)) - } - else { + } else { AstUtils.error(sourceUnit, dec, "Invalid property path ${propertyPath.join('.')} in query") } } @@ -249,29 +243,29 @@ class QueryStringTransformer extends ClassCodeExpressionTransformer { List propertyPath = [] propertyPath.add(p.propertyAsString) Expression obj = p.objectExpression - while(obj instanceof PropertyExpression) { - PropertyExpression nextProperty = (PropertyExpression)obj + while (obj instanceof PropertyExpression) { + PropertyExpression nextProperty = (PropertyExpression) obj propertyPath.add(nextProperty.propertyAsString) obj = nextProperty.objectExpression } - if(obj instanceof VariableExpression) { - propertyPath.add(((VariableExpression)obj).name) + if (obj instanceof VariableExpression) { + propertyPath.add(((VariableExpression) obj).name) } return propertyPath.reverse() } + Expression transformPropertyExpressions(Expression exp) { - if(exp instanceof PropertyExpression) { - PropertyExpression pe = (PropertyExpression)exp + if (exp instanceof PropertyExpression) { + PropertyExpression pe = (PropertyExpression) exp Expression targetObject = pe.objectExpression - if( targetObject instanceof VariableExpression) { - VariableExpression var = (VariableExpression)targetObject + if (targetObject instanceof VariableExpression) { + VariableExpression var = (VariableExpression) targetObject ClassNode domainType = declaredQueryTargets.get(var.name) - if(domainType != null) { + if (domainType != null) { String propertyName = pe.propertyAsString - if(( AstUtils.isDomainClass(domainType) && propertyName == "id" )|| AstUtils.hasOrInheritsProperty(domainType, propertyName) ) { + if ((AstUtils.isDomainClass(domainType) && propertyName == "id") || AstUtils.hasOrInheritsProperty(domainType, propertyName)) { return constX("${var.name}.$propertyName".toString()) - } - else { + } else { AstUtils.error(sourceUnit, exp, "No property [$propertyName] existing for domain class [$domainType.name]") } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/transform/ServiceTransformation.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/transform/ServiceTransformation.groovy index ab2fb657deb..ae0d36f9760 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/transform/ServiceTransformation.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/transform/ServiceTransformation.groovy @@ -57,13 +57,14 @@ import org.grails.datastore.gorm.services.implementers.CountImplementer import org.grails.datastore.gorm.services.implementers.CountWhereImplementer import org.grails.datastore.gorm.services.implementers.DeleteImplementer import org.grails.datastore.gorm.services.implementers.DeleteWhereImplementer +import org.grails.datastore.gorm.services.implementers.FindAllByImplementer import org.grails.datastore.gorm.services.implementers.FindAllByInterfaceProjectionImplementer +import org.grails.datastore.gorm.services.implementers.FindAllImplementer import org.grails.datastore.gorm.services.implementers.FindAllInterfaceProjectionImplementer +import org.grails.datastore.gorm.services.implementers.FindAllPropertyProjectionImplementer import org.grails.datastore.gorm.services.implementers.FindAllStringQueryImplementer import org.grails.datastore.gorm.services.implementers.FindAllWhereImplementer import org.grails.datastore.gorm.services.implementers.FindAndDeleteImplementer -import org.grails.datastore.gorm.services.implementers.FindAllImplementer -import org.grails.datastore.gorm.services.implementers.FindAllByImplementer import org.grails.datastore.gorm.services.implementers.FindOneByImplementer import org.grails.datastore.gorm.services.implementers.FindOneByInterfaceProjectionImplementer import org.grails.datastore.gorm.services.implementers.FindOneImplementer @@ -71,11 +72,10 @@ import org.grails.datastore.gorm.services.implementers.FindOneInterfaceProjectio import org.grails.datastore.gorm.services.implementers.FindOneInterfaceProjectionStringQueryImplementer import org.grails.datastore.gorm.services.implementers.FindOneInterfaceProjectionWhereImplementer import org.grails.datastore.gorm.services.implementers.FindOnePropertyProjectionImplementer -import org.grails.datastore.gorm.services.implementers.FindAllPropertyProjectionImplementer -import org.grails.datastore.gorm.services.implementers.SaveImplementer import org.grails.datastore.gorm.services.implementers.FindOneStringQueryImplementer -import org.grails.datastore.gorm.services.implementers.UpdateOneImplementer import org.grails.datastore.gorm.services.implementers.FindOneWhereImplementer +import org.grails.datastore.gorm.services.implementers.SaveImplementer +import org.grails.datastore.gorm.services.implementers.UpdateOneImplementer import org.grails.datastore.gorm.services.implementers.UpdateStringQueryImplementer import org.grails.datastore.gorm.transactions.transform.TransactionalTransform import org.grails.datastore.gorm.transform.AbstractTraitApplyingGormASTTransformation @@ -86,8 +86,27 @@ import org.grails.datastore.mapping.core.order.OrderedComparator import java.beans.Introspector import java.lang.reflect.Modifier -import static org.codehaus.groovy.ast.tools.GeneralUtils.* -import static org.grails.datastore.mapping.reflect.AstUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX +import static org.codehaus.groovy.ast.tools.GeneralUtils.block +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX +import static org.codehaus.groovy.ast.tools.GeneralUtils.equalsNullX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS +import static org.codehaus.groovy.ast.tools.GeneralUtils.param +import static org.codehaus.groovy.ast.tools.GeneralUtils.params +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX +import static org.grails.datastore.mapping.reflect.AstUtils.COMPILE_STATIC_TYPE +import static org.grails.datastore.mapping.reflect.AstUtils.ZERO_PARAMETERS +import static org.grails.datastore.mapping.reflect.AstUtils.addAnnotationIfNecessary +import static org.grails.datastore.mapping.reflect.AstUtils.copyAnnotations +import static org.grails.datastore.mapping.reflect.AstUtils.copyParameters +import static org.grails.datastore.mapping.reflect.AstUtils.error +import static org.grails.datastore.mapping.reflect.AstUtils.findAllUnimplementedAbstractMethods +import static org.grails.datastore.mapping.reflect.AstUtils.findAnnotation +import static org.grails.datastore.mapping.reflect.AstUtils.hasAnnotation +import static org.grails.datastore.mapping.reflect.AstUtils.warning /** * Makes a class implement the {@link org.grails.datastore.mapping.services.Service} trait and generates the necessary @@ -172,18 +191,18 @@ class ServiceTransformation extends AbstractTraitApplyingGormASTTransformation i VariableExpression fieldVar = varX(field) propertiesFields.add(field) pn.setGetterBlock( - block( - ifS( equalsNullX(fieldVar), - assignX(fieldVar, callX( varX("datastore"), "getService", classX(propertyType.plainNodeReference))) - ), - returnS(fieldVar) - ) + block( + ifS(equalsNullX(fieldVar), + assignX(fieldVar, callX(varX("datastore"), "getService", classX(propertyType.plainNodeReference))) + ), + returnS(fieldVar) + ) ) } } List constructors = classNode.getDeclaredConstructors() - if(!constructors.isEmpty()) { + if (!constructors.isEmpty()) { error(sourceUnit, classNode, "Abstract data Services should not define constructors") } @@ -200,25 +219,24 @@ class ServiceTransformation extends AbstractTraitApplyingGormASTTransformation i superClass, interfaces) - if(!propertiesFields.isEmpty()) { + if (!propertiesFields.isEmpty()) { ClassNode datastoreType = ClassHelper.make(Datastore) FieldNode datastoreField = impl.addField("datastore", Modifier.PRIVATE, datastoreType, null) VariableExpression datastoreFieldVar = varX(datastoreField) - BlockStatement body = block() Parameter datastoreParam = param(datastoreType, "d") impl.addMethod("setDatastore", Modifier.PUBLIC, ClassHelper.VOID_TYPE, params( datastoreParam - ), null, body ) + ), null, body) body.addStatement( assignS(datastoreFieldVar, varX(datastoreParam)) ) impl.addMethod("getDatastore", Modifier.PUBLIC, datastoreType.plainNodeReference, ZERO_PARAMETERS, null, - returnS( datastoreFieldVar ) + returnS(datastoreFieldVar) ) - for(FieldNode fn in propertiesFields) { + for (FieldNode fn in propertiesFields) { body.addStatement( assignS(varX(fn), callX(datastoreFieldVar, "getService", classX(fn.type.plainNodeReference))) ) @@ -227,7 +245,7 @@ class ServiceTransformation extends AbstractTraitApplyingGormASTTransformation i copyAnnotations(classNode, impl) AnnotationNode serviceAnnotation = findAnnotation(impl, Service) - if(serviceAnnotation.getMember("name") == null) { + if (serviceAnnotation.getMember("name") == null) { serviceAnnotation .setMember("name", new ConstantExpression(Introspector.decapitalize(serviceClassName))) } @@ -242,7 +260,6 @@ class ServiceTransformation extends AbstractTraitApplyingGormASTTransformation i List abstractMethods = findAllUnimplementedAbstractMethods(classNode) Iterable implementers = findServiceImplementors(annotationNode) - // first go through the existing implemented methods and just enhance them if (!isInterface) { for (MethodNode existing in classNode.methods) { @@ -283,8 +300,8 @@ class ServiceTransformation extends AbstractTraitApplyingGormASTTransformation i implementer.implement(targetDomainClass, method, methodImpl, impl) def implementedAnn = new AnnotationNode(ClassHelper.make(Implemented)) Class implementedClass = implementer.getClass() - if(implementer instanceof AdaptedImplementer) { - implementedClass = ((AdaptedImplementer)implementer).getAdapted().getClass() + if (implementer instanceof AdaptedImplementer) { + implementedClass = ((AdaptedImplementer) implementer).getAdapted().getClass() } implementedAnn.setMember("by", classX(implementedClass)) methodImpl.addAnnotation(implementedAnn) @@ -313,7 +330,6 @@ class ServiceTransformation extends AbstractTraitApplyingGormASTTransformation i TraitComposer.doExtendTraits(impl, sourceUnit, compilationUnit) } - Expression exposeExpr = annotationNode.getMember("expose") if (exposeExpr == null || (exposeExpr instanceof ConstantExpression && exposeExpr == ConstantExpression.TRUE)) { generateServiceDescriptor(sourceUnit, impl) @@ -334,7 +350,7 @@ class ServiceTransformation extends AbstractTraitApplyingGormASTTransformation i if (!cn.isPrimaryClassNode()) { Class cls = cn.typeClass if (cls != null && type.isAssignableFrom(cls)) { - implementers.add( cls.newInstance() ) + implementers.add(cls.newInstance()) } } } @@ -357,28 +373,27 @@ class ServiceTransformation extends AbstractTraitApplyingGormASTTransformation i List finalAdapters = adapters.toList() loadAnnotationDefined(annotationNode, "adapters", finalAdapters, ServiceImplementerAdapter) - if(!finalAdapters.isEmpty()) { + if (!finalAdapters.isEmpty()) { finalAdapters = finalAdapters.unique { ServiceImplementerAdapter o1 -> o1.class.name } - for(implementer in implementers) { - for(ServiceImplementerAdapter adapter in finalAdapters) { + for (implementer in implementers) { + for (ServiceImplementerAdapter adapter in finalAdapters) { ServiceImplementer adapted = adapter.adapt(implementer) - if(adapted != null) { + if (adapted != null) { finalImplementers.add(adapted) } } } } - LOADED_IMPLEMENTORS = finalImplementers.sort(true, new OrderedComparator()) } return LOADED_IMPLEMENTORS } protected void loadAnnotationDefined(AnnotationNode annotationNode, String member, List finalList, Class type) { - Expression additionalImplementers = annotationNode.getMember(member ) + Expression additionalImplementers = annotationNode.getMember(member) if (additionalImplementers instanceof ListExpression) { for (Expression exp in ((ListExpression) additionalImplementers).expressions) { addClassExpressionToImplementers(exp, finalList, type) diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/support/AbstractDatastorePersistenceContextInterceptor.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/support/AbstractDatastorePersistenceContextInterceptor.java index 501988e4372..fa5755fc66b 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/support/AbstractDatastorePersistenceContextInterceptor.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/support/AbstractDatastorePersistenceContextInterceptor.java @@ -19,7 +19,6 @@ package org.grails.datastore.gorm.support; import jakarta.persistence.FlushModeType; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.grails.datastore.mapping.core.Datastore; @@ -31,10 +30,10 @@ /** * Abstract implementation of the persistence context interceptor * - * @since 1.0 * @author Graeme Rocher + * @since 1.0 */ -public abstract class AbstractDatastorePersistenceContextInterceptor { +public abstract class AbstractDatastorePersistenceContextInterceptor { private static final Log LOG = LogFactory.getLog(AbstractDatastorePersistenceContextInterceptor.class); protected Datastore datastore; @@ -66,13 +65,12 @@ public void destroy() { // single session mode final SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(datastore); if (sessionHolder != null && this == sessionHolder.getCreator()) { - SessionHolder holder = (SessionHolder)TransactionSynchronizationManager.unbindResource(datastore); + SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.unbindResource(datastore); LOG.debug("Closing single Datastore session in DatastorePersistenceContextInterceptor"); try { Session session = holder.getSession(); DatastoreUtils.closeSession(session); - } - catch (RuntimeException ex) { + } catch (RuntimeException ex) { LOG.error("Unexpected exception on closing Datastore Session", ex); } } @@ -88,7 +86,7 @@ public void reconnect() { public void flush() { Session session = getSession(); - if(session.hasTransaction()) { + if (session.hasTransaction()) { session.flush(); } } @@ -108,8 +106,7 @@ public void setReadWrite() { public boolean isOpen() { try { return DatastoreUtils.doGetSession(datastore, false).isConnected(); - } - catch (IllegalStateException e) { + } catch (IllegalStateException e) { return false; } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/timestamp/AggregateTimestampProvider.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/timestamp/AggregateTimestampProvider.java index 161fd266d75..0b3f3549464 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/timestamp/AggregateTimestampProvider.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/timestamp/AggregateTimestampProvider.java @@ -18,22 +18,23 @@ */ package org.grails.datastore.gorm.timestamp; +import org.springframework.beans.factory.annotation.Autowired; + import java.util.Collections; import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; - /** * TimestampProvider implementation that aggregates multiple TimestampProviders * */ public class AggregateTimestampProvider implements TimestampProvider { - private List timestampProviders=Collections.emptyList(); - + + private List timestampProviders = Collections.emptyList(); + @Override public boolean supportsCreating(Class dateTimeClass) { - for(TimestampProvider provider : timestampProviders) { - if(provider.supportsCreating(dateTimeClass)) { + for (TimestampProvider provider : timestampProviders) { + if (provider.supportsCreating(dateTimeClass)) { return true; } } @@ -42,9 +43,9 @@ public boolean supportsCreating(Class dateTimeClass) { @Override public T createTimestamp(Class dateTimeClass) { - if(timestampProviders.size() > 1) { - for(TimestampProvider provider : timestampProviders) { - if(provider.supportsCreating(dateTimeClass)) { + if (timestampProviders.size() > 1) { + for (TimestampProvider provider : timestampProviders) { + if (provider.supportsCreating(dateTimeClass)) { return createTimestamp(provider, dateTimeClass); } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/timestamp/DefaultTimestampProvider.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/timestamp/DefaultTimestampProvider.java index dfd163db499..7fde32f9b2b 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/timestamp/DefaultTimestampProvider.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/timestamp/DefaultTimestampProvider.java @@ -18,16 +18,16 @@ */ package org.grails.datastore.gorm.timestamp; -import java.util.Date; - import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.springframework.util.ClassUtils; +import java.util.Date; + /** * Default implementation of TimestampProvider - * + *

    * supports creating timestamps for any class that supports a constructor that accepts a Long or long value. - * + *

    * "currentTimeMillis" can be overrided in subclasses (useful for testing purposes) * */ @@ -46,19 +46,19 @@ public boolean supportsCreating(Class dateTimeClass) { @Override public T createTimestamp(final Class dateTimeClass) { long timestampMillis = currentTimeMillis(); - if(dateTimeClass == String.class) { - return (T)String.valueOf(timestampMillis); + if (dateTimeClass == String.class) { + return (T) String.valueOf(timestampMillis); } else { Class actualDateTimeClass; - if(dateTimeClass==Object.class) { + if (dateTimeClass == Object.class) { actualDateTimeClass = Date.class; } else { actualDateTimeClass = ClassUtils.resolvePrimitiveIfNecessary(dateTimeClass); } try { - return (T)DefaultGroovyMethods.newInstance(actualDateTimeClass, new Object[] { timestampMillis }); + return (T) DefaultGroovyMethods.newInstance(actualDateTimeClass, new Object[]{timestampMillis}); } catch (Exception e) { - return (T)DefaultGroovyMethods.invokeMethod(actualDateTimeClass, "now", null); + return (T) DefaultGroovyMethods.invokeMethod(actualDateTimeClass, "now", null); } } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/timestamp/TimestampProvider.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/timestamp/TimestampProvider.java index b712612944a..47f69a6ec41 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/timestamp/TimestampProvider.java +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/timestamp/TimestampProvider.java @@ -23,19 +23,20 @@ * */ public interface TimestampProvider { + /** * Whether a timestamp can be created for the given type * * @param dateTimeClass The date time class - * * @return True if it can */ boolean supportsCreating(Class dateTimeClass); /** * Creates a timestamp for the given class + * * @param dateTimeClass The time stamp - * @param The type of the timestamp class + * @param The type of the timestamp class * @return An instance of the timestamp */ T createTimestamp(Class dateTimeClass); diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transactions/transform/TransactionalTransform.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transactions/transform/TransactionalTransform.groovy index fe90ad0e63f..8a6bd6b7c23 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transactions/transform/TransactionalTransform.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transactions/transform/TransactionalTransform.groovy @@ -21,8 +21,18 @@ import grails.gorm.transactions.Rollback import grails.gorm.transactions.Transactional import groovy.transform.CompileStatic import org.apache.grails.common.compiler.GroovyTransformOrder -import org.codehaus.groovy.ast.* -import org.codehaus.groovy.ast.expr.* +import org.codehaus.groovy.ast.AnnotatedNode +import org.codehaus.groovy.ast.AnnotationNode +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.FieldNode +import org.codehaus.groovy.ast.MethodNode +import org.codehaus.groovy.ast.Parameter +import org.codehaus.groovy.ast.expr.ClassExpression +import org.codehaus.groovy.ast.expr.ConstantExpression +import org.codehaus.groovy.ast.expr.Expression +import org.codehaus.groovy.ast.expr.ListExpression +import org.codehaus.groovy.ast.expr.MethodCallExpression +import org.codehaus.groovy.ast.expr.VariableExpression import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.Statement import org.codehaus.groovy.control.CompilePhase @@ -31,7 +41,6 @@ import org.codehaus.groovy.transform.GroovyASTTransformation import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.gorm.multitenancy.transform.TenantTransform import org.grails.datastore.gorm.transform.AbstractDatastoreMethodDecoratingTransformation -import org.grails.datastore.mapping.core.Ordered import org.grails.datastore.mapping.core.connections.MultipleConnectionSourceCapableDatastore import org.grails.datastore.mapping.multitenancy.MultiTenantCapableDatastore import org.grails.datastore.mapping.transactions.CustomizableRollbackTransactionAttribute @@ -44,9 +53,39 @@ import org.springframework.transaction.interceptor.RollbackRuleAttribute import java.lang.reflect.Modifier -import static org.codehaus.groovy.ast.ClassHelper.* -import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.* -import static org.grails.datastore.mapping.reflect.AstUtils.* +import static org.codehaus.groovy.ast.ClassHelper.CLASS_Type +import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE +import static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE +import static org.codehaus.groovy.ast.ClassHelper.make +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS +import static org.codehaus.groovy.ast.tools.GeneralUtils.block +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.castX +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifElseS +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS +import static org.codehaus.groovy.ast.tools.GeneralUtils.notNullX +import static org.codehaus.groovy.ast.tools.GeneralUtils.param +import static org.codehaus.groovy.ast.tools.GeneralUtils.params +import static org.codehaus.groovy.ast.tools.GeneralUtils.propX +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX +import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.callD +import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.callThisD +import static org.grails.datastore.mapping.reflect.AstUtils.ZERO_ARGUMENTS +import static org.grails.datastore.mapping.reflect.AstUtils.ZERO_PARAMETERS +import static org.grails.datastore.mapping.reflect.AstUtils.buildGetPropertyExpression +import static org.grails.datastore.mapping.reflect.AstUtils.copyParameters +import static org.grails.datastore.mapping.reflect.AstUtils.findAnnotation +import static org.grails.datastore.mapping.reflect.AstUtils.hasOrInheritsProperty +import static org.grails.datastore.mapping.reflect.AstUtils.implementsInterface +import static org.grails.datastore.mapping.reflect.AstUtils.isSubclassOf +import static org.grails.datastore.mapping.reflect.AstUtils.nonGeneric +import static org.grails.datastore.mapping.reflect.AstUtils.varThis /** *

    This AST transform reads the {@link Transactional} annotation and transforms method calls by @@ -57,7 +96,7 @@ import static org.grails.datastore.mapping.reflect.AstUtils.* * *

      * class FooService {
    - *   {@code @Transactional}
    + * {@code @Transactional}
      *   void updateFoo() {
      *       ...
      *   }
    @@ -96,6 +135,7 @@ import static org.grails.datastore.mapping.reflect.AstUtils.*
     @CompileStatic
     @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
     class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransformation {
    +
         private static final Set ANNOTATION_NAME_EXCLUDES = new HashSet([Transactional.class.getName(), "grails.transaction.Rollback", Rollback.class.getName(), NotTransactional.class.getName(), "grails.transaction.NotTransactional", "grails.gorm.transactions.ReadOnly"])
         public static final ClassNode MY_TYPE = new ClassNode(Transactional)
         public static final ClassNode READ_ONLY_TYPE = new ClassNode(ReadOnly)
    @@ -104,7 +144,7 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
         private static final Object APPLIED_MARKER = new Object()
         private static final String SET_TRANSACTION_MANAGER = "setTransactionManager"
         private static final Set VALID_ANNOTATION_NAMES = Collections.unmodifiableSet(
    -        new HashSet([Transactional.simpleName, Rollback.simpleName, ReadOnly.simpleName])
    +            new HashSet([Transactional.simpleName, Rollback.simpleName, ReadOnly.simpleName])
         )
         public static final String GET_TRANSACTION_MANAGER_METHOD = "getTransactionManager"
     
    @@ -135,7 +175,7 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
     
         @Override
         protected boolean isValidAnnotation(AnnotationNode annotationNode, AnnotatedNode classNode) {
    -        return VALID_ANNOTATION_NAMES.contains( annotationNode.classNode.nameWithoutPackage )
    +        return VALID_ANNOTATION_NAMES.contains(annotationNode.classNode.nameWithoutPackage)
         }
     
         @Override
    @@ -175,7 +215,7 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
         @Override
         protected void weaveTestSetupMethod(SourceUnit sourceUnit, AnnotationNode annotationNode, ClassNode classNode, MethodNode methodNode, Map genericsSpec) {
             def requiresNewTransaction = new AnnotationNode(annotationNode.classNode)
    -        requiresNewTransaction.addMember("propagation", propX( classX(Propagation), "REQUIRES_NEW") )
    +        requiresNewTransaction.addMember("propagation", propX(classX(Propagation), "REQUIRES_NEW"))
             weaveNewMethod(sourceUnit, requiresNewTransaction, classNode, methodNode, genericsSpec)
         }
     
    @@ -190,18 +230,18 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
         }
     
         protected void weaveTransactionManagerAware(SourceUnit source, AnnotationNode annotationNode, ClassNode declaringClassNode) {
    -        if ( declaringClassNode.getNodeMetaData(APPLIED_MARKER) == APPLIED_MARKER ) {
    +        if (declaringClassNode.getNodeMetaData(APPLIED_MARKER) == APPLIED_MARKER) {
                 return
             }
     
             Expression connectionName = annotationNode.getMember("connection")
    -        if( connectionName == null ) {
    +        if (connectionName == null) {
                 connectionName = annotationNode.getMember("value")
             }
             boolean hasDataSourceProperty = connectionName != null
     
             //add the transactionManager property
    -        if (!hasOrInheritsProperty(declaringClassNode, PROPERTY_TRANSACTION_MANAGER) ) {
    +        if (!hasOrInheritsProperty(declaringClassNode, PROPERTY_TRANSACTION_MANAGER)) {
     
                 ClassNode transactionManagerClassNode = make(PlatformTransactionManager)
     
    @@ -209,40 +249,39 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
                 ClassExpression gormEnhancerExpr = classX(GormEnhancer)
                 Expression val = annotationNode.getMember("datastore")
                 MethodCallExpression transactionManagerLookupExpr
    -            if(val instanceof ClassExpression) {
    +            if (val instanceof ClassExpression) {
                     transactionManagerLookupExpr = hasDataSourceProperty ? callX(gormEnhancerExpr, "findTransactionManager", args(val, connectionName)) : callX(gormEnhancerExpr, "findTransactionManager", val)
                     Parameter typeParameter = param(CLASS_Type, "type")
                     Parameter[] params = hasDataSourceProperty ? params(typeParameter, param(STRING_TYPE, "connectionName")) : params(typeParameter)
     
                     transactionManagerLookupExpr.setMethodTarget(
    -                        gormEnhancerExpr.getType().getDeclaredMethod("findTransactionManager", params )
    +                        gormEnhancerExpr.getType().getDeclaredMethod("findTransactionManager", params)
                     )
    -            }
    -            else {
    +            } else {
                     transactionManagerLookupExpr = hasDataSourceProperty ? callX(gormEnhancerExpr, "findSingleTransactionManager", connectionName) : callX(gormEnhancerExpr, "findSingleTransactionManager")
                     Parameter[] params = hasDataSourceProperty ? params(param(STRING_TYPE, "connectionName")) : ZERO_PARAMETERS
                     transactionManagerLookupExpr.setMethodTarget(
    -                        gormEnhancerExpr.getType().getDeclaredMethod("findSingleTransactionManager", params )
    +                        gormEnhancerExpr.getType().getDeclaredMethod("findSingleTransactionManager", params)
                     )
                 }
     
                 // simply logic for classes that implement Service
    -            if(implementsInterface(declaringClassNode, "org.grails.datastore.mapping.services.Service")) {
    +            if (implementsInterface(declaringClassNode, "org.grails.datastore.mapping.services.Service")) {
                     // Add Method: PlatformTransactionManager getTransactionManager()
                     // if(datastore != null)
                     //     return datastore.transactionManager
                     // else
                     //     return GormEnhancer.findSingleTransactionManager()
                     ClassNode transactionCapableDatastore = make(TransactionCapableDatastore)
    -                Expression datastoreVar = castX(transactionCapableDatastore, varX("datastore") )
    +                Expression datastoreVar = castX(transactionCapableDatastore, varX("datastore"))
                     Expression datastoreLookupExpr = datastoreVar
    -                if(hasDataSourceProperty) {
    -                    datastoreLookupExpr = callD(castX(make(MultipleConnectionSourceCapableDatastore), datastoreVar), "getDatastoreForConnection", connectionName )
    +                if (hasDataSourceProperty) {
    +                    datastoreLookupExpr = callD(castX(make(MultipleConnectionSourceCapableDatastore), datastoreVar), "getDatastoreForConnection", connectionName)
                     }
                     Statement ifElse = ifElseS(
                             notNullX(datastoreVar),
    -                        returnS( propX( castX(transactionCapableDatastore, datastoreLookupExpr), PROPERTY_TRANSACTION_MANAGER) ),
    -                        returnS( transactionManagerLookupExpr )
    +                        returnS(propX(castX(transactionCapableDatastore, datastoreLookupExpr), PROPERTY_TRANSACTION_MANAGER)),
    +                        returnS(transactionManagerLookupExpr)
                     )
     
                     declaringClassNode.addMethod(GET_TRANSACTION_MANAGER_METHOD,
    @@ -251,41 +290,38 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
                             ZERO_PARAMETERS, null,
                             ifElse)
     
    -            }
    -            else {
    +            } else {
                     /// Add field: PlatformTransactionManager $transactionManager
                     String transactionManagerFieldName = '$' + PROPERTY_TRANSACTION_MANAGER
                     FieldNode transactionManagerField = declaringClassNode.addField(transactionManagerFieldName, Modifier.PROTECTED, transactionManagerClassNode, null)
     
    -
                     VariableExpression transactionManagerPropertyExpr = varX(transactionManagerField)
                     BlockStatement getterBody = block()
     
                     // this is a hacky workaround that ensures the transaction manager is also set on the spock shared instance which seems to differ for
                     // some reason
    -                if(isSubclassOf(declaringClassNode, "spock.lang.Specification")) {
    +                if (isSubclassOf(declaringClassNode, "spock.lang.Specification")) {
                         getterBody.addStatement(
                                 stmt(
    -                                    callX( propX( propX( varThis(), "specificationContext"), "sharedInstance"),
    +                                    callX(propX(propX(varThis(), "specificationContext"), "sharedInstance"),
                                                 SET_TRANSACTION_MANAGER,
                                                 transactionManagerPropertyExpr)
                                 )
                         )
                     }
     
    -
                     // Prepare the getTransactionManager() method body
                     // if($transactionManager != null)
                     //     return $transactionManager
                     // else
                     //     return GormEnhancer.findSingleTransactionManager()
                     Statement ifElse = ifElseS(
    -                        notNullX( transactionManagerPropertyExpr ),
    -                        returnS( transactionManagerPropertyExpr ),
    +                        notNullX(transactionManagerPropertyExpr),
    +                        returnS(transactionManagerPropertyExpr),
                             returnS(transactionManagerLookupExpr)
                     )
     
    -                getterBody.addStatement( ifElse )
    +                getterBody.addStatement(ifElse)
     
                     // Add Method: PlatformTransactionManager getTransactionManager()
                     declaringClassNode.addMethod(GET_TRANSACTION_MANAGER_METHOD,
    @@ -297,7 +333,7 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
                     // Prepare setter parameters
                     Parameter p = param(transactionManagerClassNode, PROPERTY_TRANSACTION_MANAGER)
                     Parameter[] parameters = params(p)
    -                if(declaringClassNode.getMethod(SET_TRANSACTION_MANAGER, parameters) == null) {
    +                if (declaringClassNode.getMethod(SET_TRANSACTION_MANAGER, parameters) == null) {
                         Statement setterBody = assignS(transactionManagerPropertyExpr, varX(p))
     
                         // Add Setter Method: void setTransactionManager(PlatformTransactionManager transactionManager)
    @@ -310,7 +346,6 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
                     }
                 }
     
    -
             }
         }
     
    @@ -320,7 +355,7 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
             final ClassNode transactionAttributeClassNode = make(CustomizableRollbackTransactionAttribute)
             final VariableExpression transactionAttributeVar = varX('$transactionAttribute', transactionAttributeClassNode)
             newMethodBody.addStatement(
    -            declS(transactionAttributeVar, ctorX(transactionAttributeClassNode, ZERO_ARGUMENTS))
    +                declS(transactionAttributeVar, ctorX(transactionAttributeClassNode, ZERO_ARGUMENTS))
             )
     
             // apply @Transaction attributes to properties of $transactionAttribute
    @@ -329,11 +364,11 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
             boolean isMultiTenant = TenantTransform.hasTenantAnnotation(methodNode)
     
             Expression connectionName = annotationNode.getMember("connection")
    -        if( connectionName == null ) {
    +        if (connectionName == null) {
                 connectionName = annotationNode.getMember("value")
             }
    -        if(connectionName == null) {
    -            if(isMultiTenant) {
    +        if (connectionName == null) {
    +            if (isMultiTenant) {
                     connectionName = varX("tenantId")
                 }
             }
    @@ -341,19 +376,17 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
     
             // $transactionManager = connection != null ? getTargetDatastore(connection).getTransactionManager() : getTransactionManager()
             Expression transactionManagerExpression
    -        if(isMultiTenant && hasDataSourceProperty) {
    -            Expression targetDatastoreExpr = castX( make(MultiTenantCapableDatastore), callThisD(classNode, "getTargetDatastore", ZERO_ARGUMENTS) )
    -            targetDatastoreExpr = castX( make(TransactionCapableDatastore), callX( targetDatastoreExpr, "getDatastoreForTenantId", connectionName))
    -            transactionManagerExpression = castX( make(PlatformTransactionManager), propX(targetDatastoreExpr, PROPERTY_TRANSACTION_MANAGER) )
    +        if (isMultiTenant && hasDataSourceProperty) {
    +            Expression targetDatastoreExpr = castX(make(MultiTenantCapableDatastore), callThisD(classNode, "getTargetDatastore", ZERO_ARGUMENTS))
    +            targetDatastoreExpr = castX(make(TransactionCapableDatastore), callX(targetDatastoreExpr, "getDatastoreForTenantId", connectionName))
    +            transactionManagerExpression = castX(make(PlatformTransactionManager), propX(targetDatastoreExpr, PROPERTY_TRANSACTION_MANAGER))
     
    -        }
    -        else if(hasDataSourceProperty) {
    +        } else if (hasDataSourceProperty) {
                 // callX(varX("this"), "getTargetDatastore", connectionName)
    -            def targetDatastoreExpr = castX( make(TransactionCapableDatastore), callThisD(classNode, "getTargetDatastore", connectionName) )
    -            transactionManagerExpression = castX( make(PlatformTransactionManager), propX(targetDatastoreExpr, PROPERTY_TRANSACTION_MANAGER) )
    -        }
    -        else {
    -            transactionManagerExpression = propX( varX("this"), PROPERTY_TRANSACTION_MANAGER)
    +            def targetDatastoreExpr = castX(make(TransactionCapableDatastore), callThisD(classNode, "getTargetDatastore", connectionName))
    +            transactionManagerExpression = castX(make(PlatformTransactionManager), propX(targetDatastoreExpr, PROPERTY_TRANSACTION_MANAGER))
    +        } else {
    +            transactionManagerExpression = propX(varX("this"), PROPERTY_TRANSACTION_MANAGER)
             }
     
             // GrailsTransactionTemplate $transactionTemplate
    @@ -362,13 +395,13 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
             final VariableExpression transactionTemplateVar = varX('$transactionTemplate', transactionTemplateClassNode)
     
             newMethodBody.addStatement(
    -            declS(
    -                transactionTemplateVar,
    -                ctorX(transactionTemplateClassNode, args(
    -                    transactionManagerExpression,
    -                    transactionAttributeVar
    -                ))
    -            )
    +                declS(
    +                        transactionTemplateVar,
    +                        ctorX(transactionTemplateClassNode, args(
    +                                transactionManagerExpression,
    +                                transactionAttributeVar
    +                        ))
    +                )
             )
     
             // Wrap original method in closure that executes within the context of a transaction
    @@ -377,7 +410,7 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
             // }
             Parameter transactionStatusParam = param(make(TransactionStatus), "transactionStatus")
             Parameter[] parameters = params(transactionStatusParam)
    -        return makeDelegatingClosureCall(transactionTemplateVar, executeMethodName, parameters, originalMethodCall, methodNode.getVariableScope() )
    +        return makeDelegatingClosureCall(transactionTemplateVar, executeMethodName, parameters, originalMethodCall, methodNode.getVariableScope())
         }
     
         protected String getTransactionTemplateMethodName() {
    @@ -388,9 +421,9 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
             final ClassNode rollbackRuleAttributeClassNode = make(RollbackRuleAttribute)
             final ClassNode noRollbackRuleAttributeClassNode = make(NoRollbackRuleAttribute)
             final Map members = annotationNode.getMembers()
    -        if(READ_ONLY_TYPE.equals(annotationNode.classNode)) {
    +        if (READ_ONLY_TYPE.equals(annotationNode.classNode)) {
                 methodBody.addStatement(
    -                assignS(propX(transactionAttributeVar, "readOnly"), ConstantExpression.TRUE)
    +                    assignS(propX(transactionAttributeVar, "readOnly"), ConstantExpression.TRUE)
                 )
             }
     
    @@ -399,7 +432,7 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
                     final targetClassNode = (name == 'rollbackFor' || name == 'rollbackForClassName') ? rollbackRuleAttributeClassNode : noRollbackRuleAttributeClassNode
                     name = 'rollbackRules'
                     if (expr instanceof ListExpression) {
    -                    for(exprItem in ((ListExpression)expr).expressions) {
    +                    for (exprItem in ((ListExpression) expr).expressions) {
                             appendRuleElement(methodBody, transactionAttributeVar, name, ctorX(targetClassNode, exprItem))
                         }
                     } else {
    @@ -414,9 +447,9 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
                         expr = callX(expr, "value", ZERO_ARGUMENTS)
                     }
     
    -                if(name != 'value') {
    +                if (name != 'value') {
                         methodBody.addStatement(
    -                        assignS(propX(transactionAttributeVar, name), expr)
    +                            assignS(propX(transactionAttributeVar, name), expr)
                         )
                     }
                 }
    @@ -424,7 +457,7 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
     
             final transactionName = classNode.name + '.' + methodNode.name
             methodBody.addStatement(
    -            assignS(propX(transactionAttributeVar, 'name'), new ConstantExpression(transactionName))
    +                assignS(propX(transactionAttributeVar, 'name'), new ConstantExpression(transactionName))
             )
         }
     
    @@ -433,9 +466,9 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
             ClassNode rollbackRulesListClassNode = nonGeneric(make(List), rollbackRuleAttributeClassNode)
             def getRollbackRules = castX(rollbackRulesListClassNode, buildGetPropertyExpression(transactionAttributeVar, name, transactionAttributeVar.getType()))
             methodBody.addStatement(
    -            stmt(
    -                callX(getRollbackRules, 'add', expr)
    -            )
    +                stmt(
    +                        callX(getRollbackRules, 'add', expr)
    +                )
             )
         }
     
    @@ -452,7 +485,7 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma
          */
         static boolean hasTransactionalAnnotation(AnnotatedNode md) {
             for (AnnotationNode annotation : md.getAnnotations()) {
    -            if(ANNOTATION_NAME_EXCLUDES.any() { String n -> n == annotation.classNode.name}) {
    +            if (ANNOTATION_NAME_EXCLUDES.any() { String n -> n == annotation.classNode.name }) {
                     return true
                 }
             }
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractDatastoreMethodDecoratingTransformation.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractDatastoreMethodDecoratingTransformation.groovy
    index 50e828a9256..ad6e2d933e0 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractDatastoreMethodDecoratingTransformation.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractDatastoreMethodDecoratingTransformation.groovy
    @@ -19,7 +19,11 @@
     package org.grails.datastore.gorm.transform
     
     import groovy.transform.CompileStatic
    -import org.codehaus.groovy.ast.*
    +import org.codehaus.groovy.ast.AnnotationNode
    +import org.codehaus.groovy.ast.ClassNode
    +import org.codehaus.groovy.ast.FieldNode
    +import org.codehaus.groovy.ast.MethodNode
    +import org.codehaus.groovy.ast.Parameter
     import org.codehaus.groovy.ast.expr.ClassExpression
     import org.codehaus.groovy.ast.expr.Expression
     import org.codehaus.groovy.ast.expr.MethodCallExpression
    @@ -31,15 +35,30 @@ import org.grails.datastore.gorm.GormEnhancer
     import org.grails.datastore.gorm.internal.RuntimeSupport
     import org.grails.datastore.mapping.core.Datastore
     import org.grails.datastore.mapping.core.connections.MultipleConnectionSourceCapableDatastore
    -import org.grails.datastore.mapping.reflect.AstUtils
     import org.springframework.beans.factory.annotation.Autowired
     
     import java.lang.reflect.Modifier
     
    -import static org.codehaus.groovy.ast.ClassHelper.*
    -import static org.codehaus.groovy.ast.tools.GeneralUtils.*
    +import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE
    +import static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE
    +import static org.codehaus.groovy.ast.ClassHelper.make
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.block
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.castX
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifElseS
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.notNullX
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.param
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.params
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX
     import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.callD
    -import static org.grails.datastore.mapping.reflect.AstUtils.*
    +import static org.grails.datastore.mapping.reflect.AstUtils.ZERO_PARAMETERS
    +import static org.grails.datastore.mapping.reflect.AstUtils.addAnnotationOrGetExisting
    +import static org.grails.datastore.mapping.reflect.AstUtils.implementsInterface
    +import static org.grails.datastore.mapping.reflect.AstUtils.isSpockTest
     
     /**
      * An abstract implementation for transformations that decorate a method invocation such that
    @@ -56,14 +75,13 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM
         public static final String METHOD_GET_TARGET_DATASTORE = "getTargetDatastore"
         protected static final String METHOD_GET_DATASTORE_FOR_CONNECTION = "getDatastoreForConnection"
     
    -
         @Override
         protected void enhanceClassNode(SourceUnit source, AnnotationNode annotationNode, ClassNode declaringClassNode) {
             def appliedMarker = getAppliedMarker()
    -        if(declaringClassNode.getNodeMetaData(appliedMarker) == appliedMarker) {
    +        if (declaringClassNode.getNodeMetaData(appliedMarker) == appliedMarker) {
                 return
             }
    -        if(declaringClassNode.isInterface()) {
    +        if (declaringClassNode.isInterface()) {
                 return
             }
             declaringClassNode.putNodeMetaData(appliedMarker, appliedMarker)
    @@ -76,19 +94,18 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM
             Expression datastoreAttribute = annotationNode.getMember("datastore")
             ClassNode defaultType = hasDataSourceProperty ? make(MultipleConnectionSourceCapableDatastore) : make(Datastore)
             boolean hasSpecificDatastore = datastoreAttribute instanceof ClassExpression
    -        ClassNode datastoreType = hasSpecificDatastore ? ((ClassExpression)datastoreAttribute).getType().getPlainNodeReference() : defaultType
    +        ClassNode datastoreType = hasSpecificDatastore ? ((ClassExpression) datastoreAttribute).getType().getPlainNodeReference() : defaultType
             Parameter connectionNameParam = param(STRING_TYPE, "connectionName")
             MethodCallExpression datastoreLookupCall
             MethodCallExpression datastoreLookupDefaultCall
    -        if(hasSpecificDatastore) {
    +        if (hasSpecificDatastore) {
                 datastoreLookupDefaultCall = callD(gormEnhancerExpr, "findDatastoreByType", classX(datastoreType.getPlainNodeReference()))
    -        }
    -        else {
    +        } else {
                 datastoreLookupDefaultCall = callD(gormEnhancerExpr, "findSingleDatastore")
             }
             datastoreLookupCall = callD(datastoreLookupDefaultCall, METHOD_GET_DATASTORE_FOR_CONNECTION, varX(connectionNameParam))
     
    -        if(implementsInterface(declaringClassNode, "org.grails.datastore.mapping.services.Service")) {
    +        if (implementsInterface(declaringClassNode, "org.grails.datastore.mapping.services.Service")) {
                 // simplify logic for services
                 Parameter[] getTargetDatastoreParams = params(connectionNameParam)
                 VariableExpression datastoreVar = varX("datastore", make(Datastore))
    @@ -100,27 +117,26 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM
                 //    else
                 //      return GormEnhancer.findSingleDatastore().getDatastoreForConnection(connectionName)
     
    -            if(declaringClassNode.getMethod(METHOD_GET_TARGET_DATASTORE, getTargetDatastoreParams) == null) {
    +            if (declaringClassNode.getMethod(METHOD_GET_TARGET_DATASTORE, getTargetDatastoreParams) == null) {
                     MethodNode mn = declaringClassNode.addMethod(METHOD_GET_TARGET_DATASTORE, Modifier.PROTECTED, datastoreType, getTargetDatastoreParams, null,
                             ifElseS(notNullX(datastoreVar),
    -                                returnS( callD( castX(make(MultipleConnectionSourceCapableDatastore), datastoreVar ), METHOD_GET_DATASTORE_FOR_CONNECTION, varX(connectionNameParam) ) ),
    +                                returnS(callD(castX(make(MultipleConnectionSourceCapableDatastore), datastoreVar), METHOD_GET_DATASTORE_FOR_CONNECTION, varX(connectionNameParam))),
                                     returnS(datastoreLookupCall)
                             ))
                     compileMethodStatically(source, mn)
                 }
    -            if(declaringClassNode.getMethod(METHOD_GET_TARGET_DATASTORE, ZERO_PARAMETERS) == null) {
    -                MethodNode mn = declaringClassNode.addMethod(METHOD_GET_TARGET_DATASTORE, Modifier.PROTECTED,  datastoreType, ZERO_PARAMETERS, null,
    -                        ifElseS( notNullX(datastoreVar ),
    +            if (declaringClassNode.getMethod(METHOD_GET_TARGET_DATASTORE, ZERO_PARAMETERS) == null) {
    +                MethodNode mn = declaringClassNode.addMethod(METHOD_GET_TARGET_DATASTORE, Modifier.PROTECTED, datastoreType, ZERO_PARAMETERS, null,
    +                        ifElseS(notNullX(datastoreVar),
                                     returnS(datastoreVar),
                                     returnS(datastoreLookupDefaultCall))
                     )
     
                     compileMethodStatically(source, mn)
                 }
    -        }
    -        else {
    +        } else {
                 FieldNode datastoreField = declaringClassNode.getField(FIELD_TARGET_DATASTORE)
    -            if(datastoreField == null) {
    +            if (datastoreField == null) {
                     datastoreField = declaringClassNode.addField(FIELD_TARGET_DATASTORE, Modifier.PROTECTED, datastoreType, null)
     
                     Parameter datastoresParam = param(datastoreType.makeArray(), "datastores")
    @@ -130,16 +146,15 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM
                     BlockStatement setTargetDatastoreBody
                     VariableExpression datastoreFieldVar = varX(datastoreField)
     
    -                Statement assignTargetDatastore = assignS(datastoreFieldVar,datastoreVar )
    -                if(hasDataSourceProperty) {
    +                Statement assignTargetDatastore = assignS(datastoreFieldVar, datastoreVar)
    +                if (hasDataSourceProperty) {
                         // $targetDatastore = RuntimeSupport.findDefaultDatastore(datastores)
                         // datastore = datastore.getDatastoreForConnection(connectionName)
                         setTargetDatastoreBody = block(
                                 assignTargetDatastore,
    -                            assignS(datastoreFieldVar, callX(datastoreFieldVar, METHOD_GET_DATASTORE_FOR_CONNECTION, connectionName ))
    +                            assignS(datastoreFieldVar, callX(datastoreFieldVar, METHOD_GET_DATASTORE_FOR_CONNECTION, connectionName))
                         )
    -                }
    -                else {
    +                } else {
                         setTargetDatastoreBody = block(
                                 assignTargetDatastore
                         )
    @@ -149,7 +164,7 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM
     
                     // Add method: @Autowired void setTargetDatastore(Datastore[] datastores)
                     Parameter[] setTargetDatastoreParams = params(datastoresParam)
    -                if( declaringClassNode.getMethod("setTargetDatastore", setTargetDatastoreParams) == null) {
    +                if (declaringClassNode.getMethod("setTargetDatastore", setTargetDatastoreParams) == null) {
                         MethodNode setTargetDatastoreMethod = declaringClassNode.addMethod("setTargetDatastore", Modifier.PUBLIC, VOID_TYPE, setTargetDatastoreParams, null, setTargetDatastoreBody)
     
                         // Autowire setTargetDatastore via Spring
    @@ -166,28 +181,26 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM
                     //    else
                     //      return GormEnhancer.findSingleDatastore().getDatastoreForConnection(connectionName)
     
    -
    -
                     Parameter[] getTargetDatastoreParams = params(connectionNameParam)
     
    -                if(declaringClassNode.getMethod(METHOD_GET_TARGET_DATASTORE, getTargetDatastoreParams) == null) {
    +                if (declaringClassNode.getMethod(METHOD_GET_TARGET_DATASTORE, getTargetDatastoreParams) == null) {
                         MethodNode mn = declaringClassNode.addMethod(METHOD_GET_TARGET_DATASTORE, Modifier.PROTECTED, datastoreType, getTargetDatastoreParams, null,
                                 ifElseS(notNullX(datastoreFieldVar),
    -                                    returnS( callX( datastoreFieldVar, METHOD_GET_DATASTORE_FOR_CONNECTION, varX(connectionNameParam) ) ),
    +                                    returnS(callX(datastoreFieldVar, METHOD_GET_DATASTORE_FOR_CONNECTION, varX(connectionNameParam))),
                                         returnS(datastoreLookupCall)
                                 ))
    -                    if(!isSpockTest) {
    +                    if (!isSpockTest) {
                             compileMethodStatically(source, mn)
                         }
                     }
    -                if(declaringClassNode.getMethod(METHOD_GET_TARGET_DATASTORE, ZERO_PARAMETERS) == null) {
    -                    MethodNode mn = declaringClassNode.addMethod(METHOD_GET_TARGET_DATASTORE, Modifier.PROTECTED,  datastoreType, ZERO_PARAMETERS, null,
    -                            ifElseS( notNullX(datastoreFieldVar ),
    +                if (declaringClassNode.getMethod(METHOD_GET_TARGET_DATASTORE, ZERO_PARAMETERS) == null) {
    +                    MethodNode mn = declaringClassNode.addMethod(METHOD_GET_TARGET_DATASTORE, Modifier.PROTECTED, datastoreType, ZERO_PARAMETERS, null,
    +                            ifElseS(notNullX(datastoreFieldVar),
                                         returnS(datastoreFieldVar),
                                         returnS(datastoreLookupDefaultCall))
                         )
     
    -                    if(!isSpockTest) {
    +                    if (!isSpockTest) {
                             compileMethodStatically(source, mn)
                         }
     
    @@ -196,8 +209,6 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM
     
             }
     
    -
    -
         }
     
         protected void weaveSetTargetDatastoreBody(SourceUnit source, AnnotationNode annotationNode, ClassNode declaringClassNode, Expression datastoreVar, BlockStatement setTargetDatastoreBody) {
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractMethodDecoratingTransformation.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractMethodDecoratingTransformation.groovy
    index 33e57cc0c5c..16210cf4655 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractMethodDecoratingTransformation.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractMethodDecoratingTransformation.groovy
    @@ -19,8 +19,19 @@
     package org.grails.datastore.gorm.transform
     
     import groovy.transform.CompileStatic
    -import org.codehaus.groovy.ast.*
    -import org.codehaus.groovy.ast.expr.*
    +import jakarta.annotation.PostConstruct
    +import jakarta.annotation.PreDestroy
    +import org.codehaus.groovy.ast.ASTNode
    +import org.codehaus.groovy.ast.AnnotatedNode
    +import org.codehaus.groovy.ast.AnnotationNode
    +import org.codehaus.groovy.ast.ClassNode
    +import org.codehaus.groovy.ast.MethodNode
    +import org.codehaus.groovy.ast.Parameter
    +import org.codehaus.groovy.ast.VariableScope
    +import org.codehaus.groovy.ast.expr.ArgumentListExpression
    +import org.codehaus.groovy.ast.expr.ClosureExpression
    +import org.codehaus.groovy.ast.expr.Expression
    +import org.codehaus.groovy.ast.expr.MethodCallExpression
     import org.codehaus.groovy.ast.stmt.BlockStatement
     import org.codehaus.groovy.ast.stmt.Statement
     import org.codehaus.groovy.ast.tools.GenericsUtils
    @@ -31,14 +42,31 @@ import org.codehaus.groovy.transform.sc.StaticCompileTransformation
     import org.codehaus.groovy.transform.trait.Traits
     import org.grails.datastore.mapping.reflect.NameUtils
     
    -import jakarta.annotation.PostConstruct
    -import jakarta.annotation.PreDestroy
     import java.beans.Introspector
     import java.lang.reflect.Modifier
     
    -import static org.codehaus.groovy.ast.ClassHelper.*
    -import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.*
    -import static org.grails.datastore.mapping.reflect.AstUtils.*
    +import static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.args
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.block
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.castX
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.closureX
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX
    +import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.paramsForArgs
    +import static org.grails.datastore.mapping.reflect.AstUtils.COMPILE_STATIC_TYPE
    +import static org.grails.datastore.mapping.reflect.AstUtils.EMPTY_CLASS_ARRAY
    +import static org.grails.datastore.mapping.reflect.AstUtils.TYPE_CHECKED_TYPE
    +import static org.grails.datastore.mapping.reflect.AstUtils.addAnnotationIfNecessary
    +import static org.grails.datastore.mapping.reflect.AstUtils.copyParameters
    +import static org.grails.datastore.mapping.reflect.AstUtils.findAnnotation
    +import static org.grails.datastore.mapping.reflect.AstUtils.hasAnnotation
    +import static org.grails.datastore.mapping.reflect.AstUtils.hasJunitAnnotation
    +import static org.grails.datastore.mapping.reflect.AstUtils.isGetter
    +import static org.grails.datastore.mapping.reflect.AstUtils.isSetter
    +import static org.grails.datastore.mapping.reflect.AstUtils.isSpockTest
    +import static org.grails.datastore.mapping.reflect.AstUtils.processVariableScopes
     
     /**
      * An abstract implementation for transformations that decorate a method invocation such that
    @@ -60,20 +88,18 @@ abstract class AbstractMethodDecoratingTransformation extends AbstractGormASTTra
     
         @Override
         void visit(SourceUnit source, AnnotationNode annotationNode, AnnotatedNode annotatedNode) {
    -        if(annotatedNode instanceof MethodNode) {
    -            MethodNode methodNode = (MethodNode)annotatedNode
    +        if (annotatedNode instanceof MethodNode) {
    +            MethodNode methodNode = (MethodNode) annotatedNode
                 Map genericsSpec = GenericsUtils.createGenericsSpec(methodNode.declaringClass)
                 weaveNewMethod(source, annotationNode, methodNode.getDeclaringClass(), methodNode, genericsSpec)
    -        }
    -        else if(annotatedNode instanceof ClassNode) {
    +        } else if (annotatedNode instanceof ClassNode) {
                 ClassNode classNode = (ClassNode) annotatedNode
    -            if(!classNode.isInterface()) {
    -                weaveClassNode( source, annotationNode, classNode)
    +            if (!classNode.isInterface()) {
    +                weaveClassNode(source, annotationNode, classNode)
                 }
             }
         }
     
    -
         protected void weaveClassNode(SourceUnit source, AnnotationNode annotationNode, ClassNode classNode) {
             enhanceClassNode(source, annotationNode, classNode)
             Map genericsSpec = GenericsUtils.createGenericsSpec(classNode)
    @@ -161,10 +187,10 @@ abstract class AbstractMethodDecoratingTransformation extends AbstractGormASTTra
          */
         protected MethodNode weaveNewMethod(SourceUnit sourceUnit, AnnotationNode annotationNode, ClassNode classNode, MethodNode methodNode, Map genericsSpec) {
             Object appliedMarker = getAppliedMarker()
    -        if ( methodNode.getNodeMetaData(appliedMarker) == appliedMarker ) {
    +        if (methodNode.getNodeMetaData(appliedMarker) == appliedMarker) {
                 return methodNode
             }
    -        if( methodNode.isAbstract() ) {
    +        if (methodNode.isAbstract()) {
                 return methodNode
             }
     
    @@ -172,14 +198,12 @@ abstract class AbstractMethodDecoratingTransformation extends AbstractGormASTTra
     
             enhanceClassNode(sourceUnit, annotationNode, classNode)
     
    -
             // Move the existing logic into a new method called "$tt_methodName()"
             String renamedMethodName
             boolean superMethod = findAnnotation(methodNode, Override) || classNode.getSuperClass()?.getMethod(methodNode.name, methodNode.parameters) != null
    -        if(superMethod) {
    +        if (superMethod) {
                 renamedMethodName = getRenamedMethodPrefix() + Introspector.decapitalize(classNode.nameWithoutPackage) + '_' + methodNode.getName()
    -        }
    -        else {
    +        } else {
                 renamedMethodName = getRenamedMethodPrefix() + methodNode.getName()
             }
     
    @@ -190,7 +214,6 @@ abstract class AbstractMethodDecoratingTransformation extends AbstractGormASTTra
             // Start constructing new method body
             BlockStatement methodBody = block()
     
    -
             Expression executeMethodCallExpression = buildDelegatingMethodCall(
                     sourceUnit,
                     annotationNode,
    @@ -200,7 +223,7 @@ abstract class AbstractMethodDecoratingTransformation extends AbstractGormASTTra
                     methodBody
             )
     
    -        if(methodNode.getReturnType() != VOID_TYPE) {
    +        if (methodNode.getReturnType() != VOID_TYPE) {
                 methodBody.addStatement(
                         returnS(
                                 castX(methodNode.getReturnType(), executeMethodCallExpression)
    @@ -214,7 +237,7 @@ abstract class AbstractMethodDecoratingTransformation extends AbstractGormASTTra
     
             methodNode.setCode(methodBody)
             processVariableScopes(sourceUnit, classNode, methodNode)
    -        if(!isSpockTest(classNode)) {
    +        if (!isSpockTest(classNode)) {
                 compileMethodStatically(sourceUnit, methodNode)
             }
             return renamedMethod
    @@ -255,7 +278,7 @@ abstract class AbstractMethodDecoratingTransformation extends AbstractGormASTTra
          * @param originalMethodCall The original method call to delegate to
          * @return The MethodCallExpression
          */
    -    protected MethodCallExpression makeDelegatingClosureCall(Expression targetObject, String executeMethodName,  Parameter[] closureParameters, MethodCallExpression originalMethodCall, VariableScope variableScope ) {
    +    protected MethodCallExpression makeDelegatingClosureCall(Expression targetObject, String executeMethodName, Parameter[] closureParameters, MethodCallExpression originalMethodCall, VariableScope variableScope) {
             return makeDelegatingClosureCall(targetObject, executeMethodName, new ArgumentListExpression(), closureParameters, originalMethodCall, variableScope)
         }
     
    @@ -268,7 +291,7 @@ abstract class AbstractMethodDecoratingTransformation extends AbstractGormASTTra
          * @param originalMethodCall The original method call to delegate to
          * @return The MethodCallExpression
          */
    -    protected MethodCallExpression makeDelegatingClosureCall(Expression targetObject, String executeMethodName, ArgumentListExpression arguments, Parameter[] closureParameters, MethodCallExpression originalMethodCall, VariableScope variableScope ) {
    +    protected MethodCallExpression makeDelegatingClosureCall(Expression targetObject, String executeMethodName, ArgumentListExpression arguments, Parameter[] closureParameters, MethodCallExpression originalMethodCall, VariableScope variableScope) {
             final ClosureExpression closureExpression = closureX(closureParameters, createDelegingMethodBody(closureParameters, originalMethodCall))
             closureExpression.setVariableScope(
                     variableScope
    @@ -290,7 +313,6 @@ abstract class AbstractMethodDecoratingTransformation extends AbstractGormASTTra
             return stmt(originalMethodCall)
         }
     
    -
         protected MethodNode moveOriginalCodeToNewMethod(MethodNode methodNode, String renamedMethodName, Parameter[] newParameters, ClassNode classNode, SourceUnit source, Map genericsSpec) {
             Statement body = methodNode.code
     
    @@ -302,14 +324,13 @@ abstract class AbstractMethodDecoratingTransformation extends AbstractGormASTTra
                     body
             )
     
    -        List decoratedMethods = (List)methodNode.getNodeMetaData(DECORATED_METHODS)
    -        if(decoratedMethods == null) {
    +        List decoratedMethods = (List) methodNode.getNodeMetaData(DECORATED_METHODS)
    +        if (decoratedMethods == null) {
                 decoratedMethods = []
                 methodNode.putNodeMetaData(DECORATED_METHODS, decoratedMethods)
             }
             decoratedMethods.add(renamedMethodNode)
     
    -
             def newVariableScope = new VariableScope()
             for (p in newParameters) {
                 newVariableScope.putDeclaredVariable(p)
    @@ -360,7 +381,7 @@ abstract class AbstractMethodDecoratingTransformation extends AbstractGormASTTra
         protected boolean hasExcludedAnnotation(MethodNode md, Set excludes) {
             boolean excludedAnnotation = false
             for (AnnotationNode annotation : md.getAnnotations()) {
    -            AnnotationNode gormTransform = findAnnotation( annotation.classNode, GormASTTransformationClass)
    +            AnnotationNode gormTransform = findAnnotation(annotation.classNode, GormASTTransformationClass)
                 if (gormTransform != null || excludes.contains(annotation.getClassNode().getName())) {
                     excludedAnnotation = true
                     break
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractTraitApplyingGormASTTransformation.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractTraitApplyingGormASTTransformation.groovy
    index b94b1c20b43..a962ee2ff19 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractTraitApplyingGormASTTransformation.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractTraitApplyingGormASTTransformation.groovy
    @@ -41,15 +41,15 @@ abstract class AbstractTraitApplyingGormASTTransformation extends AbstractGormAS
         @Override
         void visit(SourceUnit source, AnnotationNode annotationNode, AnnotatedNode annotatedNode) {
             this.sourceUnit = source
    -        if(annotatedNode instanceof ClassNode) {
    -            visit(source, annotationNode, (ClassNode)annotatedNode)
    +        if (annotatedNode instanceof ClassNode) {
    +            visit(source, annotationNode, (ClassNode) annotatedNode)
             }
         }
     
         void visit(SourceUnit source, AnnotationNode annotationNode, ClassNode classNode) {
             this.sourceUnit = source
             Class traitJavaClass = getTraitClass()
    -        if(shouldWeave(annotationNode, classNode)) {
    +        if (shouldWeave(annotationNode, classNode)) {
                 weaveTrait(classNode, source, traitJavaClass)
             }
             visitAfterTraitApplied(source, annotationNode, classNode)
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AstMethodDispatchUtils.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AstMethodDispatchUtils.groovy
    index 7d2470284f1..732c2f5ca38 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AstMethodDispatchUtils.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AstMethodDispatchUtils.groovy
    @@ -51,12 +51,12 @@ class AstMethodDispatchUtils extends GeneralUtils {
          */
         static MapExpression namedArgs(Map args) {
             def expression = new MapExpression()
    -        for(entry in args) {
    +        for (entry in args) {
                 expression.addMapEntryExpression(
    -                new MapEntryExpression(
    -                    constX(entry.key),
    -                    entry.value
    -                )
    +                    new MapEntryExpression(
    +                            constX(entry.key),
    +                            entry.value
    +                    )
                 )
             }
             return expression
    @@ -68,7 +68,7 @@ class AstMethodDispatchUtils extends GeneralUtils {
          */
         static MethodCallExpression callD(Class targetType, String var, String methodName, Expression arguments = ZERO_ARGUMENTS) {
             ClassNode targetNode = make(targetType)
    -        callD( targetNode, var, methodName, arguments)
    +        callD(targetNode, var, methodName, arguments)
         }
     
         /**
    @@ -114,26 +114,25 @@ class AstMethodDispatchUtils extends GeneralUtils {
             MethodCallExpression methodCall = callX(varX("this", thisType), methodName, arguments)
             Parameter[] params = paramsForArgs(arguments)
             MethodNode mn = thisType.getDeclaredMethod(methodName, params)
    -        if(mn != null) {
    +        if (mn != null) {
                 methodCall.setMethodTarget(mn)
             }
             return methodCall
         }
     
         static Parameter[] paramsForArgs(Expression expression) {
    -        if(expression instanceof TupleExpression) {
    -            TupleExpression te = (TupleExpression)expression
    +        if (expression instanceof TupleExpression) {
    +            TupleExpression te = (TupleExpression) expression
                 List params = []
                 int i = 0
    -            for(exp in te.expressions) {
    +            for (exp in te.expressions) {
                     def type = exp instanceof ClassExpression ? ClassHelper.CLASS_Type : exp.type
    -                params.add( param(type, "p${i++}"))
    +                params.add(param(type, "p${i++}"))
                 }
                 return params as Parameter[]
    -        }
    -        else {
    +        } else {
                 def type = expression instanceof ClassExpression ? ClassHelper.CLASS_Type : expression.type
    -            return params( param(type, "p"))
    +            return params(param(type, "p"))
             }
         }
     }
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AstPropertyResolveUtils.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AstPropertyResolveUtils.java
    index 9f9cb6ca7a1..a2f985c049d 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AstPropertyResolveUtils.java
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AstPropertyResolveUtils.java
    @@ -16,10 +16,14 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.transform;
     
    -import org.codehaus.groovy.ast.*;
    +import org.codehaus.groovy.ast.ClassHelper;
    +import org.codehaus.groovy.ast.ClassNode;
    +import org.codehaus.groovy.ast.FieldNode;
    +import org.codehaus.groovy.ast.MethodNode;
    +import org.codehaus.groovy.ast.Parameter;
    +import org.codehaus.groovy.ast.PropertyNode;
     import org.codehaus.groovy.ast.expr.ClassExpression;
     import org.codehaus.groovy.ast.expr.Expression;
     import org.codehaus.groovy.ast.expr.MapEntryExpression;
    @@ -41,17 +45,18 @@
      * @since 6.1
      */
     public class AstPropertyResolveUtils {
    +
         protected static Map> cachedClassProperties = new HashMap<>();
     
         /**
          * Resolves the type of of the given property
          *
    -     * @param classNode The class node
    +     * @param classNode    The class node
          * @param propertyName The property
          * @return The type
          */
         public static ClassNode getPropertyType(ClassNode classNode, String propertyName) {
    -        if(propertyName == null || propertyName.length() == 0) {
    +        if (propertyName == null || propertyName.length() == 0) {
                 return null;
             }
             Map cachedProperties = getPropertiesFromCache(classNode);
    @@ -93,7 +98,7 @@ private static Map getPropertiesFromCache(ClassNode classNode
             if (cachedProperties == null) {
                 cachedProperties = new HashMap<>();
                 boolean isDomainClass = AstUtils.isDomainClass(classNode);
    -            if(isDomainClass) {
    +            if (isDomainClass) {
                     cachedProperties.put(GormProperties.IDENTITY, new ClassNode(Long.class));
                     cachedProperties.put(GormProperties.VERSION, new ClassNode(Long.class));
                 }
    @@ -103,7 +108,8 @@ private static Map getPropertiesFromCache(ClassNode classNode
                     populatePropertiesForClassNode(currentNode, cachedProperties, isDomainClass, !isDomainClass);
                     currentNode = currentNode.getSuperClass();
                 }
    -        } return cachedProperties;
    +        }
    +        return cachedProperties;
         }
     
         private static void populatePropertiesForClassNode(ClassNode classNode, Map cachedProperties, boolean isDomainClass, boolean allowAbstract) {
    @@ -111,9 +117,13 @@ private static void populatePropertiesForClassNode(ClassNode classNode, Map astTransformations = collectAndOrderGormTransformations(annotatedNode)
    -        for(transform in astTransformations) {
    +        for (transform in astTransformations) {
                 transform.invoke(source, annotatedNode)
             }
         }
     
         Iterable collectAndOrderGormTransformations(AnnotatedNode annotatedNode) {
             List annotations = new ArrayList<>(annotatedNode.getAnnotations())
    -        if(annotatedNode instanceof MethodNode) {
    -            MethodNode mn = (MethodNode)annotatedNode
    -            for(classAnn in mn.getDeclaringClass().getAnnotations()) {
    -                if(!annotations.any() { AnnotationNode ann ->
    +        if (annotatedNode instanceof MethodNode) {
    +            MethodNode mn = (MethodNode) annotatedNode
    +            for (classAnn in mn.getDeclaringClass().getAnnotations()) {
    +                if (!annotations.any() { AnnotationNode ann ->
                         ann.classNode.name == classAnn.classNode.name ||
    -                        findTransformName(ann) == findTransformName(classAnn)
    +                            findTransformName(ann) == findTransformName(classAnn)
                     }) {
                         annotations.add(classAnn)
                     }
                 }
             }
             List transforms = []
    -        for(ann in annotations) {
    +        for (ann in annotations) {
                 String transformName = findTransformName(ann)
    -            if(transformName) {
    +            if (transformName) {
                     try {
                         def newTransform = ClassUtils.forName(transformName).newInstance()
    -                    if(newTransform instanceof ASTTransformation) {
    -                        if(newTransform instanceof CompilationUnitAware) {
    -                            ((CompilationUnitAware) newTransform).setCompilationUnit( compilationUnit )
    +                    if (newTransform instanceof ASTTransformation) {
    +                        if (newTransform instanceof CompilationUnitAware) {
    +                            ((CompilationUnitAware) newTransform).setCompilationUnit(compilationUnit)
                             }
    -                        transforms.add( new TransformationInvocation(ann, newTransform) )
    +                        transforms.add(new TransformationInvocation(ann, newTransform))
                         }
                     } catch (Throwable e) {
                         addError("Could not load GORM transform for name [$transformName]: $e.message", annotatedNode)
    @@ -113,6 +113,7 @@ class OrderedGormTransformation extends AbstractASTTransformation implements Com
         }
     
         private static class TransformationInvocation {
    +
             private final AnnotationNode annotation
             private final ASTTransformation transform
     
    @@ -122,7 +123,7 @@ class OrderedGormTransformation extends AbstractASTTransformation implements Com
             }
     
             void invoke(SourceUnit sourceUnit, AnnotatedNode annotatedNode) {
    -            transform.visit( [annotation, annotatedNode] as ASTNode[], sourceUnit)
    +            transform.visit([annotation, annotatedNode] as ASTNode[], sourceUnit)
             }
         }
     }
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/AnnotationMetadataReaderFactory.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/AnnotationMetadataReaderFactory.java
    index 78b29ec5298..9fe390691a0 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/AnnotationMetadataReaderFactory.java
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/AnnotationMetadataReaderFactory.java
    @@ -14,7 +14,6 @@
      *  See the License for the specific language governing permissions and
      *  limitations under the License.
      */
    -
     package org.grails.datastore.gorm.utils;
     
     import org.apache.grails.common.compiler.asm.AnnotationMetadataReader;
    @@ -28,6 +27,7 @@
      * A {@link CachingMetadataReaderFactory} that only reads annotations and not the whole class body
      */
     class AnnotationMetadataReaderFactory extends CachingMetadataReaderFactory {
    +
         public AnnotationMetadataReaderFactory(ClassLoader classLoader) {
             super(classLoader);
         }
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/ClasspathEntityScanner.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/ClasspathEntityScanner.groovy
    index c39a25c10d1..706506842c9 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/ClasspathEntityScanner.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/utils/ClasspathEntityScanner.groovy
    @@ -54,9 +54,9 @@ class ClasspathEntityScanner {
         List ignoredPackages = ['com', 'net', '', 'org', 'java', 'javax', 'jakarta', 'groovy']
     
         ClasspathEntityScanner() {
    -        if(ClassUtils.isPresent("grails.persistence.Entity")) {
    +        if (ClassUtils.isPresent("grails.persistence.Entity")) {
                 try {
    -                annotations.add((Class)Class.forName("grails.persistence.Entity") )
    +                annotations.add((Class) Class.forName("grails.persistence.Entity"))
                 } catch (Throwable e) {
                     log.error("Annotation [grails.persistence.Entity] found on classpath, but could not be loaded: ${e.message}", e)
                 }
    @@ -71,18 +71,17 @@ class ClasspathEntityScanner {
         Class[] scan(Package... packages) {
             ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(false)
             componentProvider.setMetadataReaderFactory(new AnnotationMetadataReaderFactory(classLoader))
    -        for(ann in annotations) {
    +        for (ann in annotations) {
                 componentProvider.addIncludeFilter(new AnnotationTypeFilter(ann))
             }
             Collection classes = new HashSet<>()
    -        for(Package p in packages) {
    +        for (Package p in packages) {
                 def packageName = p.name
    -            if(ignoredPackages.contains(packageName)) {
    +            if (ignoredPackages.contains(packageName)) {
                     log.error("Package [$packageName] will not be scanned as it is too generic and will slow down startup time. Use a more specific package")
    -            }
    -            else {
    +            } else {
                     for (BeanDefinition candidate in componentProvider.findCandidateComponents(packageName)) {
    -                    Class persistentEntity = Class.forName(candidate.beanClassName, false, classLoader )
    +                    Class persistentEntity = Class.forName(candidate.beanClassName, false, classLoader)
                         classes.add persistentEntity
                     }
                 }
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/CascadingValidator.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/CascadingValidator.java
    index 1b201e84c91..c9b05ec8f91 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/CascadingValidator.java
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/CascadingValidator.java
    @@ -31,10 +31,9 @@ public interface CascadingValidator extends Validator, grails.gorm.validation.Ca
          * An extended version of the validate(errors,obj) method that takes an additional argument specifying whether
          * the Validator should cascade into associations or not.
          *
    -     * @param obj The Object to validate
    -     * @param errors The Spring Errors instance
    +     * @param obj     The Object to validate
    +     * @param errors  The Spring Errors instance
          * @param cascade True if validation should cascade into associations
    -     *
          * @see org.springframework.validation.Errors
          * @see org.springframework.validation.Validator
          * @see org.springframework.validation.Validator#validate(Object, org.springframework.validation.Errors)
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/ValidatorProvider.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/ValidatorProvider.groovy
    index 5b962807d10..186431e9686 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/ValidatorProvider.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/ValidatorProvider.groovy
    @@ -20,7 +20,6 @@ package org.grails.datastore.gorm.validation
     
     import org.springframework.validation.Validator
     
    -
     /**
      * A class that provides a validator
      *
    @@ -28,6 +27,7 @@ import org.springframework.validation.Validator
      * @since 5.0
      */
     interface ValidatorProvider {
    +
         /**
          * @return The validator
          */
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MappingContextAwareConstraintFactory.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MappingContextAwareConstraintFactory.groovy
    index 78f88ca4110..8204e666857 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MappingContextAwareConstraintFactory.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MappingContextAwareConstraintFactory.groovy
    @@ -31,6 +31,7 @@ import org.springframework.context.MessageSource
      * @since 6.0
      */
     class MappingContextAwareConstraintFactory extends DefaultConstraintFactory {
    +
         final MappingContext mappingContext
     
         MappingContextAwareConstraintFactory(Class constraintClass, MessageSource messageSource, MappingContext mappingContext, List targetTypes = [Object]) {
    @@ -40,7 +41,7 @@ class MappingContextAwareConstraintFactory extends DefaultConstraintFactory {
     
         @Override
         Constraint build(Class owner, String property, Object constrainingValue) {
    -        if(mappingContext.getPersistentEntity(owner.name) != null) {
    +        if (mappingContext.getPersistentEntity(owner.name) != null) {
                 return super.build(owner, property, constrainingValue)
             }
             return null
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/constraints/builtin/UniqueConstraint.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/constraints/builtin/UniqueConstraint.groovy
    index d2f8b863877..94fabebfea7 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/constraints/builtin/UniqueConstraint.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/constraints/builtin/UniqueConstraint.groovy
    @@ -50,12 +50,11 @@ class UniqueConstraint extends AbstractConstraint {
     
         UniqueConstraint(Class constraintOwningClass, String constraintPropertyName, Object constraintParameter, MessageSource messageSource) {
             super(constraintOwningClass, constraintPropertyName, constraintParameter, messageSource)
    -        if(constraintParameter instanceof Iterable) {
    -            for(property in ((Iterable)constraintParameter)) {
    +        if (constraintParameter instanceof Iterable) {
    +            for (property in ((Iterable) constraintParameter)) {
                     group.add(property.toString())
                 }
    -        }
    -        else if(constraintParameter instanceof CharSequence) {
    +        } else if (constraintParameter instanceof CharSequence) {
                 group.add(constraintParameter.toString())
             }
         }
    @@ -75,7 +74,7 @@ class UniqueConstraint extends AbstractConstraint {
             DetachedCriteria detachedCriteria = new DetachedCriteria(constraintOwningClass)
     
             MappingContext mappingContext = detachedCriteria.getPersistentEntity()
    -                                                        .getMappingContext()
    +                .getMappingContext()
             PersistentEntity targetEntity = mappingContext.getPersistentEntity(mappingContext.getProxyHandler().getProxiedClass(target).getName())
     
             // Determine the GORM class that actually defines this field
    @@ -88,37 +87,37 @@ class UniqueConstraint extends AbstractConstraint {
                         property = targetEntity.getPropertyByName(constraintPropertyName)
                     }
                 }
    -            constraintClass = targetEntity != null? targetEntity.javaClass: constraintClass
    +            constraintClass = targetEntity != null ? targetEntity.javaClass : constraintClass
             }
     
             // Re-create the detached criteria based on the new constraint class
             detachedCriteria = new DetachedCriteria(constraintClass)
     
    -        if(targetEntity == null) {
    +        if (targetEntity == null) {
                 throw new IllegalStateException("Cannot validate object [$target]. It is not a persistent entity")
             }
     
             EntityReflector reflector = targetEntity.reflector
             String constraintPropertyName = this.constraintPropertyName
             List group = this.group
    -        
    -        if(target instanceof DirtyCheckable) {
    +
    +        if (target instanceof DirtyCheckable) {
                 Boolean anyChanges = target.hasChanged(constraintPropertyName)
    -            for(prop in group) {
    +            for (prop in group) {
                     anyChanges |= target.hasChanged(prop.toString())
                 }
    -            if(!anyChanges) {
    +            if (!anyChanges) {
                     return
                 }
             }
     
             PersistentProperty persistentProperty = targetEntity.getPropertyByName(constraintPropertyName)
             boolean isToOne = persistentProperty instanceof ToOne
    -        if(isToOne) {
    +        if (isToOne) {
                 PersistentEntity association = ((Association) persistentProperty).getAssociatedEntity()
                 if (!association.mappingContext.proxyHandler.isProxy(propertyValue)) {
                     def associationId = association.reflector.getIdentifier(propertyValue)
    -                if(associationId == null) {
    +                if (associationId == null) {
                         // unsaved entity
                         return
                     }
    @@ -183,7 +182,6 @@ class UniqueConstraint extends AbstractConstraint {
             }
         }
     
    -
         @Override
         boolean supports(Class type) {
             return true
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/ConfigurableParameterNameProvider.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/ConfigurableParameterNameProvider.groovy
    index fe3f11c7b51..ed8946d9571 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/ConfigurableParameterNameProvider.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/ConfigurableParameterNameProvider.groovy
    @@ -20,8 +20,8 @@
     package org.grails.datastore.gorm.validation.jakarta
     
     import groovy.transform.CompileStatic
    -
     import jakarta.validation.ParameterNameProvider
    +
     import java.lang.reflect.Constructor
     import java.lang.reflect.Method
     
    @@ -32,7 +32,7 @@ import java.lang.reflect.Method
      * @since 6.1
      */
     @CompileStatic
    -class ConfigurableParameterNameProvider implements ParameterNameProvider{
    +class ConfigurableParameterNameProvider implements ParameterNameProvider {
     
         public static final String PREFIX = "arg"
         private Map> parameterNames = [:]
    @@ -45,7 +45,7 @@ class ConfigurableParameterNameProvider implements ParameterNameProvider{
          * @param parameterNames The parameter names
          */
         void addParameterNames(String methodName, Class[] parameterTypes, List names) {
    -        if(methodName != null && parameterTypes != null && names != null) {
    +        if (methodName != null && parameterTypes != null && names != null) {
                 parameterNames.put(new MethodKey(methodName, parameterTypes), names)
             }
         }
    @@ -54,10 +54,9 @@ class ConfigurableParameterNameProvider implements ParameterNameProvider{
         List getParameterNames(Constructor constructor) {
             Class[] parameterTypes = constructor.parameterTypes
             List existing = parameterNames.get(new MethodKey("", parameterTypes))
    -        if(existing != null) {
    +        if (existing != null) {
                 return existing
    -        }
    -        else {
    +        } else {
                 // return default argument names
                 return buildDefault(parameterTypes)
             }
    @@ -67,10 +66,9 @@ class ConfigurableParameterNameProvider implements ParameterNameProvider{
         List getParameterNames(Method method) {
             Class[] parameterTypes = method.parameterTypes
             List existing = parameterNames.get(new MethodKey(method.name, parameterTypes))
    -        if(existing != null) {
    +        if (existing != null) {
                 return existing
    -        }
    -        else {
    +        } else {
                 // return default argument names
                 return buildDefault(parameterTypes)
             }
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/ConstraintViolationUtils.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/ConstraintViolationUtils.groovy
    index 65d58a1866c..8100c054059 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/ConstraintViolationUtils.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/ConstraintViolationUtils.groovy
    @@ -21,11 +21,10 @@ package org.grails.datastore.gorm.validation.jakarta
     
     import grails.gorm.services.Service
     import groovy.transform.CompileStatic
    -import org.springframework.validation.Errors
    -import org.springframework.validation.MapBindingResult
    -
     import jakarta.validation.ConstraintViolation
     import jakarta.validation.ConstraintViolationException
    +import org.springframework.validation.Errors
    +import org.springframework.validation.MapBindingResult
     
     /**
      * Utility methods for handling ConstraintViolationException
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/GormValidatorAdapter.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/GormValidatorAdapter.groovy
    index c04b208a2fa..9bdb8818f72 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/GormValidatorAdapter.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/GormValidatorAdapter.groovy
    @@ -21,12 +21,11 @@ package org.grails.datastore.gorm.validation.jakarta
     
     import groovy.transform.CompileDynamic
     import groovy.transform.CompileStatic
    -import org.grails.datastore.gorm.GormValidateable
    -import org.springframework.validation.beanvalidation.SpringValidatorAdapter
    -
     import jakarta.validation.ConstraintViolation
     import jakarta.validation.Validator
     import jakarta.validation.executable.ExecutableValidator
    +import org.grails.datastore.gorm.GormValidateable
    +import org.springframework.validation.beanvalidation.SpringValidatorAdapter
     
     /**
      * A validator adapter that applies translates the constraint errors into the Errors object of a GORM entity
    @@ -47,7 +46,7 @@ class GormValidatorAdapter extends SpringValidatorAdapter {
         @Override
         def  Set> validate(T object, Class[] groups) {
             def constraintViolations = super.validate(object, groups)
    -        if(object instanceof GormValidateable) {
    +        if (object instanceof GormValidateable) {
                 def errors = ((GormValidateable) object).getErrors()
                 processConstraintViolations(constraintViolations, errors)
             }
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/GormValidatorFactoryAdapter.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/GormValidatorFactoryAdapter.groovy
    index 7b2d3277194..9fe551f483a 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/GormValidatorFactoryAdapter.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/GormValidatorFactoryAdapter.groovy
    @@ -20,7 +20,6 @@
     package org.grails.datastore.gorm.validation.jakarta
     
     import groovy.transform.CompileStatic
    -
     import jakarta.validation.ClockProvider
     import jakarta.validation.ConstraintValidatorFactory
     import jakarta.validation.MessageInterpolator
    @@ -38,7 +37,7 @@ import jakarta.validation.valueextraction.ValueExtractor
      * @since 6.1
      */
     @CompileStatic
    -class GormValidatorFactoryAdapter implements ValidatorFactory  {
    +class GormValidatorFactoryAdapter implements ValidatorFactory {
     
         final ValidatorFactory factory
     
    @@ -93,6 +92,7 @@ class GormValidatorFactoryAdapter implements ValidatorFactory  {
     
         @CompileStatic
         static class GormValidatorContext implements ValidatorContext {
    +
             final ValidatorContext delegate
     
             GormValidatorContext(ValidatorContext delegate) {
    @@ -137,7 +137,7 @@ class GormValidatorFactoryAdapter implements ValidatorFactory  {
     
             @Override
             Validator getValidator() {
    -            return new GormValidatorAdapter( delegate.getValidator() )
    +            return new GormValidatorAdapter(delegate.getValidator())
             }
         }
     }
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/JakartaValidatorRegistry.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/JakartaValidatorRegistry.groovy
    index ef4e2f4a9cd..596be8d53c2 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/JakartaValidatorRegistry.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/JakartaValidatorRegistry.groovy
    @@ -20,6 +20,15 @@
     package org.grails.datastore.gorm.validation.jakarta
     
     import groovy.transform.CompileStatic
    +import jakarta.validation.ClockProvider
    +import jakarta.validation.Configuration
    +import jakarta.validation.ConstraintValidatorFactory
    +import jakarta.validation.MessageInterpolator
    +import jakarta.validation.ParameterNameProvider
    +import jakarta.validation.TraversableResolver
    +import jakarta.validation.Validation
    +import jakarta.validation.ValidatorContext
    +import jakarta.validation.ValidatorFactory
     import org.grails.datastore.gorm.validation.constraints.registry.DefaultValidatorRegistry
     import org.grails.datastore.mapping.core.connections.ConnectionSourceSettings
     import org.grails.datastore.mapping.model.MappingContext
    @@ -34,16 +43,6 @@ import org.springframework.validation.annotation.Validated
     import org.springframework.validation.beanvalidation.MessageSourceResourceBundleLocator
     import org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory
     
    -import jakarta.validation.ClockProvider
    -import jakarta.validation.Configuration
    -import jakarta.validation.ConstraintValidatorFactory
    -import jakarta.validation.MessageInterpolator
    -import jakarta.validation.ParameterNameProvider
    -import jakarta.validation.TraversableResolver
    -import jakarta.validation.Validation
    -import jakarta.validation.ValidatorContext
    -import jakarta.validation.ValidatorFactory
    -
     /**
      * A validator registry that creates validators
      *
    @@ -111,16 +110,14 @@ class JakartaValidatorRegistry extends DefaultValidatorRegistry implements Valid
         @Override
         Validator getValidator(PersistentEntity entity) {
             def ann = entity.javaClass.getAnnotation(Validated)
    -        if(ann != null && isAvailable()) {
    +        if (ann != null && isAvailable()) {
                 def validator = validatorFactory.getValidator()
    -            if(validator instanceof GormValidatorAdapter) {
    -                return (Validator)validator
    -            }
    -            else {
    +            if (validator instanceof GormValidatorAdapter) {
    +                return (Validator) validator
    +            } else {
                     return new GormValidatorAdapter(validator)
                 }
    -        }
    -        else {
    +        } else {
                 return super.getValidator(entity)
             }
         }
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/MappingContextTraversableResolver.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/MappingContextTraversableResolver.groovy
    index 40b23a6a89f..93c8306c7ce 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/MappingContextTraversableResolver.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/MappingContextTraversableResolver.groovy
    @@ -20,14 +20,14 @@
     package org.grails.datastore.gorm.validation.jakarta
     
     import groovy.transform.CompileStatic
    +import jakarta.validation.Path
    +import jakarta.validation.TraversableResolver
     import org.grails.datastore.mapping.model.MappingContext
     import org.grails.datastore.mapping.model.PersistentEntity
     import org.grails.datastore.mapping.model.PersistentProperty
     import org.grails.datastore.mapping.model.types.Association
     import org.grails.datastore.mapping.proxy.ProxyHandler
     
    -import jakarta.validation.Path
    -import jakarta.validation.TraversableResolver
     import java.lang.annotation.ElementType
     
     /**
    @@ -56,25 +56,23 @@ class MappingContextTraversableResolver implements TraversableResolver {
         boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) {
             Class type = proxyHandler.getProxiedClass(traversableObject)
             PersistentEntity entity = mappingContext.getPersistentEntity(type.name)
    -        if(entity != null) {
    +        if (entity != null) {
                 PersistentEntity currentEntity = entity
    -            for(Path.Node n in pathToTraversableObject) {
    -                if(currentEntity == null) break
    +            for (Path.Node n in pathToTraversableObject) {
    +                if (currentEntity == null) break
                     PersistentProperty prop = currentEntity.getPropertyByName(n.name)
    -                if(prop instanceof Association) {
    -                    Association association = (Association)prop
    -                    if(association.isOwningSide()) {
    +                if (prop instanceof Association) {
    +                    Association association = (Association) prop
    +                    if (association.isOwningSide()) {
                             currentEntity = association.associatedEntity
    -                    }
    -                    else {
    +                    } else {
                             currentEntity = null
                         }
    -                }
    -                else {
    +                } else {
                         currentEntity = null
                     }
                 }
    -            if(currentEntity != null) {
    +            if (currentEntity != null) {
                     return true
                 }
             }
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/MethodKey.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/MethodKey.java
    index d659fa68cba..d4388460197 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/MethodKey.java
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/MethodKey.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.jakarta;
     
     import java.util.Arrays;
    @@ -28,6 +27,7 @@
      * @since 6.1
      */
     class MethodKey {
    +
         private final String name;
         private final Class[] parameterTypes;
     
    @@ -38,12 +38,18 @@ public MethodKey(String name, Class[] parameterTypes) {
     
         @Override
         public boolean equals(Object o) {
    -        if (this == o) return true;
    -        if (o == null || getClass() != o.getClass()) return false;
    +        if (this == o) {
    +            return true;
    +        }
    +        if (o == null || getClass() != o.getClass()) {
    +            return false;
    +        }
     
             MethodKey methodKey = (MethodKey) o;
     
    -        if (name != null ? !name.equals(methodKey.name) : methodKey.name != null) return false;
    +        if (name != null ? !name.equals(methodKey.name) : methodKey.name != null) {
    +            return false;
    +        }
             // Probably incorrect - comparing Object[] arrays with Arrays.equals
             return Arrays.equals(parameterTypes, methodKey.parameterTypes);
         }
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/ValidatedService.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/ValidatedService.groovy
    index 28a17bdfb1e..d24cae7977a 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/ValidatedService.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/ValidatedService.groovy
    @@ -20,12 +20,6 @@
     package org.grails.datastore.gorm.validation.jakarta.services
     
     import groovy.transform.CompileStatic
    -import org.grails.datastore.gorm.validation.jakarta.ConstraintViolationUtils
    -import org.grails.datastore.gorm.validation.jakarta.JakartaValidatorRegistry
    -import org.grails.datastore.mapping.services.Service
    -import org.grails.datastore.mapping.validation.ValidationException
    -import org.springframework.validation.Errors
    -
     import jakarta.validation.Configuration
     import jakarta.validation.ConstraintViolation
     import jakarta.validation.ConstraintViolationException
    @@ -33,6 +27,12 @@ import jakarta.validation.ParameterNameProvider
     import jakarta.validation.Validation
     import jakarta.validation.ValidatorFactory
     import jakarta.validation.executable.ExecutableValidator
    +import org.grails.datastore.gorm.validation.jakarta.ConstraintViolationUtils
    +import org.grails.datastore.gorm.validation.jakarta.JakartaValidatorRegistry
    +import org.grails.datastore.mapping.services.Service
    +import org.grails.datastore.mapping.validation.ValidationException
    +import org.springframework.validation.Errors
    +
     import java.lang.reflect.Method
     
     /**
    @@ -61,21 +61,20 @@ trait ValidatedService extends Service {
          * @return The validator factory for this service
          */
         ValidatorFactory getValidatorFactory() {
    -        if(validatorFactoryInstance == null) {
    +        if (validatorFactoryInstance == null) {
     
                 Configuration configuration
    -            if(datastore != null) {
    +            if (datastore != null) {
                     configuration = JakartaValidatorRegistry.buildConfigurationFor(
                             datastore.mappingContext,
                             datastore.mappingContext.validatorRegistry.messageSource
                     )
    -            }
    -            else {
    +            } else {
                     configuration = Validation.byDefaultProvider()
    -                                            .configure()
    +                        .configure()
                     configuration = configuration.ignoreXmlConfiguration()
                 }
    -            if(parameterNameProvider != null) {
    +            if (parameterNameProvider != null) {
                     configuration = configuration.parameterNameProvider(parameterNameProvider)
                 }
                 validatorFactoryInstance = configuration.buildValidatorFactory()
    @@ -92,10 +91,10 @@ trait ValidatedService extends Service {
          *
          * @throws ConstraintViolationException If a validation error occurs
          */
    -    void jakartaValidate(Object instance, Method method, Object...args) throws ConstraintViolationException {
    +    void jakartaValidate(Object instance, Method method, Object... args) throws ConstraintViolationException {
             ExecutableValidator validator = executableValidatorMap.get(method)
             Set> constraintViolations = validator.validateParameters(instance, method, args)
    -        if(!constraintViolations.isEmpty()) {
    +        if (!constraintViolations.isEmpty()) {
                 throw new ConstraintViolationException(constraintViolations)
             }
         }
    @@ -109,10 +108,10 @@ trait ValidatedService extends Service {
          *
          * @throws ValidationException If a validation error occurs
          */
    -    void validate(Object instance, Method method, Object...args) throws ValidationException {
    +    void validate(Object instance, Method method, Object... args) throws ValidationException {
             ExecutableValidator validator = executableValidatorMap.get(method)
             Set> constraintViolations = validator.validateParameters(instance, method, args)
    -        if(!constraintViolations.isEmpty()) {
    +        if (!constraintViolations.isEmpty()) {
                 throw ValidationException.newInstance("Validation failed for method: $method.name ", asErrors(instance, constraintViolations))
             }
         }
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/implementers/MethodValidationImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/implementers/MethodValidationImplementer.groovy
    index 0a61fa7c16c..45051f52f91 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/implementers/MethodValidationImplementer.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/implementers/MethodValidationImplementer.groovy
    @@ -20,8 +20,22 @@
     package org.grails.datastore.gorm.validation.jakarta.services.implementers
     
     import groovy.transform.CompileStatic
    -import org.codehaus.groovy.ast.*
    -import org.codehaus.groovy.ast.expr.*
    +import jakarta.validation.Constraint
    +import jakarta.validation.ConstraintViolationException
    +import jakarta.validation.ParameterNameProvider
    +import org.codehaus.groovy.ast.AnnotationNode
    +import org.codehaus.groovy.ast.ClassNode
    +import org.codehaus.groovy.ast.ConstructorNode
    +import org.codehaus.groovy.ast.FieldNode
    +import org.codehaus.groovy.ast.InnerClassNode
    +import org.codehaus.groovy.ast.MethodNode
    +import org.codehaus.groovy.ast.ModuleNode
    +import org.codehaus.groovy.ast.Parameter
    +import org.codehaus.groovy.ast.expr.ArgumentListExpression
    +import org.codehaus.groovy.ast.expr.ArrayExpression
    +import org.codehaus.groovy.ast.expr.Expression
    +import org.codehaus.groovy.ast.expr.ListExpression
    +import org.codehaus.groovy.ast.expr.MethodCallExpression
     import org.codehaus.groovy.ast.stmt.BlockStatement
     import org.codehaus.groovy.ast.stmt.Statement
     import org.grails.datastore.gorm.services.ServiceEnhancer
    @@ -30,16 +44,25 @@ import org.grails.datastore.gorm.validation.jakarta.ConfigurableParameterNamePro
     import org.grails.datastore.gorm.validation.jakarta.services.ValidatedService
     import org.grails.datastore.mapping.reflect.ClassUtils
     
    -import jakarta.validation.Constraint
    -import jakarta.validation.ConstraintViolationException
    -import jakarta.validation.ParameterNameProvider
     import java.lang.reflect.Method
     import java.lang.reflect.Modifier
     
    -import static org.codehaus.groovy.ast.ClassHelper.*
    -import static org.codehaus.groovy.ast.tools.GeneralUtils.*
    +import static org.codehaus.groovy.ast.ClassHelper.CLASS_Type
    +import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE
    +import static org.codehaus.groovy.ast.ClassHelper.make
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.args
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt
    +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX
     import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.callThisD
    -import static org.grails.datastore.mapping.reflect.AstUtils.*
    +import static org.grails.datastore.mapping.reflect.AstUtils.ZERO_ARGUMENTS
    +import static org.grails.datastore.mapping.reflect.AstUtils.ZERO_PARAMETERS
    +import static org.grails.datastore.mapping.reflect.AstUtils.findAnnotation
    +import static org.grails.datastore.mapping.reflect.AstUtils.varThis
     
     /**
      * Adds method parameter validation to {@link grails.gorm.services.Service} instances
    @@ -64,12 +87,12 @@ class MethodValidationImplementer implements ServiceEnhancer {
     
         @Override
         boolean doesEnhance(ClassNode domainClass, MethodNode methodNode) {
    -        if(ClassUtils.isPresent("jakarta.validation.Validation")) {
    -            for(Parameter p in methodNode.parameters) {
    -                if( p.annotations.any() { AnnotationNode ann ->
    +        if (ClassUtils.isPresent("jakarta.validation.Validation")) {
    +            for (Parameter p in methodNode.parameters) {
    +                if (p.annotations.any() { AnnotationNode ann ->
                         def constraintAnn = findAnnotation(ann.classNode, Constraint)
                         constraintAnn != null
    -                } ) {
    +                }) {
                         return true
                     }
     
    @@ -80,7 +103,7 @@ class MethodValidationImplementer implements ServiceEnhancer {
     
         @Override
         void enhance(ClassNode domainClassNode, MethodNode abstractMethodNode, MethodNode newMethodNode, ClassNode targetClassNode) {
    -        Statement body = (Statement)newMethodNode.code
    +        Statement body = (Statement) newMethodNode.code
     
             // add parameter name data for the service
             weaveParameterNameData(domainClassNode, newMethodNode, abstractMethodNode)
    @@ -92,14 +115,13 @@ class MethodValidationImplementer implements ServiceEnhancer {
                     domainClassNode
             )
     
    -        Integer validatedMethodCount = (Integer)targetClassNode.getNodeMetaData(VALIDATED_METHOD)
    -        if(validatedMethodCount == null) {
    +        Integer validatedMethodCount = (Integer) targetClassNode.getNodeMetaData(VALIDATED_METHOD)
    +        if (validatedMethodCount == null) {
                 validatedMethodCount = 0
    -        }
    -        else{
    +        } else {
                 validatedMethodCount++
             }
    -        
    +
             targetClassNode.putNodeMetaData(VALIDATED_METHOD, validatedMethodCount)
     
             // add a field that holds a reference to the java.lang.reflect.Method to be validated
    @@ -107,25 +129,24 @@ class MethodValidationImplementer implements ServiceEnhancer {
             MethodCallExpression getClassCall = callThisD(targetClassNode, "getClass", ZERO_ARGUMENTS)
             List validateArgsList = []
             List parameterTypesList = []
    -        for(Parameter p in newMethodNode.parameters) {
    +        for (Parameter p in newMethodNode.parameters) {
                 validateArgsList.add(varX(p))
                 parameterTypesList.add(classX(p.type.plainNodeReference))
             }
             ArrayExpression parameterTypes = new ArrayExpression(CLASS_Type.plainNodeReference, parameterTypesList)
    -        MethodCallExpression getMethodCall = callX(getClassCall, "getMethod", args( constX(newMethodNode.name), parameterTypes))
    +        MethodCallExpression getMethodCall = callX(getClassCall, "getMethod", args(constX(newMethodNode.name), parameterTypes))
             FieldNode methodField = targetClassNode.addField(methodFieldName, Modifier.PRIVATE, make(Method).plainNodeReference, getMethodCall)
     
             // add a first line to the method body that validates the method
             ArrayExpression argArray = new ArrayExpression(OBJECT_TYPE, validateArgsList)
    -        String validateMethodName = abstractMethodNode.exceptions?.contains( make(ConstraintViolationException) ) ? "jakartaValidate" : "validate"
    -        MethodCallExpression validateCall = callThisD(ValidatedService, validateMethodName, args(varThis(), varX(methodField),argArray))
    -        if(body instanceof BlockStatement) {
    -            ((BlockStatement)body).statements.add(0, stmt( validateCall ))
    -        }
    -        else {
    +        String validateMethodName = abstractMethodNode.exceptions?.contains(make(ConstraintViolationException)) ? "jakartaValidate" : "validate"
    +        MethodCallExpression validateCall = callThisD(ValidatedService, validateMethodName, args(varThis(), varX(methodField), argArray))
    +        if (body instanceof BlockStatement) {
    +            ((BlockStatement) body).statements.add(0, stmt(validateCall))
    +        } else {
                 body = new BlockStatement([
    -               stmt( validateCall ),
    -               body
    +                    stmt(validateCall),
    +                    body
                 ], newMethodNode.variableScope)
                 newMethodNode.setCode(body)
             }
    @@ -147,14 +168,12 @@ class MethodValidationImplementer implements ServiceEnhancer {
     
                 module.addClass(innerClassNode)
                 newClass.addObjectInitializerStatements(
    -                assignS(varX('parameterNameProvider'), ctorX(innerClassNode))
    +                    assignS(varX('parameterNameProvider'), ctorX(innerClassNode))
                 )
    -        }
    -        else {
    +        } else {
                 addParameterNamesMethodNode = innerClassNode.getMethods("addParameterNames")[0]
             }
     
    -
             ArgumentListExpression addParameterNamesArguments = args(constX(newMethodNode.name))
             ListExpression parameterNames = new ListExpression()
             List parameterTypes = []
    @@ -166,17 +185,16 @@ class MethodValidationImplementer implements ServiceEnhancer {
             addParameterNamesArguments.addExpression(parameterTypesArray)
             addParameterNamesArguments.addExpression(parameterNames)
     
    -
             def callExpression = callThisD(innerClassNode, addParameterNamesMethodNode.name, addParameterNamesArguments)
             callExpression.setMethodTarget(addParameterNamesMethodNode)
             ConstructorNode constructorNode = innerClassNode.getDeclaredConstructor(ZERO_PARAMETERS)
    -        if(constructorNode == null) {
    +        if (constructorNode == null) {
                 constructorNode = new ConstructorNode(Modifier.PUBLIC, ZERO_PARAMETERS, null, new BlockStatement())
                 innerClassNode.addConstructor(constructorNode)
             }
    -        BlockStatement constructorBody = (BlockStatement)constructorNode.code
    +        BlockStatement constructorBody = (BlockStatement) constructorNode.code
             constructorBody.addStatement(
    -            stmt(callExpression)
    +                stmt(callExpression)
             )
         }
     }
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/listener/ValidationEventListener.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/listener/ValidationEventListener.groovy
    index 8453fa72483..ccfec3b3e49 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/listener/ValidationEventListener.groovy
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/listener/ValidationEventListener.groovy
    @@ -20,6 +20,7 @@
     package org.grails.datastore.gorm.validation.listener
     
     import groovy.transform.CompileStatic
    +import jakarta.persistence.FlushModeType
     import org.grails.datastore.gorm.GormEnhancer
     import org.grails.datastore.gorm.GormValidateable
     import org.grails.datastore.gorm.GormValidationApi
    @@ -32,8 +33,6 @@ import org.grails.datastore.mapping.engine.event.PreInsertEvent
     import org.grails.datastore.mapping.engine.event.PreUpdateEvent
     import org.springframework.context.ApplicationEvent
     
    -import jakarta.persistence.FlushModeType
    -
     /**
      * An event listener for ensuring entities are valid before saving or updating
      *
    @@ -41,7 +40,8 @@ import jakarta.persistence.FlushModeType
      * @since 6.0
      */
     @CompileStatic
    -class ValidationEventListener extends AbstractPersistenceEventListener{
    +class ValidationEventListener extends AbstractPersistenceEventListener {
    +
         ValidationEventListener(Datastore datastore) {
             super(datastore)
         }
    @@ -49,31 +49,29 @@ class ValidationEventListener extends AbstractPersistenceEventListener{
         @Override
         protected void onPersistenceEvent(AbstractPersistenceEvent event) {
             def entityObject = event.getEntityObject()
    -        if(entityObject instanceof GormValidateable) {
    +        if (entityObject instanceof GormValidateable) {
                 GormValidateable gormValidateable = (GormValidateable) entityObject
    -            if(gormValidateable.shouldSkipValidation()) {
    -                if( gormValidateable.getErrors()?.hasErrors() )  {
    +            if (gormValidateable.shouldSkipValidation()) {
    +                if (gormValidateable.getErrors()?.hasErrors()) {
                         event.cancel()
                     }
    -            }
    -            else {
    +            } else {
     
    -                Datastore source = (Datastore)event.getSource()
    +                Datastore source = (Datastore) event.getSource()
     
                     Session currentSession = source.currentSession
                     FlushModeType previousFlushMode = currentSession.flushMode
                     try {
                         currentSession.setFlushMode(FlushModeType.COMMIT)
                         boolean hasErrors = false
    -                    if(source instanceof ConnectionSourcesProvider) {
    +                    if (source instanceof ConnectionSourcesProvider) {
                             def connectionSourceName = ((ConnectionSourcesProvider) source).connectionSources.defaultConnectionSource.name
    -                        GormValidationApi validationApi = GormEnhancer.findValidationApi((Class)entityObject.getClass(), connectionSourceName)
    -                        hasErrors = !validationApi.validate((Object)entityObject)
    -                    }
    -                    else {
    +                        GormValidationApi validationApi = GormEnhancer.findValidationApi((Class) entityObject.getClass(), connectionSourceName)
    +                        hasErrors = !validationApi.validate((Object) entityObject)
    +                    } else {
                             hasErrors = !gormValidateable.validate()
                         }
    -                    if( hasErrors ) {
    +                    if (hasErrors) {
                             event.cancel()
                         }
                     } finally {
    diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/registry/support/ValidatorRegistries.java b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/registry/support/ValidatorRegistries.java
    index e0a23c9cb90..83f5ab366da 100644
    --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/registry/support/ValidatorRegistries.java
    +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/registry/support/ValidatorRegistries.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.registry.support;
     
     import org.grails.datastore.gorm.validation.constraints.registry.DefaultValidatorRegistry;
    @@ -34,7 +33,7 @@
      * @author Graeme Rocher
      * @since 6.1
      */
    -public class ValidatorRegistries {
    +public final class ValidatorRegistries {
     
         private ValidatorRegistries() {
         }
    @@ -43,7 +42,7 @@ private ValidatorRegistries() {
          * Creates a validator registry with a static message source
          *
          * @param mappingContext The mapping context
    -     * @param settings The settings
    +     * @param settings       The settings
          * @return The registry
          */
         public static ValidatorRegistry createValidatorRegistry(MappingContext mappingContext, ConnectionSourceSettings settings) {
    @@ -54,16 +53,15 @@ public static ValidatorRegistry createValidatorRegistry(MappingContext mappingCo
          * Creates the most appropriate validator registry
          *
          * @param mappingContext The mapping context
    -     * @param settings the settings
    -     * @param messageSource the message source
    +     * @param settings       the settings
    +     * @param messageSource  the message source
          * @return The registry
          */
    -    public static ValidatorRegistry createValidatorRegistry(MappingContext mappingContext, ConnectionSourceSettings settings, MessageSource messageSource ) {
    +    public static ValidatorRegistry createValidatorRegistry(MappingContext mappingContext, ConnectionSourceSettings settings, MessageSource messageSource) {
             ValidatorRegistry validatorRegistry;
    -        if(isJakartaValidationAvailable()) {
    +        if (isJakartaValidationAvailable()) {
                 validatorRegistry = new JakartaValidatorRegistry(mappingContext, settings, messageSource);
    -        }
    -        else {
    +        } else {
                 validatorRegistry = new DefaultValidatorRegistry(mappingContext, settings, messageSource);
             }
             return validatorRegistry;
    diff --git a/grails-datamapping-rx/src/main/groovy/org/grails/datastore/rx/AbstractRxDatastoreClient.groovy b/grails-datamapping-rx/src/main/groovy/org/grails/datastore/rx/AbstractRxDatastoreClient.groovy
    index ca085f6db66..b3bcfda782a 100644
    --- a/grails-datamapping-rx/src/main/groovy/org/grails/datastore/rx/AbstractRxDatastoreClient.groovy
    +++ b/grails-datamapping-rx/src/main/groovy/org/grails/datastore/rx/AbstractRxDatastoreClient.groovy
    @@ -21,6 +21,9 @@ package org.grails.datastore.rx
     
     import grails.gorm.rx.proxy.ObservableProxy
     import groovy.transform.CompileStatic
    +import jakarta.persistence.CascadeType
    +import org.grails.datastore.gorm.events.ConfigurableApplicationEventPublisher
    +import org.grails.datastore.gorm.events.DefaultApplicationEventPublisher
     import org.grails.datastore.gorm.validation.registry.support.ValidatorRegistries
     import org.grails.datastore.mapping.collection.PersistentCollection
     import org.grails.datastore.mapping.config.Property
    @@ -33,7 +36,6 @@ import org.grails.datastore.mapping.core.exceptions.ConfigurationException
     import org.grails.datastore.mapping.dirty.checking.DirtyCheckable
     import org.grails.datastore.mapping.dirty.checking.DirtyCheckableCollection
     import org.grails.datastore.mapping.engine.EntityAccess
    -import org.grails.datastore.mapping.engine.event.*
     import org.grails.datastore.mapping.model.MappingContext
     import org.grails.datastore.mapping.model.PersistentEntity
     import org.grails.datastore.mapping.model.PersistentProperty
    @@ -56,8 +58,6 @@ import org.grails.gorm.rx.api.RxGormInstanceApi
     import org.grails.gorm.rx.api.RxGormStaticApi
     import org.grails.gorm.rx.api.RxGormValidationApi
     import org.grails.gorm.rx.events.AutoTimestampEventListener
    -import org.grails.datastore.gorm.events.ConfigurableApplicationEventPublisher
    -import org.grails.datastore.gorm.events.DefaultApplicationEventPublisher
     import org.grails.gorm.rx.events.DomainEventListener
     import org.grails.gorm.rx.events.MultiTenantEventListener
     import org.springframework.context.ApplicationEvent
    @@ -65,9 +65,7 @@ import org.springframework.context.ApplicationEventPublisher
     import org.springframework.context.MessageSource
     import org.springframework.context.MessageSourceAware
     import org.springframework.context.support.StaticMessageSource
    -import rx.Observable
     
    -import jakarta.persistence.CascadeType
     /**
      * Abstract implementation the {@link RxDatastoreClient} interface
      *
    diff --git a/grails-datamapping-rx/src/main/groovy/org/grails/gorm/rx/api/RxGormStaticApi.groovy b/grails-datamapping-rx/src/main/groovy/org/grails/gorm/rx/api/RxGormStaticApi.groovy
    index 4b20b8aa031..92dc16e0d57 100644
    --- a/grails-datamapping-rx/src/main/groovy/org/grails/gorm/rx/api/RxGormStaticApi.groovy
    +++ b/grails-datamapping-rx/src/main/groovy/org/grails/gorm/rx/api/RxGormStaticApi.groovy
    @@ -467,8 +467,8 @@ class RxGormStaticApi implements RxGormAllOperations {
     
             // register the method invocation for next time
             mc.static."$methodName" = { Object[] varArgs ->
    -            // FYI... This is relevant to http://jira.grails.org/browse/GRAILS-3463 and may
    -            // become problematic if http://jira.codehaus.org/browse/GROOVY-5876 is addressed...
    +            // FYI... This is relevant to GRAILS-3463 and may
    +            // become problematic if GROOVY-5876 is addressed...
                 final argumentsForMethod
                 if(varArgs == null) {
                     argumentsForMethod = [null] as Object[]
    diff --git a/grails-datamapping-support/build.gradle b/grails-datamapping-support/build.gradle
    index 01c740d8a22..fbf357c5360 100644
    --- a/grails-datamapping-support/build.gradle
    +++ b/grails-datamapping-support/build.gradle
    @@ -122,4 +122,5 @@ apply {
         from rootProject.layout.projectDirectory.file('gradle/test-config.gradle')
         from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle')
         from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle')
    +    from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle')
     }
    diff --git a/grails-datamapping-support/src/main/groovy/org/grails/compiler/gorm/EntityTraitInjector.groovy b/grails-datamapping-support/src/main/groovy/org/grails/compiler/gorm/EntityTraitInjector.groovy
    index 749692f37f6..349550670d9 100644
    --- a/grails-datamapping-support/src/main/groovy/org/grails/compiler/gorm/EntityTraitInjector.groovy
    +++ b/grails-datamapping-support/src/main/groovy/org/grails/compiler/gorm/EntityTraitInjector.groovy
    @@ -21,7 +21,6 @@ package org.grails.compiler.gorm
     import grails.compiler.traits.TraitInjector
     import grails.gorm.Entity
     import groovy.transform.CompileStatic
    -
     import org.grails.core.artefact.DomainClassArtefactHandler
     
     /**
    diff --git a/grails-datamapping-support/src/main/groovy/org/grails/compiler/gorm/GormTransformer.java b/grails-datamapping-support/src/main/groovy/org/grails/compiler/gorm/GormTransformer.java
    index cd3d1bc1ed7..5b816f1152e 100644
    --- a/grails-datamapping-support/src/main/groovy/org/grails/compiler/gorm/GormTransformer.java
    +++ b/grails-datamapping-support/src/main/groovy/org/grails/compiler/gorm/GormTransformer.java
    @@ -39,11 +39,11 @@
      * @since 2.0
      */
     @AstTransformer
    -public class GormTransformer implements GrailsArtefactClassInjector{
    +public class GormTransformer implements GrailsArtefactClassInjector {
     
         @Override
         public String[] getArtefactTypes() {
    -        return new String[] {DomainClassArtefactHandler.TYPE};
    +        return new String[]{DomainClassArtefactHandler.TYPE};
         }
     
         public boolean shouldInject(URL url) {
    @@ -54,10 +54,9 @@ public static Collection getKnownEntityNames() {
             return AstUtils.getKnownEntityNames();
         }
     
    -
         @Override
         public void performInjection(SourceUnit source, GeneratorContext context, ClassNode classNode) {
    -        if(GrailsASTUtils.hasAnnotation(classNode, Canonical.class)) {
    +        if (GrailsASTUtils.hasAnnotation(classNode, Canonical.class)) {
                 GrailsASTUtils.error(source, classNode, "Class [" + classNode.getName() + "] is marked with @groovy.transform.Canonical which is not supported for GORM entities.", true);
             }
             final GormEntityTransformation transformation = new GormEntityTransformation();
    @@ -67,7 +66,7 @@ public void performInjection(SourceUnit source, GeneratorContext context, ClassN
     
         @Override
         public void performInjection(SourceUnit source, ClassNode classNode) {
    -        if(GrailsASTUtils.hasAnnotation(classNode, Canonical.class)) {
    +        if (GrailsASTUtils.hasAnnotation(classNode, Canonical.class)) {
                 GrailsASTUtils.error(source, classNode, "Class [" + classNode.getName() + "] is marked with @groovy.transform.Canonical which is not supported for GORM entities.", true);
             }
             new GormEntityTransformation().visit(classNode, source);
    diff --git a/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/ConfigSupport.groovy b/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/ConfigSupport.groovy
    index 497a9d62686..e8c161b393c 100644
    --- a/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/ConfigSupport.groovy
    +++ b/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/plugin/support/ConfigSupport.groovy
    @@ -40,15 +40,16 @@ class ConfigSupport {
          * @param applicationContext The application context
          */
         static void prepareConfig(PropertyResolver config, ConfigurableApplicationContext applicationContext) {
    -        if(config instanceof PropertySourcesConfig) {
    +        if (config instanceof PropertySourcesConfig) {
                 ConfigurableConversionService conversionService = applicationContext.getEnvironment().getConversionService()
                 conversionService.addConverter(new Converter() {
    +
                     @Override
                     Class convert(String source) {
                         Class.forName(source)
                     }
                 })
    -            ((PropertySourcesConfig)config).setConversionService(conversionService)
    +            ((PropertySourcesConfig) config).setConversionService(conversionService)
             }
         }
     }
    diff --git a/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/proxy/EntityProxyHandlerAdapter.java b/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/proxy/EntityProxyHandlerAdapter.java
    index 98e49a184a7..578c92de795 100644
    --- a/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/proxy/EntityProxyHandlerAdapter.java
    +++ b/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/proxy/EntityProxyHandlerAdapter.java
    @@ -38,7 +38,6 @@ public EntityProxyHandlerAdapter(EntityProxyHandler proxyHandler) {
             this.proxyHandler = proxyHandler;
         }
     
    -
         @Override
         public boolean isProxy(Object object) {
             return proxyHandler.isProxy(object);
    @@ -51,7 +50,7 @@ public boolean isInitialized(Object object) {
     
         @Override
         public boolean isInitialized(Object object, String associationName) {
    -        return proxyHandler.isInitialized(object,associationName);
    +        return proxyHandler.isInitialized(object, associationName);
         }
     
         @Override
    diff --git a/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/proxy/ProxyHandlerAdapter.java b/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/proxy/ProxyHandlerAdapter.java
    index 0449332e5c9..628ac5e7f7e 100644
    --- a/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/proxy/ProxyHandlerAdapter.java
    +++ b/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/proxy/ProxyHandlerAdapter.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.proxy;
     
     import grails.core.support.proxy.EntityProxyHandler;
    diff --git a/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/support/AggregatePersistenceContextInterceptor.java b/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/support/AggregatePersistenceContextInterceptor.java
    index 5e170dd10da..39b564bdd2d 100644
    --- a/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/support/AggregatePersistenceContextInterceptor.java
    +++ b/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/support/AggregatePersistenceContextInterceptor.java
    @@ -22,7 +22,6 @@
     
     import java.util.List;
     
    -
     /**
      * @author Graeme Rocher
      * @since 1.0
    @@ -33,6 +32,7 @@ public class AggregatePersistenceContextInterceptor implements PersistenceContex
     
         /**
          * Constructor.
    +     *
          * @param interceptors the real interceptors
          */
         public AggregatePersistenceContextInterceptor(final List interceptors) {
    diff --git a/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/support/DatastorePersistenceContextInterceptor.java b/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/support/DatastorePersistenceContextInterceptor.java
    index a6fec2f2e90..e7840d4984b 100644
    --- a/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/support/DatastorePersistenceContextInterceptor.java
    +++ b/grails-datamapping-support/src/main/groovy/org/grails/datastore/gorm/support/DatastorePersistenceContextInterceptor.java
    @@ -29,6 +29,7 @@
      */
     
     public class DatastorePersistenceContextInterceptor extends AbstractDatastorePersistenceContextInterceptor implements PersistenceContextInterceptor {
    +
         public DatastorePersistenceContextInterceptor(Datastore datastore) {
             super(datastore);
         }
    diff --git a/grails-datamapping-tck/build.gradle b/grails-datamapping-tck/build.gradle
    index e89fc3067d8..9b38a4c52d2 100644
    --- a/grails-datamapping-tck/build.gradle
    +++ b/grails-datamapping-tck/build.gradle
    @@ -116,5 +116,6 @@ apply {
         from rootProject.layout.projectDirectory.file('gradle/java-config.gradle')
         from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle')
         from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle')
    +    from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle')
         // do NOT do test configuration here, this is a TCK module
     }
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/base/GrailsDataTckManager.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/base/GrailsDataTckManager.groovy
    index e41d28112e4..ec4c17f647d 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/base/GrailsDataTckManager.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/base/GrailsDataTckManager.groovy
    @@ -48,6 +48,7 @@ import org.grails.datastore.mapping.core.Session
     import spock.lang.Specification
     
     abstract class GrailsDataTckManager {
    +
         static final CURRENT_TEST_NAME = 'current.gorm.test'
     
         Session session
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/base/GrailsDataTckSpec.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/base/GrailsDataTckSpec.groovy
    index d75df8b8455..50823f04c91 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/base/GrailsDataTckSpec.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/base/GrailsDataTckSpec.groovy
    @@ -25,6 +25,7 @@ import spock.lang.Specification
     
     @Slf4j
     class GrailsDataTckSpec extends Specification {
    +
         @Shared
         T manager
     
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Book.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Book.groovy
    index 007b120607a..f45b97fd7e2 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Book.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Book.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Book implements Serializable {
    +
         Long id
         Long version
         String author
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Child.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Child.groovy
    index 3afd7fa4a1b..3729f8ee0bf 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Child.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Child.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Child implements Serializable {
    +
         private static final long serialVersionUID = 1
         Long id
         Long version
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ChildEntity.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ChildEntity.groovy
    index a386c7ffe1a..90cd2ab06be 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ChildEntity.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ChildEntity.groovy
    @@ -26,6 +26,7 @@ import grails.persistence.Entity
      */
     @Entity
     class ChildEntity implements Serializable {
    +
         Long id
         Long version
         String name
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/City.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/City.groovy
    index 88932797d88..99485f32a9d 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/City.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/City.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class City extends Location {
    +
         BigDecimal latitude
         BigDecimal longitude
     }
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithHungarianNotation.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithHungarianNotation.groovy
    index b67e0d99a49..ac0cb1bd8aa 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithHungarianNotation.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithHungarianNotation.groovy
    @@ -26,6 +26,7 @@ import grails.persistence.Entity
      */
     @Entity
     class ClassWithHungarianNotation implements Serializable {
    +
         Integer iSize
     
         static constraints = {
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithListArgBeforeValidate.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithListArgBeforeValidate.groovy
    index cc703c149aa..65b5446334a 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithListArgBeforeValidate.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithListArgBeforeValidate.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class ClassWithListArgBeforeValidate implements Serializable {
    +
         Long id
         Long version
         def listArgCounter = 0
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithNoArgBeforeValidate.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithNoArgBeforeValidate.groovy
    index a510f50d56f..66157773345 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithNoArgBeforeValidate.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithNoArgBeforeValidate.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity;
     
     @Entity
     class ClassWithNoArgBeforeValidate implements Serializable {
    +
         Long id
         Long version
         def noArgCounter = 0
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithOverloadedBeforeValidate.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithOverloadedBeforeValidate.groovy
    index a6d72d59751..6fdc621423b 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithOverloadedBeforeValidate.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ClassWithOverloadedBeforeValidate.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class ClassWithOverloadedBeforeValidate implements Serializable {
    +
         Long id
         Long version
         def noArgCounter = 0
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/CommonTypes.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/CommonTypes.groovy
    index 4dff263d2fa..79ad07f27ef 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/CommonTypes.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/CommonTypes.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class CommonTypes implements Serializable {
    +
         Long id
         Long version
         Long l
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Country.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Country.groovy
    index f5922d99509..4d375afa492 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Country.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Country.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Country extends Location {
    +
         Integer population = 0
     
         static hasMany = [residents: Person]
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Dog.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Dog.groovy
    index cc6d6e0497e..ba100f23514 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Dog.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Dog.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Dog implements Serializable {
    +
         Long id
         int age
         int deathAge
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/EnumThing.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/EnumThing.groovy
    index b241fd8fc45..2f92a5807c1 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/EnumThing.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/EnumThing.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class EnumThing {
    +
         Long id
         Long version
         String name
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Face.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Face.groovy
    index abf9a79f01e..740c93aac06 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Face.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Face.groovy
    @@ -19,11 +19,11 @@
     
     package org.apache.grails.data.testing.tck.domains
     
    -
     import grails.persistence.Entity
     
     @Entity
     class Face implements Serializable {
    +
         Long id
         Long version
         String name
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/GroupWithin.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/GroupWithin.groovy
    index 77c84d0fed6..26135ef012a 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/GroupWithin.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/GroupWithin.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class GroupWithin implements Serializable {
    +
         Long id
         Long version
         String name
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Highway.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Highway.groovy
    index b37966849af..74b9e98b905 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Highway.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Highway.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Highway implements Serializable {
    +
         Long id
         Long version
         Boolean bypassed
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ModifyPerson.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ModifyPerson.groovy
    index 3ecd2794b1f..4ce71e07582 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ModifyPerson.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/ModifyPerson.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class ModifyPerson implements Serializable {
    +
         Long id
         Long version
     
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Nose.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Nose.groovy
    index 8f2643653d6..9e281d8050b 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Nose.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Nose.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Nose implements Serializable {
    +
         Long id
         Long version
         boolean hasFreckles
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/OptLockNotVersioned.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/OptLockNotVersioned.groovy
    index d56b5c1d43a..a8f2e65a0be 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/OptLockNotVersioned.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/OptLockNotVersioned.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class OptLockNotVersioned implements Serializable {
    +
         Long id
         Long version
     
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/OptLockVersioned.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/OptLockVersioned.groovy
    index 81982af712b..1d8cf05b2a2 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/OptLockVersioned.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/OptLockVersioned.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class OptLockVersioned implements Serializable {
    +
         Long id
         Long version
     
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Parent.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Parent.groovy
    index 8ee72373530..2d4d0d49234 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Parent.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Parent.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Parent implements Serializable {
    +
         private static final long serialVersionUID = 1
         Long id
         String name
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Person.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Person.groovy
    index 7879560c532..be1ecefd40e 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Person.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Person.groovy
    @@ -19,8 +19,8 @@
     
     package org.apache.grails.data.testing.tck.domains
     
    -import grails.gorm.async.AsyncEntity
     import grails.gorm.DetachedCriteria
    +import grails.gorm.async.AsyncEntity
     import grails.gorm.dirty.checking.DirtyCheck
     import grails.persistence.Entity
     import groovy.transform.EqualsAndHashCode
    @@ -29,9 +29,10 @@ import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform
     @DirtyCheck
     @Entity
     @ApplyDetachedCriteriaTransform
    -//@groovy.transform.EqualsAndHashCode - breaks gorm-neo4j: TODO: http://jira.grails.org/browse/GPNEO4J-10
    +//@groovy.transform.EqualsAndHashCode - breaks gorm-neo4j: TODO: GPNEO4J-10
     @EqualsAndHashCode(includes = ['firstName', 'lastName', 'age'])
     class Person implements Serializable, Comparable, AsyncEntity {
    +
         static simpsons = where {
             lastName == "Simpson"
         }
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PersonEvent.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PersonEvent.groovy
    index a0c8f605e2f..5bfd411ea30 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PersonEvent.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PersonEvent.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class PersonEvent implements Serializable {
    +
         Long id
         Long version
         String name
    @@ -35,7 +36,7 @@ class PersonEvent implements Serializable {
                 beforeDelete: 0, afterDelete: 0,
                 beforeUpdate: 0, afterUpdate: 0,
                 beforeInsert: 0, afterInsert: 0,
    -            beforeLoad:   0, afterLoad:   0]
    +            beforeLoad: 0, afterLoad: 0]
     
         static STORE = [:] + STORE_INITIAL
     
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PersonWithCompositeKey.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PersonWithCompositeKey.groovy
    index cb84b3b8676..ffdcf1f6631 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PersonWithCompositeKey.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PersonWithCompositeKey.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class PersonWithCompositeKey implements Serializable {
    +
         Long version
         String firstName
         String lastName
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Pet.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Pet.groovy
    index 4efb35ed9c7..eafb3845172 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Pet.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Pet.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Pet implements Serializable {
    +
         Long id
         Long version
         String name
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PetType.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PetType.groovy
    index 48a3970fff8..cba6756e60b 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PetType.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PetType.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class PetType implements Serializable {
    +
         private static final long serialVersionUID = 1
         Long id
         Long version
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Plant.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Plant.groovy
    index 5818b46f00b..ffd347c80fd 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Plant.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Plant.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Plant implements Serializable {
    +
         Long id
         Long version
         boolean goesInPatch
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PlantCategory.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PlantCategory.groovy
    index 4fea6a55314..e0dbf38a3d4 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PlantCategory.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/PlantCategory.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class PlantCategory implements Serializable {
    +
         Long id
         Long version
         Set plants
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Practice.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Practice.groovy
    index 27ef127cdf4..9473747c3ef 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Practice.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Practice.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Practice implements Serializable {
    +
     //    Long id
         Long version
         String name
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Publication.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Publication.groovy
    index a26412f930b..6716e1dae47 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Publication.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Publication.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Publication implements Serializable {
    +
         Long id
         Long version
         String title
    @@ -30,9 +31,9 @@ class Publication implements Serializable {
         Boolean paperback = true
     
         static mapping = {
    -        title index:true
    -        paperback index:true
    -        datePublished index:true
    +        title index: true
    +        paperback index: true
    +        datePublished index: true
         }
     
         static namedQueries = {
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Record.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Record.groovy
    index 848e81ae6bb..44337b9847d 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Record.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Record.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Record {
    +
         Long id
         String name
         Date dateCreated
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/SimpleWidget.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/SimpleWidget.groovy
    index 98b135259c7..2fcf7aa0c10 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/SimpleWidget.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/SimpleWidget.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class SimpleWidget implements Serializable {
    +
         Long id
         Long version
         String name
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/SimpleWidgetWithNonStandardId.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/SimpleWidgetWithNonStandardId.groovy
    index f53b01856ae..05c4db180ce 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/SimpleWidgetWithNonStandardId.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/SimpleWidgetWithNonStandardId.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class SimpleWidgetWithNonStandardId implements Serializable {
    +
         Long myIdentifier
         Long version
         String name
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Simples.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Simples.groovy
    index 0eeedbf233b..d489bcb4cd0 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Simples.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Simples.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Simples implements Serializable {
    +
         Long id
         String name
     }
    \ No newline at end of file
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Task.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Task.groovy
    index cfa45d3d375..2435ee1f0ee 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Task.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/Task.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class Task implements Serializable {
    +
         Long id
         Long version
         Set tasks
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/TestEntity.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/TestEntity.groovy
    index 8fb9071d86f..8f3ff40e9e1 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/TestEntity.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/TestEntity.groovy
    @@ -26,6 +26,7 @@ import grails.persistence.Entity
      */
     @Entity
     class TestEntity implements Serializable {
    +
         Long id
         Long version
         String name
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/TestEnum.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/TestEnum.groovy
    index 57cb926d0c6..3e8ca244fea 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/TestEnum.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/TestEnum.groovy
    @@ -20,6 +20,7 @@
     package org.apache.grails.data.testing.tck.domains
     
     enum TestEnum {
    +
         V1,
         V2,
         V3
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/TestPlayer.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/TestPlayer.groovy
    index 05f2022388e..ad4e3c37216 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/TestPlayer.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/TestPlayer.groovy
    @@ -23,6 +23,7 @@ import grails.persistence.Entity
     
     @Entity
     class TestPlayer implements Serializable {
    +
         Long id
         String name
         List attributes
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/UniqueGroup.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/UniqueGroup.groovy
    index 2bf26c7808d..4bb9df8c307 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/UniqueGroup.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/domains/UniqueGroup.groovy
    @@ -24,6 +24,7 @@ import org.grails.datastore.mapping.dirty.checking.DirtyCheckable
     
     @Entity
     class UniqueGroup implements Serializable, DirtyCheckable {
    +
         Long id
         Long version
         String name
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/tests/BuiltinUniqueConstraintWorksWithTargetProxiesConstraintsSpec.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/tests/BuiltinUniqueConstraintWorksWithTargetProxiesConstraintsSpec.groovy
    index f57f4f0a3c7..bba558ba6dd 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/tests/BuiltinUniqueConstraintWorksWithTargetProxiesConstraintsSpec.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/tests/BuiltinUniqueConstraintWorksWithTargetProxiesConstraintsSpec.groovy
    @@ -31,7 +31,7 @@ class BuiltinUniqueConstraintWorksWithTargetProxiesConstraintsSpec extends Grail
             manager.domainClasses.addAll([ContactDetails, Patient])
         }
     
    -    @PendingFeatureIf({ !Boolean.getBoolean('hibernate5.gorm.suite') && !Boolean.getBoolean('hibernate6.gorm.suite') && !Boolean.getBoolean('mongodb.gorm.suite')})
    +    @PendingFeatureIf({ !Boolean.getBoolean('hibernate5.gorm.suite') && !Boolean.getBoolean('hibernate6.gorm.suite') && !Boolean.getBoolean('mongodb.gorm.suite') })
         void "test unique constraint on root instance"() {
     
             setup:
    @@ -52,7 +52,7 @@ class BuiltinUniqueConstraintWorksWithTargetProxiesConstraintsSpec extends Grail
             ContactDetails.deleteAll(contactDetails1)
         }
     
    -    @PendingFeatureIf({ !Boolean.getBoolean('hibernate5.gorm.suite') && !Boolean.getBoolean('hibernate6.gorm.suite') && !Boolean.getBoolean('mongodb.gorm.suite')})
    +    @PendingFeatureIf({ !Boolean.getBoolean('hibernate5.gorm.suite') && !Boolean.getBoolean('hibernate6.gorm.suite') && !Boolean.getBoolean('mongodb.gorm.suite') })
         void "test unique constraint for the associated child object"() {
     
             setup:
    diff --git a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/tests/CommonTypesPersistenceSpec.groovy b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/tests/CommonTypesPersistenceSpec.groovy
    index 8086b732848..9eb35bb1f83 100644
    --- a/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/tests/CommonTypesPersistenceSpec.groovy
    +++ b/grails-datamapping-tck/src/main/groovy/org/apache/grails/data/testing/tck/tests/CommonTypesPersistenceSpec.groovy
    @@ -36,7 +36,7 @@ class CommonTypesPersistenceSpec extends GrailsDataTckSpec {
                     s: 10 as short,
                     bool: true,
                     i: 10,
    -                url: new URL("http://google.com"),
    +                url: new URL("https://google.com"),
                     date: now,
                     c: cal,
                     bd: 1.0,
    @@ -61,7 +61,7 @@ class CommonTypesPersistenceSpec extends GrailsDataTckSpec {
             (10 as short) == ct.s
             true == ct.bool
             10 == ct.i
    -        new URL("http://google.com") == ct.url
    +        new URL("https://google.com") == ct.url
             now.time == ct.date.time
             cal == ct.c
             1.0 == ct.bd
    diff --git a/grails-datamapping-validation/build.gradle b/grails-datamapping-validation/build.gradle
    index 544cf7dc745..2fda22fea9e 100644
    --- a/grails-datamapping-validation/build.gradle
    +++ b/grails-datamapping-validation/build.gradle
    @@ -89,5 +89,6 @@ apply {
         from rootProject.layout.projectDirectory.file('gradle/test-config.gradle')
         from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle')
         from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle')
    +    from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle')
     }
     
    diff --git a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/CascadingValidator.java b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/CascadingValidator.java
    index 2a010e93023..69335bb5f31 100644
    --- a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/CascadingValidator.java
    +++ b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/CascadingValidator.java
    @@ -31,10 +31,9 @@ public interface CascadingValidator extends Validator {
          * An extended version of the validate(errors,obj) method that takes an additional argument specifying whether
          * the Validator should cascade into associations or not.
          *
    -     * @param obj The Object to validate
    -     * @param errors The Spring Errors instance
    +     * @param obj     The Object to validate
    +     * @param errors  The Spring Errors instance
          * @param cascade True if validation should cascade into associations
    -     *
          * @see org.springframework.validation.Errors
          * @see org.springframework.validation.Validator
          * @see org.springframework.validation.Validator#validate(Object, org.springframework.validation.Errors)
    diff --git a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/ConstrainedProperty.groovy b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/ConstrainedProperty.groovy
    index 9ec58ebdf4c..5534b4ffd45 100644
    --- a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/ConstrainedProperty.groovy
    +++ b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/ConstrainedProperty.groovy
    @@ -32,7 +32,6 @@ import org.springframework.validation.Errors
     @CompileStatic
     interface ConstrainedProperty extends Constrained {
     
    -
         ResourceBundle MESSAGE_BUNDLE = ResourceBundle.getBundle("grails.gorm.validation.DefaultErrorMessages")
     
         String DEFAULT_NULL_MESSAGE_CODE = "default.null.message"
    @@ -66,24 +65,26 @@ interface ConstrainedProperty extends Constrained {
         String DEFAULT_NULL_MESSAGE = MESSAGE_BUNDLE.getString(DEFAULT_NULL_MESSAGE_CODE)
         String DEFAULT_INVALID_VALIDATOR_MESSAGE = MESSAGE_BUNDLE.getString(DEFAULT_INVALID_VALIDATOR_MESSAGE_CODE)
     
    -    Map DEFAULT_MESSAGES = new HashMap() {{
    -        put(DEFAULT_BLANK_MESSAGE_CODE,DEFAULT_BLANK_MESSAGE)
    -        put(DEFAULT_DOESNT_MATCH_MESSAGE_CODE,DEFAULT_DOESNT_MATCH_MESSAGE)
    -        put(DEFAULT_INVALID_CREDIT_CARD_MESSAGE_CODE,DEFAULT_INVALID_CREDIT_CARD_MESSAGE)
    -        put(DEFAULT_INVALID_EMAIL_MESSAGE_CODE,DEFAULT_INVALID_EMAIL_MESSAGE)
    -        put(DEFAULT_INVALID_MAX_MESSAGE_CODE,DEFAULT_INVALID_MAX_MESSAGE)
    -        put(DEFAULT_INVALID_MAX_SIZE_MESSAGE_CODE,DEFAULT_INVALID_MAX_SIZE_MESSAGE)
    -        put(DEFAULT_INVALID_MIN_MESSAGE_CODE,DEFAULT_INVALID_MIN_MESSAGE)
    -        put(DEFAULT_INVALID_MIN_SIZE_MESSAGE_CODE,DEFAULT_INVALID_MIN_SIZE_MESSAGE)
    -        put(DEFAULT_INVALID_RANGE_MESSAGE_CODE,DEFAULT_INVALID_RANGE_MESSAGE)
    -        put(DEFAULT_INVALID_SIZE_MESSAGE_CODE,DEFAULT_INVALID_SIZE_MESSAGE)
    -        put(DEFAULT_INVALID_URL_MESSAGE_CODE,DEFAULT_INVALID_URL_MESSAGE)
    -        put(DEFAULT_NOT_EQUAL_MESSAGE_CODE,DEFAULT_NOT_EQUAL_MESSAGE)
    -        put(DEFAULT_NOT_INLIST_MESSAGE_CODE,DEFAULT_NOT_IN_LIST_MESSAGE)
    -        put(DEFAULT_NULL_MESSAGE_CODE,DEFAULT_NULL_MESSAGE)
    -        put(DEFAULT_INVALID_VALIDATOR_MESSAGE_CODE, DEFAULT_INVALID_VALIDATOR_MESSAGE)
    -    }}
    -
    +    Map DEFAULT_MESSAGES = new HashMap() {
    +
    +        {
    +            put(DEFAULT_BLANK_MESSAGE_CODE, DEFAULT_BLANK_MESSAGE)
    +            put(DEFAULT_DOESNT_MATCH_MESSAGE_CODE, DEFAULT_DOESNT_MATCH_MESSAGE)
    +            put(DEFAULT_INVALID_CREDIT_CARD_MESSAGE_CODE, DEFAULT_INVALID_CREDIT_CARD_MESSAGE)
    +            put(DEFAULT_INVALID_EMAIL_MESSAGE_CODE, DEFAULT_INVALID_EMAIL_MESSAGE)
    +            put(DEFAULT_INVALID_MAX_MESSAGE_CODE, DEFAULT_INVALID_MAX_MESSAGE)
    +            put(DEFAULT_INVALID_MAX_SIZE_MESSAGE_CODE, DEFAULT_INVALID_MAX_SIZE_MESSAGE)
    +            put(DEFAULT_INVALID_MIN_MESSAGE_CODE, DEFAULT_INVALID_MIN_MESSAGE)
    +            put(DEFAULT_INVALID_MIN_SIZE_MESSAGE_CODE, DEFAULT_INVALID_MIN_SIZE_MESSAGE)
    +            put(DEFAULT_INVALID_RANGE_MESSAGE_CODE, DEFAULT_INVALID_RANGE_MESSAGE)
    +            put(DEFAULT_INVALID_SIZE_MESSAGE_CODE, DEFAULT_INVALID_SIZE_MESSAGE)
    +            put(DEFAULT_INVALID_URL_MESSAGE_CODE, DEFAULT_INVALID_URL_MESSAGE)
    +            put(DEFAULT_NOT_EQUAL_MESSAGE_CODE, DEFAULT_NOT_EQUAL_MESSAGE)
    +            put(DEFAULT_NOT_INLIST_MESSAGE_CODE, DEFAULT_NOT_IN_LIST_MESSAGE)
    +            put(DEFAULT_NULL_MESSAGE_CODE, DEFAULT_NULL_MESSAGE)
    +            put(DEFAULT_INVALID_VALIDATOR_MESSAGE_CODE, DEFAULT_INVALID_VALIDATOR_MESSAGE)
    +        }
    +    }
     
         String CREDIT_CARD_CONSTRAINT = "creditCard"
         String EMAIL_CONSTRAINT = "email"
    @@ -144,7 +145,6 @@ interface ConstrainedProperty extends Constrained {
          */
         void applyConstraint(String constraintName, Object constrainingValue)
     
    -
         /**
          * @return Returns the appliedConstraints.
          */
    diff --git a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/Constraint.java b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/Constraint.java
    index c2ddaa8707a..68d5e56a5ea 100644
    --- a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/Constraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/Constraint.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package grails.gorm.validation;
     
     import org.springframework.validation.Errors;
    @@ -36,7 +35,7 @@ public interface Constraint {
          * @return true if the constraint can be applied against the specified type
          */
         @SuppressWarnings("rawtypes")
    -    boolean  supports(Class type);
    +    boolean supports(Class type);
     
         /**
          * Return whether the constraint is valid for the owning class
    @@ -51,11 +50,10 @@ public interface Constraint {
          *
          * @param target
          * @param propertyValue The property value to validate
    -     * @param errors The errors instance to record errors against
    +     * @param errors        The errors instance to record errors against
          */
         void validate(Object target, Object propertyValue, Errors errors);
     
    -
         /**
          * @return The parameter to the constraint
          */
    @@ -71,4 +69,4 @@ public interface Constraint {
          */
         String getPropertyName();
     
    -}
    \ No newline at end of file
    +}
    diff --git a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/DefaultConstrainedProperty.groovy b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/DefaultConstrainedProperty.groovy
    index 78c58ce655e..f9fa3ce1dfb 100644
    --- a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/DefaultConstrainedProperty.groovy
    +++ b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/DefaultConstrainedProperty.groovy
    @@ -111,8 +111,6 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
     
         }
     
    -
    -
         /**
          * @return Returns the appliedConstraints.
          */
    @@ -147,8 +145,8 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
         Comparable getMax() {
             Comparable maxValue = null
     
    -        MaxConstraint maxConstraint = (MaxConstraint)appliedConstraints.get(MAX_CONSTRAINT)
    -        RangeConstraint rangeConstraint = (RangeConstraint)appliedConstraints.get(RANGE_CONSTRAINT)
    +        MaxConstraint maxConstraint = (MaxConstraint) appliedConstraints.get(MAX_CONSTRAINT)
    +        RangeConstraint rangeConstraint = (RangeConstraint) appliedConstraints.get(RANGE_CONSTRAINT)
     
             if (maxConstraint != null || rangeConstraint != null) {
                 Comparable maxConstraintValue = maxConstraint == null ? null : maxConstraint.getMaxValue()
    @@ -156,11 +154,9 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
     
                 if (maxConstraintValue != null && rangeConstraintHighValue != null) {
                     maxValue = (maxConstraintValue.compareTo(rangeConstraintHighValue) < 0) ? maxConstraintValue : rangeConstraintHighValue
    -            }
    -            else if (maxConstraintValue == null && rangeConstraintHighValue != null) {
    +            } else if (maxConstraintValue == null && rangeConstraintHighValue != null) {
                     maxValue = rangeConstraintHighValue
    -            }
    -            else if (maxConstraintValue != null && rangeConstraintHighValue == null) {
    +            } else if (maxConstraintValue != null && rangeConstraintHighValue == null) {
                     maxValue = maxConstraintValue
                 }
             }
    @@ -180,7 +176,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
             }
     
             if (!propertyType.equals(max.getClass())) {
    -            throw new MissingPropertyException(constraintName,propertyType)
    +            throw new MissingPropertyException(constraintName, propertyType)
             }
     
             Range r = getRange()
    @@ -199,8 +195,8 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
         Comparable getMin() {
             Comparable minValue = null
     
    -        MinConstraint minConstraint = (MinConstraint)appliedConstraints.get(MIN_CONSTRAINT)
    -        RangeConstraint rangeConstraint = (RangeConstraint)appliedConstraints.get(RANGE_CONSTRAINT)
    +        MinConstraint minConstraint = (MinConstraint) appliedConstraints.get(MIN_CONSTRAINT)
    +        RangeConstraint rangeConstraint = (RangeConstraint) appliedConstraints.get(RANGE_CONSTRAINT)
     
             if (minConstraint != null || rangeConstraint != null) {
                 Comparable minConstraintValue = minConstraint != null ? minConstraint.getMinValue() : null
    @@ -208,11 +204,9 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
     
                 if (minConstraintValue != null && rangeConstraintLowValue != null) {
                     minValue = (minConstraintValue.compareTo(rangeConstraintLowValue) > 0) ? minConstraintValue : rangeConstraintLowValue
    -            }
    -            else if (minConstraintValue == null && rangeConstraintLowValue != null) {
    +            } else if (minConstraintValue == null && rangeConstraintLowValue != null) {
                     minValue = rangeConstraintLowValue
    -            }
    -            else if (minConstraintValue != null && rangeConstraintLowValue == null) {
    +            } else if (minConstraintValue != null && rangeConstraintLowValue == null) {
                     minValue = minConstraintValue
                 }
             }
    @@ -231,12 +225,12 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
             }
     
             if (!propertyType.equals(min.getClass())) {
    -            throw new MissingPropertyException(MIN_CONSTRAINT,propertyType)
    +            throw new MissingPropertyException(MIN_CONSTRAINT, propertyType)
             }
     
             Range r = getRange()
             if (r != null) {
    -            log.warn("Range constraint already set ignoring constraint ["+MIN_CONSTRAINT+"] for value ["+min+"]")
    +            log.warn("Range constraint already set ignoring constraint [" + MIN_CONSTRAINT + "] for value [" + min + "]")
                 return
             }
     
    @@ -249,7 +243,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
         @Override
         @SuppressWarnings("rawtypes")
         List getInList() {
    -        InListConstraint c = (InListConstraint)appliedConstraints.get(IN_LIST_CONSTRAINT)
    +        InListConstraint c = (InListConstraint) appliedConstraints.get(IN_LIST_CONSTRAINT)
             return c == null ? null : c.getList()
         }
     
    @@ -261,8 +255,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
             Constraint c = appliedConstraints.get(IN_LIST_CONSTRAINT)
             if (inList == null) {
                 appliedConstraints.remove(IN_LIST_CONSTRAINT)
    -        }
    -        else {
    +        } else {
                 applyConstraintInternal(IN_LIST_CONSTRAINT, inList)
             }
         }
    @@ -273,7 +266,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
         @Override
         @SuppressWarnings("rawtypes")
         Range getRange() {
    -        RangeConstraint c = (RangeConstraint)appliedConstraints.get(RANGE_CONSTRAINT)
    +        RangeConstraint c = (RangeConstraint) appliedConstraints.get(RANGE_CONSTRAINT)
             return c == null ? null : c.getRange()
         }
     
    @@ -283,17 +276,16 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
         @SuppressWarnings("rawtypes")
         void setRange(Range range) {
             if (appliedConstraints.containsKey(MAX_CONSTRAINT)) {
    -            log.warn("Setting range constraint on property ["+propertyName+"] of class ["+ this.owningClass +"] forced removal of max constraint")
    +            log.warn("Setting range constraint on property [" + propertyName + "] of class [" + this.owningClass + "] forced removal of max constraint")
                 appliedConstraints.remove(MAX_CONSTRAINT)
             }
             if (appliedConstraints.containsKey(MIN_CONSTRAINT)) {
    -            log.warn("Setting range constraint on property ["+propertyName+"] of class ["+ this.owningClass +"] forced removal of min constraint")
    +            log.warn("Setting range constraint on property [" + propertyName + "] of class [" + this.owningClass + "] forced removal of min constraint")
                 appliedConstraints.remove(MIN_CONSTRAINT)
             }
             if (range == null) {
                 appliedConstraints.remove(RANGE_CONSTRAINT)
    -        }
    -        else {
    +        } else {
                 applyConstraintInternal(RANGE_CONSTRAINT, range)
             }
         }
    @@ -303,7 +295,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
          */
         @Override
         Integer getScale() {
    -        ScaleConstraint scaleConstraint = (ScaleConstraint)appliedConstraints.get(SCALE_CONSTRAINT)
    +        ScaleConstraint scaleConstraint = (ScaleConstraint) appliedConstraints.get(SCALE_CONSTRAINT)
             return scaleConstraint == null ? null : scaleConstraint.getScale()
         }
     
    @@ -313,7 +305,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
         @Override
         @SuppressWarnings("rawtypes")
         Range getSize() {
    -        SizeConstraint c = (SizeConstraint)appliedConstraints.get(SIZE_CONSTRAINT)
    +        SizeConstraint c = (SizeConstraint) appliedConstraints.get(SIZE_CONSTRAINT)
             return c == null ? null : c.getRange()
         }
     
    @@ -325,8 +317,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
             Constraint c = appliedConstraints.get(SIZE_CONSTRAINT)
             if (size == null) {
                 appliedConstraints.remove(SIZE_CONSTRAINT)
    -        }
    -        else {
    +        } else {
                 applyConstraintInternal(SIZE_CONSTRAINT, size)
             }
         }
    @@ -337,7 +328,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
         @Override
         boolean isBlank() {
             Object cons = appliedConstraints.get(BLANK_CONSTRAINT)
    -        return cons == null || (Boolean)((BlankConstraint)cons).getParameter()
    +        return cons == null || (Boolean) ((BlankConstraint) cons).getParameter()
         }
     
         /**
    @@ -351,8 +342,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
     
             if (!blank) {
                 applyConstraintInternal(BLANK_CONSTRAINT, blank)
    -        }
    -        else {
    +        } else {
                 appliedConstraints.remove(BLANK_CONSTRAINT)
             }
         }
    @@ -382,8 +372,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
             Constraint c = appliedConstraints.get(EMAIL_CONSTRAINT)
             if (email) {
                 applyConstraintInternal(EMAIL_CONSTRAINT, email)
    -        }
    -        else {
    +        } else {
                 if (c != null) {
                     appliedConstraints.remove(EMAIL_CONSTRAINT)
                 }
    @@ -419,8 +408,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
             Constraint c = appliedConstraints.get(CREDIT_CARD_CONSTRAINT)
             if (creditCard) {
                 applyConstraintInternal(CREDIT_CARD_CONSTRAINT, creditCard)
    -        }
    -        else {
    +        } else {
                 if (c != null) {
                     appliedConstraints.remove(CREDIT_CARD_CONSTRAINT)
                 }
    @@ -436,7 +424,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
                 throw new MissingPropertyException("Matches constraint only applies to a String property",
                         MATCHES_CONSTRAINT, this.owningClass)
             }
    -        MatchesConstraint c = (MatchesConstraint)appliedConstraints.get(MATCHES_CONSTRAINT)
    +        MatchesConstraint c = (MatchesConstraint) appliedConstraints.get(MATCHES_CONSTRAINT)
             return c == null ? null : c.regex
         }
     
    @@ -451,8 +439,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
     
             if (regex == null) {
                 appliedConstraints.remove(MATCHES_CONSTRAINT)
    -        }
    -        else {
    +        } else {
                 applyConstraintInternal(MATCHES_CONSTRAINT, regex)
             }
         }
    @@ -462,7 +449,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
          */
         @Override
         Object getNotEqual() {
    -        NotEqualConstraint c = (NotEqualConstraint)appliedConstraints.get(NOT_EQUAL_CONSTRAINT)
    +        NotEqualConstraint c = (NotEqualConstraint) appliedConstraints.get(NOT_EQUAL_CONSTRAINT)
             return c == null ? null : c.getNotEqualTo()
         }
     
    @@ -473,8 +460,8 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
         Integer getMaxSize() {
             Integer maxSize = null
     
    -        MaxSizeConstraint maxSizeConstraint = (MaxSizeConstraint)appliedConstraints.get(MAX_SIZE_CONSTRAINT)
    -        SizeConstraint sizeConstraint = (SizeConstraint)appliedConstraints.get(SIZE_CONSTRAINT)
    +        MaxSizeConstraint maxSizeConstraint = (MaxSizeConstraint) appliedConstraints.get(MAX_SIZE_CONSTRAINT)
    +        SizeConstraint sizeConstraint = (SizeConstraint) appliedConstraints.get(SIZE_CONSTRAINT)
     
             if (maxSizeConstraint != null || sizeConstraint != null) {
                 int maxSizeConstraintValue = maxSizeConstraint == null ? Integer.MAX_VALUE : maxSizeConstraint.getMaxSize()
    @@ -499,8 +486,8 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
         Integer getMinSize() {
             Integer minSize = null
     
    -        MinSizeConstraint minSizeConstraint = (MinSizeConstraint)appliedConstraints.get(MIN_SIZE_CONSTRAINT)
    -        SizeConstraint sizeConstraint = (SizeConstraint)appliedConstraints.get(SIZE_CONSTRAINT)
    +        MinSizeConstraint minSizeConstraint = (MinSizeConstraint) appliedConstraints.get(MIN_SIZE_CONSTRAINT)
    +        SizeConstraint sizeConstraint = (SizeConstraint) appliedConstraints.get(SIZE_CONSTRAINT)
     
             if (minSizeConstraint != null || sizeConstraint != null) {
                 int minSizeConstraintValue = minSizeConstraint == null ? Integer.MIN_VALUE : minSizeConstraint.getMinSize()
    @@ -525,8 +512,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
         void setNotEqual(Object notEqual) {
             if (notEqual == null) {
                 appliedConstraints.remove(NOT_EQUAL_CONSTRAINT)
    -        }
    -        else {
    +        } else {
                 applyConstraintInternal(NOT_EQUAL_CONSTRAINT, notEqual)
             }
         }
    @@ -537,7 +523,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
         @Override
         boolean isNullable() {
             if (appliedConstraints.containsKey(NULLABLE_CONSTRAINT)) {
    -            NullableConstraint nc = (NullableConstraint)appliedConstraints.get(NULLABLE_CONSTRAINT)
    +            NullableConstraint nc = (NullableConstraint) appliedConstraints.get(NULLABLE_CONSTRAINT)
                 return nc.isNullable()
             }
             return false
    @@ -562,20 +548,18 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
             return appliedConstraints.containsKey(URL_CONSTRAINT)
         }
     
    -
         /**
          * @param url The url to set.
          */
         void setUrl(boolean url) {
             if (isNotValidStringType()) {
    -            throw new MissingPropertyException("URL constraint can only be applied to a String property",URL_CONSTRAINT, this.owningClass)
    +            throw new MissingPropertyException("URL constraint can only be applied to a String property", URL_CONSTRAINT, this.owningClass)
             }
     
             Constraint c = appliedConstraints.get(URL_CONSTRAINT)
             if (url) {
                 applyConstraintInternal(URL_CONSTRAINT, url)
    -        }
    -        else {
    +        } else {
                 if (c != null) {
                     appliedConstraints.remove(URL_CONSTRAINT)
                 }
    @@ -587,7 +571,6 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
             return attributes
         }
     
    -
         @SuppressWarnings("rawtypes")
         void setAttributes(Map attributes) {
             this.attributes = attributes
    @@ -606,11 +589,10 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
             for (Constraint c in appliedConstraints.values()) {
                 if (c instanceof VetoingConstraint) {
                     // stop validation process when constraint vetoes
    -                if (((VetoingConstraint)c).validateWithVetoing(target, propertyValue, errors)) {
    +                if (((VetoingConstraint) c).validateWithVetoing(target, propertyValue, errors)) {
                         return
                     }
    -            }
    -            else {
    +            } else {
                     delayedConstraints.add(c)
                 }
             }
    @@ -637,8 +619,8 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
     
             try {
     
    -            for(ConstraintFactory cf in constraintFactories) {
    -                if(cf.supports(propertyType)) {
    +            for (ConstraintFactory cf in constraintFactories) {
    +                if (cf.supports(propertyType)) {
                         return true
                     }
                 }
    @@ -664,8 +646,7 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
             if (!constraintFactories.isEmpty()) {
                 if (constrainingValue == null) {
                     appliedConstraints.remove(constraintName)
    -            }
    -            else {
    +            } else {
                     try {
                         Constraint c = instantiateConstraint(constraintName, constrainingValue, true)
                         if (c != null) {
    @@ -676,11 +657,9 @@ class DefaultConstrainedProperty implements ConstrainedProperty {
                         throw new ValidationConfigurationException("Exception thrown applying constraint [$constraintName] to class [$owningClass] for value [$constrainingValue]: ${e.message}", e)
                     }
                 }
    -        }
    -        else if (hasProperty(constraintName)) {
    -            ((GroovyObject)this).setProperty(constraintName, constrainingValue)
    -        }
    -        else {
    +        } else if (hasProperty(constraintName)) {
    +            ((GroovyObject) this).setProperty(constraintName, constrainingValue)
    +        } else {
                 throw new ValidationConfigurationException("Constraint [$constraintName] is not supported for property [$propertyName] of class [$owningClass] with type [$propertyType]")
             }
         }
    diff --git a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/PersistentEntityValidator.groovy b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/PersistentEntityValidator.groovy
    index ee8b41a5e5a..f712b52c526 100644
    --- a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/PersistentEntityValidator.groovy
    +++ b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/PersistentEntityValidator.groovy
    @@ -32,7 +32,6 @@ import org.grails.datastore.mapping.model.types.ToMany
     import org.grails.datastore.mapping.model.types.ToOne
     import org.grails.datastore.mapping.proxy.ProxyHandler
     import org.grails.datastore.mapping.reflect.EntityReflector
    -import org.grails.datastore.mapping.reflect.ReflectionUtils
     import org.springframework.context.MessageSource
     import org.springframework.validation.Errors
     import org.springframework.validation.FieldError
    @@ -47,8 +46,8 @@ import org.springframework.validation.FieldError
     class PersistentEntityValidator implements CascadingValidator, ConstrainedEntity {
     
         private static final List EMBEDDED_EXCLUDES = Arrays.asList(
    -                                                            GormProperties.IDENTITY,
    -                                                            GormProperties.VERSION)
    +            GormProperties.IDENTITY,
    +            GormProperties.VERSION)
     
         final PersistentEntity entity
         final EntityReflector entityReflector
    @@ -69,7 +68,7 @@ class PersistentEntityValidator implements CascadingValidator, ConstrainedEntity
     
             def evaluated = constraintsEvaluator.evaluate(targetClass)
             this.constrainedProperties = Collections.unmodifiableMap(evaluated)
    -        if(constrainedProperties == null) {
    +        if (constrainedProperties == null) {
                 throw new IllegalStateException("Constraint evaluator returned null for class: $targetClass")
             }
         }
    @@ -86,18 +85,18 @@ class PersistentEntityValidator implements CascadingValidator, ConstrainedEntity
             def validatedObjects = new HashSet()
             validatedObjects.add(obj)
     
    -        for(PersistentProperty pp in entity.persistentProperties) {
    +        for (PersistentProperty pp in entity.persistentProperties) {
                 def propertyName = pp.name
     
                 ConstrainedProperty constrainedProperty = constrainedProperties.get(propertyName)
     
    -            if(constrainedProperty != null) {
    +            if (constrainedProperty != null) {
                     validatePropertyWithConstraint(obj, propertyName, entityReflector, errors, constrainedProperty, pp)
                 }
     
    -            if(pp instanceof Association) {
    -                Association association = (Association)pp
    -                if(cascade) {
    +            if (pp instanceof Association) {
    +                Association association = (Association) pp
    +                if (cascade) {
                         cascadeToAssociativeProperty(obj, errors, entityReflector, association, validatedObjects)
                     }
                 }
    @@ -105,9 +104,9 @@ class PersistentEntityValidator implements CascadingValidator, ConstrainedEntity
                 constrainedPropertyNames.remove(propertyName)
             }
     
    -        for(String remainingProperty in constrainedPropertyNames) {
    +        for (String remainingProperty in constrainedPropertyNames) {
                 ConstrainedProperty constrainedProperty = constrainedProperties.get(remainingProperty)
    -            if(remainingProperty != null) {
    +            if (remainingProperty != null) {
                     validatePropertyWithConstraint(obj, remainingProperty, entityReflector, errors, constrainedProperty, null)
                 }
             }
    @@ -121,7 +120,7 @@ class PersistentEntityValidator implements CascadingValidator, ConstrainedEntity
          * @param bean The original bean
          * @param association The associative property
          */
    -    protected void cascadeToAssociativeProperty(Object parent, Errors errors, EntityReflector reflector, Association association, Set validatedObjects ) {
    +    protected void cascadeToAssociativeProperty(Object parent, Errors errors, EntityReflector reflector, Association association, Set validatedObjects) {
             String propertyName = association.getName()
             if (errors.hasFieldErrors(propertyName)) {
                 return
    @@ -130,23 +129,21 @@ class PersistentEntityValidator implements CascadingValidator, ConstrainedEntity
             if (association instanceof ToOne) {
                 Object associatedObject = reflector.getProperty(parent, propertyName)
     
    -            if(associatedObject != null && proxyHandler?.isInitialized(associatedObject)) {
    -                if(association.doesCascadeValidate(associatedObject)) {
    -                    cascadeValidationToOne(parent, propertyName, (ToOne)association, errors, reflector, associatedObject, null, validatedObjects)
    -                }
    -                else {
    +            if (associatedObject != null && proxyHandler?.isInitialized(associatedObject)) {
    +                if (association.doesCascadeValidate(associatedObject)) {
    +                    cascadeValidationToOne(parent, propertyName, (ToOne) association, errors, reflector, associatedObject, null, validatedObjects)
    +                } else {
                         Errors existingErrors = retrieveErrors(associatedObject)
    -                    if(existingErrors != null && existingErrors.hasErrors()) {
    -                        for(error in existingErrors.fieldErrors) {
    -                            String path = "${propertyName}." +error.field
    +                    if (existingErrors != null && existingErrors.hasErrors()) {
    +                        for (error in existingErrors.fieldErrors) {
    +                            String path = "${propertyName}." + error.field
                                 errors.rejectValue(path, error.code, error.arguments, error.defaultMessage)
                             }
                         }
                     }
                 }
    -        }
    -        else if (association instanceof ToMany) {
    -            if(association.doesCascadeValidate(null)) {
    +        } else if (association instanceof ToMany) {
    +            if (association.doesCascadeValidate(null)) {
                     cascadeValidationToMany(parent, propertyName, association, errors, reflector, validatedObjects)
                 }
             }
    @@ -171,23 +168,21 @@ class PersistentEntityValidator implements CascadingValidator, ConstrainedEntity
         protected void cascadeValidationToMany(Object parentObject, String propertyName, Association association, Errors errors, EntityReflector entityReflector, Set validatedObjects) {
     
             Object collection = entityReflector.getProperty(parentObject, propertyName)
    -        if(collection == null || !proxyHandler?.isInitialized(collection)) {
    +        if (collection == null || !proxyHandler?.isInitialized(collection)) {
                 return
             }
     
             if (collection instanceof List || collection instanceof SortedSet) {
                 int idx = 0
    -            for (Object associatedObject : ((Collection)collection)) {
    -                cascadeValidationToOne(parentObject, propertyName, association, errors, entityReflector,associatedObject, idx++, validatedObjects)
    +            for (Object associatedObject : ((Collection) collection)) {
    +                cascadeValidationToOne(parentObject, propertyName, association, errors, entityReflector, associatedObject, idx++, validatedObjects)
                 }
    -        }
    -        else if (collection instanceof Collection) {
    +        } else if (collection instanceof Collection) {
                 Integer index = 0
    -            for (Object associatedObject : ((Collection)collection)) {
    -                cascadeValidationToOne(parentObject, propertyName, association, errors, entityReflector,associatedObject, index++, validatedObjects)
    +            for (Object associatedObject : ((Collection) collection)) {
    +                cascadeValidationToOne(parentObject, propertyName, association, errors, entityReflector, associatedObject, index++, validatedObjects)
                 }
    -        }
    -        else if (collection instanceof Map) {
    +        } else if (collection instanceof Map) {
     
                 for (Object entryObject in ((Map) collection).entrySet()) {
                     Map.Entry entry = (Map.Entry) entryObject
    @@ -212,7 +207,7 @@ class PersistentEntityValidator implements CascadingValidator, ConstrainedEntity
                 return
             }
     
    -        if(validatedObjects.contains(associatedObject)) {
    +        if (validatedObjects.contains(associatedObject)) {
                 return
             }
     
    @@ -239,11 +234,10 @@ class PersistentEntityValidator implements CascadingValidator, ConstrainedEntity
             Map associatedConstrainedProperties
     
             def validator = mappingContext.getEntityValidator(associatedEntity)
    -        if(validator instanceof PersistentEntityValidator) {
    -            associatedConstrainedProperties = ((PersistentEntityValidator)validator).getConstrainedProperties()
    -        }
    -        else {
    -            associatedConstrainedProperties = Collections.emptyMap()
    +        if (validator instanceof PersistentEntityValidator) {
    +            associatedConstrainedProperties = ((PersistentEntityValidator) validator).getConstrainedProperties()
    +        } else {
    +            associatedConstrainedProperties = Collections. emptyMap()
             }
     
             // Invoke any beforeValidate callbacks on the associated object before validating
    @@ -271,18 +265,18 @@ class PersistentEntityValidator implements CascadingValidator, ConstrainedEntity
                     }
     
                     if (associatedPersistentProperty instanceof Association) {
    -                    if(association.isBidirectional() && associatedPersistentProperty == association.inverseSide) {
    +                    if (association.isBidirectional() && associatedPersistentProperty == association.inverseSide) {
                             // If this property is the inverse side of the currently processed association then
                             // we don't want to process it
                             continue
                         }
     
                         cascadeToAssociativeProperty(
    -                        associatedObject,
    -                        errors,
    -                        associatedReflector,
    -                        (Association)associatedPersistentProperty,
    -                        validatedObjects)
    +                            associatedObject,
    +                            errors,
    +                            associatedReflector,
    +                            (Association) associatedPersistentProperty,
    +                            validatedObjects)
                     }
                 }
             }
    @@ -314,22 +308,21 @@ class PersistentEntityValidator implements CascadingValidator, ConstrainedEntity
             String constrainedPropertyName
             if (i > -1) {
                 constrainedPropertyName = propertyName.substring(i + 1, propertyName.length())
    -        }
    -        else {
    +        } else {
                 constrainedPropertyName = propertyName
             }
             FieldError fieldError = errors.getFieldError(constrainedPropertyName)
             if (fieldError == null) {
    -            if(persistentProperty != null) {
    +            if (persistentProperty != null) {
                     constrainedProperty.validate(obj, reflector.getProperty(obj, constrainedPropertyName), errors)
    -            }
    -            else {
    -                if(obj instanceof GroovyObject) {
    -                    constrainedProperty.validate(obj, ((GroovyObject)obj).getProperty(constrainedPropertyName), errors)
    +            } else {
    +                if (obj instanceof GroovyObject) {
    +                    constrainedProperty.validate(obj, ((GroovyObject) obj).getProperty(constrainedPropertyName), errors)
                     }
                 }
             }
         }
    +
         @Override
         boolean supports(Class clazz) {
             return targetClass.is(clazz)
    diff --git a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/VetoingConstraint.java b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/VetoingConstraint.java
    index ce6343f4a60..615bb052978 100644
    --- a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/VetoingConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/VetoingConstraint.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package grails.gorm.validation;
     
     import org.springframework.validation.Errors;
    @@ -38,9 +37,9 @@ public interface VetoingConstraint extends Constraint {
         /**
          * Invoke validation with vetoing capabilities
          *
    -     * @param target The target to validate
    +     * @param target        The target to validate
          * @param propertyValue The property value
    -     * @param errors The errors object
    +     * @param errors        The errors object
          * @return True if it valides
          */
         boolean validateWithVetoing(Object target, Object propertyValue, Errors errors);
    diff --git a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/exceptions/ValidationConfigurationException.groovy b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/exceptions/ValidationConfigurationException.groovy
    index 3bc76fd254a..1e8aaa79ae7 100644
    --- a/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/exceptions/ValidationConfigurationException.groovy
    +++ b/grails-datamapping-validation/src/main/groovy/grails/gorm/validation/exceptions/ValidationConfigurationException.groovy
    @@ -20,7 +20,6 @@
     package grails.gorm.validation.exceptions
     
     import groovy.transform.CompileStatic
    -import groovy.transform.InheritConstructors
     
     /**
      * An exception thrown when there is an error configuration validation
    @@ -30,6 +29,7 @@ import groovy.transform.InheritConstructors
      */
     @CompileStatic
     class ValidationConfigurationException extends RuntimeException {
    +
         ValidationConfigurationException(String var1) {
             super(var1)
         }
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/support/BeforeValidateHelper.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/support/BeforeValidateHelper.java
    index fc04a8aa256..a2ad75c814f 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/support/BeforeValidateHelper.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/support/BeforeValidateHelper.java
    @@ -28,44 +28,46 @@
     import java.util.concurrent.ConcurrentHashMap;
     
     public class BeforeValidateHelper implements Serializable {
    +
         public static final String BEFORE_VALIDATE = "beforeValidate";
         private transient Map, BeforeValidateEventTriggerCaller> eventTriggerCallerCache = new ConcurrentHashMap, BeforeValidateEventTriggerCaller>();
    -    
    +
    +    public void invokeBeforeValidate(final Object target, final List validatedFieldsList) {
    +        Class domainClass = target.getClass();
    +        BeforeValidateEventTriggerCaller eventTriggerCaller = eventTriggerCallerCache.get(domainClass);
    +        if (eventTriggerCaller == null) {
    +            eventTriggerCaller = new BeforeValidateEventTriggerCaller(domainClass, null);
    +            eventTriggerCallerCache.put(domainClass, eventTriggerCaller);
    +        }
    +        eventTriggerCaller.call(target, validatedFieldsList);
    +    }
    +
    +    // Ensure that the cache is re-initalized empty when deserialized
    +    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    +        in.defaultReadObject();
    +        eventTriggerCallerCache = new ConcurrentHashMap, BeforeValidateEventTriggerCaller>();
    +    }
    +
         public static final class BeforeValidateEventTriggerCaller {
    +
             EventTriggerCaller eventTriggerCaller;
             EventTriggerCaller eventTriggerCallerNoArgs;
    -        
    +
             public BeforeValidateEventTriggerCaller(Class domainClass, MetaClass metaClass) {
                 eventTriggerCaller = build(domainClass, metaClass, new Class[]{List.class});
                 eventTriggerCallerNoArgs = build(domainClass, metaClass, new Class[]{});
             }
    -        
    +
             protected EventTriggerCaller build(Class domainClass, MetaClass metaClass, Class[] argumentTypes) {
                 return EventTriggerCaller.buildCaller(BEFORE_VALIDATE, domainClass, metaClass, argumentTypes);
             }
    -        
    +
             public void call(final Object target, final List validatedFieldsList) {
    -            if(validatedFieldsList != null && eventTriggerCaller != null) {
    +            if (validatedFieldsList != null && eventTriggerCaller != null) {
                     eventTriggerCaller.call(target, new Object[]{validatedFieldsList});
                 } else if (eventTriggerCallerNoArgs != null) {
                     eventTriggerCallerNoArgs.call(target);
                 }
             }
         }
    -    
    -    public void invokeBeforeValidate(final Object target, final List validatedFieldsList) {
    -        Class domainClass = target.getClass();
    -        BeforeValidateEventTriggerCaller eventTriggerCaller = eventTriggerCallerCache.get(domainClass);
    -        if(eventTriggerCaller==null) {
    -            eventTriggerCaller = new BeforeValidateEventTriggerCaller(domainClass, null);
    -            eventTriggerCallerCache.put(domainClass, eventTriggerCaller);
    -        }
    -        eventTriggerCaller.call(target, validatedFieldsList);
    -    }
    -
    -    // Ensure that the cache is re-initalized empty when deserialized
    -    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    -        in.defaultReadObject();
    -        eventTriggerCallerCache = new ConcurrentHashMap, BeforeValidateEventTriggerCaller>();
    -    }
    -}
    \ No newline at end of file
    +}
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/support/EventTriggerCaller.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/support/EventTriggerCaller.java
    index e027acb6443..d5b962bb862 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/support/EventTriggerCaller.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/support/EventTriggerCaller.java
    @@ -16,46 +16,49 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.support;
     
    -import groovy.lang.*;
    +import groovy.lang.Closure;
    +import groovy.lang.GroovySystem;
    +import groovy.lang.MetaClass;
    +import groovy.lang.MetaMethod;
    +import groovy.lang.MetaProperty;
    +import org.apache.commons.logging.Log;
    +import org.apache.commons.logging.LogFactory;
    +import org.springframework.util.ReflectionUtils;
     
     import java.lang.reflect.Field;
     import java.lang.reflect.Method;
     import java.lang.reflect.Modifier;
     
    -import org.apache.commons.logging.Log;
    -import org.apache.commons.logging.LogFactory;
    -import org.springframework.util.ReflectionUtils;
    -
     public abstract class EventTriggerCaller {
    +
         private static final Log LOG = LogFactory.getLog(EventTriggerCaller.class);
         private static final Object[] EMPTY_ARRAY = {};
    -    private boolean invertBooleanReturnValue=true;
    -    private static final EventTriggerCaller noopCaller = new NoopCaller();
    -    
    +    private static final EventTriggerCaller NOOP_CALLER = new NoopCaller();
    +    private boolean invertBooleanReturnValue = true;
    +
         public static EventTriggerCaller buildCaller(String eventMethodName, Class clazz) {
             return buildCaller(eventMethodName, clazz, null, null);
         }
    -    
    +
         public static EventTriggerCaller buildCaller(String eventMethodName, Class clazz, MetaClass metaClass, Class[] preferredArgumentTypes) {
             EventTriggerCaller caller = resolveMethodCaller(eventMethodName, clazz, preferredArgumentTypes);
    -        if(caller==null) {
    -            caller=resolveFieldClosureCaller(eventMethodName, clazz);
    +        if (caller == null) {
    +            caller = resolveFieldClosureCaller(eventMethodName, clazz);
             }
    -        if(caller==null) {
    -            caller=resolveMetaClassCallers(eventMethodName, clazz, metaClass);
    +        if (caller == null) {
    +            caller = resolveMetaClassCallers(eventMethodName, clazz, metaClass);
             }
             return caller;
         }
     
         private static EventTriggerCaller resolveMetaClassCallers(String eventMethodName, Class clazz, MetaClass metaClass) {
    -        if(metaClass==null) {
    -            metaClass=GroovySystem.getMetaClassRegistry().getMetaClass(clazz);
    +        if (metaClass == null) {
    +            metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(clazz);
             }
             EventTriggerCaller caller = resolveMetaMethodCaller(eventMethodName, metaClass);
    -        if(caller==null) {
    +        if (caller == null) {
                 caller = resolveMetaPropertyClosureCaller(eventMethodName, metaClass);
             }
             return caller;
    @@ -90,8 +93,8 @@ private static EventTriggerCaller resolveMethodCaller(String eventMethodName, Cl
             Method method = ReflectionUtils.findMethod(clazz, eventMethodName, preferredArgumentTypes);
             if (method == null && preferredArgumentTypes != null) {
                 method = ReflectionUtils.findMethod(clazz, eventMethodName);
    -            if(method == null) {
    -                method = ReflectionUtils.findMethod(clazz, eventMethodName, (Class[])null);
    +            if (method == null) {
    +                method = ReflectionUtils.findMethod(clazz, eventMethodName, (Class[]) null);
                 }
             }
             if (method != null) {
    @@ -100,28 +103,28 @@ private static EventTriggerCaller resolveMethodCaller(String eventMethodName, Cl
             }
             return null;
         }
    -    
    +
         public static EventTriggerCaller wrapNullInNoopCaller(EventTriggerCaller caller) {
    -        return caller != null ? caller : noopCaller;
    +        return caller != null ? caller : NOOP_CALLER;
         }
    -    
    +
         public final boolean call(Object entity) {
             return call(entity, EMPTY_ARRAY);
         }
     
         public abstract boolean call(Object entity, Object[] argumentArray);
    -    
    +
         public boolean isNoOperationCaller() {
             return false;
         }
    -    
    +
         public boolean asBoolean() {
             return !isNoOperationCaller();
         }
     
         boolean resolveReturnValue(Object retval) {
             if (retval instanceof Boolean) {
    -            boolean returnValue = (Boolean)retval;
    +            boolean returnValue = (Boolean) retval;
                 return invertBooleanReturnValue ? !returnValue : returnValue;
             }
             return false;
    @@ -134,19 +137,21 @@ public boolean isInvertBooleanReturnValue() {
         public void setInvertBooleanReturnValue(boolean invertBooleanReturnValue) {
             this.invertBooleanReturnValue = invertBooleanReturnValue;
         }
    -    
    +
         private static class NoopCaller extends EventTriggerCaller {
    +
             @Override
             public boolean call(Object entity, Object[] argumentArray) {
                 return false;
             }
    -        
    +
             public boolean isNoOperationCaller() {
                 return true;
             }
         }
    -    
    +
         private static class MethodCaller extends EventTriggerCaller {
    +
             Method method;
             int numberOfParameters;
     
    @@ -158,8 +163,8 @@ private static class MethodCaller extends EventTriggerCaller {
             @Override
             public boolean call(Object entity, Object[] argumentArray) {
                 Object[] arguments = new Object[numberOfParameters];
    -            if(argumentArray != null) {
    -                for(int i=0;i < argumentArray.length && i < arguments.length;i++) {
    +            if (argumentArray != null) {
    +                for (int i = 0; i < argumentArray.length && i < arguments.length; i++) {
                         arguments[i] = argumentArray[i];
                     }
                 }
    @@ -169,6 +174,7 @@ public boolean call(Object entity, Object[] argumentArray) {
         }
     
         private static class MetaMethodCaller extends EventTriggerCaller {
    +
             MetaMethod method;
             int numberOfParameters;
     
    @@ -184,12 +190,13 @@ public boolean call(Object entity, Object[] argumentArray) {
             }
         }
     
    -    private static abstract class ClosureCaller extends EventTriggerCaller {
    +    private abstract static class ClosureCaller extends EventTriggerCaller {
    +
             boolean cloneFirst = false;
     
             Object callClosure(Object entity, Closure callable, Object[] argumentArray) {
                 if (cloneFirst) {
    -                callable = (Closure)callable.clone();
    +                callable = (Closure) callable.clone();
                 }
                 callable.setResolveStrategy(Closure.DELEGATE_FIRST);
                 callable.setDelegate(entity);
    @@ -198,6 +205,7 @@ Object callClosure(Object entity, Closure callable, Object[] argumentArray) {
         }
     
         private static class FieldClosureCaller extends ClosureCaller {
    +
             Field field;
     
             FieldClosureCaller(Field field) {
    @@ -219,6 +227,7 @@ public boolean call(Object entity, Object[] argumentArray) {
         }
     
         private static class MetaPropertyClosureCaller extends ClosureCaller {
    +
             MetaProperty metaProperty;
     
             MetaPropertyClosureCaller(MetaProperty metaProperty) {
    @@ -238,4 +247,4 @@ public boolean call(Object entity, Object[] argumentArray) {
                 return false;
             }
         }
    -}
    \ No newline at end of file
    +}
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/AbstractConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/AbstractConstraint.java
    index 80d4e396136..b001db3d71e 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/AbstractConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/AbstractConstraint.java
    @@ -16,15 +16,8 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
    -import java.beans.Introspector;
    -import java.util.Arrays;
    -import java.util.LinkedHashSet;
    -import java.util.Locale;
    -import java.util.Set;
    -
     import grails.gorm.validation.ConstrainedProperty;
     import grails.gorm.validation.Constraint;
     import org.springframework.beans.BeanWrapperImpl;
    @@ -37,6 +30,12 @@
     import org.springframework.validation.Errors;
     import org.springframework.validation.FieldError;
     
    +import java.beans.Introspector;
    +import java.util.Arrays;
    +import java.util.LinkedHashSet;
    +import java.util.Locale;
    +import java.util.Set;
    +
     /**
      * Abstract class for constraints to extend.
      *
    @@ -71,7 +70,6 @@ public AbstractConstraint(Class constraintOwningClass, String constraintPrope
          * Validate the parameter passed
          *
          * @param constraintParameter The parameter to validate
    -     *
          * @return The validated parameter
          */
         protected abstract Object validateParameter(Object constraintParameter);
    @@ -118,14 +116,14 @@ protected boolean skipBlankValues() {
         }
     
         public void rejectValue(Object target, Errors errors, String defaultMessageCode, Object[] args) {
    -        rejectValue(target, errors, defaultMessageCode, new String[] {}, args);
    +        rejectValue(target, errors, defaultMessageCode, new String[]{}, args);
         }
     
    -    public void rejectValue(Object target,Errors errors, String defaultMessageCode, String code, Object[] args) {
    -        rejectValue(target,errors, defaultMessageCode, new String[] {code}, args);
    +    public void rejectValue(Object target, Errors errors, String defaultMessageCode, String code, Object[] args) {
    +        rejectValue(target, errors, defaultMessageCode, new String[]{code}, args);
         }
     
    -    public void rejectValue(Object target,Errors errors, String defaultMessageCode, String[] codes, Object[] args) {
    +    public void rejectValue(Object target, Errors errors, String defaultMessageCode, String[] codes, Object[] args) {
             rejectValueWithDefaultMessage(target, errors, getDefaultMessage(defaultMessageCode), codes, args);
         }
     
    @@ -145,7 +143,7 @@ public void rejectValueWithDefaultMessage(Object target, Errors errors, String d
     
                     if (resolvedClassName.equals(fullClassName)) {
                         // try short version
    -                    classNameCode = classAsPropertyName+".label";
    +                    classNameCode = classAsPropertyName + ".label";
                         resolvedClassName = messageSource.getMessage(classNameCode, null, fullClassName, locale);
                     }
     
    @@ -154,7 +152,7 @@ public void rejectValueWithDefaultMessage(Object target, Errors errors, String d
                         args[1] = resolvedClassName;
                     }
     
    -                String propertyName = (String)args[0];
    +                String propertyName = (String) args[0];
                     String propertyNameCode = fullClassName + '.' + propertyName + ".label";
                     String resolvedPropertyName = messageSource.getMessage(propertyNameCode, null, propertyName, locale);
                     if (resolvedPropertyName.equals(propertyName)) {
    @@ -187,20 +185,18 @@ public void rejectValueWithDefaultMessage(Object target, Errors errors, String d
                     newCodes.toArray(new String[newCodes.size()]),
                     args,
                     defaultMessage);
    -        ((BindingResult)errors).addError(error);
    +        ((BindingResult) errors).addError(error);
         }
     
         private Object getPropertyValue(Errors errors, Object target) {
             try {
                 return errors.getFieldValue(constraintPropertyName);
    -        }
    -        catch (Exception nre) {
    +        } catch (Exception nre) {
                 int i = constraintPropertyName.lastIndexOf(".");
                 String propertyName;
                 if (i > -1) {
                     propertyName = constraintPropertyName.substring(i, constraintPropertyName.length());
    -            }
    -            else {
    +            } else {
                     propertyName = constraintPropertyName;
                 }
                 return new BeanWrapperImpl(target).getPropertyValue(propertyName);
    @@ -209,12 +205,12 @@ private Object getPropertyValue(Errors errors, Object target) {
     
         // For backward compatibility
         public void rejectValue(Object target, Errors errors, String code, String defaultMessage) {
    -        rejectValueWithDefaultMessage(target, errors, defaultMessage, new String[] {code}, null);
    +        rejectValueWithDefaultMessage(target, errors, defaultMessage, new String[]{code}, null);
         }
     
         // For backward compatibility
         public void rejectValue(Object target, Errors errors, String code, Object[] args, String defaultMessage) {
    -        rejectValueWithDefaultMessage(target, errors, defaultMessage, new String[] {code}, args);
    +        rejectValueWithDefaultMessage(target, errors, defaultMessage, new String[]{code}, args);
         }
     
         /**
    @@ -222,6 +218,7 @@ public void rejectValue(Object target, Errors errors, String code, Object[] args
          * current locale. Note that the string returned includes any
          * placeholders that the required message has - these must be
          * expanded by the caller if required.
    +     *
          * @param code The i18n message code to look up.
          * @return The message corresponding to the given code in the
          * current locale.
    @@ -233,8 +230,7 @@ protected String getDefaultMessage(String code) {
                 }
     
                 return ConstrainedProperty.DEFAULT_MESSAGES.get(code);
    -        }
    -        catch (Exception e) {
    +        } catch (Exception e) {
                 return ConstrainedProperty.DEFAULT_MESSAGES.get(code);
             }
         }
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/AbstractVetoingConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/AbstractVetoingConstraint.java
    index 8ec8641eaa0..59d29d60e65 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/AbstractVetoingConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/AbstractVetoingConstraint.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
     import grails.gorm.validation.VetoingConstraint;
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/BlankConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/BlankConstraint.java
    index fa96b0ef0e6..5828a6a28cc 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/BlankConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/BlankConstraint.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
     import grails.gorm.validation.ConstrainedProperty;
    @@ -79,7 +78,7 @@ protected boolean skipBlankValues() {
         @Override
         protected boolean processValidateWithVetoing(Object target, Object propertyValue, Errors errors) {
             if (!blank && propertyValue instanceof String && !StringUtils.hasText((CharSequence) propertyValue)) {
    -            Object[] args = new Object[] { constraintPropertyName, constraintOwningClass };
    +            Object[] args = new Object[]{constraintPropertyName, constraintOwningClass};
                 rejectValue(target, errors, ConstrainedProperty.DEFAULT_BLANK_MESSAGE_CODE,
                         ConstrainedProperty.BLANK_CONSTRAINT, args);
                 // empty string is caught by 'blank' constraint, no addition validation needed
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/CreditCardConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/CreditCardConstraint.java
    index e1031f05f5d..eccb2591edc 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/CreditCardConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/CreditCardConstraint.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
     import grails.gorm.validation.ConstrainedProperty;
    @@ -48,7 +47,7 @@ protected void processValidate(Object target, Object propertyValue, Errors error
             CreditCardValidator validator = new CreditCardValidator();
     
             if (!validator.isValid(propertyValue.toString())) {
    -            Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue };
    +            Object[] args = new Object[]{constraintPropertyName, constraintOwningClass, propertyValue};
                 rejectValue(target, errors, ConstrainedProperty.DEFAULT_INVALID_CREDIT_CARD_MESSAGE_CODE,
                         ConstrainedProperty.CREDIT_CARD_CONSTRAINT + ConstrainedProperty.INVALID_SUFFIX, args);
             }
    @@ -65,7 +64,6 @@ protected Object validateParameter(Object constraintParameter) {
             return constraintParameter;
         }
     
    -
         public String getName() {
             return ConstrainedProperty.CREDIT_CARD_CONSTRAINT;
         }
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/EmailConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/EmailConstraint.java
    index 35bdf47ed81..c9b7aa18beb 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/EmailConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/EmailConstraint.java
    @@ -16,10 +16,8 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
    -
     import grails.gorm.validation.ConstrainedProperty;
     import org.apache.commons.validator.routines.EmailValidator;
     import org.springframework.context.MessageSource;
    @@ -61,7 +59,6 @@ protected Object validateParameter(Object constraintParameter) {
             return constraintParameter;
         }
     
    -
         public String getName() {
             return ConstrainedProperty.EMAIL_CONSTRAINT;
         }
    @@ -73,7 +70,7 @@ protected void processValidate(Object target, Object propertyValue, Errors error
             }
     
             EmailValidator emailValidator = EmailValidator.getInstance();
    -        Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue };
    +        Object[] args = new Object[]{constraintPropertyName, constraintOwningClass, propertyValue};
             String value = propertyValue.toString();
             if (StringUtils.isEmpty(value)) {
                 return;
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/InListConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/InListConstraint.java
    index 4b811201e3f..dc4667cbd8a 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/InListConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/InListConstraint.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
     import grails.gorm.validation.ConstrainedProperty;
    @@ -74,7 +73,7 @@ protected Object validateParameter(Object constraintParameter) {
         protected void processValidate(Object target, Object propertyValue, Errors errors) {
             // Check that the list contains the given value. If not, add an error.
             if (!list.contains(propertyValue)) {
    -            Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, list };
    +            Object[] args = new Object[]{constraintPropertyName, constraintOwningClass, propertyValue, list};
                 rejectValue(target, errors, ConstrainedProperty.DEFAULT_NOT_INLIST_MESSAGE_CODE,
                         ConstrainedProperty.NOT_PREFIX + ConstrainedProperty.IN_LIST_CONSTRAINT, args);
             }
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MatchesConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MatchesConstraint.java
    index 4b1c62d2ed4..90eaf6cb8ba 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MatchesConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MatchesConstraint.java
    @@ -16,10 +16,8 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
    -
     import grails.gorm.validation.ConstrainedProperty;
     import org.springframework.context.MessageSource;
     import org.springframework.validation.Errors;
    @@ -76,7 +74,7 @@ protected void processValidate(Object target, Object propertyValue, Errors error
     
             rejectValue(target, errors, ConstrainedProperty.DEFAULT_DOESNT_MATCH_MESSAGE_CODE,
                     ConstrainedProperty.MATCHES_CONSTRAINT + ConstrainedProperty.INVALID_SUFFIX,
    -                new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, regex });
    +                new Object[]{constraintPropertyName, constraintOwningClass, propertyValue, regex});
         }
     }
     
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MaxConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MaxConstraint.java
    index 42ecbe6f44b..c19a0e41bdf 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MaxConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MaxConstraint.java
    @@ -16,10 +16,8 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
    -
     import grails.gorm.validation.ConstrainedProperty;
     import org.grails.datastore.mapping.reflect.ClassPropertyFetcher;
     import org.grails.datastore.mapping.reflect.ClassUtils;
    @@ -32,7 +30,7 @@
      * @author Graeme Rocher
      * @since 0.4
      */
    -@SuppressWarnings({"unchecked","rawtypes"})
    +@SuppressWarnings({"unchecked", "rawtypes"})
     public class MaxConstraint extends AbstractConstraint {
     
         private final Comparable maxValue;
    @@ -69,7 +67,7 @@ protected Object validateParameter(Object constraintParameter) {
             if (!(constraintParameter instanceof Comparable) && (!constraintParameter.getClass().isPrimitive())) {
                 throw new IllegalArgumentException("Parameter for constraint [" +
                         ConstrainedProperty.MAX_CONSTRAINT + "] of property [" + constraintPropertyName +
    -                    "] of class ["+constraintOwningClass + "] must implement the interface [java.lang.Comparable]");
    +                    "] of class [" + constraintOwningClass + "] must implement the interface [java.lang.Comparable]");
             }
     
             Class propertyClass = ClassPropertyFetcher.getPropertyType(constraintOwningClass, constraintPropertyName);
    @@ -89,9 +87,9 @@ public String getName() {
         @Override
         protected void processValidate(Object target, Object propertyValue, Errors errors) {
             if (maxValue.compareTo(propertyValue) < 0) {
    -            Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, maxValue  };
    +            Object[] args = new Object[]{constraintPropertyName, constraintOwningClass, propertyValue, maxValue};
                 rejectValue(target, errors, ConstrainedProperty.DEFAULT_INVALID_MAX_MESSAGE_CODE,
                         ConstrainedProperty.MAX_CONSTRAINT + ConstrainedProperty.EXCEEDED_SUFFIX, args);
             }
         }
    -}
    \ No newline at end of file
    +}
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MaxSizeConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MaxSizeConstraint.java
    index 7bdc0695d18..103af32d4b2 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MaxSizeConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MaxSizeConstraint.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
     import grails.gorm.validation.ConstrainedProperty;
    @@ -39,7 +38,7 @@ public class MaxSizeConstraint extends AbstractConstraint {
     
         public MaxSizeConstraint(Class constraintOwningClass, String constraintPropertyName, Object constraintParameter, MessageSource messageSource) {
             super(constraintOwningClass, constraintPropertyName, constraintParameter, messageSource);
    -        this.maxSize = ((Number)this.constraintParameter).intValue() ;
    +        this.maxSize = ((Number) this.constraintParameter).intValue();
         }
     
         /**
    @@ -81,16 +80,14 @@ protected void processValidate(Object target, Object propertyValue, Errors error
             int length;
             if (propertyValue.getClass().isArray()) {
                 length = Array.getLength(propertyValue);
    -        }
    -        else if (propertyValue instanceof Collection) {
    -            length = ((Collection)propertyValue).size();
    -        }
    -        else { // String
    -            length = ((String)propertyValue).length();
    +        } else if (propertyValue instanceof Collection) {
    +            length = ((Collection) propertyValue).size();
    +        } else { // String
    +            length = ((String) propertyValue).length();
             }
     
             if (length > maxSize) {
    -            Object[] args = { constraintPropertyName, constraintOwningClass, propertyValue, maxSize};
    +            Object[] args = {constraintPropertyName, constraintOwningClass, propertyValue, maxSize};
                 rejectValue(target, errors, ConstrainedProperty.DEFAULT_INVALID_MAX_SIZE_MESSAGE_CODE,
                         ConstrainedProperty.MAX_SIZE_CONSTRAINT + ConstrainedProperty.EXCEEDED_SUFFIX, args);
             }
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MinConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MinConstraint.java
    index c2f88d39e2e..61dc1a07925 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MinConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MinConstraint.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
     import grails.gorm.validation.ConstrainedProperty;
    @@ -72,7 +71,7 @@ protected Object validateParameter(Object constraintParameter) {
             }
     
             Class propertyClass = ClassPropertyFetcher.getPropertyType(constraintOwningClass, constraintPropertyName);
    -        if (!ClassUtils.isAssignableOrConvertibleFrom(constraintParameter.getClass(),propertyClass)) {
    +        if (!ClassUtils.isAssignableOrConvertibleFrom(constraintParameter.getClass(), propertyClass)) {
                 throw new IllegalArgumentException("Parameter for constraint [" + ConstrainedProperty.MIN_CONSTRAINT +
                         "] of property [" + constraintPropertyName + "] of class [" + constraintOwningClass +
                         "] must be the same type as property: [" + propertyClass.getName() + "]");
    @@ -80,7 +79,6 @@ protected Object validateParameter(Object constraintParameter) {
             return constraintParameter;
         }
     
    -
         public String getName() {
             return ConstrainedProperty.MIN_CONSTRAINT;
         }
    @@ -91,7 +89,7 @@ protected void processValidate(Object target, Object propertyValue, Errors error
                 return;
             }
     
    -        Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, minValue };
    +        Object[] args = new Object[]{constraintPropertyName, constraintOwningClass, propertyValue, minValue};
             rejectValue(target, errors, ConstrainedProperty.DEFAULT_INVALID_MIN_MESSAGE_CODE,
                     ConstrainedProperty.MIN_CONSTRAINT + ConstrainedProperty.NOTMET_SUFFIX, args);
         }
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MinSizeConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MinSizeConstraint.java
    index 3a7210aa7eb..c8975c14213 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MinSizeConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/MinSizeConstraint.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
     import grails.gorm.validation.ConstrainedProperty;
    @@ -79,16 +78,14 @@ protected void processValidate(Object target, Object propertyValue, Errors error
             int length;
             if (propertyValue.getClass().isArray()) {
                 length = Array.getLength(propertyValue);
    -        }
    -        else if (propertyValue instanceof Collection) {
    -            length = ((Collection)propertyValue).size();
    -        }
    -        else { // String
    -            length = ((String)propertyValue).length();
    +        } else if (propertyValue instanceof Collection) {
    +            length = ((Collection) propertyValue).size();
    +        } else { // String
    +            length = ((String) propertyValue).length();
             }
     
             if (length < minSize) {
    -            Object[] args = { constraintPropertyName, constraintOwningClass, propertyValue, minSize};
    +            Object[] args = {constraintPropertyName, constraintOwningClass, propertyValue, minSize};
                 rejectValue(target, errors, ConstrainedProperty.DEFAULT_INVALID_MIN_SIZE_MESSAGE_CODE,
                         ConstrainedProperty.MIN_SIZE_CONSTRAINT + ConstrainedProperty.NOTMET_SUFFIX, args);
             }
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/NotEqualConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/NotEqualConstraint.java
    index f3afdf8c156..7a4ad286805 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/NotEqualConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/NotEqualConstraint.java
    @@ -16,10 +16,8 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
    -
     import grails.gorm.validation.ConstrainedProperty;
     import org.grails.datastore.mapping.reflect.ClassPropertyFetcher;
     import org.grails.datastore.mapping.reflect.ClassUtils;
    @@ -36,8 +34,8 @@ public NotEqualConstraint(Class constraintOwningClass, String constraintPrope
         }
     
         /* (non-Javadoc)
    -         * @see org.grails.validation.Constraint#supports(java.lang.Class)
    -         */
    +     * @see org.grails.validation.Constraint#supports(java.lang.Class)
    +     */
         @SuppressWarnings("rawtypes")
         public boolean supports(Class type) {
             return type != null;
    @@ -56,7 +54,7 @@ protected Object validateParameter(Object constraintParameter) {
             }
     
             Class propertyClass = ClassPropertyFetcher.getPropertyType(constraintOwningClass, constraintPropertyName);
    -        if (!ClassUtils.isAssignableOrConvertibleFrom(constraintParameter.getClass(),propertyClass)  && propertyClass != null) {
    +        if (!ClassUtils.isAssignableOrConvertibleFrom(constraintParameter.getClass(), propertyClass) && propertyClass != null) {
                 throw new IllegalArgumentException("Parameter for constraint [" +
                         ConstrainedProperty.NOT_EQUAL_CONSTRAINT + "] of property [" +
                         constraintPropertyName + "] of class [" + constraintOwningClass +
    @@ -65,7 +63,6 @@ protected Object validateParameter(Object constraintParameter) {
             return constraintParameter;
         }
     
    -
         /**
          * @return Returns the notEqualTo.
          */
    @@ -76,7 +73,7 @@ public Object getNotEqualTo() {
         @Override
         protected void processValidate(Object target, Object propertyValue, Errors errors) {
             if (constraintParameter.equals(propertyValue)) {
    -            Object[] args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue, constraintParameter };
    +            Object[] args = new Object[]{constraintPropertyName, constraintOwningClass, propertyValue, constraintParameter};
                 rejectValue(target, errors, ConstrainedProperty.DEFAULT_NOT_EQUAL_MESSAGE_CODE,
                         ConstrainedProperty.NOT_EQUAL_CONSTRAINT, args);
             }
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/NullableConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/NullableConstraint.java
    index c1d42a9cf7a..e3824c712ce 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/NullableConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/NullableConstraint.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
     import grails.gorm.validation.ConstrainedProperty;
    @@ -75,7 +74,7 @@ protected boolean skipNullValues() {
         protected boolean processValidateWithVetoing(Object target, Object propertyValue, Errors errors) {
             if (propertyValue == null) {
                 if (!nullable) {
    -                Object[] args = new Object[] { constraintPropertyName, constraintOwningClass };
    +                Object[] args = new Object[]{constraintPropertyName, constraintOwningClass};
                     rejectValue(target, errors, ConstrainedProperty.DEFAULT_NULL_MESSAGE_CODE,
                             ConstrainedProperty.NULLABLE_CONSTRAINT, args);
                     // null value is caught by 'blank' constraint, no addition validation needed
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/RangeConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/RangeConstraint.java
    index e6d7673bd92..632ebd5a183 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/RangeConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/RangeConstraint.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
     import grails.gorm.validation.ConstrainedProperty;
    @@ -30,7 +29,7 @@
      *
      * @author Graeme Rocher
      */
    -@SuppressWarnings({"unchecked","rawtypes"})
    +@SuppressWarnings({"unchecked", "rawtypes"})
     public class RangeConstraint extends AbstractConstraint {
     
         private final Range range;
    @@ -76,7 +75,7 @@ protected void processValidate(Object target, Object propertyValue, Errors error
                 return;
             }
     
    -        Object[] args = new Object[] { constraintPropertyName, constraintOwningClass,
    +        Object[] args = new Object[]{constraintPropertyName, constraintOwningClass,
                     propertyValue, range.getFrom(), range.getTo()};
     
             Comparable from = range.getFrom();
    @@ -87,10 +86,9 @@ protected void processValidate(Object target, Object propertyValue, Errors error
                 // Upgrade the numbers to Long, so all integer types can be compared.
                 from = ((Number) from).longValue();
                 to = ((Number) to).longValue();
    -            if(propertyValue instanceof Number) {
    +            if (propertyValue instanceof Number) {
                     propertyValue = ((Number) propertyValue).longValue();
    -            }
    -            else if(propertyValue instanceof CharSequence) {
    +            } else if (propertyValue instanceof CharSequence) {
                     try {
                         propertyValue = Long.valueOf(propertyValue.toString());
                     } catch (NumberFormatException e) {
    @@ -103,8 +101,7 @@ else if(propertyValue instanceof CharSequence) {
             if (from.compareTo(propertyValue) > 0) {
                 rejectValue(target, errors, ConstrainedProperty.DEFAULT_INVALID_RANGE_MESSAGE_CODE,
                         ConstrainedProperty.RANGE_CONSTRAINT + ConstrainedProperty.TOOSMALL_SUFFIX, args);
    -        }
    -        else if (to.compareTo(propertyValue) < 0) {
    +        } else if (to.compareTo(propertyValue) < 0) {
                 rejectValue(target, errors, ConstrainedProperty.DEFAULT_INVALID_RANGE_MESSAGE_CODE,
                         ConstrainedProperty.RANGE_CONSTRAINT + ConstrainedProperty.TOOBIG_SUFFIX, args);
             }
    diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/ScaleConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/ScaleConstraint.java
    index b47d9d5a11f..e34b4bde76a 100644
    --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/ScaleConstraint.java
    +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/ScaleConstraint.java
    @@ -16,7 +16,6 @@
      *  specific language governing permissions and limitations
      *  under the License.
      */
    -
     package org.grails.datastore.gorm.validation.constraints;
     
     import grails.gorm.validation.ConstrainedProperty;
    @@ -31,18 +30,18 @@
     /**
      * Manages the scale for floating point numbers (i.e., the
      * number of digits to the right of the decimal point).
    - *
    + * 

    * Supports properties of the following types: *

      *
    • java.lang.Float
    • *
    • java.lang.Double
    • *
    • java.math.BigDecimal (and its subclasses)
    • *
    - * + *

    * When applied, determines if the number includes more * nonzero decimal places than the scale permits. If so, it rounds the number * to the maximum number of decimal places allowed by the scale. - * + *

    * The rounding behavior described above occurs automatically when the * constraint is applied. This constraint does not generate * validation errors. @@ -104,11 +103,11 @@ protected Object validateParameter(Object constraintParameter) { return constraintParameter; } - /** * {@inheritDoc} + * * @see AbstractConstraint#processValidate( - * java.lang.Object, java.lang.Object, org.springframework.validation.Errors) + *java.lang.Object, java.lang.Object, org.springframework.validation.Errors) */ @Override protected void processValidate(Object target, Object propertyValue, Errors errors) { @@ -120,26 +119,23 @@ protected void processValidate(Object target, Object propertyValue, Errors error bigDecimal = new BigDecimal(propertyValue.toString()); bigDecimal = getScaledValue(bigDecimal); bean.setPropertyValue(getPropertyName(), bigDecimal.floatValue()); - } - else if (propertyValue instanceof Double) { + } else if (propertyValue instanceof Double) { bigDecimal = new BigDecimal(propertyValue.toString()); bigDecimal = getScaledValue(bigDecimal); bean.setPropertyValue(getPropertyName(), bigDecimal.doubleValue()); - } - else if (propertyValue instanceof BigDecimal) { + } else if (propertyValue instanceof BigDecimal) { bigDecimal = (BigDecimal) propertyValue; bigDecimal = getScaledValue(bigDecimal); bean.setPropertyValue(getPropertyName(), bigDecimal); - } - else { + } else { throw new IllegalArgumentException("Unsupported type detected in constraint [" + getName() + "] of property [" + constraintPropertyName + "] of class [" + constraintOwningClass + "]"); } } /** - * @return the BigDecimal object that results from applying the contraint's scale to the underlying number * @param originalValue The original value + * @return the BigDecimal object that results from applying the contraint's scale to the underlying number */ private BigDecimal getScaledValue(BigDecimal originalValue) { if (originalValue.scale() > scale) { diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/SizeConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/SizeConstraint.java index 1a4936352e9..8bce13a582c 100644 --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/SizeConstraint.java +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/SizeConstraint.java @@ -16,10 +16,8 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.validation.constraints; - import grails.gorm.validation.ConstrainedProperty; import groovy.lang.IntRange; import org.springframework.context.MessageSource; @@ -73,39 +71,35 @@ protected Object validateParameter(Object constraintParameter) { return constraintParameter; } - public String getName() { return ConstrainedProperty.SIZE_CONSTRAINT; } @Override protected void processValidate(Object target, Object propertyValue, Errors errors) { - Object[] args = { constraintPropertyName, constraintOwningClass, propertyValue, - range.getFrom(), range.getTo() }; + Object[] args = {constraintPropertyName, constraintOwningClass, propertyValue, + range.getFrom(), range.getTo()}; int size; if (propertyValue.getClass().isArray()) { size = Array.getLength(propertyValue); - } - else if (propertyValue instanceof Collection) { - size = ((Collection)propertyValue).size(); - } - else { // String - size = ((String)propertyValue).length(); + } else if (propertyValue instanceof Collection) { + size = ((Collection) propertyValue).size(); + } else { // String + size = ((String) propertyValue).length(); } if (!range.contains(size)) { if (range.getFrom().compareTo(size) == 1) { rejectValue(args, errors, target, ConstrainedProperty.TOOSMALL_SUFFIX); - } - else if (range.getTo().compareTo(size) == -1) { + } else if (range.getTo().compareTo(size) == -1) { rejectValue(args, errors, target, ConstrainedProperty.TOOBIG_SUFFIX); } } } private void rejectValue(Object[] args, Errors errors, Object target, String suffix) { - rejectValue(target,errors, ConstrainedProperty.DEFAULT_INVALID_SIZE_MESSAGE_CODE, + rejectValue(target, errors, ConstrainedProperty.DEFAULT_INVALID_SIZE_MESSAGE_CODE, ConstrainedProperty.SIZE_CONSTRAINT + suffix, args); } } diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/UrlConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/UrlConstraint.java index bb0081b4a6a..b21922cd987 100644 --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/UrlConstraint.java +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/UrlConstraint.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.validation.constraints; import grails.gorm.validation.ConstrainedProperty; @@ -59,15 +58,12 @@ protected Object validateParameter(Object constraintParameter) { // When using "importFrom" the constraintParameter is the UrlValidator even if it was defined as // url: true, so we want the same behavior. domainValidator = null; - } - else if (constraintParameter instanceof String) { + } else if (constraintParameter instanceof String) { domainValidator = new RegexValidator((String) constraintParameter); - } - else if (constraintParameter instanceof List) { + } else if (constraintParameter instanceof List) { List regexpList = (List) constraintParameter; domainValidator = new RegexValidator(regexpList.toArray(new String[regexpList.size()])); - } - else { + } else { throw new IllegalArgumentException("Parameter for constraint [" + ConstrainedProperty.URL_CONSTRAINT + "] of property [" + constraintPropertyName + "] of class [" + constraintOwningClass + "] must be a boolean, string, or list value"); @@ -76,7 +72,6 @@ else if (constraintParameter instanceof List) { UrlValidator validator = new UrlValidator(domainValidator, UrlValidator.ALLOW_ALL_SCHEMES + UrlValidator.ALLOW_2_SLASHES); - return validator; } diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/ValidatorConstraint.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/ValidatorConstraint.java index b998618febe..f14fccdcb56 100644 --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/ValidatorConstraint.java +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/ValidatorConstraint.java @@ -16,17 +16,15 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.validation.constraints; import grails.gorm.validation.ConstrainedProperty; import groovy.lang.Closure; - -import java.util.Collection; - import org.springframework.context.MessageSource; import org.springframework.validation.Errors; +import java.util.Collection; + /** *

    A constraint class that validates using a user-supplied closure.

    *

    The Closure will receive one or two parameters containing the new value of the property and the object @@ -74,11 +72,11 @@ protected Object validateParameter(Object constraintParameter) { Class[] params = validator.getParameterTypes(); // Groovy should always force one parameter, but let's check anyway... if (params.length == 0) { - throw new IllegalArgumentException("Parameter for constraint ["+ConstrainedProperty.VALIDATOR_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must be a Closure taking at least 1 parameter (value, [object])"); + throw new IllegalArgumentException("Parameter for constraint [" + ConstrainedProperty.VALIDATOR_CONSTRAINT + "] of property [" + constraintPropertyName + "] of class [" + constraintOwningClass + "] must be a Closure taking at least 1 parameter (value, [object])"); } if (params.length > 3) { - throw new IllegalArgumentException("Parameter for constraint ["+ConstrainedProperty.VALIDATOR_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class ["+constraintOwningClass+"] must be a Closure taking no more than 3 parameters (value, [object, [errors]])"); + throw new IllegalArgumentException("Parameter for constraint [" + ConstrainedProperty.VALIDATOR_CONSTRAINT + "] of property [" + constraintPropertyName + "] of class [" + constraintOwningClass + "] must be a Closure taking no more than 3 parameters (value, [object, [errors]])"); } return constraintParameter; } @@ -130,42 +128,39 @@ protected void processValidate(Object target, Object propertyValue, Errors error if (result != null) { if (result instanceof Boolean) { - bad = !(Boolean)result; - } - else if (result instanceof CharSequence) { + bad = !(Boolean) result; + } else if (result instanceof CharSequence) { bad = true; errmsg = result.toString(); - } - else if ((result instanceof Collection) || result.getClass().isArray()) { + } else if ((result instanceof Collection) || result.getClass().isArray()) { bad = true; - Object[] values = (result instanceof Collection) ? ((Collection)result).toArray() : (Object[])result; + Object[] values = (result instanceof Collection) ? ((Collection) result).toArray() : (Object[]) result; if (!(values[0] instanceof String)) { throw new IllegalArgumentException("Return value from validation closure [" + - ConstrainedProperty.VALIDATOR_CONSTRAINT+"] of property ["+constraintPropertyName+"] of class [" + - constraintOwningClass+"] is returning a list but the first element must be a string " + + ConstrainedProperty.VALIDATOR_CONSTRAINT + "] of property [" + constraintPropertyName + "] of class [" + + constraintOwningClass + "] is returning a list but the first element must be a string " + "containing the error message code"); } - errmsg = (String)values[0]; + errmsg = (String) values[0]; args = new Object[values.length - 1 + 3]; int i = 0; args[i++] = constraintPropertyName; args[i++] = constraintOwningClass; args[i++] = propertyValue; System.arraycopy(values, 1, args, i, values.length - 1); - } - else { + } else { throw new IllegalArgumentException("Return value from validation closure [" + - ConstrainedProperty.VALIDATOR_CONSTRAINT+"] of property [" + constraintPropertyName + + ConstrainedProperty.VALIDATOR_CONSTRAINT + "] of property [" + constraintPropertyName + "] of class [" + constraintOwningClass + "] must be a boolean, a string, an array or a collection"); } } if (bad) { if (args == null) { - args = new Object[] { constraintPropertyName, constraintOwningClass, propertyValue }; + args = new Object[]{constraintPropertyName, constraintOwningClass, propertyValue}; } rejectValue(target, errors, ConstrainedProperty.DEFAULT_INVALID_VALIDATOR_MESSAGE_CODE, - errmsg == null ? ConstrainedProperty.VALIDATOR_CONSTRAINT + ConstrainedProperty.INVALID_SUFFIX: errmsg, args); + errmsg == null ? ConstrainedProperty.VALIDATOR_CONSTRAINT + ConstrainedProperty.INVALID_SUFFIX : errmsg, args); } } @@ -179,6 +174,7 @@ public boolean supports(Class type) { } private static class ValidatorDelegate { + private String propertyName; @SuppressWarnings("unused") diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/builder/ConstrainedPropertyBuilder.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/builder/ConstrainedPropertyBuilder.java index 0a750d776f7..f2f781c05e9 100644 --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/builder/ConstrainedPropertyBuilder.java +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/builder/ConstrainedPropertyBuilder.java @@ -16,16 +16,19 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.validation.constraints.builder; import grails.gorm.validation.ConstrainedProperty; import grails.gorm.validation.Constraint; -import groovy.lang.*; -import groovy.util.BuilderSupport; -import org.grails.datastore.gorm.validation.constraints.registry.ConstraintRegistry; import grails.gorm.validation.DefaultConstrainedProperty; +import groovy.lang.GroovySystem; +import groovy.lang.MetaClass; +import groovy.lang.MetaProperty; +import groovy.lang.MissingMethodException; +import groovy.lang.MissingPropertyException; +import groovy.util.BuilderSupport; import org.grails.datastore.gorm.validation.constraints.eval.DefaultConstraintEvaluator; +import org.grails.datastore.gorm.validation.constraints.registry.ConstraintRegistry; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; @@ -36,7 +39,12 @@ import org.springframework.beans.InvalidPropertyException; import java.lang.reflect.Modifier; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; /** * Builder used as a delegate within the "constraints" closure of GrailsDomainClass instances . @@ -60,7 +68,6 @@ public class ConstrainedPropertyBuilder extends BuilderSupport { private boolean allowDynamic = false; private boolean defaultNullable = false; - public ConstrainedPropertyBuilder(MappingContext mappingContext, ConstraintRegistry constraintRegistry, Class targetClass, Map defaultConstraints) { this.targetClass = targetClass; this.mappingContext = mappingContext; @@ -127,15 +134,14 @@ protected Object createNode(Object name, Map attributes) { // we do this so that missing property exception is throw if it doesn't exist try { - String property = (String)name; + String property = (String) name; DefaultConstrainedProperty cp; if (constrainedProperties.containsKey(property)) { - cp = (DefaultConstrainedProperty)constrainedProperties.get(property); - } - else { + cp = (DefaultConstrainedProperty) constrainedProperties.get(property); + } else { Class propertyType = determinePropertyType(property); if (propertyType == null) { - if(!allowDynamic) { + if (!allowDynamic) { throw new MissingMethodException(property, targetClass, new Object[]{attributes}, true); } // assume in dynamic use types are strings @@ -165,16 +171,14 @@ protected Object createNode(Object name, Map attributes) { } if (cp.supportsContraint(constraintName)) { cp.applyConstraint(constraintName, value); - } - else { + } else { if (!constraintRegistry.findConstraintFactories(constraintName).isEmpty()) { // constraint is registered but doesn't support this property's type LOG.warn("Property [" + cp.getPropertyName() + "] of domain class " + targetClass.getName() + " has type [" + cp.getPropertyType().getName() + "] and doesn't support constraint [" + constraintName + "]. This constraint will not be checked during validation."); - } - else { + } else { // in the case where the constraint is not supported we still retain meta data // about the constraint in case its needed for other things cp.addMetaConstraint(constraintName, value); @@ -183,9 +187,8 @@ protected Object createNode(Object name, Map attributes) { } return cp; - } - catch(InvalidPropertyException ipe) { - throw new MissingMethodException((String)name,targetClass,new Object[]{ attributes}); + } catch (InvalidPropertyException ipe) { + throw new MissingMethodException((String) name, targetClass, new Object[]{attributes}); } } @@ -195,14 +198,14 @@ protected Object createNode(Object name, Map attributes, Object value) { if (IMPORT_FROM_CONSTRAINT.equals(name) && (value instanceof Class)) { return handleImportFrom(attributes, (Class) value); } - throw new MissingMethodException((String)name,targetClass,new Object[]{ attributes,value}); + throw new MissingMethodException((String) name, targetClass, new Object[]{attributes, value}); } @SuppressWarnings({"unchecked", "rawtypes"}) private Object handleImportFrom(Map attributes, Class importFromClazz) { - Map importFromConstrainedProperties = new DefaultConstraintEvaluator(constraintRegistry,mappingContext, defaultConstraints ) - .evaluate(importFromClazz, defaultNullable); + Map importFromConstrainedProperties = new DefaultConstraintEvaluator(constraintRegistry, mappingContext, defaultConstraints) + .evaluate(importFromClazz, defaultNullable); List metaProperties = classPropertyFetcher.getMetaProperties(); @@ -211,15 +214,14 @@ private Object handleImportFrom(Map attributes, Class importFromClazz) { List resultingPropertyNames = new ArrayList<>(); for (MetaProperty metaProperty : metaProperties) { - if(Modifier.isStatic(metaProperty.getModifiers())) { + if (Modifier.isStatic(metaProperty.getModifiers())) { continue; } String propertyName = metaProperty.getName(); if (toBeIncludedPropertyNamesParam == null) { resultingPropertyNames.add(propertyName); - } - else if (isListOfRegexpsContainsString(toBeIncludedPropertyNamesParam, propertyName)) { + } else if (isListOfRegexpsContainsString(toBeIncludedPropertyNamesParam, propertyName)) { resultingPropertyNames.add(propertyName); } @@ -246,7 +248,7 @@ && isListOfRegexpsContainsString(toBeExcludedPropertyNamesParam, propertyName)) } //add any metaContraints importFromConstrainedPropertyAttributes.putAll(importFromConstrainedProperty.getMetaConstraints()); - + createNode(targetPropertyName, importFromConstrainedPropertyAttributes); } } @@ -257,7 +259,7 @@ && isListOfRegexpsContainsString(toBeExcludedPropertyNamesParam, propertyName)) private boolean isListOfRegexpsContainsString(List listOfStrings, String stringToMatch) { boolean result = false; - for (String listElement:listOfStrings) { + for (String listElement : listOfStrings) { if (stringToMatch.matches(listElement)) { result = true; break; @@ -279,7 +281,7 @@ protected Object createNode(Object name) { @Override protected Object createNode(Object name, Object value) { - return createNode(name,Collections.EMPTY_MAP,value); + return createNode(name, Collections.EMPTY_MAP, value); } public Map getConstrainedProperties() { diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/eval/DefaultConstraintEvaluator.java b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/eval/DefaultConstraintEvaluator.java index b1674f6ea1f..3e18f8a3a42 100644 --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/eval/DefaultConstraintEvaluator.java +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/eval/DefaultConstraintEvaluator.java @@ -16,14 +16,17 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.validation.constraints.eval; import grails.gorm.validation.Constrained; import grails.gorm.validation.ConstrainedProperty; -import grails.gorm.validation.exceptions.ValidationConfigurationException; -import groovy.lang.*; import grails.gorm.validation.DefaultConstrainedProperty; +import grails.gorm.validation.exceptions.ValidationConfigurationException; +import groovy.lang.Closure; +import groovy.lang.GroovyObject; +import groovy.lang.MetaBeanProperty; +import groovy.lang.MetaMethod; +import groovy.lang.MetaProperty; import org.grails.datastore.gorm.validation.constraints.builder.ConstrainedPropertyBuilder; import org.grails.datastore.gorm.validation.constraints.registry.ConstraintRegistry; import org.grails.datastore.gorm.validation.constraints.registry.DefaultConstraintRegistry; @@ -42,7 +45,13 @@ import org.springframework.context.MessageSource; import org.springframework.context.support.StaticMessageSource; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * Evaluates constraints for entities @@ -51,18 +60,18 @@ * @since 6.0 */ public class DefaultConstraintEvaluator implements ConstraintsEvaluator { + private static final Logger LOG = LoggerFactory.getLogger(DefaultConstraintEvaluator.class); protected final ConstraintRegistry constraintRegistry; protected final MappingContext mappingContext; protected final Map defaultConstraints; - public DefaultConstraintEvaluator() { this(new DefaultConstraintRegistry(new StaticMessageSource()), new KeyValueMappingContext("default"), Collections.emptyMap()); } - public DefaultConstraintEvaluator( Map defaultConstraints ) { + public DefaultConstraintEvaluator(Map defaultConstraints) { this(new DefaultConstraintRegistry(new StaticMessageSource()), new KeyValueMappingContext("default"), defaultConstraints); } @@ -102,8 +111,8 @@ public Map evaluate(@SuppressWarnings("rawtypes") C @Override public Map evaluate(Class theClass, boolean defaultNullable, boolean useOnlyAdHocConstraints, Closure... adHocConstraintsClosures) { List constraints = useOnlyAdHocConstraints ? new ArrayList() : ClassPropertyFetcher.getStaticPropertyValuesFromInheritanceHierarchy(theClass, PROPERTY_NAME, Closure.class); - if(adHocConstraintsClosures != null) { - constraints.addAll( Arrays.asList(adHocConstraintsClosures) ); + if (adHocConstraintsClosures != null) { + constraints.addAll(Arrays.asList(adHocConstraintsClosures)); } ConstrainedPropertyBuilder delegate = newConstrainedPropertyBuilder(theClass); delegate.setDefaultNullable(defaultNullable); @@ -122,7 +131,7 @@ public Map evaluate(Class theClass, boolean defa Map constrainedProperties = delegate.getConstrainedProperties(); PersistentEntity entity = mappingContext.getPersistentEntity(theClass.getName()); List properties = null; - if(entity != null) { + if (entity != null) { properties = entity.getPersistentProperties(); if (properties != null) { @@ -169,17 +178,17 @@ public Map evaluate(Class theClass, boolean defa List metaProperties = cpf.getMetaProperties(); for (MetaProperty metaProperty : metaProperties) { String propertyName = metaProperty.getName(); - if(!constrainedProperties.containsKey(propertyName) && NameUtils.isNotConfigurational(propertyName)) { + if (!constrainedProperties.containsKey(propertyName) && NameUtils.isNotConfigurational(propertyName)) { Class propertyType = metaProperty.getType(); - if(metaProperty instanceof MetaBeanProperty) { + if (metaProperty instanceof MetaBeanProperty) { MetaBeanProperty beanProperty = (MetaBeanProperty) metaProperty; MetaMethod getter = beanProperty.getGetter(); // getters of type Boolean should start with 'get' not 'is' - if(Boolean.class == propertyType && getter != null && getter.getName().startsWith("is")) { + if (Boolean.class == propertyType && getter != null && getter.getName().startsWith("is")) { continue; } } - if(!defaultNullable) { + if (!defaultNullable) { DefaultConstrainedProperty constrainedProperty = new DefaultConstrainedProperty(theClass, propertyName, propertyType, constraintRegistry); constrainedProperty.setOrder(constrainedProperties.size() + 1); constrainedProperties.put(propertyName, constrainedProperty); @@ -208,10 +217,10 @@ protected void applySharedConstraints( String propertyName = entry.getKey(); Constrained constrainedProperty = entry.getValue(); String sharedConstraintReference = constrainedPropertyBuilder.getSharedConstraint(propertyName); - if (sharedConstraintReference != null && defaultConstraints != null) { + if (sharedConstraintReference != null && defaultConstraints != null) { Object o = defaultConstraints.get(sharedConstraintReference); if (o instanceof Map) { - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({"unchecked", "rawtypes"}) Map constraintsWithinSharedConstraint = (Map) o; for (Map.Entry e : constraintsWithinSharedConstraint.entrySet()) { constrainedProperty.applyConstraint(e.getKey(), e.getValue()); @@ -238,7 +247,7 @@ protected void applyDefaultConstraints(String propertyName, PersistentProperty p if (defaultConstraints.containsKey("*")) { final Object o = defaultConstraints.get("*"); if (o instanceof Map) { - Map globalConstraints = (Map)o; + Map globalConstraints = (Map) o; applyMapOfConstraints(globalConstraints, propertyName, persistentProperty, cp); } } @@ -259,11 +268,15 @@ protected void applyDefaultNullableConstraint(ConstrainedProperty cp, boolean de } protected boolean canApplyNullableConstraint(String propertyName, PersistentProperty property, Constrained constrained) { - if (property == null || property.getType() == null) return false; + if (property == null || property.getType() == null) { + return false; + } final PersistentEntity domainClass = property.getOwner(); // only apply default nullable to Groovy entities not legacy Java ones - if (!GroovyObject.class.isAssignableFrom(domainClass.getJavaClass())) return false; + if (!GroovyObject.class.isAssignableFrom(domainClass.getJavaClass())) { + return false; + } final PersistentProperty versionProperty = domainClass.getVersion(); final boolean isVersion = versionProperty != null && versionProperty.equals(property); @@ -277,28 +290,26 @@ protected void applyMapOfConstraints(Map constraints, String pro Object constrainingValue = entry.getValue(); if (!cp.hasAppliedConstraint(constraintName) && cp.supportsContraint(constraintName)) { if (ConstrainedProperty.NULLABLE_CONSTRAINT.equals(constraintName)) { - if (isConstrainableProperty(persistentProperty,propertyName)) { + if (isConstrainableProperty(persistentProperty, propertyName)) { cp.applyConstraint(constraintName, constrainingValue); } - } - else { - cp.applyConstraint(constraintName,constrainingValue); + } else { + cp.applyConstraint(constraintName, constrainingValue); } } } } protected boolean isConstrainableProperty(PersistentProperty persistentProperty, String propertyName) { - if(persistentProperty == null) { + if (persistentProperty == null) { return NameUtils.isNotConfigurational(propertyName); - } - else { + } else { return !propertyName.equals(GormProperties.VERSION) && !propertyName.equals(GormProperties.DATE_CREATED) && !propertyName.equals(GormProperties.LAST_UPDATED) && !(persistentProperty instanceof Identity) && !(persistentProperty.getMapping().getMappedForm().isDerived()) && - !( (persistentProperty instanceof ToOne) && ((ToOne)persistentProperty).isBidirectional() && ((ToOne) persistentProperty).isCircular()); + !((persistentProperty instanceof ToOne) && ((ToOne) persistentProperty).isBidirectional() && ((ToOne) persistentProperty).isCircular()); } } diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/factory/DefaultConstraintFactory.groovy b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/factory/DefaultConstraintFactory.groovy index 0d46586662f..e8b8ba6d1c0 100644 --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/factory/DefaultConstraintFactory.groovy +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/factory/DefaultConstraintFactory.groovy @@ -22,7 +22,6 @@ package org.grails.datastore.gorm.validation.constraints.factory import grails.gorm.validation.Constraint import grails.gorm.validation.exceptions.ValidationConfigurationException import groovy.transform.CompileStatic -import org.grails.datastore.gorm.validation.constraints.AbstractConstraint import org.grails.datastore.gorm.validation.constraints.NullableConstraint import org.grails.datastore.mapping.reflect.ClassUtils import org.springframework.context.MessageSource @@ -61,10 +60,9 @@ class DefaultConstraintFactory implements ConstraintFactory { @Override boolean supports(Class targetType) { - if(NullableConstraint.isAssignableFrom(type)) { + if (NullableConstraint.isAssignableFrom(type)) { return !targetType.isPrimitive() - } - else { + } else { return this.targetTypes.any() { Class type -> ClassUtils.isAssignableOrConvertibleFrom(type, targetType) } } } diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/registry/DefaultConstraintRegistry.groovy b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/registry/DefaultConstraintRegistry.groovy index 82d52740c3d..8af3e3c046f 100644 --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/registry/DefaultConstraintRegistry.groovy +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/registry/DefaultConstraintRegistry.groovy @@ -44,7 +44,6 @@ import org.springframework.context.MessageSource import java.util.concurrent.ConcurrentHashMap - /** * Default implementation of the {@link ConstraintRegistry} interface. Provides lookup and registration of constraints * @@ -66,7 +65,6 @@ class DefaultConstraintRegistry implements ConstraintRegistry { DefaultConstraintRegistry(MessageSource messageSource) { this.messageSource = messageSource - def charSequenceType = [CharSequence] def comparableNumberType = [Comparable, Number] def charSequenceIterableType = [CharSequence, Iterable] @@ -91,15 +89,15 @@ class DefaultConstraintRegistry implements ConstraintRegistry { @Autowired(required = false) void setConstraintFactories(ConstraintFactory... constraintFactories) { - for(factory in constraintFactories) { + for (factory in constraintFactories) { addConstraintFactory(factory) } } @Override void addConstraintFactory(ConstraintFactory factory) { - factoriesByType.get( factory.type ).add(factory) - factoriesByName.get( factory.name).add(factory) + factoriesByType.get(factory.type).add(factory) + factoriesByName.get(factory.name).add(factory) } @Override diff --git a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/registry/DefaultValidatorRegistry.groovy b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/registry/DefaultValidatorRegistry.groovy index d23d91d2852..e9a171b410f 100644 --- a/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/registry/DefaultValidatorRegistry.groovy +++ b/grails-datamapping-validation/src/main/groovy/org/grails/datastore/gorm/validation/constraints/registry/DefaultValidatorRegistry.groovy @@ -27,15 +27,11 @@ import org.grails.datastore.gorm.validation.constraints.eval.DefaultConstraintEv import org.grails.datastore.mapping.core.connections.ConnectionSourceSettings import org.grails.datastore.mapping.model.MappingContext import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.datastore.mapping.reflect.ClassUtils import org.grails.datastore.mapping.reflect.ClosureToMapPopulator import org.grails.datastore.mapping.validation.ValidatorRegistry import org.springframework.context.MessageSource import org.springframework.context.support.StaticMessageSource -import org.springframework.core.env.PropertyResolver -import org.springframework.core.env.StandardEnvironment import org.springframework.validation.Validator -import org.springframework.validation.annotation.Validated import java.util.concurrent.ConcurrentHashMap @@ -50,8 +46,10 @@ import java.util.concurrent.ConcurrentHashMap class DefaultValidatorRegistry implements ValidatorRegistry, ConstraintRegistry, ConstraintsEvaluator { final Map validatorMap = new ConcurrentHashMap<>() - final @Delegate ConstraintsEvaluator constraintsEvaluator - final @Delegate ConstraintRegistry constraintRegistry + final @Delegate + ConstraintsEvaluator constraintsEvaluator + final @Delegate + ConstraintRegistry constraintRegistry final MessageSource messageSource final MappingContext mappingContext @@ -63,7 +61,7 @@ class DefaultValidatorRegistry implements ValidatorRegistry, ConstraintRegistry, this.mappingContext = mappingContext } - protected Map resolveDefaultConstraints( ConnectionSourceSettings connectionSourceSettings ) { + protected Map resolveDefaultConstraints(ConnectionSourceSettings connectionSourceSettings) { Closure defaultConstraints = connectionSourceSettings.default.constraints Map defaultConstraintsMap = null if (defaultConstraints != null) { @@ -80,10 +78,9 @@ class DefaultValidatorRegistry implements ValidatorRegistry, ConstraintRegistry, @Override Validator getValidator(PersistentEntity entity) { Validator validator = validatorMap.get(entity) - if(validator != null) { + if (validator != null) { return validator - } - else { + } else { validator = new PersistentEntityValidator(entity, messageSource, constraintsEvaluator) validatorMap.put(entity, validator) } diff --git a/grails-datamapping-validation/src/main/resources/grails/gorm/validation/DefaultErrorMessages.properties b/grails-datamapping-validation/src/main/resources/grails/gorm/validation/DefaultErrorMessages.properties index cf9e4252b7d..00595d4e6ac 100644 --- a/grails-datamapping-validation/src/main/resources/grails/gorm/validation/DefaultErrorMessages.properties +++ b/grails-datamapping-validation/src/main/resources/grails/gorm/validation/DefaultErrorMessages.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-datasource/build.gradle b/grails-datasource/build.gradle index c5fb199e6ac..8dc3e6f7826 100644 --- a/grails-datasource/build.gradle +++ b/grails-datasource/build.gradle @@ -74,4 +74,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-datasource/src/main/groovy/org/grails/plugins/datasource/DataSourceConnectionSourcesFactoryBean.groovy b/grails-datasource/src/main/groovy/org/grails/plugins/datasource/DataSourceConnectionSourcesFactoryBean.groovy index 5646376e2f6..39e69f804e1 100644 --- a/grails-datasource/src/main/groovy/org/grails/plugins/datasource/DataSourceConnectionSourcesFactoryBean.groovy +++ b/grails-datasource/src/main/groovy/org/grails/plugins/datasource/DataSourceConnectionSourcesFactoryBean.groovy @@ -26,7 +26,6 @@ import org.grails.datastore.mapping.core.connections.ConnectionSource import org.grails.datastore.mapping.core.connections.ConnectionSourceSettings import org.grails.datastore.mapping.core.connections.ConnectionSources import org.grails.datastore.mapping.core.connections.ConnectionSourcesInitializer -import org.grails.datastore.mapping.core.connections.DefaultConnectionSource import org.springframework.beans.factory.FactoryBean import org.springframework.beans.factory.InitializingBean import org.springframework.context.ApplicationContext @@ -73,21 +72,21 @@ class DataSourceConnectionSourcesFactoryBean implements InitializingBean, Factor void afterPropertiesSet() throws Exception { DataSourceConnectionSourceFactory factory = new DataSourceConnectionSourceFactory() this.connectionSources = ConnectionSourcesInitializer.create(factory, configuration) - if(applicationContext instanceof ConfigurableApplicationContext) { - ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext)applicationContext - for(ConnectionSource connectionSource in connectionSources.allConnectionSources) { + if (applicationContext instanceof ConfigurableApplicationContext) { + ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext + for (ConnectionSource connectionSource in connectionSources.allConnectionSources) { if (connectionSource.name != ConnectionSource.DEFAULT) { String suffix = "_${connectionSource.name}" String dsName = "dataSource${suffix}" String tmName = "transactionManager${suffix}" - if(!applicationContext.containsBean(dsName)) { + if (!applicationContext.containsBean(dsName)) { DataSource dataSource = connectionSource.source configurableApplicationContext.beanFactory.registerSingleton( dsName, dataSource ) } - if(!applicationContext.containsBean(tmName)) { + if (!applicationContext.containsBean(tmName)) { DataSource dataSource = connectionSource.source configurableApplicationContext.beanFactory.registerSingleton( tmName, diff --git a/grails-datasource/src/main/groovy/org/grails/plugins/datasource/DataSourceGrailsPlugin.groovy b/grails-datasource/src/main/groovy/org/grails/plugins/datasource/DataSourceGrailsPlugin.groovy index a1823b14575..5f5989b7d1b 100644 --- a/grails-datasource/src/main/groovy/org/grails/plugins/datasource/DataSourceGrailsPlugin.groovy +++ b/grails-datasource/src/main/groovy/org/grails/plugins/datasource/DataSourceGrailsPlugin.groovy @@ -48,58 +48,60 @@ class DataSourceGrailsPlugin extends Plugin { def dependsOn = [core: version] @Override - Closure doWithSpring() {{-> - GrailsApplication application = grailsApplication + Closure doWithSpring() { + { -> + GrailsApplication application = grailsApplication - if (pluginManager.hasGrailsPlugin('hibernate')) { + if (pluginManager.hasGrailsPlugin('hibernate')) { - if (!springConfig.unrefreshedApplicationContext?.containsBean('transactionManager')) { - Boolean enabled = config.getProperty(TRANSACTION_MANAGER_ENABLED, Boolean, false) - if (enabled) { - def whitelistPattern=config.getProperty(TRANSACTION_MANAGER_WHITE_LIST_PATTERN, '') - def blacklistPattern=config.getProperty(TRANSACTION_MANAGER_BLACK_LIST_PATTERN,'') - chainedTransactionManagerPostProcessor(ChainedTransactionManagerPostProcessor, config, whitelistPattern ?: null, blacklistPattern ?: null) + if (!springConfig.unrefreshedApplicationContext?.containsBean('transactionManager')) { + Boolean enabled = config.getProperty(TRANSACTION_MANAGER_ENABLED, Boolean, false) + if (enabled) { + def whitelistPattern = config.getProperty(TRANSACTION_MANAGER_WHITE_LIST_PATTERN, '') + def blacklistPattern = config.getProperty(TRANSACTION_MANAGER_BLACK_LIST_PATTERN, '') + chainedTransactionManagerPostProcessor(ChainedTransactionManagerPostProcessor, config, whitelistPattern ?: null, blacklistPattern ?: null) + } + } + if (ClassUtils.isPresent('org.h2.Driver', this.class.classLoader)) { + embeddedDatabaseShutdownHook(EmbeddedDatabaseShutdownHook) } - } - if (ClassUtils.isPresent('org.h2.Driver', this.class.classLoader)) { - embeddedDatabaseShutdownHook(EmbeddedDatabaseShutdownHook) - } - } else { - def dataSources = config.getProperty('dataSources', Map, [:]) - if(!dataSources) { - def defaultDataSource = config.getProperty('dataSource', Map) - if(defaultDataSource) { - dataSources['dataSource'] = defaultDataSource + } else { + def dataSources = config.getProperty('dataSources', Map, [:]) + if (!dataSources) { + def defaultDataSource = config.getProperty('dataSource', Map) + if (defaultDataSource) { + dataSources['dataSource'] = defaultDataSource + } + } + if (dataSources) { + "dataSourceConnectionSources"(DataSourceConnectionSourcesFactoryBean, grailsApplication.config) + "dataSource"(InstanceFactoryBean, "#{dataSourceConnectionSources.defaultConnectionSource.source}", DataSource) } } - if(dataSources) { - "dataSourceConnectionSources"(DataSourceConnectionSourcesFactoryBean, grailsApplication.config) - "dataSource"(InstanceFactoryBean, "#{dataSourceConnectionSources.defaultConnectionSource.source}", DataSource) - } - } - if(config.getProperty('dataSource.jmxExport', Boolean, false) && ClassUtils.isPresent('org.apache.tomcat.jdbc.pool.DataSource', getClass().classLoader)) { - try { - def jmxMBeanServer = JmxUtils.locateMBeanServer() - if(jmxMBeanServer) { - tomcatJDBCPoolMBeanExporter(TomcatJDBCPoolMBeanExporter) { bean -> - delegate.grailsApplication = application - server = jmxMBeanServer + if (config.getProperty('dataSource.jmxExport', Boolean, false) && ClassUtils.isPresent('org.apache.tomcat.jdbc.pool.DataSource', getClass().classLoader)) { + try { + def jmxMBeanServer = JmxUtils.locateMBeanServer() + if (jmxMBeanServer) { + tomcatJDBCPoolMBeanExporter(TomcatJDBCPoolMBeanExporter) { bean -> + delegate.grailsApplication = application + server = jmxMBeanServer + } + } + } catch (e) { + if (!Environment.isDevelopmentMode() && Environment.isWarDeployed()) { + log.warn("Cannot locate JMX MBeanServer. Disabling autoregistering dataSource pools to JMX.", e) } - } - } catch(e) { - if(!Environment.isDevelopmentMode() && Environment.isWarDeployed()) { - log.warn("Cannot locate JMX MBeanServer. Disabling autoregistering dataSource pools to JMX.", e) } } } - }} + } @Override @CompileStatic void onShutdown(Map event) { - if(!Environment.developmentEnvironmentAvailable || !Environment.isReloadingAgentEnabled()) { + if (!Environment.developmentEnvironmentAvailable || !Environment.isReloadingAgentEnabled()) { try { DataSourceUtils.clearJdbcDriverRegistrations() } diff --git a/grails-datasource/src/main/groovy/org/grails/plugins/datasource/DataSourceUtils.groovy b/grails-datasource/src/main/groovy/org/grails/plugins/datasource/DataSourceUtils.groovy index 1d70dc8b2c8..223662f699f 100644 --- a/grails-datasource/src/main/groovy/org/grails/plugins/datasource/DataSourceUtils.groovy +++ b/grails-datasource/src/main/groovy/org/grails/plugins/datasource/DataSourceUtils.groovy @@ -52,7 +52,7 @@ class DataSourceUtils { Driver driver = drivers.nextElement() // Only unload the drivers this web app loaded if (driver.getClass().classLoader != - DataSourceUtils.classLoader) { + DataSourceUtils.classLoader) { continue } // Only report drivers that were originally registered. Skip any diff --git a/grails-datasource/src/main/groovy/org/grails/plugins/datasource/EmbeddedDatabaseShutdownHook.groovy b/grails-datasource/src/main/groovy/org/grails/plugins/datasource/EmbeddedDatabaseShutdownHook.groovy index bcae9c1c475..6e2b9dc6913 100644 --- a/grails-datasource/src/main/groovy/org/grails/plugins/datasource/EmbeddedDatabaseShutdownHook.groovy +++ b/grails-datasource/src/main/groovy/org/grails/plugins/datasource/EmbeddedDatabaseShutdownHook.groovy @@ -21,11 +21,6 @@ package org.grails.plugins.datasource import groovy.sql.Sql import groovy.transform.CompileStatic - -import java.sql.Connection - -import javax.sql.DataSource - import org.apache.commons.logging.Log import org.apache.commons.logging.LogFactory import org.grails.core.lifecycle.ShutdownOperations @@ -34,9 +29,13 @@ import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContextAware import org.springframework.context.SmartLifecycle +import javax.sql.DataSource +import java.sql.Connection + @CompileStatic class EmbeddedDatabaseShutdownHook implements SmartLifecycle, ApplicationContextAware { - private static final Log log=LogFactory.getLog(this) + + private static final Log log = LogFactory.getLog(this) private boolean running private ApplicationContext applicationContext private List embeddedDatabaseBeanNames @@ -45,7 +44,7 @@ class EmbeddedDatabaseShutdownHook implements SmartLifecycle, ApplicationContext public void start() { embeddedDatabaseBeanNames = [] applicationContext.getBeansOfType(DataSource).each { String beanName, DataSource dataSource -> - if(isEmbeddedH2orHsqldb(dataSource)) { + if (isEmbeddedH2orHsqldb(dataSource)) { embeddedDatabaseBeanNames.add(beanName) } } @@ -81,19 +80,19 @@ class EmbeddedDatabaseShutdownHook implements SmartLifecycle, ApplicationContext stop() callback.run() } - + @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext } - + protected boolean isEmbeddedH2orHsqldb(DataSource dataSource) { - MetaProperty urlProperty = dataSource.hasProperty("url") + MetaProperty urlProperty = dataSource.hasProperty("url") if (urlProperty) { String url = urlProperty.getProperty(dataSource) - if(url && (url.startsWith('jdbc:h2:') || url.startsWith('jdbc:hsqldb:'))) { + if (url && (url.startsWith('jdbc:h2:') || url.startsWith('jdbc:hsqldb:'))) { // don't shutdown remote servers - if(!(url.startsWith('jdbc:hsqldb:h') || url.startsWith('jdbc:h2:tcp:') || url.startsWith('jdbc:h2:ssl:'))) { + if (!(url.startsWith('jdbc:hsqldb:h') || url.startsWith('jdbc:h2:tcp:') || url.startsWith('jdbc:h2:ssl:'))) { return true } } @@ -118,7 +117,10 @@ class EmbeddedDatabaseShutdownHook implements SmartLifecycle, ApplicationContext } catch (e) { // already closed, ignore } finally { - try { connection?.close() } catch (ignored) {} + try { + connection?.close() + } catch (ignored) { + } } } as Runnable } diff --git a/grails-datasource/src/main/groovy/org/grails/plugins/datasource/ReadOnlyDriverManagerDataSource.java b/grails-datasource/src/main/groovy/org/grails/plugins/datasource/ReadOnlyDriverManagerDataSource.java index 38c4049f767..c4b2a84a66d 100644 --- a/grails-datasource/src/main/groovy/org/grails/plugins/datasource/ReadOnlyDriverManagerDataSource.java +++ b/grails-datasource/src/main/groovy/org/grails/plugins/datasource/ReadOnlyDriverManagerDataSource.java @@ -18,12 +18,12 @@ */ package org.grails.plugins.datasource; +import org.springframework.jdbc.datasource.DriverManagerDataSource; + import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; -import org.springframework.jdbc.datasource.DriverManagerDataSource; - /** * Used for secondary datasources that are read-only and not pooled. * diff --git a/grails-datasource/src/main/groovy/org/grails/plugins/datasource/TomcatJDBCPoolMBeanExporter.groovy b/grails-datasource/src/main/groovy/org/grails/plugins/datasource/TomcatJDBCPoolMBeanExporter.groovy index 7f9c531532c..aef94b2c517 100644 --- a/grails-datasource/src/main/groovy/org/grails/plugins/datasource/TomcatJDBCPoolMBeanExporter.groovy +++ b/grails-datasource/src/main/groovy/org/grails/plugins/datasource/TomcatJDBCPoolMBeanExporter.groovy @@ -19,25 +19,25 @@ package org.grails.plugins.datasource +import grails.core.GrailsApplication import groovy.transform.CompileStatic - -import javax.management.MalformedObjectNameException -import javax.management.ObjectName - import org.apache.commons.logging.Log import org.apache.commons.logging.LogFactory -import grails.core.GrailsApplication import org.springframework.beans.factory.BeanFactory import org.springframework.beans.factory.ListableBeanFactory import org.springframework.jmx.export.MBeanExporter import org.springframework.jmx.support.RegistrationPolicy +import javax.management.MalformedObjectNameException +import javax.management.ObjectName + @CompileStatic class TomcatJDBCPoolMBeanExporter extends MBeanExporter { + private static final Log log = LogFactory.getLog(TomcatJDBCPoolMBeanExporter.class) GrailsApplication grailsApplication private ListableBeanFactory beanFactory - + public TomcatJDBCPoolMBeanExporter() { super(); this.setRegistrationPolicy(RegistrationPolicy.REPLACE_EXISTING) @@ -53,7 +53,7 @@ class TomcatJDBCPoolMBeanExporter extends MBeanExporter { } catch (Exception e) { log.warn("Unable to access dataSource bean ${entry.key}", e) } - if(jmxEnabled) { + if (jmxEnabled) { ObjectName objectName = null try { objectName = createJmxObjectName(entry.key, entry.value) @@ -62,7 +62,7 @@ class TomcatJDBCPoolMBeanExporter extends MBeanExporter { log.warn("Unable to register JMX MBean for ${objectName} beanName:${entry.key}", e) } } - } + } } protected boolean isJmxEnabled(String beanName, org.apache.tomcat.jdbc.pool.DataSource dataSource) { @@ -70,31 +70,31 @@ class TomcatJDBCPoolMBeanExporter extends MBeanExporter { } protected ObjectName createJmxObjectName(String beanName, org.apache.tomcat.jdbc.pool.DataSource dataSource) throws MalformedObjectNameException { - Hashtable properties = new Hashtable() + Hashtable properties = new Hashtable() properties.type = 'ConnectionPool' - properties.application = ((grailsApplication?.getMetadata()?.getApplicationName())?:'grailsApplication').replaceAll(/[,=;:]/, '_') - String poolName=dataSource.pool.poolProperties.name + properties.application = ((grailsApplication?.getMetadata()?.getApplicationName()) ?: 'grailsApplication').replaceAll(/[,=;:]/, '_') + String poolName = dataSource.pool.poolProperties.name if (beanName.startsWith('dataSourceUnproxied')) { def dataSourceName = beanName - ~/^dataSourceUnproxied_?/ - if(!dataSourceName) { + if (!dataSourceName) { dataSourceName = 'default' } properties.dataSource = dataSourceName } else { - if(poolName.startsWith("Tomcat Connection Pool[")) { + if (poolName.startsWith("Tomcat Connection Pool[")) { // use bean name if the pool has a default name - poolName=beanName + poolName = beanName } } - if(!poolName.startsWith("Tomcat Connection Pool[")) { + if (!poolName.startsWith("Tomcat Connection Pool[")) { properties.pool = poolName } return new ObjectName('grails.dataSource', properties) } - + @Override public void setBeanFactory(BeanFactory beanFactory) { super.setBeanFactory(beanFactory) - this.beanFactory = (ListableBeanFactory)beanFactory + this.beanFactory = (ListableBeanFactory) beanFactory } } diff --git a/grails-datastore-async/build.gradle b/grails-datastore-async/build.gradle index 1b1838e4ae0..22dc6581383 100644 --- a/grails-datastore-async/build.gradle +++ b/grails-datastore-async/build.gradle @@ -64,4 +64,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsync.groovy b/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsync.groovy index 53dc0411866..1ef502062a0 100644 --- a/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsync.groovy +++ b/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsync.groovy @@ -18,14 +18,15 @@ */ package org.grails.datastore.gorm.async.transform + +import org.codehaus.groovy.transform.GroovyASTTransformationClass + import java.lang.annotation.Documented import java.lang.annotation.ElementType import java.lang.annotation.Retention import java.lang.annotation.RetentionPolicy import java.lang.annotation.Target -import org.codehaus.groovy.transform.GroovyASTTransformationClass - /** * An AST transformation that takes each method in the given class and adds a delegate method that returns a {@link grails.async.Promise} and executes the method asynchronously. * For example given the following class: @@ -65,5 +66,6 @@ import org.codehaus.groovy.transform.GroovyASTTransformationClass @Target([ElementType.TYPE, ElementType.FIELD]) @GroovyASTTransformationClass("org.grails.datastore.gorm.async.transform.DelegateAsyncTransformation") public @interface DelegateAsync { + Class value() default DelegateAsync } diff --git a/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncTransformation.java b/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncTransformation.java index 01695632c49..5d59de75e92 100644 --- a/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncTransformation.java +++ b/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncTransformation.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.gorm.async.transform; import grails.async.Promise; @@ -25,8 +24,24 @@ import groovy.lang.GroovyObjectSupport; import org.apache.grails.common.compiler.GroovyTransformOrder; import org.codehaus.groovy.GroovyBugError; -import org.codehaus.groovy.ast.*; -import org.codehaus.groovy.ast.expr.*; +import org.codehaus.groovy.ast.ASTNode; +import org.codehaus.groovy.ast.AnnotatedNode; +import org.codehaus.groovy.ast.AnnotationNode; +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.ClassNode; +import org.codehaus.groovy.ast.FieldNode; +import org.codehaus.groovy.ast.GenericsType; +import org.codehaus.groovy.ast.MethodNode; +import org.codehaus.groovy.ast.Parameter; +import org.codehaus.groovy.ast.VariableScope; +import org.codehaus.groovy.ast.expr.ArgumentListExpression; +import org.codehaus.groovy.ast.expr.ClassExpression; +import org.codehaus.groovy.ast.expr.ClosureExpression; +import org.codehaus.groovy.ast.expr.ConstructorCallExpression; +import org.codehaus.groovy.ast.expr.Expression; +import org.codehaus.groovy.ast.expr.ListExpression; +import org.codehaus.groovy.ast.expr.MethodCallExpression; +import org.codehaus.groovy.ast.expr.VariableExpression; import org.codehaus.groovy.ast.stmt.BlockStatement; import org.codehaus.groovy.ast.stmt.ExpressionStatement; import org.codehaus.groovy.ast.tools.GenericsUtils; @@ -40,17 +55,22 @@ import java.beans.Introspector; import java.lang.reflect.Modifier; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse; import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec; @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) public class DelegateAsyncTransformation implements ASTTransformation, TransformWithPriority { - private static final ArgumentListExpression NO_ARGS = new ArgumentListExpression(); - private static final String VOID = "void"; + public static final ClassNode GROOVY_OBJECT_CLASS_NODE = new ClassNode(GroovyObjectSupport.class); public static final ClassNode OBJECT_CLASS_NODE = new ClassNode(Object.class); + private static final ArgumentListExpression NO_ARGS = new ArgumentListExpression(); + private static final String VOID = "void"; public void visit(ASTNode[] nodes, SourceUnit source) { if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) { @@ -64,7 +84,7 @@ public void visit(ASTNode[] nodes, SourceUnit source) { Expression value = annotationNode.getMember("value"); if (value instanceof ClassExpression) { ClassNode targetApi = value.getType().getPlainNodeReference(); - ClassNode classNode = (ClassNode)parent; + ClassNode classNode = (ClassNode) parent; final String fieldName = '$' + Introspector.decapitalize(targetApi.getNameWithoutPackage()); FieldNode fieldNode = classNode.getField(fieldName); @@ -75,9 +95,8 @@ public void visit(ASTNode[] nodes, SourceUnit source) { applyDelegateAsyncTransform(classNode, targetApi, fieldName); } - } - else if(parent instanceof FieldNode) { - FieldNode fieldNode = (FieldNode)parent; + } else if (parent instanceof FieldNode) { + FieldNode fieldNode = (FieldNode) parent; ClassNode targetApi = fieldNode.getType().getPlainNodeReference(); ClassNode classNode = fieldNode.getOwner(); applyDelegateAsyncTransform(classNode, targetApi, fieldNode.getName()); @@ -90,27 +109,26 @@ private void applyDelegateAsyncTransform(ClassNode classNode, ClassNode targetAp ClassNode promisesClass = ClassHelper.make(Promises.class).getPlainNodeReference(); MethodNode createPromiseMethodTargetWithDecorators = promisesClass.getDeclaredMethod("createPromise", new Parameter[]{new Parameter(new ClassNode(Closure.class), "c"), new Parameter(new ClassNode(List.class), "c")}); - Map genericsSpec = createGenericsSpec(classNode); - for(MethodNode candidate : methods) { + Map genericsSpec = createGenericsSpec(classNode); + for (MethodNode candidate : methods) { if (isCandidateMethod(candidate)) { MethodNode existingMethod = classNode.getMethod(candidate.getName(), candidate.getParameters()); if (existingMethod == null) { List currentMethodGenPlaceholders = genericPlaceholderNames(candidate); ClassNode promiseNode = ClassHelper.make(Promise.class).getPlainNodeReference(); ClassNode originalReturnType = correctToGenericsSpecRecurse(genericsSpec, candidate.getReturnType(), currentMethodGenPlaceholders); - if(!originalReturnType.getNameWithoutPackage().equals(VOID)) { + if (!originalReturnType.getNameWithoutPackage().equals(VOID)) { ClassNode returnType = originalReturnType; - if(ClassHelper.isPrimitiveType(originalReturnType.redirect())) { + if (ClassHelper.isPrimitiveType(originalReturnType.redirect())) { returnType = ClassHelper.getWrapper(originalReturnType.redirect()); } - if(!OBJECT_CLASS_NODE.equals(returnType)) { + if (!OBJECT_CLASS_NODE.equals(returnType)) { promiseNode.setGenericsTypes(new GenericsType[]{new GenericsType(returnType)}); } } final BlockStatement methodBody = new BlockStatement(); final BlockStatement promiseBody = new BlockStatement(); - final ClosureExpression closureExpression = new ClosureExpression(new Parameter[0], promiseBody); VariableScope variableScope = new VariableScope(); closureExpression.setVariableScope(variableScope); @@ -124,8 +142,8 @@ private void applyDelegateAsyncTransform(ClassNode classNode, ClassNode targetAp MethodCallExpression getDecoratorsMethodCall = new MethodCallExpression(new ClassExpression(delegateAsyncUtilsClassNode), "getPromiseDecorators", getPromiseDecoratorsArguments); getDecoratorsMethodCall.setMethodTarget(getPromiseDecoratorsMethodNode); - MethodCallExpression createPromiseWithDecorators = new MethodCallExpression(new ClassExpression(promisesClass), "createPromise",new ArgumentListExpression( closureExpression, getDecoratorsMethodCall)); - if(createPromiseMethodTargetWithDecorators != null) { + MethodCallExpression createPromiseWithDecorators = new MethodCallExpression(new ClassExpression(promisesClass), "createPromise", new ArgumentListExpression(closureExpression, getDecoratorsMethodCall)); + if (createPromiseMethodTargetWithDecorators != null) { createPromiseWithDecorators.setMethodTarget(createPromiseMethodTargetWithDecorators); } methodBody.addStatement(new ExpressionStatement(createPromiseWithDecorators)); @@ -133,7 +151,7 @@ private void applyDelegateAsyncTransform(ClassNode classNode, ClassNode targetAp final ArgumentListExpression arguments = new ArgumentListExpression(); Parameter[] parameters = copyParameters(genericsSpec, StaticTypeCheckingSupport.parameterizeArguments(classNode, candidate), currentMethodGenPlaceholders); - for(Parameter p : parameters) { + for (Parameter p : parameters) { p.setClosureSharedVariable(true); variableScope.putReferencedLocalVariable(p); VariableExpression ve = new VariableExpression(p); @@ -142,14 +160,13 @@ private void applyDelegateAsyncTransform(ClassNode classNode, ClassNode targetAp } MethodCallExpression delegateMethodCall = new MethodCallExpression(new VariableExpression(fieldName), candidate.getName(), arguments); promiseBody.addStatement(new ExpressionStatement(delegateMethodCall)); - MethodNode newMethodNode = new MethodNode(candidate.getName(), Modifier.PUBLIC,promiseNode, parameters,null, methodBody); + MethodNode newMethodNode = new MethodNode(candidate.getName(), Modifier.PUBLIC, promiseNode, parameters, null, methodBody); classNode.addMethod(newMethodNode); } } } } - private List genericPlaceholderNames(MethodNode candidate) { GenericsType[] candidateGenericsTypes = candidate.getGenericsTypes(); List names = new ArrayList(); @@ -166,14 +183,14 @@ private static ClassNode alignReturnType(final ClassNode receiver, final ClassNo ClassNode actualReceiver = receiver; List redirectTypes = new ArrayList(); - if (actualReceiver.redirect().getGenericsTypes()!=null) { - Collections.addAll(redirectTypes,actualReceiver.redirect().getGenericsTypes()); + if (actualReceiver.redirect().getGenericsTypes() != null) { + Collections.addAll(redirectTypes, actualReceiver.redirect().getGenericsTypes()); } if (!redirectTypes.isEmpty()) { GenericsType[] redirectReceiverTypes = redirectTypes.toArray(new GenericsType[redirectTypes.size()]); GenericsType[] receiverParameterizedTypes = actualReceiver.getGenericsTypes(); - if (receiverParameterizedTypes==null) { + if (receiverParameterizedTypes == null) { receiverParameterizedTypes = redirectReceiverTypes; } @@ -187,7 +204,6 @@ private static ClassNode alignReturnType(final ClassNode receiver, final ClassNo return copiedReturnType; } - private static boolean isCandidateMethod(MethodNode declaredMethod) { ClassNode groovyMethods = GROOVY_OBJECT_CLASS_NODE; String methodName = declaredMethod.getName(); diff --git a/grails-datastore-core/build.gradle b/grails-datastore-core/build.gradle index 7a70a7915e8..1d9c21a87d8 100644 --- a/grails-datastore-core/build.gradle +++ b/grails-datastore-core/build.gradle @@ -101,5 +101,6 @@ apply { from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapter.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapter.java index db9ad5ba522..d3b983a996e 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapter.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapter.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.cache; import org.grails.datastore.mapping.cache.exception.CacheException; @@ -40,9 +39,11 @@ *

    * Concurrency: each TPCacheAdapter must be thread-safe. *

    + * * @author Roman Stepanenko */ public interface TPCacheAdapter { + /** * Stores a cached entry in a synchronous manner. *

    @@ -55,7 +56,8 @@ public interface TPCacheAdapter { * storing the entry the caller is notified about it via exception in the calling thread; also, if this method returns * successfully it means that the logistics of putting the specified value in the cache are fully done. *

    - * @param key the entry key + * + * @param key the entry key * @param entry the entry * @throws CacheException runtime exception indicating any cache-related problems */ @@ -63,6 +65,7 @@ public interface TPCacheAdapter { /** * Returns the stored value for the specified key. + * * @param key the entry key * @return the entry * @throws CacheException runtime exception indicating any cache-related problems diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapterRepository.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapterRepository.java index 30160e0419a..a74c45119a1 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapterRepository.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/TPCacheAdapterRepository.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.cache; import org.grails.datastore.mapping.model.PersistentEntity; @@ -27,8 +26,10 @@ * @author Roman Stepanenko */ public interface TPCacheAdapterRepository { + /** * Returns {@link TPCacheAdapter} for the specified {@link PersistentEntity}. + * * @param entity the entity * @return null if no {@link TPCacheAdapter} is found for the specified entity */ @@ -37,7 +38,8 @@ public interface TPCacheAdapterRepository { /** * Sets {@link TPCacheAdapter} for the specified {@link PersistentEntity}. * If the specified entity had another cache adapter before, the old one is ignored after this call. - * @param entity the entity + * + * @param entity the entity * @param cacheAdapter the adapter */ void setTPCacheAdapter(PersistentEntity entity, TPCacheAdapter cacheAdapter); @@ -45,16 +47,18 @@ public interface TPCacheAdapterRepository { /** * Sets {@link TPCacheAdapter} for the specified java class of {@link PersistentEntity}. * If the specified entity had another cache adapter before, the old one is ignored after this call. + * * @param entityJavaClass equivalent to {@link PersistentEntity#getJavaClass()} - * @param cacheAdapter the adapter + * @param cacheAdapter the adapter */ void setTPCacheAdapter(@SuppressWarnings("rawtypes") Class entityJavaClass, TPCacheAdapter cacheAdapter); /** * Sets {@link TPCacheAdapter} for the specified FQN java class of {@link PersistentEntity}. * If the specified entity had another cache adapter before, the old one is ignored after this call. + * * @param entityJavaClassFQN equivalent to {@link PersistentEntity#getJavaClass()}.getName() - * @param cacheAdapter the adapter + * @param cacheAdapter the adapter */ void setTPCacheAdapter(String entityJavaClassFQN, TPCacheAdapter cacheAdapter); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/exception/CacheException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/exception/CacheException.java index 915a85da09e..960dcb892d9 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/exception/CacheException.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/exception/CacheException.java @@ -16,14 +16,15 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.cache.exception; /** * Top-level exception used to report problems with third-party cache operations + * * @author Roman Stepanenko */ -public class CacheException extends RuntimeException{ +public class CacheException extends RuntimeException { + private static final long serialVersionUID = 1; public CacheException() { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/HashMapTPCacheAdapter.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/HashMapTPCacheAdapter.java index ff39edd8cec..a6b3b8436c0 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/HashMapTPCacheAdapter.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/HashMapTPCacheAdapter.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.cache.impl; import org.grails.datastore.mapping.cache.TPCacheAdapter; @@ -31,6 +30,9 @@ * @author Roman Stepanenko */ public class HashMapTPCacheAdapter implements TPCacheAdapter { + + private ConcurrentHashMap cache = new ConcurrentHashMap(); + public void cacheEntry(Serializable key, T entry) throws CacheException { cache.put(key, entry); } @@ -38,6 +40,4 @@ public void cacheEntry(Serializable key, T entry) throws CacheException { public T getCachedEntry(Serializable key) throws CacheException { return cache.get(key); } - - private ConcurrentHashMap cache = new ConcurrentHashMap(); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/TPCacheAdapterRepositoryImpl.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/TPCacheAdapterRepositoryImpl.java index d0eceec8632..76bfc900bfe 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/TPCacheAdapterRepositoryImpl.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/cache/impl/TPCacheAdapterRepositoryImpl.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.cache.impl; import org.grails.datastore.mapping.cache.TPCacheAdapter; @@ -31,6 +30,9 @@ * @author Roman Stepanenko */ public class TPCacheAdapterRepositoryImpl implements TPCacheAdapterRepository { + + private ConcurrentHashMap> adapters = new ConcurrentHashMap>(); + public TPCacheAdapter getTPCacheAdapter(PersistentEntity entity) { if (entity == null) { return null; @@ -50,6 +52,4 @@ public void setTPCacheAdapter(@SuppressWarnings("rawtypes") Class entityJavaClas public void setTPCacheAdapter(String entityJavaClassFQN, TPCacheAdapter cacheAdapter) { adapters.put(entityJavaClassFQN, cacheAdapter); } - - private ConcurrentHashMap> adapters = new ConcurrentHashMap>(); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/AbstractPersistentCollection.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/AbstractPersistentCollection.java index 4c8d263bb70..5d1287dd076 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/AbstractPersistentCollection.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/AbstractPersistentCollection.java @@ -32,6 +32,7 @@ */ @SuppressWarnings({"rawtypes", "unchecked"}) public abstract class AbstractPersistentCollection implements PersistentCollection, Serializable { + protected final transient Session session; protected final transient AssociationQueryExecutor indexer; protected final transient Class childType; @@ -137,7 +138,6 @@ public boolean hasChangedSize() { return isInitialized() && (size() != originalSize); } - /* Collection methods */ public Iterator iterator() { @@ -270,7 +270,9 @@ protected void setInitializing(Boolean initializing) { } public void initialize() { - if(initializing != null) return; + if (initializing != null) { + return; + } setInitializing(Boolean.TRUE); @@ -293,24 +295,21 @@ public void initialize() { loadInverseChildKeys(session, childType, keys); } - } - else { + } else { List results = indexer.query(associationKey); - if(indexer.doesReturnKeys()) { + if (indexer.doesReturnKeys()) { PersistentEntity entity = indexer.getIndexedEntity(); // This should really only happen for unit testing since entities are // mocked selectively and may not always be registered in the indexer. In this // case, there can't be any results to be added to the collection. - if( entity != null ) { + if (entity != null) { loadInverseChildKeys(session, entity.getJavaClass(), results); - } - else if(childType != null ){ + } else if (childType != null) { loadInverseChildKeys(session, childType, results); } - } - else { + } else { addAll(results); } } @@ -321,15 +320,14 @@ else if(childType != null ){ } protected void loadInverseChildKeys(Session session, Class childType, Collection keys) { - if(!keys.isEmpty()) { - if(proxyEntities) { + if (!keys.isEmpty()) { + if (proxyEntities) { for (Object key : keys) { add( session.proxy(childType, (Serializable) key) ); } - } - else { + } else { addAll(session.retrieveAll(childType, keys)); } } @@ -344,7 +342,7 @@ public void resetDirty() { } public void markDirty() { - if(!currentlyInitializing()) { + if (!currentlyInitializing()) { dirty = true; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentCollection.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentCollection.java index 059975b91f2..d6f7a2132ae 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentCollection.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentCollection.java @@ -33,6 +33,7 @@ public interface PersistentCollection extends Collection, DirtyCheckableCollecti /** * Check whether the collection has been loaded. + * * @return true if the collection has been initialized */ boolean isInitialized(); @@ -44,6 +45,7 @@ public interface PersistentCollection extends Collection, DirtyCheckableCollecti /** * Check whether the collection has been modified. + * * @return true if the collection is initialized and has been changed since initialization */ boolean isDirty(); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentList.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentList.java index f6426135ecd..5ca41adfa07 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentList.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentList.java @@ -14,16 +14,16 @@ */ package org.grails.datastore.mapping.collection; +import org.grails.datastore.mapping.core.Session; +import org.grails.datastore.mapping.engine.AssociationQueryExecutor; +import org.grails.datastore.mapping.model.types.Association; + import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.ListIterator; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.AssociationQueryExecutor; -import org.grails.datastore.mapping.model.types.Association; - /** * A lazy loaded list. * @@ -42,17 +42,17 @@ public PersistentList(Class childType, Session session, List collection) { public PersistentList(Collection keys, Class childType, Session session) { super(keys, childType, session, new ArrayList()); - list = (List)collection; + list = (List) collection; } public PersistentList(Serializable associationKey, Session session, AssociationQueryExecutor indexer) { super(associationKey, session, indexer, new ArrayList()); - list = (List)collection; + list = (List) collection; } public PersistentList(Association association, Serializable associationKey, Session session) { super(association, associationKey, session, new ArrayList()); - list = (List)collection; + list = (List) collection; } public int indexOf(Object o) { @@ -119,7 +119,7 @@ public List subList(int fromIndex, int toIndex) { return list.subList(fromIndex, toIndex); // not modification-aware } - private class PersistentListIterator implements ListIterator { + private final class PersistentListIterator implements ListIterator { private final ListIterator iterator; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSet.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSet.java index a82224fdc55..a441b7e4583 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSet.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSet.java @@ -18,15 +18,15 @@ */ package org.grails.datastore.mapping.collection; +import org.grails.datastore.mapping.core.Session; +import org.grails.datastore.mapping.engine.AssociationQueryExecutor; +import org.grails.datastore.mapping.model.types.Association; + import java.io.Serializable; import java.util.Collection; import java.util.HashSet; import java.util.Set; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.AssociationQueryExecutor; -import org.grails.datastore.mapping.model.types.Association; - /** * A lazy loaded set. * @@ -52,12 +52,12 @@ public PersistentSet(Collection keys, Class childType, Session session) { super(keys, childType, session, createCollection()); } - protected static HashSet createCollection() { - return new HashSet(); - } - public PersistentSet(Serializable associationKey, Session session, AssociationQueryExecutor indexer) { super(associationKey, session, indexer, createCollection()); } -} \ No newline at end of file + protected static HashSet createCollection() { + return new HashSet(); + } + +} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSortedSet.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSortedSet.java index f3533a0fa87..79cf7b01a54 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSortedSet.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/collection/PersistentSortedSet.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.collection; import org.grails.datastore.mapping.core.Session; @@ -24,7 +23,10 @@ import org.grails.datastore.mapping.model.types.Association; import java.io.Serializable; -import java.util.*; +import java.util.Collection; +import java.util.Comparator; +import java.util.SortedSet; +import java.util.TreeSet; /** * A lazy loaded sorted set. @@ -32,8 +34,9 @@ * @author Graeme Rocher * @since 1.0 */ -@SuppressWarnings({ "rawtypes", "unchecked" }) +@SuppressWarnings({"rawtypes", "unchecked"}) public class PersistentSortedSet extends AbstractPersistentCollection implements SortedSet { + public PersistentSortedSet(Association association, Serializable associationKey, Session session) { super(association, associationKey, session, new TreeSet()); } @@ -56,11 +59,11 @@ public Comparator comparator() { private SortedSet getSortedSet() { initialize(); - return ((SortedSet)collection); + return ((SortedSet) collection); } public SortedSet subSet(Object o, Object o1) { - return getSortedSet().subSet(o,o1); + return getSortedSet().subSet(o, o1); } public SortedSet headSet(Object o) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/column/ColumnDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/column/ColumnDatastore.java index 4872e3cac97..9e881a408f6 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/column/ColumnDatastore.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/column/ColumnDatastore.java @@ -23,4 +23,6 @@ /** * @author Guillaume Laforge */ -public interface ColumnDatastore extends Datastore {} \ No newline at end of file +public interface ColumnDatastore extends Datastore { + +} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/AbstractGormMappingFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/AbstractGormMappingFactory.java index 39c47f254b1..70d50b9cf2a 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/AbstractGormMappingFactory.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/AbstractGormMappingFactory.java @@ -16,24 +16,27 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.config; import groovy.lang.Closure; - -import java.beans.PropertyDescriptor; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.grails.datastore.mapping.config.groovy.DefaultMappingConfigurationBuilder; import org.grails.datastore.mapping.config.groovy.MappingConfigurationBuilder; import org.grails.datastore.mapping.keyvalue.mapping.config.Family; -import org.grails.datastore.mapping.model.*; +import org.grails.datastore.mapping.model.ClassMapping; +import org.grails.datastore.mapping.model.IdentityMapping; +import org.grails.datastore.mapping.model.MappingContext; +import org.grails.datastore.mapping.model.MappingFactory; +import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.config.GormProperties; import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; import org.springframework.beans.BeanUtils; +import java.beans.PropertyDescriptor; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Abstract GORM implementation that uses the GORM MappingConfigurationBuilder to configure entity mappings. * @@ -44,10 +47,10 @@ public abstract class AbstractGormMappingFactory> entityToPropertyMap = new HashMap>(); protected Map entityToMapping = new HashMap(); - private Closure defaultMapping; - private Object contextObject; protected Closure defaultConstraints; protected boolean versionByDefault = true; + private Closure defaultMapping; + private Object contextObject; /** * @param contextObject Context object to be passed to mapping blocks @@ -71,10 +74,9 @@ public void setVersionByDefault(boolean versionByDefault) { @Override public R createMappedForm(PersistentEntity entity) { - if(entityToMapping.containsKey(entity)) { + if (entityToMapping.containsKey(entity)) { return entityToMapping.get(entity); - } - else { + } else { R family = BeanUtils.instantiateClass(getEntityMappedFormType()); entityToMapping.put(entity, family); MappingConfigurationBuilder builder = createConfigurationBuilder(entity, family); @@ -85,33 +87,30 @@ public R createMappedForm(PersistentEntity entity) { if (defaultConstraints != null) { evaluateWithContext(builder, defaultConstraints); } - List values = ClassPropertyFetcher.getStaticPropertyValuesFromInheritanceHierarchy(entity.getJavaClass(),GormProperties.MAPPING, Object.class); + List values = ClassPropertyFetcher.getStaticPropertyValuesFromInheritanceHierarchy(entity.getJavaClass(), GormProperties.MAPPING, Object.class); for (Object value : values) { - if(value instanceof MappingDefinition && !(family instanceof Family)) { + if (value instanceof MappingDefinition && !(family instanceof Family)) { MappingDefinition definition = (MappingDefinition) value; definition.configure(family); - } - else if(value instanceof Closure) { + } else if (value instanceof Closure) { evaluateWithContext(builder, (Closure) value); } } - List constraintValues = ClassPropertyFetcher.getStaticPropertyValuesFromInheritanceHierarchy(entity.getJavaClass(),GormProperties.CONSTRAINTS, Closure.class); + List constraintValues = ClassPropertyFetcher.getStaticPropertyValuesFromInheritanceHierarchy(entity.getJavaClass(), GormProperties.CONSTRAINTS, Closure.class); for (Closure value : constraintValues) { evaluateWithContext(builder, value); } Map properties = builder.getProperties(); - entityToPropertyMap.put(entity, properties); return family; } } protected void evaluateWithContext(MappingConfigurationBuilder builder, Closure value) { - if(contextObject != null) { + if (contextObject != null) { builder.evaluate(value, contextObject); - } - else { + } else { builder.evaluate(value); } } @@ -131,16 +130,15 @@ public void setDefaultMapping(Closure defaultMapping) { @Override public boolean isTenantId(PersistentEntity entity, MappingContext context, PropertyDescriptor descriptor) { - if(entity.isMultiTenant()) { + if (entity.isMultiTenant()) { Map props = entityToPropertyMap.get(entity); - if(props != null && props.containsKey(GormProperties.TENANT_IDENTITY)) { + if (props != null && props.containsKey(GormProperties.TENANT_IDENTITY)) { T tenantIdProp = props.get(GormProperties.TENANT_IDENTITY); String propertyName = tenantIdProp.getName(); - if(descriptor.getName().equals(propertyName)) { + if (descriptor.getName().equals(propertyName)) { return true; } - } - else { + } else { return descriptor.getName().equals(GormProperties.TENANT_IDENTITY); } } @@ -151,8 +149,8 @@ public boolean isTenantId(PersistentEntity entity, MappingContext context, Prope public IdentityMapping createIdentityMapping(ClassMapping classMapping) { Map props = entityToPropertyMap.get(classMapping.getEntity()); if (props != null) { - T property = props.get(IDENTITY_PROPERTY); - IdentityMapping customIdentityMapping = getIdentityMappedForm(classMapping,property); + T property = props.get(IDENTITY_PROPERTY); + IdentityMapping customIdentityMapping = getIdentityMappedForm(classMapping, property); if (customIdentityMapping != null) { return customIdentityMapping; } @@ -161,10 +159,9 @@ public IdentityMapping createIdentityMapping(ClassMapping classMapping) { } protected IdentityMapping getIdentityMappedForm(final ClassMapping classMapping, T property) { - if(property != null) { + if (property != null) { return createDefaultIdentityMapping(classMapping, property); - } - else { + } else { return createDefaultIdentityMapping(classMapping); } } @@ -174,9 +171,8 @@ public T createMappedForm(PersistentProperty mpp) { Map properties = entityToPropertyMap.get(mpp.getOwner()); if (properties != null && properties.containsKey(mpp.getName())) { return properties.get(mpp.getName()); - } - else if (properties != null) { - Property property = properties.get(IDENTITY_PROPERTY); + } else if (properties != null) { + Property property = properties.get(IDENTITY_PROPERTY); if (property != null && mpp.getName().equals(property.getName())) { return (T) property; } @@ -189,8 +185,7 @@ else if (properties != null) { } catch (CloneNotSupportedException e) { return BeanUtils.instantiateClass(getPropertyMappedFormType()); } - } - else { + } else { return BeanUtils.instantiateClass(getPropertyMappedFormType()); } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/ConfigurationBuilder.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/ConfigurationBuilder.groovy index 447dc6cd623..137e1ee8a93 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/ConfigurationBuilder.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/ConfigurationBuilder.groovy @@ -35,14 +35,15 @@ import java.lang.reflect.Modifier /** * A generic configuration builder that implementers can implement to construct the configuration from the source {@link PropertyResolver} * - * @param The builder type (examples are MongoClientSettings.Builder or Neo4j Bolt's Config.ConfigBuilder - * @param The finalized configuration constructions from the builder (examples are MongoClientSettings or Neo4j Bolt's Config) + * @param The builder type (examples are MongoClientSettings.Builder or Neo4j Bolt's Config.ConfigBuilder + * @param The finalized configuration constructions from the builder (examples are MongoClientSettings or Neo4j Bolt's Config) * * @author Graeme Rocher */ @CompileStatic @Slf4j abstract class ConfigurationBuilder { + private static final Set IGNORE_METHODS = ['seProperty', 'propertyMissing'] as Set final PropertyResolver propertyResolver final String configurationPrefix @@ -75,7 +76,7 @@ abstract class ConfigurationBuilder { this.propertyResolver = propertyResolver this.configurationPrefix = configurationPrefix this.builderMethodPrefix = builderMethodPrefix - if(fallBackConfiguration != null) { + if (fallBackConfiguration != null) { def cloned try { cloned = fallBackConfiguration.clone() @@ -83,14 +84,11 @@ abstract class ConfigurationBuilder { cloned = fallBackConfiguration } this.fallBackConfiguration = cloned - } - else { + } else { this.fallBackConfiguration = null } } - - C build() { rootBuilder = createBuilder() buildInternal(rootBuilder, this.configurationPrefix) @@ -119,9 +117,9 @@ abstract class ConfigurationBuilder { private List toHierarchy(Class cls) { List classes = [cls] - while(cls != Object) { + while (cls != Object) { def superClass = cls.getSuperclass() - if(superClass == Object || superClass == LinkedHashMap) break + if (superClass == Object || superClass == LinkedHashMap) break classes.add(superClass) cls = superClass @@ -133,7 +131,7 @@ abstract class ConfigurationBuilder { * @deprecated use {@link ConfigurationBuilder#buildRecurse(Object, List, Object, String)} instead */ protected void buildRecurse(Object builder, Object fallBackConfig, String startingPrefix) { - buildRecurse(builder, new ArrayList(), fallBackConfig, startingPrefix) + buildRecurse(builder, new ArrayList(), fallBackConfig, startingPrefix) } protected void buildRecurse(Object builder, List builderQueue, Object fallBackConfig, String startingPrefix) { @@ -142,7 +140,7 @@ abstract class ConfigurationBuilder { startBuild(builder, startingPrefix) - for(Class builderClass in hierarchy) { + for (Class builderClass in hierarchy) { def methods = builderClass.declaredMethods for (method in methods) { @@ -161,17 +159,14 @@ abstract class ConfigurationBuilder { if (hasBuilderPrefix && methodName.startsWith(builderMethodPrefix)) { settingName = methodName.substring(builderMethodPrefix.size()).uncapitalize() - } - else if (hasBuilderPrefix) { + } else if (hasBuilderPrefix) { continue - } - else if (!hasBuilderPrefix && + } else if (!hasBuilderPrefix && ((org.grails.datastore.mapping.reflect.ReflectionUtils.isGetter(methodName, parameterTypes) && method.returnType.getAnnotation(Builder) == null) || org.grails.datastore.mapping.reflect.ReflectionUtils.isSetter(methodName, parameterTypes))) { // don't process getters or setters, unless the getter returns a builder continue - } - else { + } else { settingName = methodName } @@ -291,7 +286,6 @@ abstract class ConfigurationBuilder { newBuilder = (ConfigurationBuilder) argType.newInstance(this.propertyResolver, propertyPath) } - } newChildBuilder(newBuilder, propertyPath) method.invoke(builder, newBuilder) @@ -338,7 +332,7 @@ abstract class ConfigurationBuilder { boolean appendArgName = parameterTypes.length > 1 int argIndex = 0 - for (Class argType: parameterTypes) { + for (Class argType : parameterTypes) { String propertyPathForArg = propertyPath if (appendArgName) { propertyPathForArg += ".arg${argIndex}" @@ -355,29 +349,26 @@ abstract class ConfigurationBuilder { } catch (Throwable e) { throw new ConfigurationException("Cannot read configuration for path $propertyPathForArg: $e.message", e) } - } - else { + } else { Object fallBackValue = getFallBackValue(fallBackConfig, settingName) def value try { value = propertyResolver.getProperty(propertyPathForArg, argType, fallBackValue) } catch (ConversionFailedException e) { - if(argType.isEnum()) { + if (argType.isEnum()) { value = propertyResolver.getProperty(propertyPathForArg, String) if (value != null) { try { - value = Enum.valueOf((Class)argType, value.toUpperCase()) + value = Enum.valueOf((Class) argType, value.toUpperCase()) } catch (Throwable e2) { // ignore e2 and throw original throw new ConfigurationException("Invalid value for setting [$propertyPathForArg]: $e.message", e) } - } - else { + } else { throw new ConfigurationException("Invalid value for setting [$propertyPathForArg]: $e.message", e) } - } - else { + } else { throw new ConfigurationException("Invalid value for setting [$propertyPathForArg]: $e.message", e) } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/ConfigurationUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/ConfigurationUtils.java index 9149c188bdb..5c9812489a7 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/ConfigurationUtils.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/ConfigurationUtils.java @@ -28,7 +28,7 @@ /** * Utility methods for configuration - * + * * @author Graeme Rocher * @since 6.0 */ @@ -37,10 +37,10 @@ public class ConfigurationUtils { /** * Finds services of the given type from configuration or via {@link ServiceLoader} * - * @param configuration The configuration + * @param configuration The configuration * @param configurationKey The configuration key - * @param serviceType The type of service - * @param The service type + * @param serviceType The type of service + * @param The service type * @return A list of services */ public static Iterable findServices(PropertyResolver configuration, String configurationKey, Class serviceType) { @@ -52,27 +52,25 @@ public static Iterable findServices(PropertyResolver configuration, Strin * Finds services of the given type from the given list or via {@link ServiceLoader} * * @param servicesList The list of services - * @param serviceType The type of service - * @param The service type + * @param serviceType The type of service + * @param The service type * @return A list of services */ public static Iterable findServices(List servicesList, Class serviceType) { List services = new ArrayList<>(); - if(servicesList != null) { + if (servicesList != null) { for (Object serviceObject : servicesList) { - if(serviceType.isInstance(serviceObject)) { - services.add((T)serviceObject); - } - else { + if (serviceType.isInstance(serviceObject)) { + services.add((T) serviceObject); + } else { Class serviceTypeClass = null; - if(serviceObject instanceof Class) { + if (serviceObject instanceof Class) { serviceTypeClass = (Class) serviceObject; + } else if (serviceObject instanceof CharSequence) { + serviceTypeClass = ReflectionUtils.forName(serviceObject.toString(), ConfigurationUtils.class.getClassLoader()); } - else if(serviceObject instanceof CharSequence) { - serviceTypeClass = ReflectionUtils.forName(serviceObject.toString(),ConfigurationUtils.class.getClassLoader()); - } - if(serviceTypeClass != null && serviceType.isAssignableFrom(serviceTypeClass)) { + if (serviceTypeClass != null && serviceType.isAssignableFrom(serviceTypeClass)) { T serviceInstance = (T) ReflectionUtils.instantiate(serviceTypeClass); services.add(serviceInstance); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Entity.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Entity.groovy index f68d821ab7e..7e4d950ee41 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Entity.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Entity.groovy @@ -96,7 +96,7 @@ class Entity

    { * Get the datasource names that this domain class works with. * @return the datasource names */ - List datasources = [ ConnectionSource.DEFAULT ] + List datasources = [ConnectionSource.DEFAULT] /** * Sets the datastore to use @@ -109,7 +109,6 @@ class Entity

    { return this } - /** * Sets the datastore to use * @@ -121,14 +120,13 @@ class Entity

    { return this } - /** * Sets the connection to use * * @param name * @return */ - Entity

    connections(String...names) { + Entity

    connections(String... names) { connections(Arrays.asList(names)) return this } @@ -140,7 +138,7 @@ class Entity

    { * @return */ Entity

    connections(List names) { - if(names != null && names.size() > 0) { + if (names != null && names.size() > 0) { this.datasources = names } return this @@ -167,8 +165,8 @@ class Entity

    { */ Entity

    id(Map identityConfig) { Property.configureExisting( - getOrInitializePropertyConfig(GormProperties.IDENTITY), - identityConfig + getOrInitializePropertyConfig(GormProperties.IDENTITY), + identityConfig ) return this } @@ -177,7 +175,7 @@ class Entity

    { * @param identityConfig The id config * @return This mapping */ - Entity

    id(@DelegatesTo(type='P') Closure identityConfig) { + Entity

    id(@DelegatesTo(type = 'P') Closure identityConfig) { Property.configureExisting( getOrInitializePropertyConfig(GormProperties.IDENTITY), identityConfig @@ -190,7 +188,7 @@ class Entity

    { * * @param isVersioned True if a version property should be configured */ - Entity

    version(@DelegatesTo(type='P') Closure versionConfig) { + Entity

    version(@DelegatesTo(type = 'P') Closure versionConfig) { P pc = getOrInitializePropertyConfig(GormProperties.VERSION) Property.configureExisting(pc, versionConfig) return this @@ -223,7 +221,7 @@ class Entity

    { * @param propertyConfig The property config * @return This mapping */ - Entity

    property(String name, @DelegatesTo(type='P') Closure propertyConfig) { + Entity

    property(String name, @DelegatesTo(type = 'P') Closure propertyConfig) { P pc = getOrInitializePropertyConfig(name) Property.configureExisting(pc, propertyConfig) return this @@ -247,12 +245,11 @@ class Entity

    { * @param propertyConfig The property config * @return This mapping */ - P property(@DelegatesTo(type='P') Closure propertyConfig) { - if(propertyConfigs.containsKey('*')) { + P property(@DelegatesTo(type = 'P') Closure propertyConfig) { + if (propertyConfigs.containsKey('*')) { P cloned = cloneGlobalConstraint() return Property.configureExisting(cloned, propertyConfig) - } - else { + } else { P prop = newProperty() return Property.configureExisting(prop, propertyConfig) } @@ -264,13 +261,12 @@ class Entity

    { * @param propertyConfig The property config * @return This mapping */ - P property( Map propertyConfig) { - if(propertyConfigs.containsKey('*')) { + P property(Map propertyConfig) { + if (propertyConfigs.containsKey('*')) { // apply global constraints constraints P cloned = cloneGlobalConstraint() return Property.configureExisting(cloned, propertyConfig) - } - else { + } else { P prop = newProperty() return Property.configureExisting(prop, propertyConfig) } @@ -290,57 +286,50 @@ class Entity

    { } def propertyMissing(String name, Object val) { - if(val instanceof Closure) { - property(name, (Closure)val) - } - else if(val instanceof Property) { - propertyConfigs[name] =((P)val) - } - else { + if (val instanceof Closure) { + property(name, (Closure) val) + } else if (val instanceof Property) { + propertyConfigs[name] = ((P) val) + } else { throw new MissingPropertyException(name, Entity) } } @CompileDynamic def methodMissing(String name, Object args) { - if(args && args.getClass().isArray()) { - if(args[0] instanceof Closure) { - property(name, (Closure)args[0]) - } - else if(args[0] instanceof Property) { - propertyConfigs[name] = (P)args[0] - } - else if(args[0] instanceof Map) { + if (args && args.getClass().isArray()) { + if (args[0] instanceof Closure) { + property(name, (Closure) args[0]) + } else if (args[0] instanceof Property) { + propertyConfigs[name] = (P) args[0] + } else if (args[0] instanceof Map) { P property = getOrInitializePropertyConfig(name) Map namedArgs = (Map) args[0] - if(args[-1] instanceof Closure) { + if (args[-1] instanceof Closure) { Property.configureExisting( property, - ((Closure)args[-1]) + ((Closure) args[-1]) ) } Property.configureExisting(property, namedArgs) - } - else { + } else { throw new MissingMethodException(name, getClass(), args) } - } - else { + } else { throw new MissingMethodException(name, getClass(), args) } } protected P getOrInitializePropertyConfig(String name) { P pc = propertyConfigs[name] - if(pc == null && propertyConfigs.containsKey('*')) { + if (pc == null && propertyConfigs.containsKey('*')) { // apply global constraints constraints P globalConstraints = propertyConfigs.get('*') - if(globalConstraints != null) { - pc = (P)globalConstraints.clone() + if (globalConstraints != null) { + pc = (P) globalConstraints.clone() } - } - else { + } else { pc = propertyConfigs[name] } if (pc == null) { @@ -351,7 +340,7 @@ class Entity

    { } protected P newProperty() { - (P)new Property() + (P) new Property() } protected P cloneGlobalConstraint() { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Property.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Property.groovy index 39b30bd5887..c62b988023f 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Property.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Property.groovy @@ -22,13 +22,12 @@ import groovy.transform.CompileDynamic import groovy.transform.CompileStatic import groovy.transform.builder.Builder import groovy.transform.builder.SimpleStrategy -import org.springframework.beans.MutablePropertyValues -import org.springframework.validation.DataBinder - import jakarta.persistence.AccessType import jakarta.persistence.CascadeType import jakarta.persistence.EnumType import jakarta.persistence.FetchType +import org.springframework.beans.MutablePropertyValues +import org.springframework.validation.DataBinder /** * Base class for classes returned from {@link org.grails.datastore.mapping.model.PropertyMapping#getMappedForm()} @@ -157,7 +156,7 @@ class Property implements Cloneable { Property clone() throws CloneNotSupportedException { Property cloned = (Property) super.clone() cloned.uniquenessGroup = new ArrayList<>(uniquenessGroup) - if(inList != null) { + if (inList != null) { cloned.inList = new ArrayList<>(inList) } @@ -251,7 +250,6 @@ class Property implements Cloneable { return !uniquenessGroup.isEmpty() } - void setUnique(boolean unique) { this.unique = unique } @@ -310,7 +308,7 @@ class Property implements Cloneable { * @param config The configuration * @return The new instance */ - static T configureExisting(T property, @DelegatesTo(Property) Closure config) { + static T configureExisting(T property, @DelegatesTo(Property) Closure config) { config.setDelegate(property) config.setResolveStrategy(Closure.DELEGATE_ONLY) config.call() diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Settings.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Settings.java index e7f24385385..d25fe0856b0 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Settings.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/Settings.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.config; /** @@ -26,6 +25,7 @@ * @since 6.0 */ public interface Settings { + /** * The default prefix */ @@ -78,7 +78,6 @@ public interface Settings { */ String SETTING_DATASOURCES = "dataSources"; - /** * The data source setting */ diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/groovy/DefaultMappingConfigurationBuilder.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/groovy/DefaultMappingConfigurationBuilder.groovy index 5a90a413aff..1a9511e435a 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/groovy/DefaultMappingConfigurationBuilder.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/groovy/DefaultMappingConfigurationBuilder.groovy @@ -25,8 +25,6 @@ import org.grails.datastore.mapping.reflect.NameUtils import org.springframework.beans.MutablePropertyValues import org.springframework.validation.DataBinder -import java.lang.reflect.Constructor - /** * @author Graeme Rocher * @since 1.0 @@ -46,8 +44,8 @@ class DefaultMappingConfigurationBuilder implements MappingConfigurationBuilder } Map getProperties() { - if(!target.propertyConfigs.isEmpty()) { - properties.putAll( target.propertyConfigs ) + if (!target.propertyConfigs.isEmpty()) { + properties.putAll(target.propertyConfigs) } return properties } @@ -66,18 +64,15 @@ class DefaultMappingConfigurationBuilder implements MappingConfigurationBuilder def setterName = NameUtils.getSetterName(name) if (target.respondsTo(setterName)) { target[name] = args.size() == 1 ? args[0] : args - } - else { - if(target.respondsTo(name)) { + } else { + if (target.respondsTo(name)) { target."$name"(*args) - } - else if (args.size() == 1 && args[0] instanceof Map) { + } else if (args.size() == 1 && args[0] instanceof Map) { def instance if (properties['*']) { instance = properties['*'].clone() - } - else { + } else { instance = properties[name] ?: propertyClass.newInstance() } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/ConfigUtils.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/ConfigUtils.groovy index b28627599b3..9244329eaed 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/ConfigUtils.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/ConfigUtils.groovy @@ -22,7 +22,6 @@ import groovy.transform.CompileStatic import org.grails.datastore.mapping.model.types.conversion.DefaultConversionService import org.springframework.core.convert.ConversionService - /** * @author Graeme Rocher * @since 3.0 @@ -30,6 +29,7 @@ import org.springframework.core.convert.ConversionService @CompileStatic @Deprecated class ConfigUtils { + private static ConversionService conversionService = new DefaultConversionService(); public static T read(Class type, String key, Map config, T defaultValue) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/PropertyResolverMap.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/PropertyResolverMap.groovy index 13e371cd3e6..b4fb9ae562a 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/PropertyResolverMap.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/config/utils/PropertyResolverMap.groovy @@ -21,8 +21,6 @@ package org.grails.datastore.mapping.config.utils import groovy.transform.CompileStatic import org.springframework.core.env.PropertyResolver - - /** * Adapts a property resolver to the Map interface * @@ -32,7 +30,9 @@ import org.springframework.core.env.PropertyResolver @CompileStatic @Deprecated class PropertyResolverMap implements Map, PropertyResolver { - @Delegate final PropertyResolver propertyResolver + + @Delegate + final PropertyResolver propertyResolver PropertyResolverMap(PropertyResolver propertyResolver) { this.propertyResolver = propertyResolver diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractAttributeStoringSession.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractAttributeStoringSession.java index 77e43bded70..b69893f8461 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractAttributeStoringSession.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractAttributeStoringSession.java @@ -16,15 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - import org.grails.datastore.mapping.transactions.SessionHolder; import org.springframework.transaction.support.TransactionSynchronizationManager; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + public abstract class AbstractAttributeStoringSession implements Session { protected Map> attributes = new ConcurrentHashMap>(); @@ -113,9 +112,8 @@ public void disconnect() { try { clear(); attributes.clear(); - } - finally { - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(getDatastore()); + } finally { + SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(getDatastore()); if (sessionHolder != null) { sessionHolder.removeSession(this); if (sessionHolder.isEmpty()) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractDatastore.java index 48c2e17c936..479c30920f0 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractDatastore.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractDatastore.java @@ -17,6 +17,7 @@ import groovy.lang.Closure; import groovy.lang.GroovySystem; import groovy.lang.MetaClassRegistry; +import jakarta.annotation.PreDestroy; import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.model.MappingContext; @@ -39,7 +40,6 @@ import org.springframework.core.env.PropertyResolver; import org.springframework.transaction.support.TransactionSynchronizationManager; -import jakarta.annotation.PreDestroy; import java.util.Map; /** @@ -50,27 +50,27 @@ */ @SuppressWarnings({"rawtypes", "unchecked"}) public abstract class AbstractDatastore implements Datastore, StatelessDatastore, ServiceRegistry { + protected static final Logger LOG = LoggerFactory.getLogger(AbstractDatastore.class); - private ApplicationContext applicationContext; protected final MappingContext mappingContext; protected final ServiceRegistry serviceRegistry; protected final PropertyResolver connectionDetails; protected final TPCacheAdapterRepository cacheAdapterRepository; - + private ApplicationContext applicationContext; public AbstractDatastore(MappingContext mappingContext) { - this(mappingContext,(PropertyResolver) null, null); + this(mappingContext, (PropertyResolver) null, null); } public AbstractDatastore(MappingContext mappingContext, Map connectionDetails, - ConfigurableApplicationContext ctx) { - this(mappingContext, connectionDetails, ctx, null); + ConfigurableApplicationContext ctx) { + this(mappingContext, connectionDetails, ctx, null); } public AbstractDatastore(MappingContext mappingContext, PropertyResolver connectionDetails, ConfigurableApplicationContext ctx) { - this(mappingContext, connectionDetails, ctx, null); + this(mappingContext, connectionDetails, ctx, null); } public AbstractDatastore(MappingContext mappingContext, PropertyResolver connectionDetails, @@ -85,11 +85,11 @@ public AbstractDatastore(MappingContext mappingContext, PropertyResolver connect } public AbstractDatastore(MappingContext mappingContext, Map connectionDetails, - ConfigurableApplicationContext ctx, TPCacheAdapterRepository cacheAdapterRepository) { + ConfigurableApplicationContext ctx, TPCacheAdapterRepository cacheAdapterRepository) { this(mappingContext, mapToPropertyResolver(connectionDetails), ctx, cacheAdapterRepository); } - protected static PropertyResolver mapToPropertyResolver(Map connectionDetails) { + protected static PropertyResolver mapToPropertyResolver(Map connectionDetails) { return DatastoreUtils.createPropertyResolver(connectionDetails); } @@ -112,7 +112,7 @@ public void destroy() { try { registry.removeMetaClass(cls); } catch (Exception e) { - LOG.error("There was an error shutting down GORM for entity ["+cls.getName()+"]: " + e.getMessage(), e); + LOG.error("There was an error shutting down GORM for entity [" + cls.getName() + "]: " + e.getMessage(), e); } } } @@ -133,7 +133,7 @@ public final Session connect(PropertyResolver connDetails) { private void publishSessionCreationEvent(Session session) { ApplicationEventPublisher applicationEventPublisher = getApplicationEventPublisher(); - if(applicationEventPublisher != null) { + if (applicationEventPublisher != null) { applicationEventPublisher.publishEvent(new SessionCreationEvent(session)); } } @@ -145,7 +145,6 @@ public Session connectStateless() { return session; } - /** * Creates the native session * @@ -164,7 +163,6 @@ protected Session createStatelessSession(PropertyResolver connectionDetails) { return createSession(connectionDetails); } - public Session getCurrentSession() throws ConnectionNotFoundException { return DatastoreUtils.doGetSession(this, false); } @@ -175,6 +173,7 @@ public boolean hasCurrentSession() { /** * Static way to retrieve the session + * * @return The session instance * @throws ConnectionNotFoundException If no session has been created */ @@ -184,6 +183,7 @@ public static Session retrieveSession() throws ConnectionNotFoundException { /** * Static way to retrieve the session + * * @param datastoreClass The type of datastore * @return The session instance * @throws ConnectionNotFoundException If no session has been created @@ -214,19 +214,17 @@ public MappingContext getMappingContext() { } /** - * @deprecated Deprecated, will be removed in a future version of GORM + * @deprecated Deprecated, will be removed in a future version of GORM */ @Deprecated public ConfigurableApplicationContext getApplicationContext() { - return (ConfigurableApplicationContext)applicationContext; + return (ConfigurableApplicationContext) applicationContext; } - public ApplicationEventPublisher getApplicationEventPublisher() { return getApplicationContext(); } - protected void initializeConverters(MappingContext mappingContext) { final ConverterRegistry conversionService = mappingContext.getConverterRegistry(); BasicTypeConverterRegistrar registrar = new BasicTypeConverterRegistrar(); @@ -243,7 +241,6 @@ public boolean isSchemaless() { return false; } - @Override public T withSession(final Closure callable) { return DatastoreUtils.execute(this, new SessionCallback() { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractSession.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractSession.java index 3f248557dfd..8588cc99af8 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractSession.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/AbstractSession.java @@ -16,6 +16,7 @@ import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.RemovalListener; +import jakarta.persistence.FlushModeType; import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; import org.grails.datastore.mapping.config.Entity; import org.grails.datastore.mapping.core.impl.PendingDelete; @@ -48,7 +49,6 @@ import org.springframework.transaction.support.DefaultTransactionDefinition; import org.springframework.util.Assert; -import jakarta.persistence.FlushModeType; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; @@ -61,7 +61,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; - /** * Abstract implementation of the {@link org.grails.datastore.mapping.core.Session} interface that uses * a list of {@link org.grails.datastore.mapping.engine.Persister} instances @@ -100,18 +99,22 @@ public abstract class AbstractSession extends AbstractAttributeStoringSession protected Map persisters = new ConcurrentHashMap<>(); protected boolean isSynchronizedWithTransaction = false; - private MappingContext mappingContext; protected ConcurrentLinkedQueue lockedObjects = new ConcurrentLinkedQueue(); protected Transaction transaction; - private Datastore datastore; - private FlushModeType flushMode = FlushModeType.AUTO; protected Map> firstLevelCache = new ConcurrentHashMap<>(); protected Map> firstLevelEntryCache = new ConcurrentHashMap<>(); protected Map> firstLevelEntryCacheDirtyCheck = new ConcurrentHashMap<>(); protected Map firstLevelCollectionCache = new ConcurrentHashMap<>(); - protected TPCacheAdapterRepository cacheAdapterRepository; + protected Collection postFlushOperations = new ConcurrentLinkedQueue<>(); + protected ApplicationEventPublisher publisher; + + protected boolean stateless = false; + protected boolean flushActive = false; + private MappingContext mappingContext; + private Datastore datastore; + private FlushModeType flushMode = FlushModeType.AUTO; private Collection objectsPendingOperations = new ConcurrentLinkedQueue<>(); private Map> pendingInserts = Caffeine.newBuilder() @@ -131,13 +134,7 @@ public abstract class AbstractSession extends AbstractAttributeStoringSession .executor(Runnable::run) .maximumSize(5000).build().asMap(); - protected Collection postFlushOperations = new ConcurrentLinkedQueue<>(); private boolean exceptionOccurred; - protected ApplicationEventPublisher publisher; - - protected boolean stateless = false; - protected boolean flushActive = false; - public AbstractSession(Datastore datastore, MappingContext mappingContext, ApplicationEventPublisher publisher) { @@ -253,12 +250,16 @@ public void addPendingDelete(PendingDelete delete) { } public Object getCachedEntry(PersistentEntity entity, Serializable key) { - if (isStateless(entity)) return null; + if (isStateless(entity)) { + return null; + } return getCachedEntry(entity, key, false); } public Object getCachedEntry(PersistentEntity entity, Serializable key, boolean forDirtyCheck) { - if (isStateless(entity)) return null; + if (isStateless(entity)) { + return null; + } if (key == null) { return null; } @@ -267,7 +268,9 @@ public Object getCachedEntry(PersistentEntity entity, Serializable key, boolean } public void cacheEntry(PersistentEntity entity, Serializable key, Object entry) { - if (isStateless(entity)) return; + if (isStateless(entity)) { + return; + } if (key == null || entry == null) { return; } @@ -282,12 +285,16 @@ public boolean isStateless(PersistentEntity entity) { } protected void cacheEntry(Serializable key, Object entry, Map entryCache, boolean forDirtyCheck) { - if (isStateless()) return; + if (isStateless()) { + return; + } entryCache.put(key, entry); } public Collection getCachedCollection(PersistentEntity entity, Serializable key, String name) { - if (isStateless(entity)) return null; + if (isStateless(entity)) { + return null; + } if (key == null || name == null) { return null; } @@ -297,7 +304,9 @@ public Collection getCachedCollection(PersistentEntity entity, Serializable key, } public void cacheCollection(PersistentEntity entity, Serializable key, Collection collection, String name) { - if (isStateless(entity)) return; + if (isStateless(entity)) { + return; + } if (key == null || collection == null || name == null) { return; } @@ -336,7 +345,9 @@ public MappingContext getMappingContext() { } public void flush() { - if (flushActive) return; + if (flushActive) { + return; + } boolean hasInserts; try { @@ -378,7 +389,6 @@ public boolean isDirty(Object instance) { return false; } - EntityPersister persister = (EntityPersister) getPersister(instance); if (persister == null) { return false; @@ -412,7 +422,6 @@ public Serializable getObjectIdentifier(Object instance) { return null; } - /** * The default implementation of flushPendingUpdates is to iterate over each update operation * and execute them one by one. This may be suboptimal for stores that support batch update @@ -497,7 +506,9 @@ private void clearMaps(Map> mapOfMaps) { } public final Persister getPersister(Object o) { - if (o == null) return null; + if (o == null) { + return null; + } Class cls; if (o instanceof Class) { cls = (Class) o; @@ -547,16 +558,22 @@ public void cacheInstance(Class type, Serializable key, Object instance) { if (type == null || key == null || instance == null) { return; } - if (isStateless(getMappingContext().getPersistentEntity(type.getName()))) return; + if (isStateless(getMappingContext().getPersistentEntity(type.getName()))) { + return; + } getInstanceCache(type).put(key, instance); } public Object getCachedInstance(Class type, Serializable key) { - if (isStateless()) return null; + if (isStateless()) { + return null; + } if (type == null || key == null) { return null; } - if (isStateless(getMappingContext().getPersistentEntity(type.getName()))) return null; + if (isStateless(getMappingContext().getPersistentEntity(type.getName()))) { + return null; + } return getInstanceCache(type).get(key); } @@ -760,7 +777,6 @@ public void delete(final Object obj) { return; } - p.delete(obj); clear(obj); } @@ -782,7 +798,8 @@ public void delete(final Iterable objects) { } List listForPersister = toDelete.get(p); if (listForPersister == null) { - toDelete.put(p, listForPersister = new ArrayList()); + listForPersister = new ArrayList(); + toDelete.put(p, listForPersister); } listForPersister.add(object); } @@ -933,7 +950,8 @@ public void setSynchronizedWithTransaction(boolean isSynchronizedWithTransaction this.isSynchronizedWithTransaction = isSynchronizedWithTransaction; } - private static class CollectionKey { + private static final class CollectionKey { + final Class clazz; final Serializable key; final String collectionName; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Datastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Datastore.java index df94d43ea52..d56137f6551 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Datastore.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Datastore.java @@ -46,14 +46,15 @@ public interface Datastore extends ServiceRegistry { /** * Obtains the current session (if any) - * @return The current thread bound session * + * @return The current thread bound session * @throws ConnectionNotFoundException Thrown if the {@link #connect()} method has not yet been called */ Session getCurrentSession() throws ConnectionNotFoundException; /** * Checks if there is a current session. + * * @return true if there's a bound active session */ boolean hasCurrentSession(); @@ -67,17 +68,18 @@ public interface Datastore extends ServiceRegistry { /** * Get the application event publisher. + * * @return the publisher */ ApplicationEventPublisher getApplicationEventPublisher(); /** * Get the application context. + * * @return the context */ ConfigurableApplicationContext getApplicationContext(); - /** * Whether the datastore is schema-less. That is it allows changes to the schema runtime, dynamic attributes etc. * @@ -89,9 +91,9 @@ public interface Datastore extends ServiceRegistry { * Execute the given closure with a session * * @param callable The callable - * @param The return type + * @param The return type * @return An instance of the return type */ - public T withSession(Closure callable); + T withSession(Closure callable); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreAware.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreAware.java index 2a278db89fb..711a77ec0dd 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreAware.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreAware.java @@ -28,6 +28,7 @@ public interface DatastoreAware { /** * Sets the datastore on this instance + * * @param datastore The datastore */ void setDatastore(Datastore datastore); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreUtils.java index 2a60febf845..8ce5f9e866c 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreUtils.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/DatastoreUtils.java @@ -15,22 +15,12 @@ package org.grails.datastore.mapping.core; import groovy.lang.Closure; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - import groovy.util.ConfigObject; import groovy.util.ConfigSlurper; import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.grails.datastore.mapping.config.DatastoreEnvironment; +import org.grails.datastore.mapping.transactions.SessionHolder; +import org.grails.datastore.mapping.transactions.support.SpringSessionSynchronization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.NamedThreadLocal; @@ -45,12 +35,21 @@ import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.dao.DataAccessResourceFailureException; -import org.grails.datastore.mapping.transactions.SessionHolder; -import org.grails.datastore.mapping.transactions.support.SpringSessionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + /** * Helper class for obtaining Datastore sessions. Based on similar work * for Hibernate such as SessionFactoryUtils @@ -61,9 +60,9 @@ @SuppressWarnings("rawtypes") public abstract class DatastoreUtils { - private static final Logger logger = LoggerFactory.getLogger(DatastoreUtils.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DatastoreUtils.class); private static final String DATASTORE_CONFIG_FLAT = "datastoreConfigFlat"; - private static final ThreadLocal>> deferredCloseHolder = + private static final ThreadLocal>> DEFERRED_CLOSE_HOLDER = new NamedThreadLocal>>( "Datastore Sessions registered for deferred close"); private static final String DATASTORE_CONFIG = "datastoreConfig"; @@ -77,21 +76,20 @@ public abstract class DatastoreUtils { * in combination with releaseSession called when done with * the Session. * - * @param datastore Datastore to create the session with + * @param datastore Datastore to create the session with * @param allowCreate whether a non-transactional Session should be created - * when no transactional Session can be found for the current thread + * when no transactional Session can be found for the current thread * @return the Datastore Session * @throws org.springframework.dao.DataAccessResourceFailureException if the Session couldn't be created - * @throws IllegalStateException if no thread-bound Session found and - * "allowCreate" is false + * @throws IllegalStateException if no thread-bound Session found and + * "allowCreate" is false */ public static Session getSession(Datastore datastore, boolean allowCreate) throws DataAccessResourceFailureException, IllegalStateException { try { return doGetSession(datastore, allowCreate); - } - catch (Exception ex) { + } catch (Exception ex) { throw new DataAccessResourceFailureException("Could not open Datastore Session", ex); } } @@ -102,13 +100,13 @@ public static Session getSession(Datastore datastore, boolean allowCreate) * example when using {@link org.grails.datastore.mapping.transactions.DatastoreTransactionManager}. Will create a new * Session otherwise, if "allowCreate" is true. * - * @param datastore Datastore to create the session with - * Session on transaction synchronization (may be null) + * @param datastore Datastore to create the session with + * Session on transaction synchronization (may be null) * @param allowCreate whether a non-transactional Session should be created - * when no transactional Session can be found for the current thread + * when no transactional Session can be found for the current thread * @return the Datastore Session * @throws IllegalStateException if no thread-bound Session found and - * "allowCreate" is false + * "allowCreate" is false */ public static Session doGetSession(Datastore datastore, boolean allowCreate) { @@ -125,8 +123,8 @@ public static Session doGetSession(Datastore datastore, boolean allowCreate) { // register pre-bound Session with it for transactional flushing. session = sessionHolder.getValidatedSession(); if (session != null && !sessionHolder.isSynchronizedWithTransaction()) { - if(logger.isDebugEnabled()) { - logger.debug("Registering Spring transaction synchronization for existing Datastore Session"); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Registering Spring transaction synchronization for existing Datastore Session"); } TransactionSynchronizationManager.registerSynchronization( new SpringSessionSynchronization(sessionHolder, datastore, false)); @@ -136,8 +134,7 @@ public static Session doGetSession(Datastore datastore, boolean allowCreate) { if (session != null) { return session; } - } - else { + } else { session = sessionHolder.getValidatedSession(); if (session != null) { return session; @@ -145,8 +142,8 @@ public static Session doGetSession(Datastore datastore, boolean allowCreate) { } } - if(logger.isDebugEnabled()) { - logger.debug("Opening Datastore Session"); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Opening Datastore Session"); } Session session = datastore.connect(); @@ -154,14 +151,13 @@ public static Session doGetSession(Datastore datastore, boolean allowCreate) { // Thread object will get removed by synchronization at transaction completion. if (TransactionSynchronizationManager.isSynchronizationActive()) { // We're within a Spring-managed transaction, possibly from JtaTransactionManager. - if(logger.isDebugEnabled()) { - logger.debug("Registering Spring transaction synchronization for new Datastore Session"); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Registering Spring transaction synchronization for new Datastore Session"); } SessionHolder holderToUse = sessionHolder; if (holderToUse == null) { holderToUse = new SessionHolder(session); - } - else { + } else { holderToUse.addSession(session); } TransactionSynchronizationManager.registerSynchronization( @@ -176,7 +172,7 @@ public static Session doGetSession(Datastore datastore, boolean allowCreate) { if (!allowCreate && !isSessionTransactional(session, datastore)) { closeSession(session); throw new IllegalStateException("No Datastore Session bound to thread, " + - "and configuration does not allow creation of non-transactional one here"); + "and configuration does not allow creation of non-transactional one here"); } return session; @@ -185,9 +181,10 @@ public static Session doGetSession(Datastore datastore, boolean allowCreate) { /** * Return whether the given Datastore Session is transactional, that is, * bound to the current thread by Spring's transaction facilities. - * @param session the Datastore Session to check + * + * @param session the Datastore Session to check * @param datastore Datastore that the Session was created with - * (may be null) + * (may be null) * @return whether the Session is transactional */ public static boolean isSessionTransactional(Session session, Datastore datastore) { @@ -202,6 +199,7 @@ public static boolean isSessionTransactional(Session session, Datastore datastor /** * Perform actual closing of the Session, * catching and logging any cleanup exceptions thrown. + * * @param session The Session instance */ public static void closeSession(Session session) { @@ -209,21 +207,21 @@ public static void closeSession(Session session) { return; } - logger.debug("Closing Datastore Session"); + LOGGER.debug("Closing Datastore Session"); try { session.disconnect(); - } - catch (Throwable ex) { - logger.debug("Unexpected exception on closing Datastore Session", ex); + } catch (Throwable ex) { + LOGGER.debug("Unexpected exception on closing Datastore Session", ex); } } /** * Close the given Session, created via the given factory, * if it is not managed externally (i.e. not bound to the thread). - * @param session the Datastore Session to close (may be null) + * + * @param session the Datastore Session to close (may be null) * @param datastore Datastore that the Session was created with - * (may be null) + * (may be null) */ public static void releaseSession(Session session, Datastore datastore) { if (session == null) { @@ -238,25 +236,26 @@ public static void releaseSession(Session session, Datastore datastore) { /** * Process all Datastore Sessions that have been registered for deferred close * for the given SessionFactory. + * * @param datastore the Datastore to process deferred close for * @see #initDeferredClose * @see #releaseSession */ public static void processDeferredClose(Datastore datastore) { Assert.notNull(datastore, "No Datastore specified"); - Map> holderMap = deferredCloseHolder.get(); + Map> holderMap = DEFERRED_CLOSE_HOLDER.get(); if (holderMap == null || !holderMap.containsKey(datastore)) { throw new IllegalStateException("Deferred close not active for Datastore [" + datastore + "]"); } - if(logger.isDebugEnabled()) { - logger.debug("Processing deferred close of Datastore Sessions"); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Processing deferred close of Datastore Sessions"); } Set sessions = holderMap.remove(datastore); for (Session session : sessions) { closeSession(session); } if (holderMap.isEmpty()) { - deferredCloseHolder.set(null); + DEFERRED_CLOSE_HOLDER.set(null); } } @@ -271,38 +270,39 @@ public static void processDeferredClose(Datastore datastore) { */ public static void initDeferredClose(Datastore datastore) { Assert.notNull(datastore, "No Datastore specified"); - logger.debug("Initializing deferred close of Datastore Sessions"); - Map> holderMap = deferredCloseHolder.get(); + LOGGER.debug("Initializing deferred close of Datastore Sessions"); + Map> holderMap = DEFERRED_CLOSE_HOLDER.get(); if (holderMap == null) { holderMap = new HashMap>(); - deferredCloseHolder.set(holderMap); + DEFERRED_CLOSE_HOLDER.set(holderMap); } holderMap.put(datastore, new LinkedHashSet(4)); } /** * Close the given Session or register it for deferred close. - * @param session the Datastore Session to close + * + * @param session the Datastore Session to close * @param datastore Datastore that the Session was created with - * (may be null) + * (may be null) * @see #initDeferredClose * @see #processDeferredClose */ public static void closeSessionOrRegisterDeferredClose(Session session, Datastore datastore) { - Map> holderMap = deferredCloseHolder.get(); + Map> holderMap = DEFERRED_CLOSE_HOLDER.get(); if (holderMap != null && datastore != null && holderMap.containsKey(datastore)) { - logger.debug("Registering Datastore Session for deferred close"); + LOGGER.debug("Registering Datastore Session for deferred close"); holderMap.get(datastore).add(session); - } - else { + } else { closeSession(session); } } /** * Execute the closure in the current session if it exists, or create a new one and close it otherwise. + * * @param datastore the datastore - * @param c the closure to execute + * @param c the closure to execute * @return the return value from the closure */ public static Object doWithSession(final Datastore datastore, final Closure c) { @@ -310,8 +310,7 @@ public static Object doWithSession(final Datastore datastore, final Closure c) { Session session = existing ? datastore.getCurrentSession() : bindSession(datastore.connect()); try { return c.call(session); - } - finally { + } finally { if (!existing) { TransactionSynchronizationManager.unbindResource(session.getDatastore()); closeSessionOrRegisterDeferredClose(session, datastore); @@ -321,9 +320,10 @@ public static Object doWithSession(final Datastore datastore, final Closure c) { /** * Execute the callback in the current session if it exists, or create a new one and close it otherwise. - * @param the return type + * + * @param the return type * @param datastore the datastore - * @param callback the callback to execute + * @param callback the callback to execute * @return the return value from the callback */ public static T execute(final Datastore datastore, final SessionCallback callback) { @@ -331,8 +331,7 @@ public static T execute(final Datastore datastore, final SessionCallback Session session = existing ? datastore.getCurrentSession() : bindSession(datastore.connect()); try { return callback.doInSession(session); - } - finally { + } finally { if (!existing) { TransactionSynchronizationManager.unbindResource(session.getDatastore()); closeSessionOrRegisterDeferredClose(session, datastore); @@ -342,16 +341,16 @@ public static T execute(final Datastore datastore, final SessionCallback /** * Execute the callback in the current session if it exists, or create a new one and close it otherwise. + * * @param datastore the datastore - * @param callback the callback to execute + * @param callback the callback to execute */ public static void execute(final Datastore datastore, final VoidSessionCallback callback) { boolean existing = datastore.hasCurrentSession(); Session session = existing ? datastore.getCurrentSession() : bindSession(datastore.connect()); try { callback.doInSession(session); - } - finally { + } finally { if (!existing) { TransactionSynchronizationManager.unbindResource(datastore); closeSessionOrRegisterDeferredClose(session, datastore); @@ -361,6 +360,7 @@ public static void execute(final Datastore datastore, final VoidSessionCallback /** * Bind the session to the thread with a SessionHolder keyed by its Datastore. + * * @param session the session * @return the session (for method chaining) */ @@ -371,6 +371,7 @@ public static Session bindSession(final Session session) { /** * Bind the session to the thread with a SessionHolder keyed by its Datastore. + * * @param session the session * @return the session (for method chaining) */ @@ -382,11 +383,12 @@ public static Session bindSession(final Session session, Object creator) { /** * Adds the session to the current SessionHolder's list of sessions, making it the current session. * If there's no current session, calls bindSession. + * * @param session the session * @return the session */ public static Session bindNewSession(final Session session) { - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(session.getDatastore()); + SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(session.getDatastore()); if (sessionHolder == null) { return bindSession(session); } @@ -398,29 +400,29 @@ public static Session bindNewSession(final Session session) { /** * Unbinds and closes a session. If it's the only session in the SessionHolder, unbinds * the SessionHolder, otherwise just removes the session from the holder's list. + * * @param session the session */ public static void unbindSession(final Session session) { - SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(session.getDatastore()); + SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(session.getDatastore()); if (sessionHolder == null) { - if(logger.isWarnEnabled()) { - logger.warn("Cannot unbind session, there's no SessionHolder registered"); + if (LOGGER.isWarnEnabled()) { + LOGGER.warn("Cannot unbind session, there's no SessionHolder registered"); } return; } if (!sessionHolder.containsSession(session)) { - if(logger.isWarnEnabled()) { - logger.warn("Cannot unbind session, it's not registered in a SessionHolder"); + if (LOGGER.isWarnEnabled()) { + LOGGER.warn("Cannot unbind session, it's not registered in a SessionHolder"); } return; } if (sessionHolder.size() > 1) { sessionHolder.removeSession(session); - } - else { - TransactionSynchronizationManager.unbindResource(session.getDatastore()); + } else { + TransactionSynchronizationManager.unbindResource(session.getDatastore()); } closeSessionOrRegisterDeferredClose(session, session.getDatastore()); @@ -440,27 +442,26 @@ public static PropertyResolver preparePropertyResolver(PropertyResolver property * Prepares a property resolver and ensures it is suitable for GORM configuration * * @param propertyResolver The property resolver - * @param keyPrefixes The configuration prefixes + * @param keyPrefixes The configuration prefixes * @return The property resolver */ - public static PropertyResolver preparePropertyResolver(PropertyResolver propertyResolver, String...keyPrefixes) { + public static PropertyResolver preparePropertyResolver(PropertyResolver propertyResolver, String... keyPrefixes) { // if it is a map then it is a Grails configuration object, therefore it is already prepared - if((propertyResolver instanceof Map) || (propertyResolver instanceof DatastoreEnvironment)) { + if ((propertyResolver instanceof Map) || (propertyResolver instanceof DatastoreEnvironment)) { return propertyResolver; - } - else if(propertyResolver instanceof ConfigurableEnvironment) { + } else if (propertyResolver instanceof ConfigurableEnvironment) { // Spring Boot Environment config ConfigurableEnvironment env = (ConfigurableEnvironment) propertyResolver; List> propertySources = DefaultGroovyMethods.asList(env.getPropertySources()); Collections.reverse(propertySources); Map configuration = new LinkedHashMap<>(); for (PropertySource propertySource : propertySources) { - if(propertySource instanceof EnumerablePropertySource) { + if (propertySource instanceof EnumerablePropertySource) { EnumerablePropertySource eps = (EnumerablePropertySource) propertySource; String[] propertyNames = eps.getPropertyNames(); for (String propertyName : propertyNames) { for (String keyPrefix : keyPrefixes) { - if(propertyName.startsWith(keyPrefix)) { + if (propertyName.startsWith(keyPrefix)) { configuration.put(propertyName, eps.getProperty(propertyName)); break; } @@ -469,22 +470,21 @@ else if(propertyResolver instanceof ConfigurableEnvironment) { } } return createPropertyResolver(configuration); - } - else { + } else { return propertyResolver; } } + /** * Creates a {@link PropertyResolver} from the given configuration - * @param configuration The configuration * + * @param configuration The configuration * @return A {@link PropertyResolver} instance */ public static PropertyResolver createPropertyResolver(Map configuration) { - if(configuration instanceof PropertyResolver) { - return (PropertyResolver)configuration; - } - else { + if (configuration instanceof PropertyResolver) { + return (PropertyResolver) configuration; + } else { Map[] configurations = new Map[1]; configurations[0] = configuration; @@ -494,8 +494,8 @@ public static PropertyResolver createPropertyResolver(Map config /** * Creates a {@link PropertyResolver} from the given configuration - * @param configurations The configuration * + * @param configurations The configuration * @return A {@link PropertyResolver} instance */ public static PropertyResolver createPropertyResolvers(Map... configurations) { @@ -504,8 +504,8 @@ public static PropertyResolver createPropertyResolvers(Map... co /** * Creates a {@link PropertyResolver} from the given configuration - * @param configurations The configuration * + * @param configurations The configuration * @return A {@link PropertyResolver} instance */ public static PropertyResolver createPropertyResolvers(Collection> configurations) { @@ -516,7 +516,8 @@ public Class convert(String source) { try { return ClassUtils.forName(source, getClass().getClassLoader()); } catch (ClassNotFoundException e) { - throw new ConversionException("Cannot convert String ["+source+"] to class. The class was not found.", e) {}; + throw new ConversionException("Cannot convert String [" + source + "] to class. The class was not found.", e) { + }; } } }); @@ -529,22 +530,21 @@ public Resource convert(String source) { int i = 0; for (Map configuration : configurations) { i++; - if(configuration != null) { + if (configuration != null) { MutablePropertySources propertySources = env.getPropertySources(); - if(configuration instanceof ConfigObject) { + if (configuration instanceof ConfigObject) { ConfigObject existingConfig = (ConfigObject) configuration; ConfigObject cloned = existingConfig.clone(); propertySources.addFirst(new ConfigObjectPropertySource(DATASTORE_CONFIG + i, cloned)); - propertySources.addFirst(new ConfigObjectPropertySource(DATASTORE_CONFIG_FLAT+ i, createFlatConfig(cloned))); - } - else { + propertySources.addFirst(new ConfigObjectPropertySource(DATASTORE_CONFIG_FLAT + i, createFlatConfig(cloned))); + } else { ConfigSlurper configSlurper = new ConfigSlurper(); Properties properties = new Properties(); Map finalConfig = new LinkedHashMap<>(); for (String name : configuration.keySet()) { Object value = configuration.get(name); - if(value != null) { + if (value != null) { finalConfig.put(name, value); } } @@ -561,6 +561,7 @@ public Resource convert(String source) { return env; } + private static Map createFlatConfig(ConfigObject configuration) { Map flatConfig = new LinkedHashMap<>(); String prefix = ""; @@ -573,25 +574,25 @@ private static void createFlatConfig(ConfigObject currentConfigObject, Map * Can be used in combination with {@link org.grails.datastore.mapping.core.order.OrderedComparator} to sort objects * * @author Graeme Rocher @@ -35,4 +34,4 @@ public interface Ordered { default int getOrder() { return 0; } -} \ No newline at end of file +} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Session.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Session.java index 9f747e1c8d1..0c139af3d19 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Session.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/Session.java @@ -18,12 +18,7 @@ */ package org.grails.datastore.mapping.core; -import java.io.Serializable; -import java.util.List; -import java.util.Map; - import jakarta.persistence.FlushModeType; - import org.grails.datastore.mapping.engine.Persister; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.query.Query; @@ -32,12 +27,15 @@ import org.grails.datastore.mapping.transactions.Transaction; import org.springframework.transaction.TransactionDefinition; +import java.io.Serializable; +import java.util.List; +import java.util.Map; + /** * The Session represents the active interaction with a datastore. * * @author Graeme Rocher * @author Guillaume Laforge - * * @since 1.0 */ @SuppressWarnings("rawtypes") @@ -47,16 +45,16 @@ public interface Session extends QueryCreator { * Associates an attribute with the given persistent entity. Attributes will * be cleared out when the Session is closed or cleared. * - * @param entity The persistent instance (must be associated with this Session) + * @param entity The persistent instance (must be associated with this Session) * @param attributeName The attribute name - * @param value The value + * @param value The value */ void setAttribute(Object entity, String attributeName, Object value); /** * Obtains an attribute for the given entity * - * @param entity The entity + * @param entity The entity * @param attributeName The attribute * @return The attribute value */ @@ -64,14 +62,16 @@ public interface Session extends QueryCreator { /** * Set a property on this session. Note that properties are not cleared out when a session is cleared. + * * @param property The property name. - * @param value The property value. + * @param value The property value. * @return The previous property value, if there was one (or null). */ Object setSessionProperty(String property, Object value); /** * Get the value of a property of the session. + * * @param property The name of the property. * @return The value. */ @@ -79,6 +79,7 @@ public interface Session extends QueryCreator { /** * Clear a property in a session. + * * @param property The property name. * @return The property value, if there was one (or null). */ @@ -96,17 +97,19 @@ public interface Session extends QueryCreator { /** * Starts a transaction + * * @return The transaction */ Transaction beginTransaction(); /** * Starts a transaction + * * @return The transaction */ Transaction beginTransaction(TransactionDefinition definition); - /** + /** * Obtains the MappingContext instance * * @return The MappingContext @@ -131,12 +134,14 @@ public interface Session extends QueryCreator { /** * Refreshes the given objects state + * * @param o The object to refresh */ void refresh(Object o); /** * Attaches an object the current session + * * @param o The object to attach */ void attach(Object o); @@ -153,12 +158,14 @@ public interface Session extends QueryCreator { /** * Clear a specific object + * * @param o The object to clear */ void clear(Object o); /** * Whether the object is contained within the first level cache + * * @param o The object to check * @return true if it is */ @@ -173,6 +180,7 @@ public interface Session extends QueryCreator { /** * Obtains the current FlushModeType + * * @return The FlushModeType instance */ FlushModeType getFlushMode(); @@ -203,7 +211,7 @@ public interface Session extends QueryCreator { * Retrieves an individual object * * @param type The type - * @param key The key + * @param key The key * @return The object */ T retrieve(Class type, Serializable key); @@ -212,7 +220,7 @@ public interface Session extends QueryCreator { * Retrieves a proxy for the given key * * @param type The type - * @param key The key + * @param key The key * @return The object */ T proxy(Class type, Serializable key); @@ -221,7 +229,7 @@ public interface Session extends QueryCreator { * Retrieves an individual object, using a write lock to prevent loss of updates * * @param type The type - * @param key The key + * @param key The key * @return The object */ T lock(Class type, Serializable key); @@ -235,6 +243,7 @@ public interface Session extends QueryCreator { /** * Deletes a single object + * * @param obj The object to delete */ void delete(Object obj); @@ -249,7 +258,8 @@ public interface Session extends QueryCreator { /** * Updates all objects matching the given criteria and property values - * @param criteria The criteria + * + * @param criteria The criteria * @param properties The properties * @return The total number of records updated */ @@ -257,6 +267,7 @@ public interface Session extends QueryCreator { /** * Retrieves several objects for the specified keys + * * @param type The type * @param keys The keys * @return A list of objects @@ -265,11 +276,12 @@ public interface Session extends QueryCreator { /** * Retrieves several objects for the specified keys + * * @param type The type * @param keys The keys * @return A list of objects */ - List retrieveAll(Class type, Serializable...keys); + List retrieveAll(Class type, Serializable... keys); /** * Creates a query instance for the give type @@ -286,6 +298,7 @@ public interface Session extends QueryCreator { /** * The persister for the given object + * * @param o The object * @return The persister */ @@ -293,6 +306,7 @@ public interface Session extends QueryCreator { /** * Obtains the current transaction instance + * * @return The Transaction instance */ Transaction getTransaction(); @@ -304,12 +318,14 @@ public interface Session extends QueryCreator { /** * The Datastore that created this Session + * * @return The Datastore instance */ Datastore getDatastore(); /** * Check if the instance has been modified since loading. + * * @param instance the instance * @return true if one or more fields have changed */ @@ -317,12 +333,12 @@ public interface Session extends QueryCreator { /** * Obtains the identifier for the instance + * * @param instance The instance * @return The identifier or null if it cannot be established */ Serializable getObjectIdentifier(Object instance); - /** * Whether the session is synchronized with a transaction * diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCallback.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCallback.java index cff3c173549..cd136421302 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCallback.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCallback.java @@ -18,12 +18,11 @@ */ package org.grails.datastore.mapping.core; -import org.grails.datastore.mapping.core.Session; - /** - * @author Burt Beckwith * @param + * @author Burt Beckwith */ public interface SessionCallback { + T doInSession(Session session); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCreationEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCreationEvent.java index 0fd9267ac41..c6bd11e47bf 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCreationEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionCreationEvent.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core; import org.springframework.context.ApplicationEvent; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionImplementor.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionImplementor.java index 0bf5cc2083e..0c72fcf0b80 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionImplementor.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SessionImplementor.java @@ -18,16 +18,16 @@ */ package org.grails.datastore.mapping.core; -import java.io.Serializable; -import java.util.Collection; -import java.util.Map; - import org.grails.datastore.mapping.core.impl.PendingDelete; import org.grails.datastore.mapping.core.impl.PendingInsert; import org.grails.datastore.mapping.core.impl.PendingUpdate; import org.grails.datastore.mapping.engine.EntityAccess; import org.grails.datastore.mapping.model.PersistentEntity; +import java.io.Serializable; +import java.util.Collection; +import java.util.Map; + /** * Methods for the implementation of the {@link Session} interface to implement. * @@ -56,6 +56,7 @@ public interface SessionImplementor { /** * Adds a pending update operation + * * @param update The pending update operation */ void addPendingUpdate(PendingUpdate update); @@ -77,23 +78,27 @@ public interface SessionImplementor { /** * Caches a native entry + * * @param entity The entity - * @param key The key - * @param entry The native entry + * @param key The key + * @param entry The native entry */ void cacheEntry(PersistentEntity entity, Serializable key, T entry); /** * Obtains a cached entry + * * @param entity The entity - * @param key The key + * @param key The key * @return The cached entry */ T getCachedEntry(PersistentEntity entity, Serializable key); + /** * Obtains a cached entry - * @param entity The entity - * @param key The key + * + * @param entity The entity + * @param key The key * @param forDirtyCheck Whether to obtain for purposes for dirty checking * @return The cached entry */ @@ -101,24 +106,27 @@ public interface SessionImplementor { /** * Caches an instance - * @param type The type - * @param key The key + * + * @param type The type + * @param key The key * @param instance The instance */ void cacheInstance(Class type, Serializable key, Object instance); /** * Get the cached instance if it exists. + * * @param type the object type - * @param key the object key + * @param key the object key * @return the instance or null */ Object getCachedInstance(Class type, Serializable key); /** * Whether an object with the specified key is contained within the first level cache. + * * @param type the object type - * @param key The key to check + * @param key The key to check * @return true if it is */ boolean isCached(Class type, Serializable key); @@ -127,8 +135,8 @@ public interface SessionImplementor { * Obtains a cached collection * * @param entity The entity - * @param key The key - * @param name The name + * @param key The key + * @param name The name * @return The cached collection or null */ Collection getCachedCollection(PersistentEntity entity, Serializable key, String name); @@ -136,15 +144,16 @@ public interface SessionImplementor { /** * Caches a collection * - * @param entity The entity - * @param key The key + * @param entity The entity + * @param key The key * @param collection The collection - * @param name The name of the collection + * @param name The name of the collection */ void cacheCollection(PersistentEntity entity, Serializable key, Collection collection, String name); /** * Adds an operation to be executed after a flush + * * @param runnable The runnable */ void addPostFlushOperation(Runnable runnable); @@ -157,6 +166,7 @@ public interface SessionImplementor { /** * Register a pending object + * * @param obj The object to register */ void registerPending(T obj); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SoftThreadLocalMap.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SoftThreadLocalMap.java index 3f27fcd49f5..8eb98e0365b 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SoftThreadLocalMap.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/SoftThreadLocalMap.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core; import org.springframework.util.ConcurrentReferenceHashMap; @@ -25,7 +24,6 @@ * Creates a InheritableThreadLocal with an intial value of a Map. * * @author Graeme Rocher - * * @deprecated Do not use */ @Deprecated diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/StatelessDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/StatelessDatastore.java index ad06c78d952..b782926b852 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/StatelessDatastore.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/StatelessDatastore.java @@ -24,10 +24,11 @@ * @author Graeme Rocher * @since 2.3 */ -public interface StatelessDatastore extends Datastore{ +public interface StatelessDatastore extends Datastore { /** * Connect and return a stateless session + * * @return The session */ Session connectStateless(); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/VoidSessionCallback.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/VoidSessionCallback.java index 274107c348d..7d958fc1bcf 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/VoidSessionCallback.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/VoidSessionCallback.java @@ -18,11 +18,10 @@ */ package org.grails.datastore.mapping.core; -import org.grails.datastore.mapping.core.Session; - /** * @author Burt Beckwith */ public interface VoidSessionCallback { + void doInSession(Session session); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/AbstractConnectionSourceFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/AbstractConnectionSourceFactory.java index 227f4c824f6..7bd080ee33a 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/AbstractConnectionSourceFactory.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/AbstractConnectionSourceFactory.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core.connections; import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller; @@ -61,11 +60,11 @@ public void setCustomTypes(List customTypes) { public ConnectionSource create(String name, PropertyResolver configuration) { ConnectionSourceSettingsBuilder builder = new ConnectionSourceSettingsBuilder(configuration); ConnectionSourceSettings fallbackSettings = builder.build(); - if(tenantResolver != null) { + if (tenantResolver != null) { fallbackSettings.getMultiTenancy().setTenantResolver(tenantResolver); } - if(customTypes != null) { - fallbackSettings.getCustom().getTypes().addAll( this.customTypes ); + if (customTypes != null) { + fallbackSettings.getCustom().getTypes().addAll(this.customTypes); } return create(name, configuration, fallbackSettings); } @@ -87,7 +86,7 @@ public ConnectionSource createRuntime(String name, PropertyResolver config S settings = buildRuntimeSettings(name, configuration, fallbackSettings); return create(name, settings); } - + public S buildRuntimeSettings(String name, PropertyResolver configuration, F fallbackSettings) { return buildSettings(name, configuration, fallbackSettings, false); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/AbstractConnectionSources.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/AbstractConnectionSources.groovy index 0513ca6af6d..ee48488444e 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/AbstractConnectionSources.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/AbstractConnectionSources.groovy @@ -31,24 +31,23 @@ import org.springframework.core.env.PropertyResolver * @since 6.0 */ @CompileStatic -abstract class AbstractConnectionSources implements ConnectionSources { +abstract class AbstractConnectionSources implements ConnectionSources { protected final ConnectionSource defaultConnectionSource; protected final ConnectionSourceFactory connectionSourceFactory; protected final PropertyResolver configuration; - protected final Collection> listeners = [] + protected final Collection> listeners = [] AbstractConnectionSources(ConnectionSource defaultConnectionSource, ConnectionSourceFactory connectionSourceFactory, PropertyResolver configuration) { - if(connectionSourceFactory == null) { + if (connectionSourceFactory == null) { throw new IllegalArgumentException("Argument [connectionSourceFactory] cannot be null"); } - if(defaultConnectionSource == null) { + if (defaultConnectionSource == null) { throw new IllegalStateException("The default ConnectionSource cannot be null!"); } - if(configuration == null) { + if (configuration == null) { this.configuration = DatastoreUtils.createPropertyResolver(Collections.emptyMap()); - } - else { + } else { this.configuration = configuration } this.defaultConnectionSource = defaultConnectionSource @@ -77,10 +76,9 @@ abstract class AbstractConnectionSources Set newNames = new LinkedHashSet<>(); for (String name : names) { int i = name.indexOf('.'); - if(i > -1) { - newNames.add( name.substring(0,i) ); - } - else { + if (i > -1) { + newNames.add(name.substring(0, i)); + } else { newNames.add(name); } } @@ -99,7 +97,7 @@ abstract class AbstractConnectionSources @Override public void close() throws IOException { - for(ConnectionSource connectionSource : allConnectionSources) { + for (ConnectionSource connectionSource : allConnectionSources) { connectionSource.close() } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSource.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSource.java index cc68a6b4b82..7dc39a09382 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSource.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSource.java @@ -16,10 +16,8 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core.connections; - import java.io.Closeable; /** @@ -29,6 +27,7 @@ * @since 6.0 */ public interface ConnectionSource extends Closeable { + /** * The name of the default connection source */ diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourceFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourceFactory.java index 7a7d810c3ad..fd29c2c1b0e 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourceFactory.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourceFactory.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core.connections; import org.grails.datastore.mapping.config.Settings; @@ -35,10 +34,9 @@ public interface ConnectionSourceFactory /** * Creates a new {@link ConnectionSource} for the given name and configuration * - * @param name The name + * @param name The name * @param configuration The configuration * @return The {@link ConnectionSource} - * * @throws org.grails.datastore.mapping.core.exceptions.ConfigurationException If there is an issue with the configuration */ ConnectionSource create(String name, PropertyResolver configuration); @@ -46,10 +44,9 @@ public interface ConnectionSourceFactory /** * Creates a new {@link ConnectionSource} for the given name and settings * - * @param name The name + * @param name The name * @param settings The settings * @return The {@link ConnectionSource} - * * @throws org.grails.datastore.mapping.core.exceptions.ConfigurationException If there is an issue with the configuration */ ConnectionSource create(String name, S settings); @@ -57,12 +54,10 @@ public interface ConnectionSourceFactory /** * Creates a new {@link ConnectionSource} for the given name and configuration * - * @param name The name - * @param configuration The configuration + * @param name The name + * @param configuration The configuration * @param fallbackConnectionSource The fallback connection source - * * @return The {@link ConnectionSource} - * * @throws org.grails.datastore.mapping.core.exceptions.ConfigurationException If there is an issue with the configuration */ ConnectionSource create(String name, PropertyResolver configuration, ConnectionSource fallbackConnectionSource); @@ -70,12 +65,10 @@ public interface ConnectionSourceFactory /** * Creates a new {@link ConnectionSource} for the given name and configuration * - * @param name The name - * @param configuration The configuration + * @param name The name + * @param configuration The configuration * @param fallbackSettings The settings to fallback to if none are specified - * * @return The {@link ConnectionSource} - * * @throws org.grails.datastore.mapping.core.exceptions.ConfigurationException If there is an issue with the configuration */ ConnectionSource create(String name, PropertyResolver configuration, F fallbackSettings); @@ -87,10 +80,11 @@ public interface ConnectionSourceFactory /** * Creates a connection at runtime. This method differs from the `create` method is that it handles the runtime creation (as oppose to boot time) creation of connection sources - * @param name The name of the connection source - * @param configuration The configuration + * + * @param name The name of the connection source + * @param configuration The configuration * @param fallbackSettings The fallback settings * @return The new connection source */ - ConnectionSource createRuntime(String name, PropertyResolver configuration, S fallbackSettings); + ConnectionSource createRuntime(String name, PropertyResolver configuration, S fallbackSettings); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourceSettings.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourceSettings.groovy index bade39fac43..2cd78be44d6 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourceSettings.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourceSettings.groovy @@ -23,12 +23,11 @@ import groovy.transform.AutoClone import groovy.transform.CompileStatic import groovy.transform.builder.Builder import groovy.transform.builder.SimpleStrategy +import jakarta.persistence.FlushModeType import org.grails.datastore.mapping.config.Settings import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller import org.grails.datastore.mapping.multitenancy.MultiTenancySettings -import jakarta.persistence.FlushModeType - /** * Default settings shared across all implementations * @@ -104,7 +103,6 @@ class ConnectionSourceSettings implements Settings { this.defaults = defaults } - /** * Represents the default settings */ diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourceSettingsBuilder.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourceSettingsBuilder.groovy index 3e4dfcc7a55..56c579fee20 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourceSettingsBuilder.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourceSettingsBuilder.groovy @@ -32,6 +32,7 @@ import org.springframework.core.env.PropertyResolver */ @CompileStatic class ConnectionSourceSettingsBuilder extends ConfigurationBuilder { + ConnectionSourceSettingsBuilder(PropertyResolver propertyResolver, String configurationPrefix = Settings.PREFIX) { super(propertyResolver, configurationPrefix) } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSources.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSources.java index 4845a56c899..f2bfc04b03a 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSources.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSources.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core.connections; import org.springframework.core.env.PropertyResolver; @@ -27,10 +26,9 @@ /** * Models multiple connection sources * + * @param The underlying native type of the {@link ConnectionSource}, for example a SQL {@link javax.sql.DataSource} * @author Graeme Rocher * @since 6.0 - * - * @param The underlying native type of the {@link ConnectionSource}, for example a SQL {@link javax.sql.DataSource} */ public interface ConnectionSources extends Iterable>, Closeable { @@ -38,6 +36,7 @@ public interface ConnectionSources extend * @return Obtains the base configuration */ PropertyResolver getBaseConfiguration(); + /** * @return The factory used to create new connections */ @@ -52,7 +51,6 @@ public interface ConnectionSources extend * Obtain a {@link ConnectionSource} by name * * @param name The name of the source - * * @return A {@link ConnectionSource} or null if it doesn't exist */ ConnectionSource getConnectionSource(String name); @@ -67,25 +65,22 @@ public interface ConnectionSources extend /** * Adds a new {@link ConnectionSource} * - * @param name The name of the connection source + * @param name The name of the connection source * @param configuration The configuration * @return The {@link ConnectionSource} - * * @throws org.grails.datastore.mapping.core.exceptions.ConfigurationException if the configuration is invalid */ ConnectionSource addConnectionSource(String name, PropertyResolver configuration); - /** * Adds a new {@link ConnectionSource} * - * @param name The name of the connection source + * @param name The name of the connection source * @param configuration The configuration * @return The {@link ConnectionSource} - * * @throws org.grails.datastore.mapping.core.exceptions.ConfigurationException if the configuration is invalid */ - ConnectionSource addConnectionSource(String name, Map configuration); + ConnectionSource addConnectionSource(String name, Map configuration); /** * Adds a listener @@ -93,5 +88,5 @@ public interface ConnectionSources extend * @param listener The listener * @return This connection sources */ - ConnectionSources addListener(ConnectionSourcesListener listener); + ConnectionSources addListener(ConnectionSourcesListener listener); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesInitializer.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesInitializer.groovy index 30f13899f6c..c718d48c4dc 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesInitializer.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesInitializer.groovy @@ -39,14 +39,13 @@ class ConnectionSourcesInitializer { * @param configuration The configuration * @return The {@link ConnectionSources} */ - public static ConnectionSources create(ConnectionSourceFactory connectionSourceFactory, PropertyResolver configuration) { + public static ConnectionSources create(ConnectionSourceFactory connectionSourceFactory, PropertyResolver configuration) { ConnectionSource defaultConnectionSource = connectionSourceFactory.create(ConnectionSource.DEFAULT, configuration); Class connectionSourcesClass = defaultConnectionSource.getSettings().getConnectionSourcesClass(); - if(connectionSourcesClass == null) { + if (connectionSourcesClass == null) { return new InMemoryConnectionSources(defaultConnectionSource, connectionSourceFactory, configuration); - } - else { + } else { try { return connectionSourcesClass.newInstance(defaultConnectionSource, connectionSourceFactory, configuration) } catch (Throwable e) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesListener.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesListener.groovy index 01dc513fc36..451d40f79fd 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesListener.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesListener.groovy @@ -33,5 +33,5 @@ interface ConnectionSourcesListener { * * @param connectionSource The connection source */ - void newConnectionSource(ConnectionSource connectionSource) + void newConnectionSource(ConnectionSource connectionSource) } \ No newline at end of file diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesProvider.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesProvider.java index 1a559769230..8bba87b00c6 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesProvider.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesProvider.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core.connections; /** @@ -30,5 +29,5 @@ public interface ConnectionSourcesProvider getConnectionSources(); + ConnectionSources getConnectionSources(); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesSupport.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesSupport.java index 4a3ae7046ee..8814d8baecf 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesSupport.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/ConnectionSourcesSupport.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core.connections; import org.grails.datastore.mapping.config.Entity; @@ -61,7 +60,7 @@ public static String getDefaultConnectionSourceName(PersistentEntity entity) { */ public static List getConnectionSourceNames(PersistentEntity entity) { final Entity mappedForm = entity.getMapping().getMappedForm(); - if(mappedForm != null) { + if (mappedForm != null) { return mappedForm.getDatasources(); } return DEFAULT_CONNECTION_SOURCE_NAMES; @@ -70,16 +69,15 @@ public static List getConnectionSourceNames(PersistentEntity entity) { /** * Returns whether the given entity uses the give connection source name or not * - * @param entity The name of the entity + * @param entity The name of the entity * @param connectionSourceName The connection source name * @return Whether the given connection source is used */ public static boolean usesConnectionSource(PersistentEntity entity, String connectionSourceName) { Class[] interfaces = ClassUtils.getAllInterfacesForClass(entity.getJavaClass()); - if(isMultiTenant(interfaces)) { - return !isMultiTenantExcludedDataSource( entity, connectionSourceName ); - } - else { + if (isMultiTenant(interfaces)) { + return !isMultiTenantExcludedDataSource(entity, connectionSourceName); + } else { List names = getConnectionSourceNames(entity); return names.contains(connectionSourceName) || names.contains(ConnectionSource.ALL); @@ -89,7 +87,7 @@ public static boolean usesConnectionSource(PersistentEntity entity, String conne protected static boolean isMultiTenant(Class[] interfaces) { for (Class anInterface : interfaces) { String name = anInterface.getName(); - if(name.startsWith("grails.gorm") && name.endsWith(".MultiTenant")) { + if (name.startsWith("grails.gorm") && name.endsWith(".MultiTenant")) { return true; } } @@ -100,14 +98,14 @@ protected static boolean isMultiTenant(Class[] interfaces) { * Returns whether the given entity should be excluded from given connection source name or not. * It can be configured over {@link TenantDataSourceConfig} annotation * - * @param entity The name of the multi tenant entity + * @param entity The name of the multi tenant entity * @param connectionSourceName The connection source name to check * @return Whether the given connection should be excluded */ protected static boolean isMultiTenantExcludedDataSource(PersistentEntity entity, String connectionSourceName) { TenantDataSourceConfig tdsc = (TenantDataSourceConfig) entity.getJavaClass().getAnnotation(TenantDataSourceConfig.class); boolean result = false; - if ( null != tdsc ) { + if (null != tdsc) { final String[] dataSourcesToExclude = tdsc.dataSourcesToExclude(); result = Arrays.asList(dataSourcesToExclude).contains(connectionSourceName); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/DefaultConnectionSource.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/DefaultConnectionSource.java index ae790019279..c3fff364070 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/DefaultConnectionSource.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/DefaultConnectionSource.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core.connections; import java.io.Closeable; @@ -58,20 +57,18 @@ public S getSettings() { @Override public void close() throws IOException { - if(source instanceof Closeable) { + if (source instanceof Closeable) { try { - ((Closeable)source).close(); + ((Closeable) source).close(); } finally { this.closed = true; } - } - else if(source instanceof AutoCloseable) { + } else if (source instanceof AutoCloseable) { try { - ((AutoCloseable)source).close(); + ((AutoCloseable) source).close(); } catch (Exception e) { - throw new IOException("Error closing connection source ["+name+"]:" + e.getMessage(), e); - } - finally { + throw new IOException("Error closing connection source [" + name + "]:" + e.getMessage(), e); + } finally { this.closed = true; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/InMemoryConnectionSources.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/InMemoryConnectionSources.groovy index 45f03638cfc..378a99a804f 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/InMemoryConnectionSources.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/InMemoryConnectionSources.groovy @@ -39,10 +39,10 @@ class InMemoryConnectionSources extends A super(defaultConnectionSource, connectionSourceFactory, configuration) this.connectionSourceMap.put(ConnectionSource.DEFAULT, defaultConnectionSource) - for(String name : getConnectionSourceNames(connectionSourceFactory, configuration)) { - if(name.equals("dataSource")) continue // data source is reserved name for the default + for (String name : getConnectionSourceNames(connectionSourceFactory, configuration)) { + if (name.equals("dataSource")) continue // data source is reserved name for the default ConnectionSource connectionSource = connectionSourceFactory.create(name, configuration, defaultConnectionSource.getSettings()) - if(connectionSource != null) { + if (connectionSource != null) { this.connectionSourceMap.put(name, connectionSource) } } @@ -60,24 +60,23 @@ class InMemoryConnectionSources extends A @Override ConnectionSource addConnectionSource(String name, PropertyResolver configuration) { - if(name == null) { + if (name == null) { throw new IllegalArgumentException("Argument [name] cannot be null") } - if(configuration == null) { + if (configuration == null) { throw new IllegalArgumentException("Argument [configuration] cannot be null") } - ConnectionSource connectionSource = connectionSourceFactory.createRuntime(name, configuration, (S)this.defaultConnectionSource.getSettings()) - if(connectionSource == null) { + ConnectionSource connectionSource = connectionSourceFactory.createRuntime(name, configuration, (S) this.defaultConnectionSource.getSettings()) + if (connectionSource == null) { throw new IllegalStateException("ConnectionSource factory returned null") } this.connectionSourceMap.put(name, connectionSource) - for(listener in listeners) { + for (listener in listeners) { listener.newConnectionSource(connectionSource) } return connectionSource } - } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/SingletonConnectionSources.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/SingletonConnectionSources.groovy index 6292c5d4b32..a7ac77e917c 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/SingletonConnectionSources.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/SingletonConnectionSources.groovy @@ -31,9 +31,10 @@ import org.springframework.core.env.PropertyResolver @CompileStatic class SingletonConnectionSources extends AbstractConnectionSources { - SingletonConnectionSources(ConnectionSource connectionSource, PropertyResolver configuration) { + SingletonConnectionSources(ConnectionSource connectionSource, PropertyResolver configuration) { super(connectionSource, new NullConnectionFactory(), configuration) } + @Override protected Iterable getConnectionSourceNames(ConnectionSourceFactory connectionSourceFactory, PropertyResolver configuration) { Arrays.asList(ConnectionSource.DEFAULT) @@ -54,7 +55,7 @@ class SingletonConnectionSources extends throw new UnsupportedOperationException("Cannot add a connection source it a SingletonConnectionSources") } - static class NullConnectionFactory extends AbstractConnectionSourceFactory { + static class NullConnectionFactory extends AbstractConnectionSourceFactory { @Override protected S buildSettings(String name, PropertyResolver configuration, F fallbackSettings, boolean isDefaultDataSource) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/StaticConnectionSources.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/StaticConnectionSources.groovy index cd31c62f069..6634b9502f7 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/StaticConnectionSources.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/connections/StaticConnectionSources.groovy @@ -23,7 +23,6 @@ import groovy.transform.CompileStatic import org.grails.datastore.mapping.core.DatastoreUtils import org.springframework.core.env.PropertyResolver - /** * A static non-mutable implementation for existing for a set of existing {@link ConnectionSource} instances * @@ -39,7 +38,7 @@ class StaticConnectionSources extends Abs super(defaultConnectionSource, new SingletonConnectionSources.NullConnectionFactory(), configuration) connectionSourceMap.put(ConnectionSource.DEFAULT, defaultConnectionSource) - for( ConnectionSource source in otherConnectionSources) { + for (ConnectionSource source in otherConnectionSources) { connectionSourceMap.put(source.name, source) } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/exceptions/ConfigurationException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/exceptions/ConfigurationException.java index 5ee4403907f..cda06a21456 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/exceptions/ConfigurationException.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/exceptions/ConfigurationException.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core.exceptions; /** diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/grailsversion/GrailsVersion.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/grailsversion/GrailsVersion.groovy index 8ed53afeb6d..8d48ee14fce 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/grailsversion/GrailsVersion.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/grailsversion/GrailsVersion.groovy @@ -23,7 +23,6 @@ import groovy.transform.CompileStatic import groovy.transform.EqualsAndHashCode import org.grails.datastore.mapping.reflect.ClassUtils - /** * A class to represent a version of Grails for comparison * @@ -159,10 +158,9 @@ class GrailsVersion implements Comparable { * @return Obtains the current Grails version */ static GrailsVersion getCurrent() { - if(currentVersion != null) { + if (currentVersion != null) { return currentVersion - } - else if (ClassUtils.isPresent("grails.util.BuildSettings")) { + } else if (ClassUtils.isPresent("grails.util.BuildSettings")) { currentVersion = new GrailsVersion(Class.forName("grails.util.BuildSettings").package.implementationVersion) return currentVersion } else { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingDelete.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingDelete.java index 1cd9b974cab..0061f343fb8 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingDelete.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingDelete.java @@ -25,4 +25,5 @@ * @since 5.0.0 */ public interface PendingDelete extends Runnable, PendingOperation { + } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingDeleteAdapter.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingDeleteAdapter.java index 92428f9cff5..78752040488 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingDeleteAdapter.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingDeleteAdapter.java @@ -23,15 +23,14 @@ /** * Adapter for the {@link org.grails.datastore.mapping.core.impl.PendingDelete} interface * - * @since 5.0.0 * @author Graeme Rocher + * @since 5.0.0 */ -public abstract class PendingDeleteAdapter extends PendingOperationAdapter implements PendingDelete{ - +public abstract class PendingDeleteAdapter extends PendingOperationAdapter implements PendingDelete { private boolean vetoed; - public PendingDeleteAdapter(PersistentEntity entity, K nativeKey, E nativeEntry) { + public PendingDeleteAdapter(PersistentEntity entity, K nativeKey, E nativeEntry) { super(entity, nativeKey, nativeEntry); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsert.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsert.java index c0faf99eb55..ed52202a252 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsert.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsert.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core.impl; import org.grails.datastore.mapping.engine.EntityAccess; @@ -25,11 +24,11 @@ * An insert that is pending execution in a flush() operation * * @param The native entry to persist - * * @author Graeme Rocher * @since 1.0 */ -public interface PendingInsert extends Runnable, PendingOperation{ +public interface PendingInsert extends Runnable, PendingOperation { + /** * @return The EntityAccess object for the entity to be inserted */ diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsertAdapter.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsertAdapter.java index 3e1228edbc5..cb0de3d5607 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsertAdapter.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingInsertAdapter.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core.impl; import org.grails.datastore.mapping.engine.EntityAccess; @@ -26,11 +25,10 @@ * Provides default implementation for most of the methods in the {@link PendingInsert} interafce * * @param The native entry to persist - * * @author Graeme Rocher * @since 1.0 */ -public abstract class PendingInsertAdapter extends PendingOperationAdapter implements PendingInsert{ +public abstract class PendingInsertAdapter extends PendingOperationAdapter implements PendingInsert { private EntityAccess entityAccess; @@ -56,7 +54,7 @@ public EntityAccess getEntityAccess() { @Override public Object getObject() { final EntityAccess ea = getEntityAccess(); - if(ea != null) { + if (ea != null) { return ea.getEntity(); } return null; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperation.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperation.java index e3560c99b96..07b5b267e90 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperation.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperation.java @@ -18,25 +18,24 @@ */ package org.grails.datastore.mapping.core.impl; -import java.util.List; - import org.grails.datastore.mapping.model.PersistentEntity; +import java.util.List; + /** * An operation that is pending execution. * - * @author Graeme Rocher - * * @param The native entity type (examples could be Row, Document etc.) * @param The native key + * @author Graeme Rocher */ public interface PendingOperation extends Runnable { - /** * @return Whether it was already executed */ boolean wasExecuted(); + /** * @return Whether the operation has been vetoed */ @@ -64,21 +63,24 @@ public interface PendingOperation extends Runnable { /** * Operations to be executed directly prior to this operation + * * @return The operations to execute prior */ - List> getPreOperations(); + List> getPreOperations(); /** * Adds an operation to executed prior to other operations + * * @param preOperation The prior operation */ void addPreOperation(PendingOperation preOperation); /** * Operations to be executed directly following this operation + * * @return The operations to cascade to */ - List> getCascadeOperations(); + List> getCascadeOperations(); /** * Adds an operation that should be executed after this operation diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationAdapter.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationAdapter.java index b932da0f523..2c3582818ed 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationAdapter.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationAdapter.java @@ -18,29 +18,28 @@ */ package org.grails.datastore.mapping.core.impl; +import org.grails.datastore.mapping.model.PersistentEntity; + import java.util.Collections; import java.util.LinkedList; import java.util.List; -import org.grails.datastore.mapping.model.PersistentEntity; - /** * Base implementation of the {@link PendingOperation} interface. * - * @author Graeme Rocher - * * @param The native entity type (examples could be Row, Document etc.) * @param The native key + * @author Graeme Rocher */ public abstract class PendingOperationAdapter implements PendingOperation { protected PersistentEntity entity; protected K nativeKey; protected E nativeEntry; + protected boolean executed; private List> pendingOperations = new LinkedList>(); private List> preOperations = new LinkedList>(); private boolean vetoed; - protected boolean executed; public PendingOperationAdapter(PersistentEntity entity, K nativeKey, E nativeEntry) { this.entity = entity; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationExecution.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationExecution.java index 937c2c5cca5..62d7d97dfe0 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationExecution.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingOperationExecution.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core.impl; import java.util.List; @@ -35,7 +34,7 @@ public static void executePendingOperation(PendingOperation pendingOperation) { preOperation.run(); } pendingOperation.run(); - if(!pendingOperation.isVetoed()) { + if (!pendingOperation.isVetoed()) { List cascadeOperations = pendingOperation.getCascadeOperations(); for (PendingOperation cascadeOperation : cascadeOperations) { cascadeOperation.run(); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdate.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdate.java index a4408418dd7..a190ca79a8e 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdate.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdate.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core.impl; import org.grails.datastore.mapping.engine.EntityAccess; @@ -26,11 +25,11 @@ * * @param The native entry to persist * @param The native key - * * @author Graeme Rocher * @since 1.0 */ -public interface PendingUpdate extends Runnable, PendingOperation{ +public interface PendingUpdate extends Runnable, PendingOperation { + /** * @return The EntityAccess object for the entity to be inserted */ diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdateAdapter.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdateAdapter.java index 6248a9c4545..b7949dea44e 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdateAdapter.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/core/impl/PendingUpdateAdapter.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.core.impl; import org.grails.datastore.mapping.engine.EntityAccess; @@ -26,11 +25,10 @@ * Provides a default implementation for the {@link PendingUpdate} interface * * @param The native entry to persist - * * @author Graeme Rocher * @since 1.0 */ -public abstract class PendingUpdateAdapter extends PendingOperationAdapter implements PendingUpdate{ +public abstract class PendingUpdateAdapter extends PendingOperationAdapter implements PendingUpdate { private EntityAccess entityAccess; @@ -56,7 +54,7 @@ public EntityAccess getEntityAccess() { @Override public Object getObject() { final EntityAccess ea = getEntityAccess(); - if(ea != null) { + if (ea != null) { return ea.getEntity(); } return null; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckable.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckable.groovy index 1d1ccf2c47b..50c7a84323d 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckable.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckable.groovy @@ -20,9 +20,8 @@ package org.grails.datastore.mapping.dirty.checking import groovy.transform.CompileStatic -import org.grails.datastore.mapping.proxy.EntityProxy - import jakarta.persistence.Transient +import org.grails.datastore.mapping.proxy.EntityProxy /** * Interface to classes that are able to track changes to their internal state. @@ -61,7 +60,7 @@ trait DirtyCheckable { * * @param changedProperties The changes. */ - void trackChanges(Map changedProperties) { + void trackChanges(Map changedProperties) { $changedProperties = changedProperties } @@ -69,10 +68,9 @@ trait DirtyCheckable { * @return True if the instance has any changes */ boolean hasChanged() { - if(this instanceof EntityProxy && !((EntityProxy)this).isInitialized()) { + if (this instanceof EntityProxy && !((EntityProxy) this).isInitialized()) { return false - } - else { + } else { return $changedProperties == null || DirtyCheckingSupport.DIRTY_CLASS_MARKER.is($changedProperties) || !$changedProperties.isEmpty() } } @@ -82,10 +80,9 @@ trait DirtyCheckable { * @return True if the given property has any changes */ boolean hasChanged(String propertyName) { - if(this instanceof EntityProxy && !((EntityProxy)this).isInitialized()) { + if (this instanceof EntityProxy && !((EntityProxy) this).isInitialized()) { return false - } - else { + } else { return $changedProperties == null || DirtyCheckingSupport.DIRTY_CLASS_MARKER.is($changedProperties) || $changedProperties?.containsKey(propertyName) } } @@ -94,7 +91,7 @@ trait DirtyCheckable { * Marks the whole class and all its properties as dirty. When called any future call to any of the hasChanged methods will return true. */ void markDirty() { - if( $changedProperties != null && $changedProperties.isEmpty()) { + if ($changedProperties != null && $changedProperties.isEmpty()) { $changedProperties = DirtyCheckingSupport.DIRTY_CLASS_MARKER } } @@ -104,11 +101,11 @@ trait DirtyCheckable { * @param propertyName The property name */ void markDirty(String propertyName) { - if( $changedProperties != null && !$changedProperties.containsKey(propertyName)) { + if ($changedProperties != null && !$changedProperties.containsKey(propertyName)) { if (DirtyCheckingSupport.DIRTY_CLASS_MARKER.is($changedProperties)) { trackChanges() } - $changedProperties.put propertyName, ((GroovyObject)this).getProperty(propertyName) + $changedProperties.put propertyName, ((GroovyObject) this).getProperty(propertyName) } } @@ -118,7 +115,7 @@ trait DirtyCheckable { * @param newValue The new value */ void markDirty(String propertyName, newValue) { - if( $changedProperties != null && !$changedProperties.containsKey(propertyName)) { + if ($changedProperties != null && !$changedProperties.containsKey(propertyName)) { def oldValue = ((GroovyObject) this).getProperty(propertyName) markDirty(propertyName, newValue, oldValue) } @@ -130,7 +127,7 @@ trait DirtyCheckable { * @param newValue The new value */ void markDirty(String propertyName, newValue, oldValue) { - if( $changedProperties != null && !$changedProperties.containsKey(propertyName)) { + if ($changedProperties != null && !$changedProperties.containsKey(propertyName)) { boolean isNull = newValue == null if ((isNull && oldValue != null) || (!isNull && oldValue == null) || @@ -147,13 +144,13 @@ trait DirtyCheckable { * @return A list of the dirty property names */ List listDirtyPropertyNames() { - if(this instanceof EntityProxy && !((EntityProxy)this).isInitialized()) { + if (this instanceof EntityProxy && !((EntityProxy) this).isInitialized()) { return Collections.emptyList() } - if($changedProperties != null) { + if ($changedProperties != null) { return Collections.unmodifiableList( - $changedProperties.keySet().toList() + $changedProperties.keySet().toList() ) } return Collections.emptyList() @@ -166,7 +163,7 @@ trait DirtyCheckable { * @return The original value */ Object getOriginalValue(String propertyName) { - if($changedProperties != null && $changedProperties.containsKey(propertyName)) { + if ($changedProperties != null && $changedProperties.containsKey(propertyName)) { return $changedProperties.get(propertyName) } else { return null diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckableCollection.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckableCollection.java index cd275c16177..e64cdd9f3d1 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckableCollection.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckableCollection.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.dirty.checking; import java.io.Serializable; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingCollection.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingCollection.groovy index 603cbd0b0d4..406228e01a1 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingCollection.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingCollection.groovy @@ -30,7 +30,8 @@ import groovy.transform.CompileStatic @CompileStatic class DirtyCheckingCollection implements Collection, DirtyCheckableCollection { - final @Delegate Collection target + final @Delegate + Collection target final DirtyCheckable parent final String property final int originalSize @@ -95,6 +96,5 @@ class DirtyCheckingCollection implements Collection, DirtyCheckableCollection { target.remove(o) } - } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingList.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingList.groovy index ba7379e3c5e..b71606991f9 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingList.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingList.groovy @@ -30,7 +30,8 @@ import groovy.transform.CompileStatic @CompileStatic class DirtyCheckingList extends DirtyCheckingCollection implements List { - @Delegate List target + @Delegate + List target DirtyCheckingList(List target, DirtyCheckable parent, String property) { super(target, parent, property) @@ -55,10 +56,9 @@ class DirtyCheckingList extends DirtyCheckingCollection implements List { target.add(index, element) } - @Override Object remove(int index) { parent.markDirty(property) - target.remove((int)index) + target.remove((int) index) } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingMap.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingMap.groovy index 70ce8368f1c..bdfd86ffa08 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingMap.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingMap.groovy @@ -30,7 +30,8 @@ import groovy.transform.CompileStatic @CompileStatic class DirtyCheckingMap implements Map, DirtyCheckableCollection { - final @Delegate Map target + final @Delegate + Map target final DirtyCheckable parent final String property final int originalSize diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSet.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSet.groovy index bfca6fa5a88..d9c1583c50a 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSet.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSet.groovy @@ -30,7 +30,8 @@ import groovy.transform.CompileStatic @CompileStatic class DirtyCheckingSet extends DirtyCheckingCollection implements Set { - @Delegate Set target + @Delegate + Set target DirtyCheckingSet(Set target, DirtyCheckable parent, String property) { super(target, parent, property) diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSortedSet.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSortedSet.groovy index 956b62f5e7d..1d9e0ad32d7 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSortedSet.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSortedSet.groovy @@ -21,7 +21,6 @@ package org.grails.datastore.mapping.dirty.checking import groovy.transform.CompileStatic - /** * Dirty checks sorted sets * @@ -31,7 +30,8 @@ import groovy.transform.CompileStatic @CompileStatic class DirtyCheckingSortedSet extends DirtyCheckingCollection implements SortedSet { - @Delegate SortedSet target + @Delegate + SortedSet target DirtyCheckingSortedSet(SortedSet target, DirtyCheckable parent, String property) { super(target, parent, property) diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSupport.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSupport.groovy index c294c4d799a..c519beecf40 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSupport.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckingSupport.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.dirty.checking import groovy.transform.CompileStatic -import groovy.transform.PackageScope import org.grails.datastore.mapping.collection.PersistentCollection import org.grails.datastore.mapping.core.Session import org.grails.datastore.mapping.model.MappingContext @@ -27,7 +26,6 @@ import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.model.types.Association import org.grails.datastore.mapping.model.types.Embedded import org.grails.datastore.mapping.model.types.ToOne -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher import org.grails.datastore.mapping.reflect.EntityReflector /** @@ -41,7 +39,7 @@ class DirtyCheckingSupport { /** * Used internally as a marker. Do not use in user code */ - public static final Map DIRTY_CLASS_MARKER = [:].asImmutable() + public static final Map DIRTY_CLASS_MARKER = [:].asImmutable() /** * Checks whether associations are dirty * @@ -56,7 +54,6 @@ class DirtyCheckingSupport { areAssociationsDirty(entity, instance) } - /** * Checks whether associations are dirty * @@ -66,34 +63,32 @@ class DirtyCheckingSupport { * @return True if they are */ static boolean areAssociationsDirty(PersistentEntity entity, Object instance) { - if(!instance) return false - + if (!instance) return false MappingContext mappingContext = entity.mappingContext final proxyFactory = mappingContext.proxyFactory final EntityReflector entityReflector = mappingContext.getEntityReflector(entity) final associations = entity.associations - for(Association a in associations) { + for (Association a in associations) { final isOwner = a.isOwningSide() || (a.bidirectional && !a.inverseSide?.owningSide) - if(isOwner) { - if(a instanceof ToOne) { + if (isOwner) { + if (a instanceof ToOne) { final value = entityReflector.getProperty(instance, a.name) - if(proxyFactory.isInitialized(value)) { - if(value instanceof DirtyCheckable) { + if (proxyFactory.isInitialized(value)) { + if (value instanceof DirtyCheckable) { DirtyCheckable dirtyCheckable = (DirtyCheckable) value - if(dirtyCheckable.hasChanged()) { + if (dirtyCheckable.hasChanged()) { return true } } } - } - else { + } else { final value = entityReflector.getProperty(instance, a.name) - if(value instanceof PersistentCollection) { - PersistentCollection coll = (PersistentCollection)value - if(coll.isInitialized()) { - if(coll.isDirty()) return true + if (value instanceof PersistentCollection) { + PersistentCollection coll = (PersistentCollection) value + if (coll.isInitialized()) { + if (coll.isDirty()) return true } } } @@ -103,7 +98,6 @@ class DirtyCheckingSupport { return false } - /** * Checks whether embedded associations are dirty * @@ -113,15 +107,14 @@ class DirtyCheckingSupport { * @return True if they are */ static boolean areEmbeddedDirty(PersistentEntity entity, Object instance) { - if(instance == null) return false - + if (instance == null) return false final associations = entity.getEmbedded() - for(Embedded a in associations) { + for (Embedded a in associations) { final value = a.reader.read(instance) - if(value instanceof DirtyCheckable) { + if (value instanceof DirtyCheckable) { DirtyCheckable dirtyCheckable = (DirtyCheckable) value - if(dirtyCheckable.hasChanged()) { + if (dirtyCheckable.hasChanged()) { return true } } @@ -137,13 +130,13 @@ class DirtyCheckingSupport { * @return The wrapped collection */ static Collection wrap(Collection coll, DirtyCheckable parent, String property) { - if(coll instanceof DirtyCheckingCollection) { + if (coll instanceof DirtyCheckingCollection) { return coll } - if(coll instanceof List) { + if (coll instanceof List) { return new DirtyCheckingList(coll, parent, property) } - if(coll instanceof Set) { + if (coll instanceof Set) { return new DirtyCheckingSet(coll, parent, property) } return new DirtyCheckingCollection(coll, parent, property) diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/DocumentDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/DocumentDatastore.java index 248be893d9f..2326eea6a1b 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/DocumentDatastore.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/DocumentDatastore.java @@ -23,4 +23,6 @@ /** * @author Guillaume Laforge */ -public interface DocumentDatastore extends Datastore {} \ No newline at end of file +public interface DocumentDatastore extends Datastore { + +} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentMappingContext.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentMappingContext.java index 21877a1be59..5ea24cb9c38 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentMappingContext.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentMappingContext.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.document.config; import groovy.lang.Closure; @@ -36,6 +35,7 @@ */ @SuppressWarnings({"rawtypes", "unchecked"}) public class DocumentMappingContext extends AbstractMappingContext { + protected String defaultDatabaseName; protected MappingFactory mappingFactory; @@ -70,7 +70,7 @@ public DocumentMappingContext(String defaultDatabaseName, Closure defaultMapping protected void initialize(ConnectionSourceSettings settings) { this.defaultMapping = settings.getDefault().getMapping(); - AbstractGormMappingFactory documentMappingFactory = (AbstractGormMappingFactory)createDocumentMappingFactory(defaultMapping); + AbstractGormMappingFactory documentMappingFactory = (AbstractGormMappingFactory) createDocumentMappingFactory(defaultMapping); documentMappingFactory.setDefaultConstraints(settings.getDefault().getConstraints()); mappingFactory = documentMappingFactory; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentPersistentEntity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentPersistentEntity.java index 837fadb0688..2d0ea20d7a0 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentPersistentEntity.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/document/config/DocumentPersistentEntity.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.document.config; import org.grails.datastore.mapping.model.AbstractClassMapping; @@ -47,21 +46,23 @@ public ClassMapping getMapping() { } public class DocumentCollectionMapping extends AbstractClassMapping { + private final Collection mappedForm; private IdentityMapping identityMapping; + public DocumentCollectionMapping(PersistentEntity entity, MappingContext context) { super(entity, context); - if(entity.isExternal()) { + if (entity.isExternal()) { this.mappedForm = null; - } - else { + } else { this.mappedForm = (Collection) context.getMappingFactory().createMappedForm(DocumentPersistentEntity.this); } } + @Override public Collection getMappedForm() { - return mappedForm ; + return mappedForm; } @Override diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/AssociationIndexer.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/AssociationIndexer.java index e8d2978e295..69d4d50089b 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/AssociationIndexer.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/AssociationIndexer.java @@ -22,7 +22,7 @@ /** * Responsible for creating indices for associations used in queries. - * + *

    * An instance may be specific to a particular association of a particular native instance of an entity (the parent * of the association). * @@ -35,10 +35,11 @@ public interface AssociationIndexer extends AssociationQueryExecutor * Creates an index queryable via the primary key. This is called *before* the entity that this association * indexer is part of is persisted, but after the native entry has been updated ready to be persisted. * This allows the index to be placed in the native instance itself, e.g. in a document database. - * + *

    * Usually, for a particular association type, only this OR {@link #index(Object, java.util.List)} will be * implemented. - * @param primaryKey The primary key + * + * @param primaryKey The primary key * @param foreignKeys The foreign keys */ void preIndex(K primaryKey, List foreignKeys); @@ -46,16 +47,18 @@ public interface AssociationIndexer extends AssociationQueryExecutor /** * Creates an index queryable via the primary key. This is called *after* the entity this association indexer * is part of has been persisted. - * + *

    * Usually, for a particular association type, only this OR {@link #preIndex(Object, java.util.List)} will be * implemented. - * @param primaryKey The primary key + * + * @param primaryKey The primary key * @param foreignKeys The foreign keys */ void index(K primaryKey, List foreignKeys); /** * Index a single foreign key + * * @param primaryKey The primaryKey * @param foreignKey The foreignKey */ diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/BeanEntityAccess.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/BeanEntityAccess.java index 29d5d15b833..330b281e1fb 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/BeanEntityAccess.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/BeanEntityAccess.java @@ -14,20 +14,20 @@ */ package org.grails.datastore.mapping.engine; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; -import java.util.Set; - +import org.grails.datastore.mapping.model.ClassMapping; +import org.grails.datastore.mapping.model.IdentityMapping; +import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; import org.springframework.beans.BeanWrapper; import org.springframework.beans.PropertyAccessorFactory; import org.springframework.core.convert.ConversionService; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.IdentityMapping; -import org.grails.datastore.mapping.model.PersistentEntity; import org.springframework.util.ReflectionUtils; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.util.Set; + /** * Class used to access properties of an entity. Also responsible for * any conversion from source to target types. @@ -77,12 +77,11 @@ public Class getPropertyType(String name) { @Override public void setProperty(String name, Object value) { Class type = getPropertyType(name); - if(value == null) { - if(!type.isPrimitive()) { + if (value == null) { + if (!type.isPrimitive()) { beanWrapper.setPropertyValue(name, value); } - } - else { + } else { beanWrapper.setPropertyValue(name, value); } @@ -95,7 +94,7 @@ public Object getIdentifier() { return getProperty(idName); } PersistentProperty identity = persistentEntity.getIdentity(); - if(identity != null) { + if (identity != null) { return getProperty(identity.getName()); } return null; @@ -117,7 +116,7 @@ protected String getIdentifierName(ClassMapping cm) { final IdentityMapping identifier = cm.getIdentifier(); if (identifier != null && identifier.getIdentifierName() != null) { String[] identifierName = identifier.getIdentifierName(); - if(identifierName.length > 0) { + if (identifierName.length > 0) { return identifierName[0]; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityAccess.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityAccess.java index dc97643141e..07549ed5ace 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityAccess.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityAccess.java @@ -16,18 +16,17 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.engine; import org.grails.datastore.mapping.model.PersistentEntity; /** * @author Graeme Rocher - * * @since 4.1 * */ public interface EntityAccess { + /** * @return The entity being persisted */ @@ -35,6 +34,7 @@ public interface EntityAccess { /** * Obtains a property value + * * @param name the name of the value * @return The value of the property */ @@ -42,6 +42,7 @@ public interface EntityAccess { /** * Obtains a property value + * * @param name the name of the value * @return The value of the property */ @@ -49,6 +50,7 @@ public interface EntityAccess { /** * Obtains a property type + * * @param name The name of the property * @return The type of of the property */ @@ -56,7 +58,8 @@ public interface EntityAccess { /** * Sets a property value - * @param name The name of the property + * + * @param name The name of the property * @param value The value of the property */ void setProperty(String name, Object value); @@ -68,12 +71,14 @@ public interface EntityAccess { /** * Sets the entity identifier to the given value + * * @param id The value to set */ void setIdentifier(Object id); /** * Sets the entity identifier to the given value + * * @param id The value to set */ void setIdentifierNoConversion(Object id); @@ -96,7 +101,7 @@ public interface EntityAccess { /** * Sets a property without applying any automatic type conversion * - * @param name The name of the property + * @param name The name of the property * @param value The value */ void setPropertyNoConversion(String name, Object value); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityPersister.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityPersister.java index 72f8b601c35..075eda4e0e4 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityPersister.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/EntityPersister.java @@ -18,11 +18,6 @@ */ package org.grails.datastore.mapping.engine; -import java.io.Serializable; -import java.sql.Timestamp; -import java.util.Date; -import java.util.List; - import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.core.SessionImplementor; @@ -43,6 +38,11 @@ import org.grails.datastore.mapping.reflect.EntityReflector; import org.springframework.context.ApplicationEventPublisher; +import java.io.Serializable; +import java.sql.Timestamp; +import java.util.Date; +import java.util.List; + /** * A {@link org.grails.datastore.mapping.engine.Persister} specifically for persisting PersistentEntity instances. * @@ -50,15 +50,16 @@ * @since 1.0 */ public abstract class EntityPersister implements Persister { - private final PersistentEntity persistentEntity; - private final MappingContext mappingContext; + protected final Session session; protected final ApplicationEventPublisher publisher; protected final EntityReflector reflector; protected org.grails.datastore.mapping.proxy.ProxyFactory proxyFactory; + private final PersistentEntity persistentEntity; + private final MappingContext mappingContext; public EntityPersister(MappingContext mappingContext, PersistentEntity entity, - Session session, ApplicationEventPublisher publisher) { + Session session, ApplicationEventPublisher publisher) { this.persistentEntity = entity; this.mappingContext = mappingContext; this.session = session; @@ -74,7 +75,7 @@ public Session getSession() { public Object proxy(Serializable key) { PersistentEntity entity = getPersistentEntity(); PersistentProperty identity = entity.getIdentity(); - if(identity != null) { + if (identity != null) { key = (Serializable) mappingContext.getConversionService().convert(key, identity.getType()); } return getProxyFactory().createProxy(session, entity.getJavaClass(), key); @@ -108,24 +109,25 @@ public Class getType() { /** * Obtains an objects identifer + * * @param obj The object * @return The identifier or null if it doesn't have one */ public Serializable getObjectIdentifier(Object obj) { - if (obj == null) return null; + if (obj == null) { + return null; + } final ProxyFactory pf = getProxyFactory(); if (pf.isProxy(obj)) { return pf.getIdentifier(obj); } - if(persistentEntity.getJavaClass().equals(obj.getClass())) { + if (persistentEntity.getJavaClass().equals(obj.getClass())) { return reflector.getIdentifier(obj); - } - else { + } else { EntityPersister persister = (EntityPersister) getSession().getPersister(obj); - if(persister != null) { + if (persister != null) { return persister.getObjectIdentifier(obj); - } - else { + } else { return null; } } @@ -149,8 +151,9 @@ public Serializable insert(Object obj) { /** * Subclasses should override to support explicit inserts - * @param entity The entity - * @param obj The object + * + * @param entity The entity + * @param obj The object * @param isInsert Whether it is an insert * @return The id */ @@ -160,6 +163,7 @@ protected Serializable persistEntity(PersistentEntity entity, Object obj, boolea /** * Obtains an objects identifer + * * @param obj The object */ public void setObjectIdentifier(Object obj, Serializable id) { @@ -177,8 +181,8 @@ public final Serializable persist(Object obj) { final Persister persister = getSession().getPersister(obj); if (persister == null) { throw new IllegalArgumentException("Object [" + obj + - "] is not an instance supported by the persister for class [" + - getType().getName() + "]"); + "] is not an instance supported by the persister for class [" + + getType().getName() + "]"); } return persister.persist(obj); @@ -204,7 +208,7 @@ public List retrieveAll(Serializable[] keys) { public Object getCurrentVersion(final EntityAccess ea) { Object currentVersion = ea.getProperty(GormProperties.VERSION); if (Number.class.isAssignableFrom(ea.getPropertyType(GormProperties.VERSION))) { - currentVersion = currentVersion != null ? ((Number)currentVersion).longValue() : currentVersion; + currentVersion = currentVersion != null ? ((Number) currentVersion).longValue() : currentVersion; } return currentVersion; } @@ -231,7 +235,7 @@ public final Object retrieve(Serializable key) { /** * Retrieve a PersistentEntity for the given mappingContext and key * - * @param pe The entity + * @param pe The entity * @param key The key * @return The object or null if it doesn't exist */ @@ -240,7 +244,7 @@ public final Object retrieve(Serializable key) { protected boolean isAssignedId(PersistentEntity persistentEntity) { boolean assignedId = false; PersistentProperty identity = persistentEntity.getIdentity(); - if(identity != null) { + if (identity != null) { PropertyMapping mapping = identity.getMapping(); if (mapping != null) { Property p = mapping.getMappedForm(); @@ -253,7 +257,7 @@ protected boolean isAssignedId(PersistentEntity persistentEntity) { /** * Persist the given persistent entity * - * @param pe The PersistentEntity + * @param pe The PersistentEntity * @param obj * @return The generated key */ @@ -280,7 +284,7 @@ public void delete(Object obj) { protected abstract void deleteEntities(PersistentEntity pe, @SuppressWarnings("rawtypes") Iterable objects); protected EntityAccess createEntityAccess(PersistentEntity pe, Object obj) { - final SessionImplementor si = (SessionImplementor)getSession(); + final SessionImplementor si = (SessionImplementor) getSession(); return si.createEntityAccess(pe, obj); } @@ -291,42 +295,45 @@ protected Object newEntityInstance(PersistentEntity persistentEntity) { return o; } - /** - * Fire the beforeInsert even on an entityAccess object and return true if the operation should be cancelled - * @param persistentEntity The entity - * @param entityAccess The entity access - * @return true if the operation should be cancelled - */ + /** + * Fire the beforeInsert even on an entityAccess object and return true if the operation should be cancelled + * + * @param persistentEntity The entity + * @param entityAccess The entity access + * @return true if the operation should be cancelled + */ public boolean cancelInsert(final PersistentEntity persistentEntity, final EntityAccess entityAccess) { - PreInsertEvent event = new PreInsertEvent(session.getDatastore(), persistentEntity, entityAccess); - publisher.publishEvent(event); - return event.isCancelled(); - } + PreInsertEvent event = new PreInsertEvent(session.getDatastore(), persistentEntity, entityAccess); + publisher.publishEvent(event); + return event.isCancelled(); + } public void firePostInsertEvent(final PersistentEntity persistentEntity, final EntityAccess entityAccess) { publisher.publishEvent(new PostInsertEvent( session.getDatastore(), persistentEntity, entityAccess)); } - /** - * Fire the beforeUpdate event on an entityAccess object and return true if the operation should be cancelled - * @param persistentEntity The entity - * @param entityAccess The entity access - * @return true if the operation should be cancelled - */ + /** + * Fire the beforeUpdate event on an entityAccess object and return true if the operation should be cancelled + * + * @param persistentEntity The entity + * @param entityAccess The entity access + * @return true if the operation should be cancelled + */ public boolean cancelUpdate(final PersistentEntity persistentEntity, final EntityAccess entityAccess) { - PreUpdateEvent event = new PreUpdateEvent(session.getDatastore(), persistentEntity, entityAccess); - publisher.publishEvent(event); - return event.isCancelled(); - } + PreUpdateEvent event = new PreUpdateEvent(session.getDatastore(), persistentEntity, entityAccess); + publisher.publishEvent(event); + return event.isCancelled(); + } /** * Fire the beforeDelete event on an entityAccess object and return true if the operation should be cancelled + * * @param persistentEntity The entity - * @param entityAccess The entity access + * @param entityAccess The entity access * @return true if the operation should be cancelled */ - public boolean cancelDelete( final PersistentEntity persistentEntity, final EntityAccess entityAccess) { + public boolean cancelDelete(final PersistentEntity persistentEntity, final EntityAccess entityAccess) { PreDeleteEvent event = new PreDeleteEvent(session.getDatastore(), persistentEntity, entityAccess); publisher.publishEvent(event); return event.isCancelled(); @@ -334,11 +341,12 @@ public boolean cancelDelete( final PersistentEntity persistentEntity, final Enti /** * Fire the beforeDelete event on an entityAccess object and return true if the operation should be cancelled + * * @param persistentEntity The entity - * @param entityAccess The entity access + * @param entityAccess The entity access * @return true if the operation should be cancelled */ - public boolean cancelLoad( final PersistentEntity persistentEntity, final EntityAccess entityAccess) { + public boolean cancelLoad(final PersistentEntity persistentEntity, final EntityAccess entityAccess) { PreLoadEvent event = new PreLoadEvent(session.getDatastore(), persistentEntity, entityAccess); publisher.publishEvent(event); return event.isCancelled(); @@ -386,8 +394,7 @@ public static void incrementEntityVersion(EntityAccess ea) { currentVersion = 0L; } ea.setProperty(versionName, currentVersion.longValue() + 1); - } - else { + } else { setDateVersionInternal(versionName, ea); } } @@ -396,8 +403,7 @@ protected void setVersion(final EntityAccess ea) { final String versionName = ea.getPersistentEntity().getVersion().getName(); if (Number.class.isAssignableFrom(ea.getPropertyType(versionName))) { ea.setProperty(versionName, 0); - } - else { + } else { setDateVersion(ea); } } @@ -409,8 +415,7 @@ protected void setDateVersion(final EntityAccess ea) { private static void setDateVersionInternal(String versionName, EntityAccess ea) { if (Timestamp.class.isAssignableFrom(ea.getPropertyType(versionName))) { ea.setProperty(versionName, new Timestamp(System.currentTimeMillis())); - } - else { + } else { ea.setProperty(versionName, new Date()); } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/LockableEntityPersister.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/LockableEntityPersister.java index b28c3a7d6c9..cbcea9d28d0 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/LockableEntityPersister.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/LockableEntityPersister.java @@ -18,14 +18,14 @@ */ package org.grails.datastore.mapping.engine; -import java.io.Serializable; - -import org.grails.datastore.mapping.model.PersistentProperty; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.dao.CannotAcquireLockException; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.model.PersistentProperty; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.dao.CannotAcquireLockException; + +import java.io.Serializable; /** * Abstract base class for entity persisters that support locking. @@ -35,10 +35,12 @@ */ public abstract class LockableEntityPersister extends EntityPersister { + //CHECKSTYLE:OFF public static int DEFAULT_TIMEOUT = 30; + //CHECKSTYLE:ON public LockableEntityPersister(MappingContext mappingContext, PersistentEntity entity, - Session session, ApplicationEventPublisher publisher) { + Session session, ApplicationEventPublisher publisher) { super(mappingContext, entity, session, publisher); } @@ -53,7 +55,8 @@ public LockableEntityPersister(MappingContext mappingContext, PersistentEntity e /** * Acquire a lock using the given identifier and timeout delay - * @param id the identifier + * + * @param id the identifier * @param timeout the amount of time to wait before giving up in seconds * @return The locked object * @throws CannotAcquireLockException @@ -62,13 +65,15 @@ public LockableEntityPersister(MappingContext mappingContext, PersistentEntity e /** * Return whether an object is locked or not + * * @param o The object - * @return True if it is locked + * @return True if it is locked */ public abstract boolean isLocked(Object o); /** * Unlocks a locked object + * * @param o The object to unlock */ public abstract void unlock(Object o); @@ -78,7 +83,7 @@ public LockableEntityPersister(MappingContext mappingContext, PersistentEntity e public Object proxy(Serializable key) { PersistentEntity entity = getPersistentEntity(); PersistentProperty identity = entity.getIdentity(); - if(identity != null) { + if (identity != null) { key = (Serializable) getMappingContext().getConversionService().convert(key, identity.getType()); } return getProxyFactory().createProxy(session, entity.getJavaClass(), key); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/ModificationTrackingEntityAccess.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/ModificationTrackingEntityAccess.groovy index bd3c3af4eca..a69b440c1e2 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/ModificationTrackingEntityAccess.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/ModificationTrackingEntityAccess.groovy @@ -33,11 +33,12 @@ class ModificationTrackingEntityAccess implements EntityAccess { /** * The target entity access */ - final @Delegate EntityAccess target + final @Delegate + EntityAccess target /** * The modified properties */ - final Map modifiedProperties = [:] + final Map modifiedProperties = [:] ModificationTrackingEntityAccess(EntityAccess target) { this.target = target diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/NativeEntryEntityPersister.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/NativeEntryEntityPersister.java index 7292d8c11e6..660c82f1b25 100755 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/NativeEntryEntityPersister.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/NativeEntryEntityPersister.java @@ -18,24 +18,9 @@ */ package org.grails.datastore.mapping.engine; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; - import jakarta.persistence.CascadeType; import jakarta.persistence.FetchType; import jakarta.persistence.FlushModeType; - import org.grails.datastore.mapping.cache.TPCacheAdapterRepository; import org.grails.datastore.mapping.collection.AbstractPersistentCollection; import org.grails.datastore.mapping.collection.PersistentCollection; @@ -61,33 +46,56 @@ import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.PropertyMapping; -import org.grails.datastore.mapping.model.types.*; +import org.grails.datastore.mapping.model.types.Association; +import org.grails.datastore.mapping.model.types.Basic; +import org.grails.datastore.mapping.model.types.Custom; +import org.grails.datastore.mapping.model.types.Embedded; +import org.grails.datastore.mapping.model.types.EmbeddedCollection; +import org.grails.datastore.mapping.model.types.ManyToMany; +import org.grails.datastore.mapping.model.types.OneToMany; +import org.grails.datastore.mapping.model.types.Simple; +import org.grails.datastore.mapping.model.types.ToOne; import org.grails.datastore.mapping.proxy.ProxyFactory; import org.grails.datastore.mapping.query.Query; import org.springframework.context.ApplicationEventPublisher; import org.springframework.core.convert.ConversionService; import org.springframework.dao.CannotAcquireLockException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; + /** * Provides an implementation of the {@link org.grails.datastore.mapping.engine.EntityPersister} class that * reads and writes against a native datastore type specified by the generic type parameter T * * @author Graeme Rocher - * @since 1.0 + * @since 1.0 */ @SuppressWarnings({"unused", "rawtypes", "unchecked"}) public abstract class NativeEntryEntityPersister extends ThirdPartyCacheEntityPersister { + public static final String EMBEDDED_PREFIX = "embedded:"; protected ClassMapping classMapping; public NativeEntryEntityPersister(MappingContext mappingContext, PersistentEntity entity, - Session session, ApplicationEventPublisher publisher) { + Session session, ApplicationEventPublisher publisher) { super(mappingContext, entity, session, publisher); classMapping = entity.getMapping(); } public NativeEntryEntityPersister(MappingContext mappingContext, PersistentEntity entity, - Session session, ApplicationEventPublisher publisher, TPCacheAdapterRepository cacheAdapterRepository) { + Session session, ApplicationEventPublisher publisher, TPCacheAdapterRepository cacheAdapterRepository) { super(mappingContext, entity, session, publisher, cacheAdapterRepository); classMapping = entity.getMapping(); } @@ -103,7 +111,9 @@ public ClassMapping getClassMapping() { * * @return True if property indexing is required (the default) */ - protected boolean doesRequirePropertyIndexing() { return true; } + protected boolean doesRequirePropertyIndexing() { + return true; + } @Override protected void deleteEntity(PersistentEntity persistentEntity, Object obj) { @@ -112,7 +122,7 @@ protected void deleteEntity(PersistentEntity persistentEntity, Object obj) { } EntityAccess entityAccess = createEntityAccess(persistentEntity, obj); - if(cancelDelete(persistentEntity, entityAccess)) { + if (cancelDelete(persistentEntity, entityAccess)) { return; } @@ -127,8 +137,7 @@ protected void deleteEntity(PersistentEntity persistentEntity, Object obj) { cascadeBeforeDelete(persistentEntity, entityAccess, key, obj); deleteEntry(getEntityFamily(), key, obj); cascadeAfterDelete(persistentEntity, entityAccess, key, obj); - } - finally { + } finally { session.setFlushMode(flushMode); } @@ -159,8 +168,8 @@ protected EntityAccess createEntityAccess(PersistentEntity persistentEntity, Obj * Deletes a single entry * * @param family The family - * @param key The key - * @param entry the entry + * @param key The key + * @param entry the entry */ protected abstract void deleteEntry(String family, K key, Object entry); @@ -168,22 +177,21 @@ protected EntityAccess createEntityAccess(PersistentEntity persistentEntity, Obj * Delete collections before owner delete. */ protected void cascadeBeforeDelete(PersistentEntity persistentEntity, EntityAccess entityAccess, - K key, Object instance) { + K key, Object instance) { List props = persistentEntity.getPersistentProperties(); for (PersistentProperty prop : props) { String propertyKey = getPropertyKey(prop); if (prop instanceof OneToMany) { - OneToMany oneToMany = (OneToMany)prop; + OneToMany oneToMany = (OneToMany) prop; if (oneToMany.isOwningSide() && oneToMany.doesCascade(CascadeType.REMOVE)) { if (Collection.class.isAssignableFrom(oneToMany.getType())) { cascadeDeleteCollection(entityAccess, oneToMany); } } - } - else if (prop instanceof ManyToMany) { - ManyToMany manyToMany = (ManyToMany)prop; + } else if (prop instanceof ManyToMany) { + ManyToMany manyToMany = (ManyToMany) prop; if (manyToMany.isOwningSide() && manyToMany.doesCascade(CascadeType.REMOVE)) { Object propValue = entityAccess.getProperty(manyToMany.getName()); if (Collection.class.isAssignableFrom(manyToMany.getType())) { @@ -198,23 +206,21 @@ else if (prop instanceof ManyToMany) { * Delete many-to-ones after owner delete. */ protected void cascadeAfterDelete(PersistentEntity persistentEntity, EntityAccess entityAccess, - K key, Object instance) { + K key, Object instance) { List props = persistentEntity.getPersistentProperties(); for (PersistentProperty prop : props) { String propertyKey = getPropertyKey(prop); if (prop instanceof Basic) { Object propValue = entityAccess.getProperty(prop.getName()); - } - else if (prop instanceof OneToMany) { - OneToMany oneToMany = (OneToMany)prop; + } else if (prop instanceof OneToMany) { + OneToMany oneToMany = (OneToMany) prop; if (oneToMany.isOwningSide() && oneToMany.doesCascade(CascadeType.REMOVE)) { if (Collection.class.isAssignableFrom(oneToMany.getType())) { cascadeDeleteCollection(entityAccess, oneToMany); } } - } - else if (prop instanceof ToOne) { + } else if (prop instanceof ToOne) { ToOne association = (ToOne) prop; if (!(prop instanceof Embedded) && !(prop instanceof EmbeddedCollection) && association.doesCascade(CascadeType.REMOVE)) { @@ -285,9 +291,9 @@ public final Object lock(Serializable id, int timeout) throws CannotAcquireLockE * Subclasses can override to provide locking semantics * * @param persistentEntity The PesistentEntity instnace - * @param entityFamily The family - * @param id The identifer - * @param timeout The lock timeout in seconds + * @param entityFamily The family + * @param id The identifer + * @param timeout The lock timeout in seconds */ protected void lockEntry(PersistentEntity persistentEntity, String entityFamily, Serializable id, int timeout) { // do nothing, @@ -311,9 +317,10 @@ public void unlock(Object o) { /** * Subclasses to override to provide locking semantics + * * @param persistentEntity The persistent entity - * @param entityFamily The entity family - * @param id The identifer + * @param entityFamily The entity family + * @param id The identifer */ protected void unlockEntry(PersistentEntity persistentEntity, String entityFamily, Serializable id) { // do nothing @@ -376,9 +383,9 @@ public Object createObjectFromEmbeddedNativeEntry(PersistentEntity persistentEnt } protected void cacheNativeEntry(PersistentEntity persistentEntity, - Serializable nativeKey, T nativeEntry) { + Serializable nativeKey, T nativeEntry) { SessionImplementor si = (SessionImplementor) session; - Serializable key = convertIdIfNecessary(persistentEntity, nativeKey) ; + Serializable key = convertIdIfNecessary(persistentEntity, nativeKey); si.cacheEntry(persistentEntity, key, nativeEntry); } @@ -389,15 +396,16 @@ protected Serializable convertIdIfNecessary(PersistentEntity entity, Serializabl } protected void cacheEmbeddedEntry(PersistentEntity persistentEntity, - Serializable nativeKey, T nativeEntry) { + Serializable nativeKey, T nativeEntry) { SessionImplementor si = (SessionImplementor) session; - si.cacheEntry(persistentEntity, "embedded:"+nativeEntry, nativeEntry); + si.cacheEntry(persistentEntity, "embedded:" + nativeEntry, nativeEntry); } protected void refreshObjectStateFromNativeEntry(PersistentEntity persistentEntity, Object obj, Serializable nativeKey, T nativeEntry) { refreshObjectStateFromNativeEntry(persistentEntity, obj, nativeKey, nativeEntry, false); } + protected void refreshObjectStateFromNativeEntry(PersistentEntity persistentEntity, Object obj, Serializable nativeKey, T nativeEntry, boolean isEmbedded) { EntityAccess ea = createEntityAccess(persistentEntity, obj, nativeEntry); @@ -413,35 +421,30 @@ protected void refreshObjectStateFromNativeEntry(PersistentEntity persistentEnti if (prop instanceof Simple) { // this magically converts most types to the correct property type, using bean converters. ea.setProperty(prop.getName(), getEntryValue(nativeEntry, propKey)); - } - else if (prop instanceof Basic) { + } else if (prop instanceof Basic) { Basic basic = (Basic) prop; CustomTypeMarshaller customTypeMarshaller = basic.getCustomTypeMarshaller(); - if(customTypeMarshaller != null) { + if (customTypeMarshaller != null) { if (!customTypeMarshaller.supports(getMappingContext())) { return; } Object value = customTypeMarshaller.read(prop, nativeEntry); ea.setProperty(prop.getName(), value); - } - else { + } else { Object entryValue = getEntryValue(nativeEntry, propKey); - entryValue = convertBasicEntryValue(persistentEntity, (Basic)prop, entryValue); + entryValue = convertBasicEntryValue(persistentEntity, (Basic) prop, entryValue); ea.setProperty(prop.getName(), entryValue); } - } - else if (prop instanceof Custom) { + } else if (prop instanceof Custom) { handleCustom(prop, ea, nativeEntry); - } - else if (prop instanceof ToOne) { + } else if (prop instanceof ToOne) { if (prop instanceof Embedded) { Embedded embedded = (Embedded) prop; - if(embedded.getAssociatedEntity() != null) { + if (embedded.getAssociatedEntity() != null) { T embeddedEntry = getEmbedded(nativeEntry, propKey); - if (embeddedEntry != null) { Object embeddedInstance = createObjectFromEmbeddedNativeEntry(embedded.getAssociatedEntity(), embeddedEntry); @@ -457,24 +460,21 @@ else if (prop instanceof ToOne) { } } } - } - else { + } else { ToOne association = (ToOne) prop; Serializable tmp = null; if (!association.isForeignKeyInChild()) { tmp = (Serializable) getEntryValue(nativeEntry, propKey); - } - else { + } else { if (association.isBidirectional() && association.getAssociatedEntity() != null) { Query query = session.createQuery(association.getAssociatedEntity().getJavaClass()); query.eq(association.getInverseSide().getName(), obj) - .projections().id(); + .projections().id(); tmp = (Serializable) query.singleResult(); - } - else { + } else { // TODO: handle unidirectional? } } @@ -483,12 +483,11 @@ else if (prop instanceof ToOne) { PersistentEntity associatedEntity = ((ToOne) prop).getAssociatedEntity(); associatedEntity = discriminatePersistentEntity(associatedEntity, (T) tmp); Object instance = newEntityInstance(associatedEntity); - refreshObjectStateFromNativeEntry(associatedEntity,instance, null, (T) tmp, false); + refreshObjectStateFromNativeEntry(associatedEntity, instance, null, (T) tmp, false); ea.setProperty(prop.getName(), instance); - } - else if (tmp != null && !prop.getType().isInstance(tmp)) { + } else if (tmp != null && !prop.getType().isInstance(tmp)) { PersistentEntity associatedEntity = association.getAssociatedEntity(); - if(associatedEntity != null) { + if (associatedEntity != null) { final Serializable associationKey = convertIdIfNecessary(associatedEntity, tmp); if (associationKey != null) { @@ -504,8 +503,7 @@ else if (tmp != null && !prop.getType().isInstance(tmp)) { } } } - } - else if (prop instanceof EmbeddedCollection) { + } else if (prop instanceof EmbeddedCollection) { final Object embeddedInstances = getEntryValue(nativeEntry, propKey); EmbeddedCollection embeddedCollection = (EmbeddedCollection) prop; loadEmbeddedCollection(embeddedCollection, ea, embeddedInstances, propKey); @@ -524,8 +522,7 @@ else if (prop instanceof EmbeddedCollection) { } } } - } - else if (prop instanceof OneToMany) { + } else if (prop instanceof OneToMany) { Association association = (Association) prop; PropertyMapping associationPropertyMapping = association.getMapping(); @@ -534,32 +531,27 @@ else if (prop instanceof OneToMany) { if (List.class.isAssignableFrom(association.getType())) { ea.setPropertyNoConversion(association.getName(), new PersistentList(keys, association.getAssociatedEntity().getJavaClass(), session)); - } - else if (Set.class.isAssignableFrom(association.getType())) { + } else if (Set.class.isAssignableFrom(association.getType())) { ea.setPropertyNoConversion(association.getName(), new PersistentSet(keys, association.getAssociatedEntity().getJavaClass(), session)); } - } - else { + } else { boolean isLazy = isLazyAssociation(associationPropertyMapping); AssociationIndexer indexer = getAssociationIndexer(nativeEntry, association); - if(indexer != null) { - nativeKey = convertIdIfNecessary(getPersistentEntity(), nativeKey ); + if (indexer != null) { + nativeKey = convertIdIfNecessary(getPersistentEntity(), nativeKey); if (isLazy) { if (List.class.isAssignableFrom(association.getType())) { ea.setPropertyNoConversion(association.getName(), new PersistentList(nativeKey, session, indexer)); - } - else if (SortedSet.class.isAssignableFrom(association.getType())) { + } else if (SortedSet.class.isAssignableFrom(association.getType())) { ea.setPropertyNoConversion(association.getName(), new PersistentSortedSet(nativeKey, session, indexer)); - } - else if (Set.class.isAssignableFrom(association.getType())) { + } else if (Set.class.isAssignableFrom(association.getType())) { ea.setPropertyNoConversion(association.getName(), new PersistentSet(nativeKey, session, indexer)); } - } - else { + } else { if (indexer != null) { List keys = indexer.query(nativeKey); ea.setProperty(association.getName(), @@ -568,18 +560,17 @@ else if (Set.class.isAssignableFrom(association.getType())) { } } } - } - else if (prop instanceof ManyToMany) { + } else if (prop instanceof ManyToMany) { ManyToMany manyToMany = (ManyToMany) prop; PropertyMapping associationPropertyMapping = manyToMany.getMapping(); boolean isLazy = isLazyAssociation(associationPropertyMapping); nativeKey = convertIdIfNecessary(getPersistentEntity(), nativeKey); PersistentEntity associatedEntity = manyToMany.getAssociatedEntity(); - if(associatedEntity != null) { + if (associatedEntity != null) { Class childType = associatedEntity.getJavaClass(); - Collection cached = ((SessionImplementor)session).getCachedCollection( + Collection cached = ((SessionImplementor) session).getCachedCollection( persistentEntity, nativeKey, manyToMany.getName()); if (cached == null) { Collection collection; @@ -589,38 +580,31 @@ else if (prop instanceof ManyToMany) { if (List.class.isAssignableFrom(manyToMany.getType())) { collection = new PersistentList(keys, childType, session); ea.setPropertyNoConversion(manyToMany.getName(), collection); - } - else if (Set.class.isAssignableFrom(manyToMany.getType())) { + } else if (Set.class.isAssignableFrom(manyToMany.getType())) { collection = new PersistentSet(keys, childType, session); ea.setPropertyNoConversion(manyToMany.getName(), collection); - } - else { + } else { collection = Collections.emptyList(); } - } - else { + } else { AssociationIndexer indexer = getAssociationIndexer(nativeEntry, manyToMany); if (indexer == null) { if (List.class.isAssignableFrom(manyToMany.getType())) { collection = Collections.emptyList(); - } - else if (Set.class.isAssignableFrom(manyToMany.getType())) { + } else if (Set.class.isAssignableFrom(manyToMany.getType())) { collection = Collections.emptySet(); - } - else { + } else { collection = Collections.emptyList(); } - } - else { + } else { List keys = indexer.query(nativeKey); collection = session.retrieveAll(childType, keys); ea.setProperty(manyToMany.getName(), collection); } } - ((SessionImplementor)session).cacheCollection( + ((SessionImplementor) session).cacheCollection( persistentEntity, nativeKey, collection, manyToMany.getName()); - } - else { + } else { ea.setProperty(manyToMany.getName(), cached); } } @@ -639,12 +623,13 @@ public static String createEmbeddedCacheEntryKey(Object instance) { * type. This takes into account any generic parameter types specified on the property (e.g. Collection<Locale> * tells us to convert elements into Locale objects). If you don't specify generic properties, collection elements * are not modified. - * + *

    * If the target type is known from the generic parameters, the conversion process is essentially identical to that * used for single Simple properties. + * * @param persistentEntity The persistent entity - * @param prop The property in question - * @param entryValue The value of the entry + * @param prop The property in question + * @param entryValue The value of the entry * @return The transformed entry type. */ protected Object convertBasicEntryValue(PersistentEntity persistentEntity, Basic prop, Object entryValue) { @@ -671,8 +656,7 @@ protected Object convertBasicEntryValue(PersistentEntity persistentEntity, Basic } entryValue = targetMap; - } - else if (entryValue instanceof Collection) { + } else if (entryValue instanceof Collection) { Collection collection = MappingUtils.createConcreteCollection(prop.getType()); Class propertyType = prop.getType(); @@ -684,8 +668,7 @@ else if (entryValue instanceof Collection) { o = conversionService.convert(o, genericType); collection.add(o); } - } - else { + } else { // just hope they don't need converting! collection.addAll(collectionValue); } @@ -701,7 +684,6 @@ else if (entryValue instanceof Collection) { * @param association The association * @param ea * @param nativeEntry - * * @return A list of keys loaded from the embedded instance */ protected List loadEmbeddedCollectionKeys(Association association, EntityAccess ea, T nativeEntry) { @@ -727,9 +709,9 @@ protected boolean isEmbeddedEntry(Object entry) { * Implementors who want to the ability to read embedded collections should implement this method * * @param embeddedCollection The EmbeddedCollection instance - * @param ea The EntityAccess instance - * @param embeddedInstances The embedded instances - * @param propertyKey The property key + * @param ea The EntityAccess instance + * @param embeddedInstances The embedded instances + * @param propertyKey The property key */ protected void loadEmbeddedCollection(EmbeddedCollection embeddedCollection, EntityAccess ea, Object embeddedInstances, String propertyKey) { @@ -740,7 +722,7 @@ protected void loadEmbeddedCollection(EmbeddedCollection embeddedCollection, Ent * Implementors should override to provide support for embedded objects. * * @param nativeEntry The native entry to read the embedded instance from - * @param key The key + * @param key The key * @return The native entry of the embedded instance */ protected T getEmbedded(T nativeEntry, String key) { @@ -758,14 +740,14 @@ private void handleCustom(PersistentProperty prop, EntityAccess ea, T nativeEntr } protected Collection getManyToManyKeys(PersistentEntity persistentEntity, Object obj, - Serializable nativeKey, T nativeEntry, ManyToMany manyToMany) { + Serializable nativeKey, T nativeEntry, ManyToMany manyToMany) { return null; } protected String getNativePropertyKey(PersistentProperty prop) { PropertyMapping pm = prop.getMapping(); String propKey = null; - if (pm.getMappedForm()!=null) { + if (pm.getMappedForm() != null) { propKey = pm.getMappedForm().getTargetName(); } if (propKey == null) { @@ -776,8 +758,9 @@ protected String getNativePropertyKey(PersistentProperty prop) { /** * Subclasses should override to customize how entities in hierarchies are discriminated + * * @param persistentEntity The PersistentEntity - * @param nativeEntry The native entry + * @param nativeEntry The native entry * @return The discriminated entity */ protected PersistentEntity discriminatePersistentEntity(PersistentEntity persistentEntity, T nativeEntry) { @@ -812,10 +795,9 @@ protected Serializable persistEntity(final PersistentEntity persistentEntity, Ob SessionImplementor si = (SessionImplementor) session; - if(si.isPendingAlready(obj)) { + if (si.isPendingAlready(obj)) { return (Serializable) k; - } - else { + } else { si.registerPending(obj); } @@ -837,15 +819,14 @@ protected Serializable persistEntity(final PersistentEntity persistentEntity, Ob pendingOperation = new PendingInsertAdapter(persistentEntity, k, tmp, entityAccess) { public void run() { K insertResult = executeInsert(persistentEntity, entityAccess, getNativeKey(), getNativeEntry()); - if(insertResult == null) { + if (insertResult == null) { setVetoed(true); } } }; entityAccess.setProperty(entityAccess.getIdentifierName(), k); - } - else { + } else { tmp = (T) si.getCachedEntry(persistentEntity, (Serializable) k); if (tmp == null) { tmp = getFromTPCache(persistentEntity, (Serializable) k); @@ -888,54 +869,51 @@ public void run() { if (mappedProperty != null) { key = mappedProperty.getTargetName(); } - if (key == null) key = prop.getName(); + if (key == null) { + key = prop.getName(); + } final boolean indexed = isPropertyIndexed(mappedProperty); - if ((prop instanceof Simple) ) { + if ((prop instanceof Simple)) { Object propValue = entityAccess.getProperty(prop.getName()); - if(propValue == null && !isUpdate) { + if (propValue == null && !isUpdate) { continue; } handleIndexing(isUpdate, e, toIndex, toUnindex, prop, key, indexed, propValue); setEntryValue(e, key, propValue); - } - else if((prop instanceof Basic)) { + } else if ((prop instanceof Basic)) { Basic basic = (Basic) prop; CustomTypeMarshaller customTypeMarshaller = basic.getCustomTypeMarshaller(); if (customTypeMarshaller != null && customTypeMarshaller.supports(getMappingContext())) { Object propValue = entityAccess.getProperty(prop.getName()); Object customValue = customTypeMarshaller.write(prop, propValue, e); handleIndexing(isUpdate, e, toIndex, toUnindex, prop, key, indexed, customValue); - } - else { + } else { Object propValue = entityAccess.getProperty(prop.getName()); - if(propValue == null && !isUpdate) { + if (propValue == null && !isUpdate) { continue; } - handleIndexing(isUpdate, e, toIndex, toUnindex, prop, key, indexed, propValue); setEntryValue(e, key, propValue); } - } - else if ((prop instanceof Custom)) { + } else if ((prop instanceof Custom)) { CustomTypeMarshaller customTypeMarshaller = ((Custom) prop).getCustomTypeMarshaller(); if (customTypeMarshaller.supports(getMappingContext())) { Object propValue = entityAccess.getProperty(prop.getName()); - if(propValue == null && !isUpdate) { + if (propValue == null && !isUpdate) { continue; } Object customValue = customTypeMarshaller.write(prop, propValue, e); handleIndexing(isUpdate, e, toIndex, toUnindex, prop, key, indexed, customValue); - if(customValue == null) { + if (customValue == null) { setEntryValue(e, key, null); } } - } - else if (prop instanceof OneToMany) { + } else if (prop instanceof OneToMany) { final OneToMany oneToMany = (OneToMany) prop; final Object propValue = entityAccess.getProperty(oneToMany.getName()); @@ -943,15 +921,14 @@ else if (prop instanceof OneToMany) { Collection associatedObjects = (Collection) propValue; if (isInitializedCollection(associatedObjects)) { PersistentEntity associatedEntity = oneToMany.getAssociatedEntity(); - if(associatedEntity != null) { + if (associatedEntity != null) { EntityPersister associationPersister = (EntityPersister) session.getPersister(associatedEntity); if (associationPersister != null) { PersistentCollection persistentCollection; boolean newCollection = false; if (associatedObjects instanceof PersistentCollection) { persistentCollection = (PersistentCollection) associatedObjects; - } - else { + } else { Class associationType = associatedEntity.getJavaClass(); persistentCollection = getPersistentCollection(associatedObjects, associationType); entityAccess.setPropertyNoConversion(oneToMany.getName(), persistentCollection); @@ -962,7 +939,7 @@ else if (prop instanceof OneToMany) { persistentCollection.resetDirty(); List keys = associationPersister.persist(associatedObjects); toManyKeys.put(oneToMany, keys); - if (newCollection ) { + if (newCollection) { entityAccess.setProperty(oneToMany.getName(), associatedObjects); } } @@ -970,8 +947,7 @@ else if (prop instanceof OneToMany) { } } } - } - else if (prop instanceof ManyToMany) { + } else if (prop instanceof ManyToMany) { final ManyToMany manyToMany = (ManyToMany) prop; final Object propValue = entityAccess.getProperty(manyToMany.getName()); @@ -981,21 +957,18 @@ else if (prop instanceof ManyToMany) { setManyToMany(persistentEntity, obj, e, manyToMany, associatedObjects, toManyKeys); } } - } - else if (prop instanceof ToOne) { + } else if (prop instanceof ToOne) { ToOne association = (ToOne) prop; if (prop instanceof Embedded) { // For embedded properties simply set the entry value, the underlying implementation // will have to store the embedded entity in an appropriate way (as a sub-document in a document store for example) handleEmbeddedToOne(association, key, entityAccess, e); - } - - else if (association.getAssociatedEntity() != null) { + } else if (association.getAssociatedEntity() != null) { final Object associatedObject = entityAccess.getProperty(prop.getName()); if (associatedObject != null) { Serializable associationId; NativeEntryEntityPersister associationPersister = (NativeEntryEntityPersister) session.getPersister(associatedObject); - if (proxyFactory.isInitialized(associatedObject) && !session.contains(associatedObject) ) { + if (proxyFactory.isInitialized(associatedObject) && !session.contains(associatedObject)) { Serializable tempId = associationPersister.getObjectIdentifier(associatedObject); if (tempId == null) { if (association.doesCascade(CascadeType.PERSIST)) { @@ -1021,19 +994,18 @@ else if (association.getAssociatedEntity() != null) { } } - if (association.isBidirectional()) { - Association inverseSide = association.getInverseSide(); - if (inverseSide != null) { - EntityAccess inverseAccess = createEntityAccess(inverseSide.getOwner(), associatedObject); - inverseAccess.setProperty(inverseSide.getName(), obj); - } - } - if( association.doesCascade(CascadeType.PERSIST) ) { - associationPersister.persist(associatedObject); + if (association.isBidirectional()) { + Association inverseSide = association.getInverseSide(); + if (inverseSide != null) { + EntityAccess inverseAccess = createEntityAccess(inverseSide.getOwner(), associatedObject); + inverseAccess.setProperty(inverseSide.getName(), obj); } - } - // handle of standard many-to-one - else { + } + if (association.doesCascade(CascadeType.PERSIST)) { + associationPersister.persist(associatedObject); + } + } else { + // handle of standard many-to-one if (associationId != null) { if (indexed && doesRequirePropertyIndexing()) { toIndex.put(prop, associationId); @@ -1064,8 +1036,9 @@ else if (association.getAssociatedEntity() != null) { existingValues = MappingUtils.createConcreteCollection(inverse.getType()); inverseAccess.setProperty(inverse.getName(), existingValues); } - if (!existingValues.contains(entity)) + if (!existingValues.contains(entity)) { existingValues.add(entity); + } } else if (inverse instanceof ToOne) { inverseAccess.setProperty(inverse.getName(), entity); } @@ -1077,8 +1050,7 @@ else if (association.getAssociatedEntity() != null) { setEntryValue(e, getPropertyKey(prop), null); } } - } - else if (prop instanceof EmbeddedCollection) { + } else if (prop instanceof EmbeddedCollection) { handleEmbeddedToMany(entityAccess, e, prop, key); } } @@ -1112,12 +1084,10 @@ public void run() { // If the key is still null at this point we have to execute the pending operation now to get the key if (k == null) { PendingOperationExecution.executePendingOperation(pendingOperation); - } - else { + } else { si.addPendingInsert((PendingInsert) pendingOperation); } - } - else { + } else { final K updateId = k; PendingOperation postOperation = new PendingOperationAdapter(persistentEntity, k, e) { @@ -1135,7 +1105,7 @@ public void run() { } private boolean isNotUpdateForAssignedId(PersistentEntity persistentEntity, Object obj, boolean update, boolean assignedId, SessionImplementor si) { - return assignedId && update && !si.isStateless(persistentEntity) && !session.contains(obj); + return assignedId && update && !si.isStateless(persistentEntity) && !session.contains(obj); } @Override @@ -1145,9 +1115,9 @@ protected final Serializable persistEntity(final PersistentEntity persistentEnti private AbstractPersistentCollection getPersistentCollection(Collection associatedObjects, Class associationType) { if (associatedObjects instanceof Set) { - return associatedObjects instanceof SortedSet ? new PersistentSortedSet(associationType,getSession(), (SortedSet) associatedObjects) : new PersistentSet(associationType, getSession(), associatedObjects); + return associatedObjects instanceof SortedSet ? new PersistentSortedSet(associationType, getSession(), (SortedSet) associatedObjects) : new PersistentSet(associationType, getSession(), associatedObjects); } - return new PersistentList(associationType,getSession(), (List) associatedObjects); + return new PersistentList(associationType, getSession(), (List) associatedObjects); } private boolean isInitializedCollection(Collection associatedObjects) { @@ -1158,8 +1128,8 @@ private boolean isInitializedCollection(Collection associatedObjects) { * Formulates a database reference for the given entity, association and association id * * @param persistentEntity The entity being persisted - * @param association The association - * @param associationId The association id + * @param association The association + * @param associationId The association id * @return A database reference */ protected Object formulateDatabaseReference(PersistentEntity persistentEntity, Association association, Serializable associationId) { @@ -1170,37 +1140,33 @@ protected void handleEmbeddedToMany(EntityAccess entityAccess, T e, PersistentPr // For embedded properties simply set the entry value, the underlying implementation // will have to store the embedded entity in an appropriate way (as a sub-document in a document store for example) Object embeddedInstances = entityAccess.getProperty(prop.getName()); - if(embeddedInstances instanceof Map) { - Map instances = (Map)embeddedInstances; + if (embeddedInstances instanceof Map) { + Map instances = (Map) embeddedInstances; Map embeddedEntries = new HashMap(); for (Object k : instances.keySet()) { embeddedEntries.put(k, handleEmbeddedInstance((Association) prop, instances.get(k))); } setEmbeddedMap(e, key, instances, embeddedEntries); - } - else if (!(embeddedInstances instanceof Collection) || ((Collection)embeddedInstances).isEmpty()) { - if (embeddedInstances == null) + } else if (!(embeddedInstances instanceof Collection) || ((Collection) embeddedInstances).isEmpty()) { + if (embeddedInstances == null) { setEmbeddedCollection(e, key, null, null); - else { + } else { setEmbeddedCollection(e, key, MappingUtils.createConcreteCollection(prop.getType()), new ArrayList()); } - } - else { - Collection instances = (Collection)embeddedInstances; + } else { + Collection instances = (Collection) embeddedInstances; List embeddedEntries = new ArrayList(); for (Object instance : instances) { - T entry = handleEmbeddedInstance((Association)prop, instance); + T entry = handleEmbeddedInstance((Association) prop, instance); embeddedEntries.add(entry); } setEmbeddedCollection(e, key, instances, embeddedEntries); } - } - protected void handleEmbeddedToOne(Association association, String key, EntityAccess entityAccess, T nativeEntry) { Object embeddedInstance = entityAccess.getProperty(association.getName()); if (embeddedInstance == null) { @@ -1219,15 +1185,15 @@ public T createNativeObjectForEmbedded(Association embedded, Object instance) { protected T handleEmbeddedInstance(Association association, Object embeddedInstance) { return handleEmbeddedInstance(association, embeddedInstance, false); } + protected T handleEmbeddedInstance(Association association, Object embeddedInstance, boolean includeNulls) { - NativeEntryEntityPersister embeddedPersister = (NativeEntryEntityPersister) session.getPersister(embeddedInstance); + NativeEntryEntityPersister embeddedPersister = (NativeEntryEntityPersister) session.getPersister(embeddedInstance); // embeddedPersister would be null if the associated entity is a EmbeddedPersistentEntity T embeddedEntry; if (embeddedPersister == null) { embeddedEntry = createNewEntry(association.getName()); - } - else { + } else { embeddedEntry = embeddedPersister.createNewEntry(embeddedPersister.getEntityFamily()); } @@ -1245,29 +1211,27 @@ protected T handleEmbeddedInstance(Association association, Object embeddedInsta for (PersistentProperty persistentProperty : embeddedProperties) { if (persistentProperty instanceof Simple) { Object value = embeddedEntityAccess.getProperty(persistentProperty.getName()); - if(value == null && !includeNulls) continue; + if (value == null && !includeNulls) { + continue; + } setEntryValue(embeddedEntry, getPropertyKey(persistentProperty), value); - } - else if (persistentProperty instanceof Custom) { + } else if (persistentProperty instanceof Custom) { CustomTypeMarshaller customTypeMarshaller = ((Custom) persistentProperty).getCustomTypeMarshaller(); if (customTypeMarshaller.supports(getMappingContext())) { customTypeMarshaller.write(persistentProperty, embeddedEntityAccess.getProperty(persistentProperty.getName()), embeddedEntry); } - } - else if (persistentProperty instanceof Association) { + } else if (persistentProperty instanceof Association) { Association inverseSide = ((Association) persistentProperty).getInverseSide(); if (inverseSide instanceof Embedded || inverseSide instanceof EmbeddedCollection) { // these are the back links to the parents we might be embedded in, and don't need to be saved. // they are recreated during a refresh. - } - else if (persistentProperty instanceof Embedded) { + } else if (persistentProperty instanceof Embedded) { Association toOne = (Association) persistentProperty; handleEmbeddedToOne(toOne, getPropertyKey(persistentProperty), embeddedEntityAccess, embeddedEntry); - } - else if (persistentProperty instanceof ToOne) { + } else if (persistentProperty instanceof ToOne) { Association toOne = (Association) persistentProperty; Object obj = embeddedEntityAccess.getProperty(toOne.getName()); @@ -1278,14 +1242,11 @@ else if (persistentProperty instanceof ToOne) { setEntryValue(embeddedEntry, getPropertyKey(toOne), formulateDatabaseReference(associatedEntity, toOne, id)); } } - } - else if (persistentProperty instanceof Basic) { + } else if (persistentProperty instanceof Basic) { setEntryValue(embeddedEntry, getPropertyKey(persistentProperty), embeddedEntityAccess.getProperty(persistentProperty.getName())); - } - else if (persistentProperty instanceof EmbeddedCollection) { + } else if (persistentProperty instanceof EmbeddedCollection) { handleEmbeddedToMany(embeddedEntityAccess, embeddedEntry, persistentProperty, persistentProperty.getName()); - } - else { + } else { if (persistentProperty instanceof OneToMany) { final OneToMany oneToMany = (OneToMany) persistentProperty; @@ -1296,8 +1257,7 @@ else if (persistentProperty instanceof EmbeddedCollection) { setEmbeddedCollectionKeys(oneToMany, embeddedEntityAccess, embeddedEntry, keys); } - } - else if (persistentProperty instanceof ManyToMany) { + } else if (persistentProperty instanceof ManyToMany) { final ManyToMany manyToMany = (ManyToMany) persistentProperty; final Object propValue = embeddedEntityAccess.getProperty(manyToMany.getName()); @@ -1315,8 +1275,8 @@ else if (persistentProperty instanceof ManyToMany) { } private void handleIndexing(boolean update, T e, Map toIndex, - Map toUnindex, PersistentProperty prop, String key, - boolean indexed, Object propValue) { + Map toUnindex, PersistentProperty prop, String key, + boolean indexed, Object propValue) { if (!indexed) { return; @@ -1342,16 +1302,16 @@ protected boolean isPropertyIndexed(Property mappedProperty) { } protected void setManyToMany(PersistentEntity persistentEntity, Object obj, - T nativeEntry, ManyToMany manyToMany, Collection associatedObjects, - Map> toManyKeys) { + T nativeEntry, ManyToMany manyToMany, Collection associatedObjects, + Map> toManyKeys) { // override as necessary } /** * Implementors should override this method to provide support for embedded objects * - * @param nativeEntry The native entry - * @param key The key + * @param nativeEntry The native entry + * @param key The key * @param embeddedEntry The embedded object */ protected void setEmbedded(T nativeEntry, String key, T embeddedEntry) { @@ -1361,9 +1321,9 @@ protected void setEmbedded(T nativeEntry, String key, T embeddedEntry) { /** * Implementors should override this method to provide support for embedded objects * - * @param nativeEntry The native entry - * @param key The key - * @param instances the embedded instances + * @param nativeEntry The native entry + * @param key The key + * @param instances the embedded instances * @param embeddedEntries the native entries */ protected void setEmbeddedCollection(T nativeEntry, String key, Collection instances, List embeddedEntries) { @@ -1373,22 +1333,21 @@ protected void setEmbeddedCollection(T nativeEntry, String key, Collection in /** * Implementors should override this method to provide support for maps of embedded objects * - * @param nativeEntry The native entry - * @param key The key - * @param instances the embedded instances + * @param nativeEntry The native entry + * @param key The key + * @param instances the embedded instances * @param embeddedEntries the native entries */ protected void setEmbeddedMap(T nativeEntry, String key, Map instances, Map embeddedEntries) { // do nothing. The default is no support for embedded maps } - /** * Subclasses should override to provide id generation. If an identifier is only generated via an insert operation then this * method should return null * * @param persistentEntity The entity - * @param entry The native entry + * @param entry The native entry * @return The identifier or null if an identifier is generated only on insert */ protected abstract K generateIdentifier(PersistentEntity persistentEntity, T entry); @@ -1441,7 +1400,6 @@ private void updatePropertyIndices(Object identifier, Map persistEntities(PersistentEntity persistentEntity, if (persistentEntity.isInstance(obj)) { if (persistentEntity.getJavaClass().equals(obj.getClass())) { keys.add(persist(obj)); - } - else { + } else { // subclass persister EntityPersister persister = (EntityPersister) getSession().getPersister(obj); keys.add(persister.persist(obj)); @@ -1502,7 +1461,7 @@ protected List persistEntities(PersistentEntity persistentEntity, * one-by-one. Data stores that support batch retrieval can optimize this to retrieve all entities in one go. * * @param persistentEntity The persist entity - * @param keys The keys + * @param keys The keys * @return A list of entities */ @Override @@ -1519,7 +1478,7 @@ protected List retrieveAllEntities(PersistentEntity persistentEntity, It * one-by-one. Data stores that support batch retrieval can optimize this to retrieve all entities in one go. * * @param persistentEntity The persist entity - * @param keys The keys + * @param keys The keys * @return A list of entities */ @Override @@ -1533,7 +1492,8 @@ protected List retrieveAllEntities(PersistentEntity persistentEntity, Se /** * Used to establish the native key to use from the identifier defined by the object - * @param family The family + * + * @param family The family * @param identifier The identifier specified by the object * @return The native key which may just be a cast from the identifier parameter to K */ @@ -1563,16 +1523,17 @@ protected T createNewEntry(String family, Object instance) { * Reads a value for the given key from the native entry * * @param nativeEntry The native entry. Could be a ColumnFamily, a BigTable entity, a Map etc. - * @param property The property key + * @param property The property key * @return The value */ protected abstract Object getEntryValue(T nativeEntry, String property); /** * Sets a value on an entry + * * @param nativeEntry The native entry such as a BigTable Entity, ColumnFamily etc. - * @param key The key - * @param value The value + * @param key The key + * @param value The value */ protected abstract void setEntryValue(T nativeEntry, String key, Object value); @@ -1581,8 +1542,8 @@ protected T createNewEntry(String family, Object instance) { * a ColumnFamily, a BigTable Entity, a Map etc. * * @param persistentEntity The persistent entity - * @param family The family - * @param key The key + * @param family The family + * @param key The key * @return The native form */ protected abstract T retrieveEntry(PersistentEntity persistentEntity, String family, Serializable key); @@ -1591,9 +1552,9 @@ protected T createNewEntry(String family, Object instance) { * Stores the native form of a Key/value datastore to the actual data store * * @param persistentEntity The persistent entity - * @param entityAccess The EntityAccess + * @param entityAccess The EntityAccess * @param storeId - * @param nativeEntry The native form. Could be a a ColumnFamily, BigTable Entity etc. + * @param nativeEntry The native form. Could be a a ColumnFamily, BigTable Entity etc. * @return The native key */ protected abstract K storeEntry(PersistentEntity persistentEntity, EntityAccess entityAccess, @@ -1603,18 +1564,18 @@ protected abstract K storeEntry(PersistentEntity persistentEntity, EntityAccess * Updates an existing entry to the actual datastore * * @param persistentEntity The PersistentEntity - * @param entityAccess The EntityAccess - * @param key The key of the object to update - * @param entry The entry + * @param entityAccess The EntityAccess + * @param key The key of the object to update + * @param entry The entry */ protected abstract void updateEntry(PersistentEntity persistentEntity, - EntityAccess entityAccess, K key, T entry); + EntityAccess entityAccess, K key, T entry); /** * Deletes one or many entries for the given list of Keys * * @param family The family - * @param keys The keys + * @param keys The keys */ protected abstract void deleteEntries(String family, List keys); @@ -1631,7 +1592,9 @@ protected abstract void updateEntry(PersistentEntity persistentEntity, protected K executeInsert(final PersistentEntity persistentEntity, final NativeEntryModifyingEntityAccess entityAccess, final K id, final T e) { - if (cancelInsert(persistentEntity, entityAccess)) return null; + if (cancelInsert(persistentEntity, entityAccess)) { + return null; + } final K newId = storeEntry(persistentEntity, entityAccess, id, e); entityAccess.setIdentifier(newId); updateTPCache(persistentEntity, e, (Serializable) newId); @@ -1640,58 +1603,6 @@ protected K executeInsert(final PersistentEntity persistentEntity, return newId; } - protected class NativeEntryModifyingEntityAccess extends BeanEntityAccess { - - T nativeEntry; - private Map toIndex; - - public NativeEntryModifyingEntityAccess(PersistentEntity persistentEntity, Object entity) { - super(persistentEntity, entity); - } - - @Override - public void setProperty(String name, Object value) { - super.setProperty(name, value); - if (nativeEntry != null) { - PersistentProperty property = persistentEntity.getPropertyByName(name); - if (property != null && (property instanceof Simple || property instanceof Basic)) { - setEntryValue(nativeEntry, name, value); - } - - if (toIndex != null && property != null) { - PropertyMapping pm = property.getMapping(); - if (pm != null && isPropertyIndexed(pm.getMappedForm())) { - if (property instanceof ToOne) { - ToOne association = (ToOne) property; - if (!association.isForeignKeyInChild()) { - NativeEntryEntityPersister associationPersister = (NativeEntryEntityPersister) session.getPersister(value); - if(associationPersister != null) { - if (value == null) { - toIndex.put(property, null); - } - else { - toIndex.put(property, associationPersister.getObjectIdentifier(value)); - } - } - } - } - else { - toIndex.put(property, value); - } - } - } - } - } - - public void setNativeEntry(T nativeEntry) { - this.nativeEntry = nativeEntry; - } - - public void setToIndex(Map toIndex) { - this.toIndex = toIndex; - } - } - public boolean isDirty(Object instance, Object entry) { if ((instance == null)) { return false; @@ -1700,10 +1611,9 @@ public boolean isDirty(Object instance, Object entry) { return true; } - if(instance instanceof DirtyCheckable) { - return ((DirtyCheckable)instance).hasChanged(); - } - else { + if (instance instanceof DirtyCheckable) { + return ((DirtyCheckable) instance).hasChanged(); + } else { return doManualDirtyCheck(instance, entry); } } @@ -1711,9 +1621,8 @@ public boolean isDirty(Object instance, Object entry) { protected boolean doManualDirtyCheck(Object instance, Object entry) { T nativeEntry; try { - nativeEntry = (T)entry; - } - catch (ClassCastException ignored) { + nativeEntry = (T) entry; + } catch (ClassCastException ignored) { return false; } @@ -1729,34 +1638,31 @@ protected boolean doManualDirtyCheck(Object instance, Object entry) { if (!areEqual(oldValue, currentValue, key)) { return true; } - } - else if (prop instanceof OneToMany || prop instanceof ManyToMany) { + } else if (prop instanceof OneToMany || prop instanceof ManyToMany) { if (!areCollectionsEqual(oldValue, currentValue)) { return true; } - } - else if (prop instanceof EmbeddedCollection) { - if (currentValue != null && oldValue == null) return true; + } else if (prop instanceof EmbeddedCollection) { + if (currentValue != null && oldValue == null) { + return true; + } if ((currentValue instanceof Collection) && (oldValue instanceof Collection)) { Collection currentCollection = (Collection) currentValue; Collection oldCollection = (Collection) oldValue; if (currentCollection.size() != oldCollection.size()) { return true; - } - else { + } else { if (!areCollectionsEqual(oldValue, currentValue)) { return true; } } } - } - else if (prop instanceof Custom) { - CustomTypeMarshaller marshaller = ((Custom)prop).getCustomTypeMarshaller(); + } else if (prop instanceof Custom) { + CustomTypeMarshaller marshaller = ((Custom) prop).getCustomTypeMarshaller(); if (!areEqual(marshaller.read(prop, entry), currentValue, key)) { return true; } - } - else { + } else { throw new UnsupportedOperationException("dirty not detected for property " + prop.toString() + " " + prop.getClass().getSuperclass().toString()); } } @@ -1771,7 +1677,9 @@ protected String getPropertyKey(PersistentProperty prop) { if (mappedProperty != null) { key = mappedProperty.getTargetName(); } - if (key == null) key = prop.getName(); + if (key == null) { + key = prop.getName(); + } return key; } @@ -1782,7 +1690,7 @@ protected boolean areCollectionsEqual(Object oldValue, Object currentValue) { } if (currentValue instanceof PersistentCollection) { - return !((PersistentCollection)currentValue).isDirty(); + return !((PersistentCollection) currentValue).isDirty(); } return replaceNullOrUninitialized(oldValue, currentValue).equals( @@ -1797,7 +1705,7 @@ private Object replaceNullOrUninitialized(Object c, Object other) { return Collections.emptyList(); } - if (c instanceof PersistentCollection && !((PersistentCollection)c).isInitialized()) { + if (c instanceof PersistentCollection && !((PersistentCollection) c).isInitialized()) { if (c instanceof Set) { return Collections.emptySet(); } @@ -1819,10 +1727,9 @@ protected boolean areEqual(Object oldValue, Object currentValue, String propName if ("version".equals(propName)) { // special case where comparing int and long would fail artifically if (oldValue instanceof Number && currentValue instanceof Number) { - oldValue = ((Number)oldValue).longValue(); - currentValue = ((Number)currentValue).longValue(); - } - else { + oldValue = ((Number) oldValue).longValue(); + currentValue = ((Number) currentValue).longValue(); + } else { oldValue = oldValue.toString(); currentValue = currentValue.toString(); } @@ -1831,10 +1738,10 @@ protected boolean areEqual(Object oldValue, Object currentValue, String propName Class oldValueClass = oldValue.getClass(); if (!oldValueClass.isArray()) { if (oldValue instanceof Float) { - return Float.floatToIntBits((Float)oldValue) == Float.floatToIntBits((Float)currentValue); + return Float.floatToIntBits((Float) oldValue) == Float.floatToIntBits((Float) currentValue); } if (oldValue instanceof Double) { - return Double.doubleToLongBits((Double)oldValue) == Double.doubleToLongBits((Double)currentValue); + return Double.doubleToLongBits((Double) oldValue) == Double.doubleToLongBits((Double) currentValue); } return oldValue.equals(currentValue); } @@ -1847,37 +1754,87 @@ protected boolean areEqual(Object oldValue, Object currentValue, String propName } if (oldValue instanceof long[]) { - return Arrays.equals((long[])oldValue, (long[])currentValue); + return Arrays.equals((long[]) oldValue, (long[]) currentValue); } if (oldValue instanceof int[]) { - return Arrays.equals((int[])oldValue, (int[])currentValue); + return Arrays.equals((int[]) oldValue, (int[]) currentValue); } if (oldValue instanceof short[]) { - return Arrays.equals((short[])oldValue, (short[])currentValue); + return Arrays.equals((short[]) oldValue, (short[]) currentValue); } if (oldValue instanceof char[]) { - return Arrays.equals((char[])oldValue, (char[])currentValue); + return Arrays.equals((char[]) oldValue, (char[]) currentValue); } if (oldValue instanceof byte[]) { - return Arrays.equals((byte[])oldValue, (byte[])currentValue); + return Arrays.equals((byte[]) oldValue, (byte[]) currentValue); } if (oldValue instanceof double[]) { - return Arrays.equals((double[])oldValue, (double[])currentValue); + return Arrays.equals((double[]) oldValue, (double[]) currentValue); } if (oldValue instanceof float[]) { - return Arrays.equals((float[])oldValue, (float[])currentValue); + return Arrays.equals((float[]) oldValue, (float[]) currentValue); } if (oldValue instanceof boolean[]) { - return Arrays.equals((boolean[])oldValue, (boolean[])currentValue); + return Arrays.equals((boolean[]) oldValue, (boolean[]) currentValue); + } + + return Arrays.equals((Object[]) oldValue, (Object[]) currentValue); + } + + protected class NativeEntryModifyingEntityAccess extends BeanEntityAccess { + + T nativeEntry; + private Map toIndex; + + public NativeEntryModifyingEntityAccess(PersistentEntity persistentEntity, Object entity) { + super(persistentEntity, entity); + } + + @Override + public void setProperty(String name, Object value) { + super.setProperty(name, value); + if (nativeEntry != null) { + PersistentProperty property = persistentEntity.getPropertyByName(name); + if (property != null && (property instanceof Simple || property instanceof Basic)) { + setEntryValue(nativeEntry, name, value); + } + + if (toIndex != null && property != null) { + PropertyMapping pm = property.getMapping(); + if (pm != null && isPropertyIndexed(pm.getMappedForm())) { + if (property instanceof ToOne) { + ToOne association = (ToOne) property; + if (!association.isForeignKeyInChild()) { + NativeEntryEntityPersister associationPersister = (NativeEntryEntityPersister) session.getPersister(value); + if (associationPersister != null) { + if (value == null) { + toIndex.put(property, null); + } else { + toIndex.put(property, associationPersister.getObjectIdentifier(value)); + } + } + } + } else { + toIndex.put(property, value); + } + } + } + } } - return Arrays.equals((Object[])oldValue, (Object[])currentValue); + public void setNativeEntry(T nativeEntry) { + this.nativeEntry = nativeEntry; + } + + public void setToIndex(Map toIndex) { + this.toIndex = toIndex; + } } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/Persister.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/Persister.java index c91a034c38a..d502a1be580 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/Persister.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/Persister.java @@ -18,11 +18,11 @@ */ package org.grails.datastore.mapping.engine; +import org.grails.datastore.mapping.query.Query; + import java.io.Serializable; import java.util.List; -import org.grails.datastore.mapping.query.Query; - /** * A Persister is responsible for persisting and retrieving an object. * @@ -60,7 +60,6 @@ public interface Persister { * Retrieves an object for the given context and Key * * @param key The key - * * @return The object in question */ Object retrieve(Serializable key); @@ -75,6 +74,7 @@ public interface Persister { /** * Deletes one or many objects + * * @param objects The objects to delete. Must all be of the same type or an exception will be thrown. */ void delete(@SuppressWarnings("rawtypes") Iterable objects); @@ -89,6 +89,7 @@ public interface Persister { /** * Deletes a single object + * * @param obj The object */ void delete(Object obj); @@ -110,6 +111,7 @@ public interface Persister { /** * Refreshes the given objects state + * * @param o The object to refresh * @return The objects id */ @@ -117,6 +119,7 @@ public interface Persister { /** * Get the identifier for the given object, if it has one. + * * @param o The object. * @return The object's id. */ @@ -124,6 +127,7 @@ public interface Persister { /** * Forces an insert of an object rather than trying to guess if it is an insert or an update + * * @param o The object * @return The id */ diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/PropertyValueIndexer.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/PropertyValueIndexer.java index ef69dbfe357..b7f69caf643 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/PropertyValueIndexer.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/PropertyValueIndexer.java @@ -22,7 +22,7 @@ /** * Responsible for creating indices for property values used in queries. - * + *

    * This interface is designed for usage in datastores that don't automatically * create indices and require the application to create the indices manually. * @@ -34,7 +34,7 @@ public interface PropertyValueIndexer { /** * Creates an index for the given value to the specified key * - * @param value The value + * @param value The value * @param primaryKey The key */ void index(Object value, K primaryKey); @@ -43,7 +43,6 @@ public interface PropertyValueIndexer { * Queries the given value and returns the keys * * @param value The value to query by - * * @return The primary keys */ List query(Object value); @@ -51,9 +50,9 @@ public interface PropertyValueIndexer { /** * Queries the given value and returns the keys * - * @param value The value to query by + * @param value The value to query by * @param offset The offset position to start from - * @param max The maximum number of records + * @param max The maximum number of records * @return The primary keys */ List query(Object value, int offset, int max); @@ -66,7 +65,8 @@ public interface PropertyValueIndexer { /** * Removes the index for the given value and key - * @param value The value + * + * @param value The value * @param primaryKey The key */ void deindex(Object value, K primaryKey); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/ThirdPartyCacheEntityPersister.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/ThirdPartyCacheEntityPersister.java index d1c6f10bf56..f14141cf1d5 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/ThirdPartyCacheEntityPersister.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/ThirdPartyCacheEntityPersister.java @@ -35,6 +35,7 @@ * @since 4.1 */ public abstract class ThirdPartyCacheEntityPersister extends LockableEntityPersister { + protected TPCacheAdapterRepository cacheAdapterRepository; public ThirdPartyCacheEntityPersister(MappingContext mappingContext, PersistentEntity entity, Session session, ApplicationEventPublisher publisher) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEvent.java index fd8b6dd7358..3bde53435b5 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEvent.java @@ -18,15 +18,15 @@ */ package org.grails.datastore.mapping.engine.event; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - +import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.engine.EntityAccess; import org.grails.datastore.mapping.model.MappingContext; -import org.springframework.context.ApplicationEvent; -import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.model.PersistentEntity; +import org.springframework.context.ApplicationEvent; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; /** * @author Burt Beckwith @@ -53,8 +53,8 @@ public abstract class AbstractPersistenceEvent extends ApplicationEvent { private Serializable nativeEvent; protected AbstractPersistenceEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { - this((Object)source, entity, entityAccess); + final EntityAccess entityAccess) { + this((Object) source, entity, entityAccess); } protected AbstractPersistenceEvent(final Object source, final PersistentEntity entity, @@ -62,10 +62,9 @@ protected AbstractPersistenceEvent(final Object source, final PersistentEntity e super(source); this.entity = entity; this.entityAccess = entityAccess; - if(entityAccess != null) { + if (entityAccess != null) { this.entityObject = entityAccess.getEntity(); - } - else { + } else { this.entityObject = null; } } @@ -79,10 +78,9 @@ protected AbstractPersistenceEvent(final Datastore source, final Object entity) MappingContext mappingContext = source.getMappingContext(); entityObject = mappingContext.getProxyHandler().unwrap(entity); this.entity = mappingContext.getPersistentEntity(entityObject.getClass().getName()); - if(this.entity != null) { + if (this.entity != null) { this.entityAccess = mappingContext.createEntityAccess(this.entity, entityObject); - } - else { + } else { this.entityAccess = null; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEventListener.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEventListener.java index 835b2ca8eb2..bd9cb76f701 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEventListener.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/AbstractPersistenceEventListener.java @@ -18,8 +18,8 @@ */ package org.grails.datastore.mapping.engine.event; -import org.springframework.context.ApplicationEvent; import org.grails.datastore.mapping.core.Datastore; +import org.springframework.context.ApplicationEvent; /** * @author Burt Beckwith @@ -34,14 +34,15 @@ protected AbstractPersistenceEventListener(final Datastore datastore) { /** * {@inheritDoc} + * * @see org.springframework.context.ApplicationListener#onApplicationEvent( - * org.springframework.context.ApplicationEvent) + *org.springframework.context.ApplicationEvent) */ public final void onApplicationEvent(ApplicationEvent e) { - if(e instanceof AbstractPersistenceEvent) { + if (e instanceof AbstractPersistenceEvent) { - AbstractPersistenceEvent event = (AbstractPersistenceEvent)e; - if(!isValidSource(event)) { + AbstractPersistenceEvent event = (AbstractPersistenceEvent) e; + if (!isValidSource(event)) { return; } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/DatastoreInitializedEvent.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/DatastoreInitializedEvent.groovy index f934fcf929f..f6e10c85b4b 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/DatastoreInitializedEvent.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/DatastoreInitializedEvent.groovy @@ -20,7 +20,6 @@ package org.grails.datastore.mapping.engine.event import org.springframework.context.ApplicationEvent - /** * Fired when the datastore is initialised * @@ -28,6 +27,7 @@ import org.springframework.context.ApplicationEvent * @since 4.0.x */ class DatastoreInitializedEvent extends ApplicationEvent { + DatastoreInitializedEvent(Object source) { super(source) } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PersistenceEventListener.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PersistenceEventListener.java index 3a2a0efeb30..ce378b52983 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PersistenceEventListener.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PersistenceEventListener.java @@ -24,5 +24,6 @@ * @author Burt Beckwith */ public interface PersistenceEventListener extends SmartApplicationListener { + int DEFAULT_ORDER = Integer.MAX_VALUE / 2; } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostDeleteEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostDeleteEvent.java index 87f9910be68..946d5a64c32 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostDeleteEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostDeleteEvent.java @@ -30,7 +30,7 @@ public class PostDeleteEvent extends AbstractPersistenceEvent { private static final long serialVersionUID = 1; public PostDeleteEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { + final EntityAccess entityAccess) { super(source, entity, entityAccess); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostInsertEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostInsertEvent.java index eba244b08a1..49f82f6876d 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostInsertEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostInsertEvent.java @@ -30,7 +30,7 @@ public class PostInsertEvent extends AbstractPersistenceEvent { private static final long serialVersionUID = 1; public PostInsertEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { + final EntityAccess entityAccess) { super(source, entity, entityAccess); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostLoadEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostLoadEvent.java index 2bdf187ee09..0d0c6fe1d33 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostLoadEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostLoadEvent.java @@ -30,7 +30,7 @@ public class PostLoadEvent extends AbstractPersistenceEvent { private static final long serialVersionUID = 1; public PostLoadEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { + final EntityAccess entityAccess) { super(source, entity, entityAccess); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostUpdateEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostUpdateEvent.java index 6d341bd2d63..c9851ac5234 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostUpdateEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PostUpdateEvent.java @@ -30,7 +30,7 @@ public class PostUpdateEvent extends AbstractPersistenceEvent { private static final long serialVersionUID = 1; public PostUpdateEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { + final EntityAccess entityAccess) { super(source, entity, entityAccess); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreDeleteEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreDeleteEvent.java index b6304aa775c..ad6c8729ff6 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreDeleteEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreDeleteEvent.java @@ -30,7 +30,7 @@ public class PreDeleteEvent extends AbstractPersistenceEvent { private static final long serialVersionUID = 1; public PreDeleteEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { + final EntityAccess entityAccess) { super(source, entity, entityAccess); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreInsertEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreInsertEvent.java index d681a0e593c..1c80391b13a 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreInsertEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreInsertEvent.java @@ -30,7 +30,7 @@ public class PreInsertEvent extends AbstractPersistenceEvent { private static final long serialVersionUID = 1; public PreInsertEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { + final EntityAccess entityAccess) { super(source, entity, entityAccess); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreLoadEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreLoadEvent.java index 272c3e15271..f0ebb86e07f 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreLoadEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreLoadEvent.java @@ -30,7 +30,7 @@ public class PreLoadEvent extends AbstractPersistenceEvent { private static final long serialVersionUID = 1; public PreLoadEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { + final EntityAccess entityAccess) { super(source, entity, entityAccess); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreUpdateEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreUpdateEvent.java index 9b43206ef93..fcda0cafa49 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreUpdateEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/PreUpdateEvent.java @@ -30,7 +30,7 @@ public class PreUpdateEvent extends AbstractPersistenceEvent { private static final long serialVersionUID = 1; public PreUpdateEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { + final EntityAccess entityAccess) { super(source, entity, entityAccess); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/SaveOrUpdateEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/SaveOrUpdateEvent.java index fed27a7b5df..a0ab02c4f76 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/SaveOrUpdateEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/SaveOrUpdateEvent.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.engine.event; import org.grails.datastore.mapping.core.Datastore; @@ -31,7 +30,7 @@ public class SaveOrUpdateEvent extends AbstractPersistenceEvent { private static final long serialVersionUID = 1; public SaveOrUpdateEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { + final EntityAccess entityAccess) { super(source, entity, entityAccess); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/ValidationEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/ValidationEvent.java index 8e7e5357543..2509760a028 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/ValidationEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/event/ValidationEvent.java @@ -16,15 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.engine.event; -import java.util.List; - import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.engine.EntityAccess; import org.grails.datastore.mapping.model.PersistentEntity; +import java.util.List; + /** * @author Burt Beckwith */ @@ -35,7 +34,7 @@ public class ValidationEvent extends AbstractPersistenceEvent { private List validatedFields; public ValidationEvent(final Datastore source, final PersistentEntity entity, - final EntityAccess entityAccess) { + final EntityAccess entityAccess) { super(source, entity, entityAccess); } @@ -47,8 +46,6 @@ public ValidationEvent(Object source, PersistentEntity entity, EntityAccess enti super(source, entity, entityAccess); } - - public List getValidatedFields() { return validatedFields; } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/internal/MappingUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/internal/MappingUtils.java index 0f9fd532525..b79433fcdcb 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/internal/MappingUtils.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/internal/MappingUtils.java @@ -18,15 +18,23 @@ */ package org.grails.datastore.mapping.engine.internal; +import org.grails.datastore.mapping.config.Property; +import org.grails.datastore.mapping.model.PersistentProperty; +import org.grails.datastore.mapping.model.PropertyMapping; + import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; -import java.util.*; - -import org.grails.datastore.mapping.config.Property; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.model.PropertyMapping; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.SortedSet; +import java.util.TreeSet; /** * Utility methods for mapping logic. @@ -36,21 +44,24 @@ */ @SuppressWarnings({"rawtypes", "unchecked"}) public class MappingUtils { + private static final String PROPERTY_SET_PREFIX = "set"; private static final String PROPERTY_GET_PREFIX = "get"; /** * Retrieves the name of a setter for the specified property name + * * @param propertyName The property name * @return The setter equivalent */ public static String getSetterName(String propertyName) { final String suffix = getSuffixForGetterOrSetter(propertyName); - return PROPERTY_SET_PREFIX+suffix; + return PROPERTY_SET_PREFIX + suffix; } /** * Calculate the name for a getter method to retrieve the specified property + * * @param propertyName * @return The name for the getter method for this property, if it were to exist, i.e. getConstraints */ @@ -78,8 +89,7 @@ public static String getTargetKey(PersistentProperty property) { if (mapping != null && mapping.getMappedForm() != null) { String tmp = mapping.getMappedForm().getTargetName(); targetName = tmp != null ? tmp : property.getName(); - } - else { + } else { targetName = property.getName(); } return targetName; @@ -87,6 +97,7 @@ public static String getTargetKey(PersistentProperty property) { /** * Creates a concrete collection for the supplied interface + * * @param interfaceType The interface * @return ArrayList for List, TreeSet for SortedSet, LinkedHashSet for Set etc. */ @@ -94,14 +105,11 @@ public static Collection createConcreteCollection(Class interfaceType) { Collection elements; if (interfaceType.equals(List.class)) { elements = new ArrayList(); - } - else if (interfaceType.equals(SortedSet.class)) { + } else if (interfaceType.equals(SortedSet.class)) { elements = new TreeSet(); - } - else if (interfaceType.equals(Queue.class)) { + } else if (interfaceType.equals(Queue.class)) { elements = new ArrayDeque(); - } - else { + } else { elements = new LinkedHashSet(); } return elements; @@ -109,7 +117,8 @@ else if (interfaceType.equals(Queue.class)) { /** * Get a declared field, searching super classes for the field if it is not found in the class. - * @param javaClass The class to search. + * + * @param javaClass The class to search. * @param propertyName The name of the field. * @return The field, or null if it couldn't be found. */ @@ -130,19 +139,19 @@ public static Class getGenericTypeForProperty(Class javaClass, String propertyNa Class genericClass = null; Field declaredField = getDeclaredField(javaClass, propertyName); - if(declaredField != null) { + if (declaredField != null) { Class type = declaredField.getType(); Type genericType = declaredField.getGenericType(); if (genericType instanceof ParameterizedType) { Type[] typeArguments = ((ParameterizedType) genericType).getActualTypeArguments(); int len = typeArguments.length; - if (len >0) { + if (len > 0) { int i = 0; - if(Map.class.isAssignableFrom(type) && len == 2) { + if (Map.class.isAssignableFrom(type) && len == 2) { i++; } Type typeArg = typeArguments[i]; - if(typeArg instanceof Class) { + if (typeArg instanceof Class) { genericClass = (Class) typeArg; } } @@ -158,9 +167,9 @@ public static Class getGenericTypeForMapProperty(Class javaClass, String propert Type genericType = declaredField != null ? declaredField.getGenericType() : null; if (genericType instanceof ParameterizedType) { Type[] typeArguments = ((ParameterizedType) genericType).getActualTypeArguments(); - if (typeArguments.length>0) { + if (typeArguments.length > 0) { Type typeArg = typeArguments[isKeyType ? 0 : 1]; - if(typeArg instanceof Class) { + if (typeArg instanceof Class) { genericClass = (Class) typeArg; } } @@ -171,9 +180,9 @@ public static Class getGenericTypeForMapProperty(Class javaClass, String propert public static Class getGenericType(Class propertyType) { Class genericType = null; TypeVariable[] typeParameters = propertyType.getTypeParameters(); - if (typeParameters != null && typeParameters.length>0) { + if (typeParameters != null && typeParameters.length > 0) { Type[] bounds = typeParameters[0].getBounds(); - if (bounds != null && bounds.length>0 && (bounds[0] instanceof Class)) { + if (bounds != null && bounds.length > 0 && (bounds[0] instanceof Class)) { genericType = (Class) bounds[0]; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/AbstractMappingAwareCustomTypeMarshaller.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/AbstractMappingAwareCustomTypeMarshaller.java index a46169ce8c0..80cc60ca9e9 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/AbstractMappingAwareCustomTypeMarshaller.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/AbstractMappingAwareCustomTypeMarshaller.java @@ -32,7 +32,7 @@ * @since 1.0 */ @SuppressWarnings("rawtypes") -public abstract class AbstractMappingAwareCustomTypeMarshaller implements CustomTypeMarshaller{ +public abstract class AbstractMappingAwareCustomTypeMarshaller implements CustomTypeMarshaller { private Class targetType; @@ -55,7 +55,7 @@ public Class getTargetType() { public Object write(PersistentProperty property, T value, N nativeTarget) { String targetName = MappingUtils.getTargetKey(property); - return writeInternal(property, targetName,value,nativeTarget); + return writeInternal(property, targetName, value, nativeTarget); } protected abstract Object writeInternal(PersistentProperty property, String key, T value, N nativeTarget); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/CustomTypeMarshaller.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/CustomTypeMarshaller.java index 0498d7e6141..b4e4a4e7bc9 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/CustomTypeMarshaller.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/types/CustomTypeMarshaller.java @@ -27,12 +27,11 @@ * Interface for defining custom datastore types beyond the simple and association * types supported out of the box. * - * @author Graeme Rocher - * @since 1.0 - * * @param The target type to be marshalled * @param The native database type * @param The return type of the query + * @author Graeme Rocher + * @since 1.0 */ public interface CustomTypeMarshaller { @@ -59,8 +58,8 @@ public interface CustomTypeMarshaller { /** * Converts a value to its native form * - * @param property The property being converted - * @param value The value + * @param property The property being converted + * @param value The value * @param nativeTarget The nativeTarget * @return The written value */ @@ -69,17 +68,18 @@ public interface CustomTypeMarshaller { /** * Populates a query * - * @param property The property being converted - * @param criterion The criterion + * @param property The property being converted + * @param criterion The criterion * @param nativeQuery The nativeQuery * @return The native query */ - Q query(@SuppressWarnings("rawtypes") PersistentProperty property, Query.PropertyCriterion criterion, Q nativeQuery); + Q query(@SuppressWarnings("rawtypes") PersistentProperty property, Query.PropertyCriterion criterion, Q nativeQuery); /** * Converts a value from its native form + * * @param property The property being converted - * @param source The native form + * @param source The native form * @return The converted type */ T read(@SuppressWarnings("rawtypes") PersistentProperty property, N source); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/graph/GraphDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/graph/GraphDatastore.java index ce7ba8d9f02..aca223426d3 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/graph/GraphDatastore.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/graph/GraphDatastore.java @@ -25,7 +25,8 @@ * * @author Guillaume Laforge * @author Graeme Rocher - * * @since 1.0 */ -public interface GraphDatastore extends Datastore {} \ No newline at end of file +public interface GraphDatastore extends Datastore { + +} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/engine/AbstractKeyValueEntityPersister.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/engine/AbstractKeyValueEntityPersister.java index 49893d71505..7c57fbdfdf9 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/engine/AbstractKeyValueEntityPersister.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/engine/AbstractKeyValueEntityPersister.java @@ -18,7 +18,6 @@ */ package org.grails.datastore.mapping.keyvalue.engine; -import org.springframework.context.ApplicationEventPublisher; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.engine.NativeEntryEntityPersister; import org.grails.datastore.mapping.keyvalue.mapping.config.Family; @@ -28,6 +27,7 @@ import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.PropertyMapping; +import org.springframework.context.ApplicationEventPublisher; /** * Abstract implementation of the EntityPersister abstract class @@ -37,11 +37,12 @@ * @since 1.0 */ @SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class AbstractKeyValueEntityPersister extends NativeEntryEntityPersister { +public abstract class AbstractKeyValueEntityPersister extends NativeEntryEntityPersister { + protected String entityFamily; protected AbstractKeyValueEntityPersister(MappingContext context, PersistentEntity entity, - Session session, ApplicationEventPublisher publisher) { + Session session, ApplicationEventPublisher publisher) { super(context, entity, session, publisher); entityFamily = getFamily(entity, classMapping); } @@ -60,7 +61,7 @@ public ClassMapping getClassMapping() { protected String getNativePropertyKey(PersistentProperty prop) { PropertyMapping pm = prop.getMapping(); String propKey = null; - if (pm.getMappedForm()!=null) { + if (pm.getMappedForm() != null) { propKey = pm.getMappedForm().getKey(); } if (propKey == null) { @@ -74,7 +75,9 @@ protected String getFamily(PersistentEntity persistentEntity, ClassMapping cm, String defaultValue) { if (cm.getMappedForm() != null) { keyspace = cm.getMappedForm().getKeyspace(); } - if (keyspace == null) keyspace = defaultValue; + if (keyspace == null) { + keyspace = defaultValue; + } return keyspace; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/Family.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/Family.groovy index ed85f304f3a..d69fef8aa1c 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/Family.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/Family.groovy @@ -22,7 +22,6 @@ import groovy.transform.CompileStatic import groovy.transform.builder.Builder import groovy.transform.builder.SimpleStrategy import org.grails.datastore.mapping.config.Entity -import org.grails.datastore.mapping.config.Property /** *

    A Family is a grouping of KeyValue pairs and is typically composed diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValueMappingContext.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValueMappingContext.java index 02f41a42813..e82adb635ea 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValueMappingContext.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValueMappingContext.java @@ -33,16 +33,11 @@ * @since 1.0 */ public class KeyValueMappingContext extends AbstractMappingContext { + + public static final String GROOVY_OBJECT_CLASS = "groovy.lang.GroovyObject"; protected MappingFactory mappingFactory; protected MappingConfigurationStrategy syntaxStrategy; private String keyspace; - public static final String GROOVY_OBJECT_CLASS = "groovy.lang.GroovyObject"; - - @Override - public void setCanInitializeEntities(boolean canInitializeEntities) { - super.setCanInitializeEntities(canInitializeEntities); - syntaxStrategy.setCanExpandMappingContext(false); - } /** * Constructs a context using the given keyspace @@ -70,6 +65,12 @@ public KeyValueMappingContext(String keyspace, ConnectionSourceSettings settings super.initialize(settings); } + @Override + public void setCanInitializeEntities(boolean canInitializeEntities) { + super.setCanInitializeEntities(canInitializeEntities); + syntaxStrategy.setCanExpandMappingContext(false); + } + public String getKeyspace() { return keyspace; } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValuePersistentEntity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValuePersistentEntity.java index d03d0a7e887..631dc863b57 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValuePersistentEntity.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/keyvalue/mapping/config/KeyValuePersistentEntity.java @@ -30,7 +30,8 @@ * @author Graeme Rocher * @since 1.0 */ -public class KeyValuePersistentEntity extends AbstractPersistentEntity{ +public class KeyValuePersistentEntity extends AbstractPersistentEntity { + private Object mappedForm; private KeyValueClassMapping classMapping; @@ -49,7 +50,7 @@ public ClassMapping getMapping() { @Override public PersistentEntity getParentEntity() { Class superclass = this.javaClass.getSuperclass(); - if( superclass != null ) { + if (superclass != null) { return context.getPersistentEntity(superclass.getName()); } @@ -58,28 +59,29 @@ public PersistentEntity getParentEntity() { @Override public PersistentProperty getPropertyByName(String name) { - if(name != null && name.contains(".")) { + if (name != null && name.contains(".")) { String[] props = name.split("\\."); // Get the embedded property type PersistentProperty embeddedProp = super.getPropertyByName(props[0]); - if( embeddedProp instanceof Embedded) { + if (embeddedProp instanceof Embedded) { PersistentEntity embeddedEntity = ((Embedded) embeddedProp).getAssociatedEntity(); return embeddedEntity.getPropertyByName(props[1]); } return super.getPropertyByName(name); - } - else { + } else { return super.getPropertyByName(name); } } public class KeyValueClassMapping extends AbstractClassMapping { + public KeyValueClassMapping(PersistentEntity entity, MappingContext context) { super(entity, context); } + @Override public Family getMappedForm() { return (Family) mappedForm; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractClassMapping.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractClassMapping.java index 4f6ca53da5e..9d50680c8bd 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractClassMapping.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractClassMapping.java @@ -28,6 +28,7 @@ */ @SuppressWarnings("rawtypes") public abstract class AbstractClassMapping implements ClassMapping { + protected PersistentEntity entity; protected MappingContext context; private IdentityMapping identifierMapping; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractMappingContext.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractMappingContext.java index 3b84f2112b5..7907a6ba7bf 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractMappingContext.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractMappingContext.java @@ -14,13 +14,6 @@ */ package org.grails.datastore.mapping.model; -import java.beans.Introspector; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; - import org.grails.datastore.mapping.config.AbstractGormMappingFactory; import org.grails.datastore.mapping.config.ConfigurationUtils; import org.grails.datastore.mapping.core.connections.ConnectionSourceSettings; @@ -47,6 +40,18 @@ import org.springframework.util.ClassUtils; import org.springframework.validation.Validator; +import java.beans.Introspector; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + /** * Abstract implementation of the MappingContext interface. * @@ -60,10 +65,10 @@ public abstract class AbstractMappingContext implements MappingContext, Initiali public static final String JAVASIST_PROXY_FACTORY = "javassist.util.proxy.ProxyFactory"; public static final String CONFIGURATION_PREFIX = "grails.gorm."; protected Collection persistentEntities = new ConcurrentLinkedQueue<>(); - protected Map persistentEntitiesByName = new ConcurrentHashMap<>(); - protected Map> persistentEntitiesByDiscriminator = new ConcurrentHashMap<>(); - protected Map> persistentEntitiesByParent = new ConcurrentHashMap<>(); - protected Map entityValidators = new ConcurrentHashMap<>(); + protected Map persistentEntitiesByName = new ConcurrentHashMap<>(); + protected Map> persistentEntitiesByDiscriminator = new ConcurrentHashMap<>(); + protected Map> persistentEntitiesByParent = new ConcurrentHashMap<>(); + protected Map entityValidators = new ConcurrentHashMap<>(); protected Collection eventListeners = new ConcurrentLinkedQueue<>(); protected GenericConversionService conversionService = new DefaultConversionService(); protected ProxyFactory proxyFactory; @@ -93,13 +98,13 @@ protected void initialize(ConnectionSourceSettings settings) { MappingFactory mappingFactory = getMappingFactory(); Iterable customTypeMarshallers = ConfigurationUtils.findServices(settings.getCustom().getTypes(), CustomTypeMarshaller.class); for (CustomTypeMarshaller customTypeMarshaller : customTypeMarshallers) { - if(customTypeMarshaller.supports(this)) { + if (customTypeMarshaller.supports(this)) { mappingFactory.registerCustomType(customTypeMarshaller); } } // default constraints and mapping - if(mappingFactory instanceof AbstractGormMappingFactory) { + if (mappingFactory instanceof AbstractGormMappingFactory) { AbstractGormMappingFactory gormMappingFactory = (AbstractGormMappingFactory) mappingFactory; gormMappingFactory.setDefaultConstraints(settings.getDefault().getConstraints()); gormMappingFactory.setDefaultMapping(settings.getDefault().getMapping()); @@ -121,14 +126,14 @@ public void setCanInitializeEntities(boolean canInitializeEntities) { public abstract MappingFactory getMappingFactory(); public void configure(PropertyResolver configuration) { - if(configuration == null) { + if (configuration == null) { return; } String simpleName = Introspector.decapitalize(getClass().getSimpleName()); String suffix = "MappingContext"; - if(simpleName.endsWith(suffix)) { + if (simpleName.endsWith(suffix)) { simpleName = simpleName.substring(0, simpleName.length() - suffix.length()); } @@ -137,7 +142,7 @@ public void configure(PropertyResolver configuration) { Iterable customTypeMarshallers = ConfigurationUtils.findServices(configuration, configurationKey, CustomTypeMarshaller.class); for (CustomTypeMarshaller customTypeMarshaller : customTypeMarshallers) { - if(customTypeMarshaller.supports(this)) { + if (customTypeMarshaller.supports(this)) { getMappingFactory().registerCustomType(customTypeMarshaller); } } @@ -153,15 +158,13 @@ public ProxyFactory getProxyFactory() { ClassLoader classLoader = AbstractMappingContext.class.getClassLoader(); if (ClassUtils.isPresent(JAVASIST_PROXY_FACTORY, classLoader)) { proxyFactory = DefaultProxyFactoryCreator.create(); - } - else if (ClassUtils.isPresent(GROOVY_PROXY_FACTORY_NAME, classLoader)) { + } else if (ClassUtils.isPresent(GROOVY_PROXY_FACTORY_NAME, classLoader)) { try { proxyFactory = (ProxyFactory) BeanUtils.instantiateClass(ClassUtils.forName(GROOVY_PROXY_FACTORY_NAME, classLoader)); } catch (ClassNotFoundException e) { proxyFactory = DefaultProxyFactoryCreator.create(); } - } - else { + } else { proxyFactory = DefaultProxyFactoryCreator.create(); } } @@ -169,8 +172,9 @@ else if (ClassUtils.isPresent(GROOVY_PROXY_FACTORY_NAME, classLoader)) { } public void addMappingContextListener(Listener listener) { - if (listener != null) + if (listener != null) { eventListeners.add(listener); + } } public void setProxyFactory(ProxyFactory factory) { @@ -189,12 +193,6 @@ public ValidatorRegistry getValidatorRegistry() { return validatorRegistry; } - private static class DefaultProxyFactoryCreator { - public static ProxyFactory create() { - return new JavassistProxyFactory(); - } - } - public void addTypeConverter(Converter converter) { conversionService.addConverter(converter); } @@ -209,9 +207,9 @@ public Validator getEntityValidator(PersistentEntity entity) { if (entity != null) { Validator validator = entityValidators.get(entity); - if(validator == null && validatorRegistry != null) { + if (validator == null && validatorRegistry != null) { Validator v = validatorRegistry.getValidator(entity); - if(v != null) { + if (v != null) { entityValidators.put(entity, v); return v; } @@ -224,7 +222,7 @@ public Validator getEntityValidator(PersistentEntity entity) { /** * Adds a validator for an entity * - * @param entity The PersistentEntity The entity + * @param entity The PersistentEntity The entity * @param validator The validator The validator */ public void addEntityValidator(PersistentEntity entity, Validator validator) { @@ -271,13 +269,15 @@ public Collection addPersistentEntities(Class... javaClasses) for (Class javaClass : javaClasses) { PersistentEntity entity = createPersistentEntity(javaClass); - if(entity == null) continue; + if (entity == null) { + continue; + } registerEntityWithContext(entity); entities.add(entity); } - if(canInitializeEntities) { + if (canInitializeEntities) { for (PersistentEntity entity : entities) { initializePersistentEntity(entity); } @@ -317,7 +317,7 @@ private PersistentEntity addPersistentEntityInternal(Class javaClass, boolean is registerEntityWithContext(entity); - if(isInitialize) { + if (isInitialize) { initializePersistentEntity(entity); } @@ -335,7 +335,7 @@ private void registerEntityWithContext(PersistentEntity entity) { } public void initialize() { - for(PersistentEntity entity : persistentEntities) { + for (PersistentEntity entity : persistentEntities) { initializePersistentEntity(entity); FieldEntityAccess.getOrIntializeReflector(entity); } @@ -349,8 +349,7 @@ public boolean isInitialized() { private void initializePersistentEntity(PersistentEntity entity) { try { entity.initialize(); - } - catch(IllegalMappingException x) { + } catch (IllegalMappingException x) { persistentEntities.remove(entity); persistentEntitiesByName.remove(entity.getName()); throw x; @@ -367,7 +366,7 @@ private void initializePersistentEntity(PersistentEntity entity) { directChildren.add(entity); while (parent != null) { - if(!parent.isInitialized()) { + if (!parent.isInitialized()) { parent.initialize(); } @@ -392,7 +391,9 @@ private void initializePersistentEntity(PersistentEntity entity) { */ public boolean isInInheritanceHierarchy(PersistentEntity entity) { if (entity != null) { - if (!entity.isRoot()) return true; + if (!entity.isRoot()) { + return true; + } PersistentEntity rootEntity = entity.getRootEntity(); final Map children = persistentEntitiesByDiscriminator.get(rootEntity); if (children != null && !children.isEmpty()) { @@ -405,10 +406,9 @@ public boolean isInInheritanceHierarchy(PersistentEntity entity) { @Override public Collection getChildEntities(PersistentEntity root) { final Map children = persistentEntitiesByDiscriminator.get(root); - if(children != null) { + if (children != null) { return Collections.unmodifiableCollection(children.values()); - } - else { + } else { return Collections.emptySet(); } } @@ -416,7 +416,7 @@ public Collection getChildEntities(PersistentEntity root) { @Override public Collection getDirectChildEntities(PersistentEntity root) { Collection entities = persistentEntitiesByParent.get(root); - if(entities == null) { + if (entities == null) { return Collections.emptyList(); } return Collections.unmodifiableCollection(entities); @@ -432,10 +432,10 @@ public PersistentEntity getChildEntityByDiscriminator(PersistentEntity root, Str protected abstract PersistentEntity createPersistentEntity(Class javaClass); - protected Object resolveMappingStrategy(Class javaClass){ + protected Object resolveMappingStrategy(Class javaClass) { try { Field field = javaClass.getDeclaredField(GormProperties.MAPPING_STRATEGY); - if(field != null && Modifier.isStatic(field.getModifiers())) { + if (field != null && Modifier.isStatic(field.getModifiers())) { field.setAccessible(true); return field.get(javaClass); } @@ -446,13 +446,13 @@ protected Object resolveMappingStrategy(Class javaClass){ } protected boolean isValidMappingStrategy(Class javaClass, Object mappingStrategy) { - if(mappingStrategy == null) { + if (mappingStrategy == null) { return true; } String name = getClass().getSimpleName(); String suffix = MappingContext.class.getSimpleName(); - if(name.endsWith(suffix)) { + if (name.endsWith(suffix)) { name = name.substring(0, name.length() - suffix.length()).toLowerCase(Locale.ENGLISH); return name.equalsIgnoreCase(mappingStrategy.toString()); } @@ -506,7 +506,7 @@ public EntityReflector getEntityReflector(PersistentEntity entity) { public EntityAccess createEntityAccess(PersistentEntity entity, Object instance) { final ProxyFactory proxyFactory = getProxyFactory(); instance = proxyFactory.unwrap(instance); - if(entity != null) { + if (entity != null) { if (entity.getJavaClass() != instance.getClass()) { // try subclass @@ -516,15 +516,20 @@ public EntityAccess createEntityAccess(PersistentEntity entity, Object instance) } } return new FieldEntityAccess(entity, instance, getConversionService()); - } - else { + } else { EntityReflector reflector = FieldEntityAccess.getReflector(instance.getClass().getName()); - if(reflector != null) { + if (reflector != null) { return new FieldEntityAccess(reflector.getPersitentEntity(), instance, conversionService); - } - else { + } else { return new BeanEntityAccess(null, instance); } } } + + private static class DefaultProxyFactoryCreator { + + public static ProxyFactory create() { + return new JavassistProxyFactory(); + } + } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentEntity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentEntity.java index d7d86daadad..24a8a142744 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentEntity.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentEntity.java @@ -18,23 +18,34 @@ */ package org.grails.datastore.mapping.model; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.annotation.Annotation; -import java.lang.reflect.Modifier; -import java.util.*; - import org.grails.datastore.mapping.config.Entity; import org.grails.datastore.mapping.core.EntityCreationException; import org.grails.datastore.mapping.core.exceptions.ConfigurationException; import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.model.types.*; +import org.grails.datastore.mapping.model.types.Association; +import org.grails.datastore.mapping.model.types.Embedded; +import org.grails.datastore.mapping.model.types.Identity; +import org.grails.datastore.mapping.model.types.OneToMany; +import org.grails.datastore.mapping.model.types.TenantId; import org.grails.datastore.mapping.multitenancy.MultiTenancySettings; import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; import org.grails.datastore.mapping.reflect.EntityReflector; import org.springframework.beans.BeanUtils; import org.springframework.util.Assert; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * Abstract implementation to be subclasses on a per datastore basis * @@ -43,18 +54,19 @@ */ @SuppressWarnings({"rawtypes", "unchecked"}) public abstract class AbstractPersistentEntity implements PersistentEntity { + protected final Class javaClass; protected final MappingContext context; protected List persistentProperties; protected List associations; protected List embedded; - protected Map propertiesByName = new HashMap(); - protected Map mappedPropertiesByName = new HashMap(); + protected Map propertiesByName = new HashMap(); + protected Map mappedPropertiesByName = new HashMap(); protected PersistentProperty identity; protected PersistentProperty version; protected List persistentPropertyNames; - private final String decapitalizedName; protected Set owners; + private final String decapitalizedName; private PersistentEntity parentEntity; private boolean external; private boolean initialized = false; @@ -93,7 +105,6 @@ public boolean isMultiTenant() { return this.isMultiTenant; } - public boolean isExternal() { return external; } @@ -105,6 +116,7 @@ public boolean isAbstract() { public String getMappingStrategy() { return this.mappingStrategy; } + public void setExternal(boolean external) { this.external = external; } @@ -119,8 +131,7 @@ public boolean isInitialized() { public void initialize() { ClassMapping mapping = getMapping(); - if(!initialized) { - + if (!initialized) { initialized = true; @@ -128,9 +139,9 @@ public void initialize() { owners = mappingSyntaxStrategy.getOwningEntities(javaClass, context); Class superClass = javaClass.getSuperclass(); if (superClass != null && - !superClass.equals(Object.class) ) { + !superClass.equals(Object.class)) { - if(mappingSyntaxStrategy.isPersistentEntity(superClass)) { + if (mappingSyntaxStrategy.isPersistentEntity(superClass)) { parentEntity = context.addPersistentEntity(superClass); } } @@ -139,25 +150,22 @@ public void initialize() { persistentPropertyNames = new ArrayList<>(); associations = new ArrayList(); - embedded = new ArrayList(); - + embedded = new ArrayList(); boolean multiTenancyEnabled = isMultiTenant && context.getMultiTenancyMode() == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR; for (PersistentProperty persistentProperty : persistentProperties) { - if(multiTenancyEnabled && persistentProperty instanceof TenantId) { + if (multiTenancyEnabled && persistentProperty instanceof TenantId) { this.tenantId = (TenantId) persistentProperty; } - if(persistentProperty instanceof Identity) { - if(compositeIdentity != null) { + if (persistentProperty instanceof Identity) { + if (compositeIdentity != null) { int l = compositeIdentity.length; - compositeIdentity = Arrays.copyOf(compositeIdentity, l +1); + compositeIdentity = Arrays.copyOf(compositeIdentity, l + 1); compositeIdentity[l] = identity; - } - else if(identity != null) { - compositeIdentity = new PersistentProperty[] { identity, persistentProperty }; + } else if (identity != null) { + compositeIdentity = new PersistentProperty[]{identity, persistentProperty}; identity = null; - } - else { + } else { identity = persistentProperty; } } @@ -169,77 +177,73 @@ else if(identity != null) { if (persistentProperty instanceof Association) { associations.add((Association) persistentProperty); } - if( persistentProperty instanceof Embedded) { - embedded.add((Embedded)persistentProperty); + if (persistentProperty instanceof Embedded) { + embedded.add((Embedded) persistentProperty); } propertiesByName.put(persistentProperty.getName(), persistentProperty); final String targetName = persistentProperty.getMapping().getMappedForm().getTargetName(); - if(targetName != null) { + if (targetName != null) { mappedPropertiesByName.put(targetName, persistentProperty); } } - if(associations.isEmpty()) { + if (associations.isEmpty()) { associations = Collections.emptyList(); } - if(embedded.isEmpty()) { + if (embedded.isEmpty()) { embedded = Collections.emptyList(); } - if(identity == null && compositeIdentity == null) { + if (identity == null && compositeIdentity == null) { identity = resolveIdentifier(); } - if(multiTenancyEnabled && tenantId == null) { - throw new ConfigurationException("Class ["+javaClass.getName()+"] is multi tenant but does not specify a tenant identifier property"); + if (multiTenancyEnabled && tenantId == null) { + throw new ConfigurationException("Class [" + javaClass.getName() + "] is multi tenant but does not specify a tenant identifier property"); } - if(!isExternal()) { - - final T mappedForm = mapping.getMappedForm();// initialize mapping + if (!isExternal()) { + final T mappedForm = mapping.getMappedForm(); // initialize mapping if (mappedForm.isVersioned()) { version = propertiesByName.get(GormProperties.VERSION); - if(version == null) { + if (version == null) { versioned = false; } - } - else { + } else { versioned = false; } } final PersistentProperty v = getVersion(); - if(v != null) { + if (v != null) { final Class type = v.getType(); this.versionCompatibleType = Number.class.isAssignableFrom(type) || Date.class.isAssignableFrom(type); } - - if(identity != null) { + if (identity != null) { String idName = identity.getName(); PersistentProperty idProp = propertiesByName.get(idName); - if(idProp == null) { + if (idProp == null) { propertiesByName.put(idName, identity); - } - else { + } else { persistentProperties.remove(idProp); persistentPropertyNames.remove(idProp.getName()); - if(!idProp.getName().equals(GormProperties.IDENTITY)) { + if (!idProp.getName().equals(GormProperties.IDENTITY)) { disableDefaultId(); } } } IdentityMapping identifier = mapping != null ? mapping.getIdentifier() : null; - if(identity == null && identifier != null) { + if (identity == null && identifier != null) { final String[] identifierName = identifier.getIdentifierName(); final MappingContext mappingContext = getMappingContext(); - if(identifierName.length > 1) { + if (identifierName.length > 1) { compositeIdentity = mappingContext.getMappingSyntaxStrategy().getCompositeIdentity(javaClass, mappingContext); } for (String in : identifierName) { final PersistentProperty p = propertiesByName.get(in); - if(p != null) { + if (p != null) { persistentProperties.remove(p); } persistentPropertyNames.remove(in); @@ -248,15 +252,13 @@ else if(identity != null) { } } - - propertiesInitialized = true; this.entityReflector = getMappingContext().getEntityReflector(this); } private void disableDefaultId() { PersistentProperty otherId = getPropertyByName(GormProperties.IDENTITY); - if(otherId != null) { + if (otherId != null) { persistentProperties.remove(otherId); persistentPropertyNames.remove(GormProperties.IDENTITY); } @@ -272,7 +274,7 @@ protected boolean isAnnotatedSuperClass(MappingConfigurationStrategy mappingSynt Annotation[] annotations = superClass.getAnnotations(); for (Annotation annotation : annotations) { String name = annotation.annotationType().getName(); - if(name.equals("grails.persistence.Entity") || name.equals("grails.gorm.annotation.Entity")) { + if (name.equals("grails.persistence.Entity") || name.equals("grails.gorm.annotation.Entity")) { return true; } } @@ -308,7 +310,7 @@ public PersistentEntity getRootEntity() { PersistentEntity root = this; PersistentEntity parent = getParentEntity(); while (parent != null) { - if(!parent.isInitialized()) { + if (!parent.isInitialized()) { parent.initialize(); } root = parent; @@ -393,18 +395,44 @@ public List getEmbedded() { public PersistentProperty getPropertyByName(String name) { PersistentProperty pp = propertiesByName.get(name); - if(pp != null) { + if (pp != null) { return pp; } return mappedPropertiesByName.get(name); } - private static class MappingProperties { + @Override + public int hashCode() { + return javaClass.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof PersistentEntity)) { + return false; + } + if (this == o) { + return true; + } + PersistentEntity other = (PersistentEntity) o; + return javaClass.equals(other.getJavaClass()); + } + + @Override + public String toString() { + return javaClass.getName(); + } + + public boolean addOwner(Class type) { + return owners.add(type); + } + private static class MappingProperties { private Boolean version = true; private boolean intialized = false; + public boolean isIntialized() { return intialized; } @@ -422,27 +450,4 @@ public boolean isVersioned() { } } - @Override - public int hashCode() { - return javaClass.hashCode(); - } - - @Override - public boolean equals(Object o) { - if (o == null || !(o instanceof PersistentEntity)) return false; - if (this == o) return true; - - PersistentEntity other = (PersistentEntity) o; - return javaClass.equals(other.getJavaClass()); - } - - @Override - public String toString() { - return javaClass.getName(); - } - - public boolean addOwner(Class type) { - return owners.add(type); - } - } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentProperty.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentProperty.java index 1266c892f35..5f05fe93695 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentProperty.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/AbstractPersistentProperty.java @@ -18,12 +18,12 @@ */ package org.grails.datastore.mapping.model; -import java.beans.PropertyDescriptor; - import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.reflect.EntityReflector; import org.grails.datastore.mapping.reflect.NameUtils; +import java.beans.PropertyDescriptor; + /** * Abstract implementation of the PersistentProperty interface that uses the * PropertyDescriptor instance to establish name and type. @@ -33,6 +33,7 @@ */ @SuppressWarnings("rawtypes") public abstract class AbstractPersistentProperty implements PersistentProperty { + protected final PersistentEntity owner; protected final MappingContext context; protected final String name; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ClassMapping.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ClassMapping.java index ee861e46380..544701c2ec9 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ClassMapping.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ClassMapping.java @@ -38,6 +38,7 @@ public interface ClassMapping { /** * Returns the mapped form of the class such as a Table, a Key Space, Document etc. + * * @return The mapped representation */ T getMappedForm(); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/DatastoreConfigurationException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/DatastoreConfigurationException.java index 2f3c42b9c9f..42c1a19a570 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/DatastoreConfigurationException.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/DatastoreConfigurationException.java @@ -24,7 +24,7 @@ * @author Graeme Rocher * @since 1.0 */ -public class DatastoreConfigurationException extends RuntimeException{ +public class DatastoreConfigurationException extends RuntimeException { private static final long serialVersionUID = 1; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/EmbeddedPersistentEntity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/EmbeddedPersistentEntity.java index 5c4abb8e2d3..e7d7af81016 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/EmbeddedPersistentEntity.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/EmbeddedPersistentEntity.java @@ -27,7 +27,8 @@ * @since 1.0 */ @SuppressWarnings({"rawtypes", "unchecked"}) -public class EmbeddedPersistentEntity extends AbstractPersistentEntity{ +public class EmbeddedPersistentEntity extends AbstractPersistentEntity { + public EmbeddedPersistentEntity(Class type, MappingContext ctx) { super(type, ctx); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingConfigurationStrategy.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingConfigurationStrategy.java index 018ffd10606..b56e9094103 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingConfigurationStrategy.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingConfigurationStrategy.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.model; import java.util.List; @@ -62,8 +61,8 @@ public interface MappingConfigurationStrategy { * Obtains a List of PersistentProperty instances for the given Mapped class * * @param javaClass The Java class - * @param context The MappingContext instance - * @param mapping The mapping for this class + * @param context The MappingContext instance + * @param mapping The mapping for this class * @return The PersistentProperty instances */ List getPersistentProperties(Class javaClass, MappingContext context, ClassMapping mapping); @@ -72,7 +71,7 @@ public interface MappingConfigurationStrategy { * Obtains the identity of a persistent entity * * @param javaClass The Java class - * @param context The MappingContext + * @param context The MappingContext * @return A PersistentProperty instance */ PersistentProperty getIdentity(Class javaClass, MappingContext context); @@ -81,7 +80,7 @@ public interface MappingConfigurationStrategy { * Obtains the identity of a persistent entity * * @param javaClass The Java class - * @param context The MappingContext + * @param context The MappingContext * @return A PersistentProperty instance */ PersistentProperty[] getCompositeIdentity(Class javaClass, MappingContext context); @@ -91,8 +90,8 @@ public interface MappingConfigurationStrategy { * this is just using a property called 'id', but in other frameworks this * may differ. For example JPA expects an annotated @Id property * - * @return The default identifier mapping * @param classMapping The ClassMapping instance + * @return The default identifier mapping */ IdentityMapping getDefaultIdentityMapping(ClassMapping classMapping); @@ -102,7 +101,7 @@ public interface MappingConfigurationStrategy { * then saves, updates and deletes will cascade from A to B * * @param javaClass The Java class - * @param context The MappingContext + * @param context The MappingContext * @return A Set of owning classes */ Set getOwningEntities(Class javaClass, MappingContext context); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingContext.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingContext.java index 9594c908be3..259b332a134 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingContext.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingContext.java @@ -18,19 +18,19 @@ */ package org.grails.datastore.mapping.model; -import java.util.Collection; - import org.grails.datastore.mapping.engine.EntityAccess; import org.grails.datastore.mapping.multitenancy.MultiTenancySettings; +import org.grails.datastore.mapping.proxy.ProxyFactory; import org.grails.datastore.mapping.proxy.ProxyHandler; import org.grails.datastore.mapping.reflect.EntityReflector; import org.grails.datastore.mapping.validation.ValidatorRegistry; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.ConverterRegistry; -import org.grails.datastore.mapping.proxy.ProxyFactory; import org.springframework.validation.Validator; +import java.util.Collection; + /** *

    Defines the overall context including all known * PersistentEntity instances and methods to obtain instances on demand

    @@ -72,13 +72,16 @@ public interface MappingContext { /** * Returns true if the given entity is in an inheritance hierarchy + * * @param entity The entity * @return True if it is */ boolean isInInheritanceHierarchy(PersistentEntity entity); + /** * Obtains a child of the given root entity using the given discriminator - * @param root The root entity + * + * @param root The root entity * @param discriminator The discriminator * @return The child entity or null if non exists */ @@ -106,7 +109,8 @@ public interface MappingContext { * @param javaClasses The Java class representing the entity * @return The PersistentEntity instance */ - Collection addPersistentEntities(Class...javaClasses); + Collection addPersistentEntities(Class... javaClasses); + /** * Adds a PersistentEntity instance * @@ -119,8 +123,7 @@ public interface MappingContext { * Adds a PersistentEntity instance * * @param javaClass The Java class representing the entity - * @param override Whether to override an existing entity - * + * @param override Whether to override an existing entity * @return The PersistentEntity instance */ PersistentEntity addPersistentEntity(Class javaClass, boolean override); @@ -136,7 +139,8 @@ public interface MappingContext { /** * Adds a validator to be used by the entity for validation - * @param entity The PersistentEntity + * + * @param entity The PersistentEntity * @param validator The validator */ void addEntityValidator(PersistentEntity entity, Validator validator); @@ -162,6 +166,7 @@ public interface MappingContext { /** * Obtains the ConversionService instance to use for type conversion + * * @return The conversion service instance */ ConversionService getConversionService(); @@ -175,6 +180,7 @@ public interface MappingContext { /** * Obtains a validator for the given entity + * * @param entity The entity * @return A validator or null if none exists for the given entity */ @@ -190,12 +196,14 @@ public interface MappingContext { /** * Obtains the MappingFactory instance + * * @return The mapping factory instance */ MappingFactory getMappingFactory(); /** * Returns whether the specified class is a persistent entity + * * @param type The type to check * @return True if it is */ @@ -203,6 +211,7 @@ public interface MappingContext { /** * Returns whether the specified value is a persistent entity + * * @param value The value to check * @return True if it is */ @@ -210,6 +219,7 @@ public interface MappingContext { /** * Factory used for creating proxies + * * @return The proxy factory */ ProxyFactory getProxyFactory(); @@ -223,12 +233,14 @@ public interface MappingContext { /** * Factory to use for creating proxies + * * @param factory The proxy factory */ void setProxyFactory(ProxyFactory factory); /** * Adds a new mapping context listener instance + * * @param listener The listener */ void addMappingContextListener(Listener listener); @@ -243,11 +255,10 @@ public interface MappingContext { */ EntityReflector getEntityReflector(PersistentEntity entity); - /** * Creates an {@link EntityAccess} instance for the given entity and instance of said entity * - * @param entity The entity + * @param entity The entity * @param instance The instance * @return The {@link EntityAccess} */ @@ -260,6 +271,7 @@ interface Listener { /** * Fired when a new entity is added + * * @param entity The entity */ void persistentEntityAdded(PersistentEntity entity); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingFactory.java index 95745542457..501e936e110 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingFactory.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/MappingFactory.java @@ -23,7 +23,19 @@ import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller; import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.model.types.*; +import org.grails.datastore.mapping.model.types.Association; +import org.grails.datastore.mapping.model.types.Basic; +import org.grails.datastore.mapping.model.types.Custom; +import org.grails.datastore.mapping.model.types.Embedded; +import org.grails.datastore.mapping.model.types.EmbeddedCollection; +import org.grails.datastore.mapping.model.types.Identity; +import org.grails.datastore.mapping.model.types.ManyToMany; +import org.grails.datastore.mapping.model.types.ManyToOne; +import org.grails.datastore.mapping.model.types.OneToMany; +import org.grails.datastore.mapping.model.types.OneToOne; +import org.grails.datastore.mapping.model.types.Simple; +import org.grails.datastore.mapping.model.types.TenantId; +import org.grails.datastore.mapping.model.types.ToOne; import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; import java.beans.PropertyDescriptor; @@ -36,7 +48,17 @@ import java.sql.Clob; import java.sql.Time; import java.sql.Timestamp; -import java.util.*; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collection; +import java.util.Collections; +import java.util.GregorianCalendar; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; @@ -61,68 +83,68 @@ * @since 1.0 */ @SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class MappingFactory { +public abstract class MappingFactory { public static final String IDENTITY_PROPERTY = GormProperties.IDENTITY; public static final Set SIMPLE_TYPES; static { SIMPLE_TYPES = Collections.unmodifiableSet(new HashSet(Arrays.asList( - boolean.class.getName(), - long.class.getName(), - short.class.getName(), - int.class.getName(), - byte.class.getName(), - float.class.getName(), - double.class.getName(), - char.class.getName(), - Boolean.class.getName(), - Long.class.getName(), - Short.class.getName(), - Integer.class.getName(), - Byte.class.getName(), - Float.class.getName(), - Double.class.getName(), - Character.class.getName(), - String.class.getName(), - java.util.Date.class.getName(), - Time.class.getName(), - Timestamp.class.getName(), - java.sql.Date.class.getName(), - BigDecimal.class.getName(), - BigInteger.class.getName(), - Locale.class.getName(), - Calendar.class.getName(), - GregorianCalendar.class.getName(), - java.util.Currency.class.getName(), - TimeZone.class.getName(), - Object.class.getName(), - Class.class.getName(), - byte[].class.getName(), - Byte[].class.getName(), - char[].class.getName(), - Character[].class.getName(), - Blob.class.getName(), - Clob.class.getName(), - Serializable.class.getName(), - URI.class.getName(), - URL.class.getName(), - UUID.class.getName(), - "org.bson.types.ObjectId", - "java.time.Instant", - "java.time.LocalDateTime", - "java.time.LocalDate", - "java.time.LocalTime", - "java.time.OffsetDateTime", - "java.time.OffsetTime", - "java.time.ZonedDateTime"))); + boolean.class.getName(), + long.class.getName(), + short.class.getName(), + int.class.getName(), + byte.class.getName(), + float.class.getName(), + double.class.getName(), + char.class.getName(), + Boolean.class.getName(), + Long.class.getName(), + Short.class.getName(), + Integer.class.getName(), + Byte.class.getName(), + Float.class.getName(), + Double.class.getName(), + Character.class.getName(), + String.class.getName(), + java.util.Date.class.getName(), + Time.class.getName(), + Timestamp.class.getName(), + java.sql.Date.class.getName(), + BigDecimal.class.getName(), + BigInteger.class.getName(), + Locale.class.getName(), + Calendar.class.getName(), + GregorianCalendar.class.getName(), + java.util.Currency.class.getName(), + TimeZone.class.getName(), + Object.class.getName(), + Class.class.getName(), + byte[].class.getName(), + Byte[].class.getName(), + char[].class.getName(), + Character[].class.getName(), + Blob.class.getName(), + Clob.class.getName(), + Serializable.class.getName(), + URI.class.getName(), + URL.class.getName(), + UUID.class.getName(), + "org.bson.types.ObjectId", + "java.time.Instant", + "java.time.LocalDateTime", + "java.time.LocalDate", + "java.time.LocalTime", + "java.time.OffsetDateTime", + "java.time.OffsetTime", + "java.time.ZonedDateTime"))); } private Map> typeConverterMap = new ConcurrentHashMap<>(); public void registerCustomType(CustomTypeMarshaller marshallerCustom) { Collection marshallers = typeConverterMap.get(marshallerCustom.getTargetType()); - if(marshallers == null) { + if (marshallers == null) { marshallers = new ConcurrentLinkedQueue<>(); typeConverterMap.put(marshallerCustom.getTargetType(), marshallers); } @@ -130,7 +152,9 @@ public void registerCustomType(CustomTypeMarshaller marshallerCustom) { } public boolean isSimpleType(Class propType) { - if (propType == null) return false; + if (propType == null) { + return false; + } if (propType.isEnum()) { // Check if prop (any enum) supports custom type marshaller. if (isCustomType(propType)) { @@ -159,6 +183,7 @@ public static boolean isSimpleType(final String typeName) { /** * Creates the mapped form of a PersistentProperty instance + * * @param mpp The PersistentProperty instance * @return The mapped form */ @@ -167,14 +192,15 @@ public static boolean isSimpleType(final String typeName) { /** * Creates an identifier property * - * @param owner The owner + * @param owner The owner * @param context The context - * @param pd The PropertyDescriptor + * @param pd The PropertyDescriptor * @return An Identity instance */ public Identity createIdentity(PersistentEntity owner, MappingContext context, PropertyDescriptor pd) { return new Identity(owner, context, pd) { PropertyMapping propertyMapping = createPropertyMapping(this, owner); + public PropertyMapping getMapping() { return propertyMapping; } @@ -184,14 +210,15 @@ public PropertyMapping getMapping() { /** * Creates the tenant identifier property * - * @param owner The owner + * @param owner The owner * @param context The context - * @param pd The PropertyDescriptor + * @param pd The PropertyDescriptor * @return An Identity instance */ public TenantId createTenantId(PersistentEntity owner, MappingContext context, PropertyDescriptor pd) { return new TenantId(owner, context, pd) { PropertyMapping propertyMapping = createDerivedPropertyMapping(this, owner); + public PropertyMapping getMapping() { return propertyMapping; } @@ -201,8 +228,8 @@ public PropertyMapping getMapping() { /** * Return whether the given property descriptor is the tenant id * - * @param entity The entity - * @param context The context + * @param entity The entity + * @param context The context * @param descriptor The descriptor * @return True if it is */ @@ -211,9 +238,9 @@ public PropertyMapping getMapping() { /** * Creates a custom prpoerty type * - * @param owner The owner + * @param owner The owner * @param context The context - * @param pd The PropertyDescriptor + * @param pd The PropertyDescriptor * @return A custom property type */ public Custom createCustom(PersistentEntity owner, MappingContext context, PropertyDescriptor pd) { @@ -228,6 +255,7 @@ public Custom createCustom(PersistentEntity owner, MappingContext context, Pr } return new Custom(owner, context, pd, customTypeMarshaller) { PropertyMapping propertyMapping = createPropertyMapping(this, owner); + public PropertyMapping getMapping() { return propertyMapping; } @@ -240,9 +268,9 @@ protected boolean allowArbitraryCustomTypes() { protected CustomTypeMarshaller findCustomType(MappingContext context, Class propertyType) { final Collection allMarshallers = typeConverterMap.get(propertyType); - if(allMarshallers != null) { + if (allMarshallers != null) { for (CustomTypeMarshaller marshaller : allMarshallers) { - if(marshaller.supports(context)) { + if (marshaller.supports(context)) { return marshaller; } } @@ -263,14 +291,15 @@ public PropertyDescriptor createPropertyDescriptor(Class declaringClass, MetaPro /** * Creates a simple property type used for mapping basic types such as String, long, integer etc. * - * @param owner The owner + * @param owner The owner * @param context The MappingContext - * @param pd The PropertyDescriptor + * @param pd The PropertyDescriptor * @return A Simple property type */ public Simple createSimple(PersistentEntity owner, MappingContext context, PropertyDescriptor pd) { return new Simple(owner, context, pd) { PropertyMapping propertyMapping = createPropertyMapping(this, owner); + public PropertyMapping getMapping() { return propertyMapping; } @@ -280,9 +309,11 @@ public PropertyMapping getMapping() { protected PropertyMapping createPropertyMapping(final PersistentProperty property, final PersistentEntity owner) { return new PropertyMapping() { private T mappedForm = createMappedForm(property); + public ClassMapping getClassMapping() { return owner.getMapping(); } + public T getMappedForm() { return mappedForm; } @@ -294,21 +325,22 @@ private PropertyMapping createDerivedPropertyMapping(final PersistentProperty mappedFormObject.setDerived(true); return new PropertyMapping() { private T mappedForm = mappedFormObject; + public ClassMapping getClassMapping() { return owner.getMapping(); } + public T getMappedForm() { return mappedForm; } }; } - /** * Creates a one-to-one association type used for mapping a one-to-one association between entities * - * @param entity The entity - * @param context The context + * @param entity The entity + * @param context The context * @param property The property * @return The ToOne instance */ @@ -330,14 +362,15 @@ public String toString() { /** * Creates a many-to-one association type used for a mapping a many-to-one association between entities * - * @param entity The entity - * @param context The context + * @param entity The entity + * @param context The context * @param property The property * @return The ToOne instance */ public ToOne createManyToOne(PersistentEntity entity, MappingContext context, PropertyDescriptor property) { return new ManyToOne(entity, context, property) { PropertyMapping propertyMapping = createPropertyMapping(this, owner); + public PropertyMapping getMapping() { return propertyMapping; } @@ -354,14 +387,15 @@ public String toString() { /** * Creates a {@link OneToMany} type used to model a one-to-many association between entities * - * @param entity The entity - * @param context The context + * @param entity The entity + * @param context The context * @param property The property * @return The {@link OneToMany} instance */ public OneToMany createOneToMany(PersistentEntity entity, MappingContext context, PropertyDescriptor property) { return new OneToMany(entity, context, property) { PropertyMapping propertyMapping = createPropertyMapping(this, owner); + public PropertyMapping getMapping() { return propertyMapping; } @@ -377,17 +411,19 @@ public String toString() { /** * Creates a {@link ManyToMany} type used to model a many-to-many association between entities * - * @param entity The entity - * @param context The context + * @param entity The entity + * @param context The context * @param property The property * @return The {@link ManyToMany} instance */ public ManyToMany createManyToMany(PersistentEntity entity, MappingContext context, PropertyDescriptor property) { return new ManyToMany(entity, context, property) { PropertyMapping propertyMapping = createPropertyMapping(this, owner); + public PropertyMapping getMapping() { return propertyMapping; } + @Override public String toString() { return associationtoString("many-to-many: ", this); @@ -398,18 +434,20 @@ public String toString() { /** * Creates an {@link Embedded} type used to model an embedded association (composition) * - * @param entity The entity - * @param context The context + * @param entity The entity + * @param context The context * @param property The property * @return The {@link Embedded} instance */ public Embedded createEmbedded(PersistentEntity entity, - MappingContext context, PropertyDescriptor property) { + MappingContext context, PropertyDescriptor property) { return new Embedded(entity, context, property) { PropertyMapping propertyMapping = createPropertyMapping(this, owner); + public PropertyMapping getMapping() { return propertyMapping; } + @Override public String toString() { return associationtoString("embedded: ", this); @@ -420,18 +458,20 @@ public String toString() { /** * Creates an {@link EmbeddedCollection} type used to model an embedded collection association (composition). * - * @param entity The entity - * @param context The context + * @param entity The entity + * @param context The context * @param property The property * @return The {@link Embedded} instance */ public EmbeddedCollection createEmbeddedCollection(PersistentEntity entity, - MappingContext context, PropertyDescriptor property) { + MappingContext context, PropertyDescriptor property) { return new EmbeddedCollection(entity, context, property) { PropertyMapping propertyMapping = createPropertyMapping(this, owner); + public PropertyMapping getMapping() { return propertyMapping; } + @Override public String toString() { return associationtoString("embedded: ", this); @@ -442,13 +482,13 @@ public String toString() { /** * Creates a {@link Basic} collection type * - * @param entity The entity - * @param context The context + * @param entity The entity + * @param context The context * @param property The property * @return The Basic collection type */ public Basic createBasicCollection(PersistentEntity entity, - MappingContext context, PropertyDescriptor property, Class collectionType) { + MappingContext context, PropertyDescriptor property, Class collectionType) { Basic basic = new Basic(entity, context, property) { PropertyMapping propertyMapping = createPropertyMapping(this, owner); @@ -461,16 +501,16 @@ public PropertyMapping getMapping() { // This is to allow using custom marshaller for list of enum. // If no custom type marshaller for current enum. - if(collectionType != null && collectionType.isEnum()) { + if (collectionType != null && collectionType.isEnum()) { // First look custom marshaller for related type of collection. customTypeMarshaller = findCustomType(context, collectionType); - if(customTypeMarshaller == null) { + if (customTypeMarshaller == null) { // If null, look for enum class itself. customTypeMarshaller = findCustomType(context, Enum.class); } } - if(customTypeMarshaller != null) { + if (customTypeMarshaller != null) { basic.setCustomTypeMarshaller(customTypeMarshaller); } @@ -482,10 +522,10 @@ public Basic createBasicCollection(PersistentEntity entity, MappingContext conte } public boolean isCustomType(Class propertyType) { - if(typeConverterMap.containsKey(propertyType)) { + if (typeConverterMap.containsKey(propertyType)) { return true; } - if(propertyType.isEnum()) { + if (propertyType.isEnum()) { // Check if enum itself supports custom type. return typeConverterMap.containsKey(Enum.class); } @@ -502,11 +542,10 @@ public IdentityMapping createDefaultIdentityMapping(final ClassMapping classMapp public String[] getIdentifierName() { PersistentProperty identity = classMapping.getEntity().getIdentity(); String propertyName = identity != null ? identity.getMapping().getMappedForm().getName() : null; - if(propertyName != null) { - return new String[] { propertyName }; - } - else { - return new String[] { IDENTITY_PROPERTY }; + if (propertyName != null) { + return new String[]{propertyName}; + } else { + return new String[]{IDENTITY_PROPERTY}; } } @@ -531,11 +570,10 @@ protected IdentityMapping createDefaultIdentityMapping(final ClassMapping classM return new IdentityMapping() { public String[] getIdentifierName() { - if(targetName != null) { - return new String[] { targetName }; - } - else { - return new String[] { IDENTITY_PROPERTY }; + if (targetName != null) { + return new String[]{targetName}; + } else { + return new String[]{IDENTITY_PROPERTY}; } } @@ -554,10 +592,8 @@ public Property getMappedForm() { }; } - public static String associationtoString(String desc, Association a) { return desc + a.getOwner().getName() + "-> " + a.getName() + " ->" + a.getAssociatedEntity().getName(); } - } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentEntity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentEntity.java index 293142ce884..f795d3a48cf 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentEntity.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentEntity.java @@ -18,14 +18,14 @@ */ package org.grails.datastore.mapping.model; -import java.util.List; - import org.grails.datastore.mapping.model.lifecycle.Initializable; import org.grails.datastore.mapping.model.types.Association; import org.grails.datastore.mapping.model.types.Embedded; import org.grails.datastore.mapping.model.types.TenantId; import org.grails.datastore.mapping.reflect.EntityReflector; +import java.util.List; + /** * Represents a persistent entity. * @@ -68,6 +68,7 @@ public interface PersistentEntity extends Initializable { /** * Whether this PersistentEntity is mapped using a different store. Used for cross store persistence. + * * @param external true if this entity is externally mapped */ void setExternal(boolean external); @@ -95,6 +96,7 @@ public interface PersistentEntity extends Initializable { /** * A list of properties to be persisted + * * @return A list of PersistentProperty instances */ List getPersistentProperties(); @@ -105,7 +107,7 @@ public interface PersistentEntity extends Initializable { * * @return A list of associations */ - List getAssociations(); + List getAssociations(); /** * A list of embedded associations for this entity. This is typically @@ -113,7 +115,7 @@ public interface PersistentEntity extends Initializable { * * @return A list of associations */ - List getEmbedded(); + List getEmbedded(); /** * Obtains a PersistentProperty instance by name @@ -146,12 +148,14 @@ public interface PersistentEntity extends Initializable { /** * Constructs a new instance + * * @return The new instnace */ Object newInstance(); /** * A list of property names that a persistent + * * @return A List of strings */ List getPersistentPropertyNames(); @@ -172,36 +176,42 @@ public interface PersistentEntity extends Initializable { /** * Returns the parent entity of this entity + * * @return The ParentEntity instance */ PersistentEntity getParentEntity(); /** * Obtains the root entity of an inheritance hierarchy + * * @return The root entity */ PersistentEntity getRootEntity(); /** * Whether this entity is a root entity + * * @return True if it is a root entity */ boolean isRoot(); /** * The discriminator used when persisting subclasses of an inheritance hierarchy + * * @return The discriminator */ String getDiscriminator(); /** * Obtains the MappingContext where this PersistentEntity is defined + * * @return The MappingContext instance */ MappingContext getMappingContext(); /** * Checks whether an entity has a bean property of the given name and type + * * @param name The name * @param type The type * @return True if it does @@ -210,6 +220,7 @@ public interface PersistentEntity extends Initializable { /** * True if the given property is the identifier + * * @param propertyName the property name * @return True if it is the identifier */ @@ -222,6 +233,7 @@ public interface PersistentEntity extends Initializable { /** * Add a class to the owners list of this PersistentEntity + * * @param type The class to add * @return True if the operation was successful */ diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentProperty.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentProperty.java index 057291808c2..85b4678c3bf 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentProperty.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PersistentProperty.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.model; import org.grails.datastore.mapping.config.Property; @@ -30,28 +29,31 @@ public interface PersistentProperty { /** * The name of the property + * * @return The property name */ String getName(); /** * The name with the first letter in upper case as per Java bean conventions + * * @return The capitilized name */ String getCapitilizedName(); /** * The type of the property + * * @return The property type */ Class getType(); /** - * Specifies the mapping between this property and an external form - * such as a column, key/value pair etc. - * - * @return The PropertyMapping instance - */ + * Specifies the mapping between this property and an external form + * such as a column, key/value pair etc. + * + * @return The PropertyMapping instance + */ PropertyMapping getMapping(); /** diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PropertyMapping.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PropertyMapping.java index 9e2da31194b..6ac5cd95cf5 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PropertyMapping.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/PropertyMapping.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.model; import org.grails.datastore.mapping.config.Property; @@ -39,6 +38,7 @@ public interface PropertyMapping { /** * Returns the mapped form of the property such as a Column, a Key/Value pair, attribute etc. + * * @return The mapped representation */ T getMappedForm(); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ValueGenerator.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ValueGenerator.java index 560e4b51287..7fc9057077f 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ValueGenerator.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/ValueGenerator.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.model; /** diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormMappingConfigurationStrategy.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormMappingConfigurationStrategy.java index 50301c7ea4c..9485c8c7ddd 100755 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormMappingConfigurationStrategy.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormMappingConfigurationStrategy.java @@ -19,6 +19,26 @@ package org.grails.datastore.mapping.model.config; import groovy.lang.Closure; +import groovy.lang.MetaProperty; +import jakarta.persistence.Entity; +import org.grails.datastore.mapping.engine.internal.MappingUtils; +import org.grails.datastore.mapping.model.ClassMapping; +import org.grails.datastore.mapping.model.IdentityMapping; +import org.grails.datastore.mapping.model.IllegalMappingException; +import org.grails.datastore.mapping.model.MappingConfigurationStrategy; +import org.grails.datastore.mapping.model.MappingContext; +import org.grails.datastore.mapping.model.MappingFactory; +import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.model.PersistentProperty; +import org.grails.datastore.mapping.model.types.Association; +import org.grails.datastore.mapping.model.types.Basic; +import org.grails.datastore.mapping.model.types.EmbeddedCollection; +import org.grails.datastore.mapping.model.types.ManyToMany; +import org.grails.datastore.mapping.model.types.OneToOne; +import org.grails.datastore.mapping.model.types.ToOne; +import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; +import org.grails.datastore.mapping.reflect.ReflectionUtils; +import org.springframework.util.StringUtils; import java.beans.Introspector; import java.beans.PropertyDescriptor; @@ -35,24 +55,14 @@ import java.util.Map; import java.util.Set; -import jakarta.persistence.Entity; - -import groovy.lang.MetaProperty; -import org.grails.datastore.mapping.engine.internal.MappingUtils; -import org.grails.datastore.mapping.model.ClassMapping; -import org.grails.datastore.mapping.model.IdentityMapping; -import org.grails.datastore.mapping.model.IllegalMappingException; -import org.grails.datastore.mapping.model.MappingConfigurationStrategy; -import org.grails.datastore.mapping.model.MappingContext; -import org.grails.datastore.mapping.model.MappingFactory; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.model.types.*; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.grails.datastore.mapping.reflect.ReflectionUtils; -import org.springframework.util.StringUtils; - -import static org.grails.datastore.mapping.model.config.GormProperties.*; +import static org.grails.datastore.mapping.model.config.GormProperties.BELONGS_TO; +import static org.grails.datastore.mapping.model.config.GormProperties.EMBEDDED; +import static org.grails.datastore.mapping.model.config.GormProperties.HAS_MANY; +import static org.grails.datastore.mapping.model.config.GormProperties.HAS_ONE; +import static org.grails.datastore.mapping.model.config.GormProperties.IDENTITY; +import static org.grails.datastore.mapping.model.config.GormProperties.MAPPED_BY; +import static org.grails.datastore.mapping.model.config.GormProperties.TRANSIENT; +import static org.grails.datastore.mapping.model.config.GormProperties.VERSION; /** *

    This implementation of the MappingConfigurationStrategy interface @@ -70,7 +80,7 @@ * class Book { * String title * static belongsTo = [author:Author] - } + * } * * * @@ -80,11 +90,12 @@ */ @SuppressWarnings({"rawtypes", "unchecked"}) public class GormMappingConfigurationStrategy implements MappingConfigurationStrategy { + + public static final String MAPPED_BY_NONE = "none"; private static final String IDENTITY_PROPERTY = IDENTITY; private static final String VERSION_PROPERTY = VERSION; - public static final String MAPPED_BY_NONE = "none"; - protected MappingFactory propertyFactory; private static final Set EXCLUDED_PROPERTIES = ClassPropertyFetcher.EXCLUDED_PROPERTIES; + protected MappingFactory propertyFactory; private boolean canExpandMappingContext = true; public GormMappingConfigurationStrategy(MappingFactory propertyFactory) { @@ -98,30 +109,37 @@ public void setCanExpandMappingContext(boolean canExpandMappingContext) { this.canExpandMappingContext = canExpandMappingContext; } - /** * Tests whether an class is a persistent entity - * + *

    * Based on the same method in Grails core within the DomainClassArtefactHandler class - * @param clazz The java class * + * @param clazz The java class * @return True if it is a persistent entity */ public boolean isPersistentEntity(Class clazz) { // its not a closure - if (clazz == null) return false; + if (clazz == null) { + return false; + } if (Closure.class.isAssignableFrom(clazz)) { return false; } - if (Enum.class.isAssignableFrom(clazz)) return false; + if (Enum.class.isAssignableFrom(clazz)) { + return false; + } if (clazz.isAnnotationPresent(Entity.class)) { return true; } // this is done so we don't need a statically typed reference to the Grails annotation for (Annotation annotation : clazz.getAnnotations()) { String annName = annotation.annotationType().getName(); - if (annName.equals("grails.persistence.Entity")) return true; - if (annName.equals("grails.gorm.annotation.Entity")) return true; + if (annName.equals("grails.persistence.Entity")) { + return true; + } + if (annName.equals("grails.gorm.annotation.Entity")) { + return true; + } } return false; } @@ -157,7 +175,7 @@ public List getPersistentProperties(PersistentEntity entity, for (MetaProperty metaProperty : cpf.getMetaProperties()) { PropertyDescriptor propertyDescriptor = propertyFactory.createPropertyDescriptor(entity.getJavaClass(), metaProperty); - if(propertyDescriptor == null) { + if (propertyDescriptor == null) { continue; } Class propertyType = metaProperty.getType(); @@ -182,7 +200,9 @@ public List getPersistentProperties(PersistentEntity entity, if (java.lang.reflect.Modifier.isTransient(readMethod.getModifiers())) { continue; } - if (isExcludedProperty(propertyName, classMapping, transients, includeIdentifiers)) continue; + if (isExcludedProperty(propertyName, classMapping, transients, includeIdentifiers)) { + continue; + } Class currentPropType = propertyType; // establish if the property is a one-to-many // if it is a Set and there are relationships defined @@ -193,36 +213,30 @@ public List getPersistentProperties(PersistentEntity entity, if (association != null) { persistentProperties.add(association); } - } - else { + } else { final ToOne association = establishDomainClassRelationship(entity, propertyDescriptor, context, hasOneMap, true); if (association != null) { persistentProperties.add(association); } } - } - else if (isCollectionType(currentPropType)) { + } else if (isCollectionType(currentPropType)) { final Association association = establishRelationshipForCollection(propertyDescriptor, entity, context, hasManyMap, mappedByMap, false); if (association != null) { configureOwningSide(association); persistentProperties.add(association); } - } - // otherwise if the type is a domain class establish relationship - else if (isPersistentEntity(currentPropType)) { + } else if (isPersistentEntity(currentPropType)) { + // otherwise if the type is a domain class establish relationship final ToOne association = establishDomainClassRelationship(entity, propertyDescriptor, context, hasOneMap, false); if (association != null) { configureOwningSide(association); persistentProperties.add(association); } - } - else if(propertyFactory.isTenantId(entity, context, propertyDescriptor)) { + } else if (propertyFactory.isTenantId(entity, context, propertyDescriptor)) { persistentProperties.add(propertyFactory.createTenantId(entity, context, propertyDescriptor)); - } - else if (propertyFactory.isSimpleType(propertyType)) { + } else if (propertyFactory.isSimpleType(propertyType)) { persistentProperties.add(propertyFactory.createSimple(entity, context, propertyDescriptor)); - } - else if (supportsCustomType(propertyType)) { + } else if (supportsCustomType(propertyType)) { persistentProperties.add(propertyFactory.createCustom(entity, context, propertyDescriptor)); } } @@ -264,24 +278,22 @@ private Map getMapStaticProperty(ClassPropertyFetcher cpf, String property) { protected void configureOwningSide(Association association) { PersistentEntity associatedEntity = association.getAssociatedEntity(); - if(associatedEntity == null) { + if (associatedEntity == null) { association.setOwningSide(true); - } - else { + } else { if (association.isBidirectional()) { if (associatedEntity.isOwningEntity(association.getOwner())) { association.setOwningSide(true); } - } - else { + } else { if (association instanceof OneToOne) { - if (associatedEntity.isOwningEntity(association.getOwner())) + if (associatedEntity.isOwningEntity(association.getOwner())) { association.setOwningSide(true); + } } else if (!(association instanceof Basic)) { if (associatedEntity.isOwningEntity(association.getOwner())) { association.setOwningSide(true); - } - else { + } else { association.setOwningSide(false); } } @@ -322,16 +334,14 @@ protected Association establishRelationshipForCollection(PropertyDescriptor prop if (embedded) { if (propertyFactory.isSimpleType(relatedClassType)) { return propertyFactory.createBasicCollection(entity, context, property, relatedClassType); - } - else if (!isPersistentEntity(relatedClassType)) { + } else if (!isPersistentEntity(relatedClassType)) { // no point in setting up bidirectional link here, since target isn't an entity. EmbeddedCollection association = propertyFactory.createEmbeddedCollection(entity, context, property); PersistentEntity associatedEntity = getOrCreateEmbeddedEntity(entity, context, relatedClassType); association.setAssociatedEntity(associatedEntity); return association; } - } - else if (!isPersistentEntity(relatedClassType) && !relatedClassType.equals(entity.getJavaClass())) { + } else if (!isPersistentEntity(relatedClassType) && !relatedClassType.equals(entity.getJavaClass())) { // otherwise set it to not persistent as you can't persist // relationships to non-domain classes return propertyFactory.createBasicCollection(entity, context, property, relatedClassType); @@ -353,7 +363,7 @@ else if (!isPersistentEntity(relatedClassType) && !relatedClassType.equals(entit ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity.getJavaClass()); // First check whether there is an explicit relationship // mapping for this property (as provided by "mappedBy"). - String mappingProperty = (String)mappedByMap.get(property.getName()); + String mappingProperty = (String) mappedByMap.get(property.getName()); if (StringUtils.hasText(mappingProperty)) { // First find the specified property on the related class, if it exists. PropertyDescriptor pd = findProperty(getPropertiesAssignableFromType(entity.getJavaClass(), referencedCpf), @@ -373,15 +383,13 @@ else if (!isPersistentEntity(relatedClassType) && !relatedClassType.equals(entit throw new IllegalMappingException("Non-existent mapping property [" + mappingProperty + "] specified for property [" + property.getName() + "] in class [" + entity.getJavaClass().getName() + "]"); - } - else if(pd != null) { + } else if (pd != null) { // Tie the properties together. relatedClassPropertyType = pd.getPropertyType(); referencedPropertyName = pd.getName(); relatedClassPropertyName = referencedPropertyName; } - } - else { + } else { if (!forceUnidirectional(property, mappedByMap)) { // if the related type has a relationships map it may be a many-to-many @@ -392,18 +400,20 @@ else if(pd != null) { for (Object o : relatedClassRelationships.keySet()) { String currentKey = (String) o; String mappedByProperty = (String) relatedClassMappedBy.get(currentKey); - if (mappedByProperty != null && !mappedByProperty.equals(property.getName())) continue; - Class currentClass = (Class)relatedClassRelationships.get(currentKey); + if (mappedByProperty != null && !mappedByProperty.equals(property.getName())) { + continue; + } + Class currentClass = (Class) relatedClassRelationships.get(currentKey); if (currentClass.isAssignableFrom(entity.getJavaClass())) { relatedClassPropertyName = currentKey; break; } } - // Map classRelationships = cpf.getPropertyValue(HAS_MANY, Map.class); - // - // if (isRelationshipToMany(entity, relatedClassType, classRelationships)) { - // String relatedClassPropertyName = findManyRelatedClassPropertyName( - // property.getName(), referencedCpf, classRelationships, relatedClassType); + // Map classRelationships = cpf.getPropertyValue(HAS_MANY, Map.class); + // + // if (isRelationshipToMany(entity, relatedClassType, classRelationships)) { + // String relatedClassPropertyName = findManyRelatedClassPropertyName( + // property.getName(), referencedCpf, classRelationships, relatedClassType); // if there is one defined get the type if (relatedClassPropertyName != null) { @@ -418,24 +428,23 @@ else if(pd != null) { Map relatedMappedBy = referencedCpf.getStaticPropertyValue(GormProperties.MAPPED_BY, Map.class); List referencedTransients = referencedCpf.getStaticPropertyValue(GormProperties.TRANSIENT, List.class); List referencedEmbedded = referencedCpf.getStaticPropertyValue(GormProperties.EMBEDDED, List.class); - if(referencedTransients == null) { + if (referencedTransients == null) { referencedTransients = Collections.emptyList(); } - if(referencedEmbedded == null) { + if (referencedEmbedded == null) { referencedEmbedded = Collections.emptyList(); } - if(relatedMappedBy == null) { + if (relatedMappedBy == null) { relatedMappedBy = Collections.emptyMap(); } if (descriptors.size() == 1) { final PropertyDescriptor pd = descriptors.get(0); - if(!referencedTransients.contains(pd.getName()) && !referencedEmbedded.contains(pd.getName()) && isNotMappedToDifferentProperty(property, pd.getName(), relatedMappedBy)) { + if (!referencedTransients.contains(pd.getName()) && !referencedEmbedded.contains(pd.getName()) && isNotMappedToDifferentProperty(property, pd.getName(), relatedMappedBy)) { relatedClassPropertyType = pd.getPropertyType(); referencedPropertyName = pd.getName(); } - } - else if (descriptors.size() > 1) { + } else if (descriptors.size() > 1) { // try now to use the class name by convention String classPropertyName = entity.getDecapitalizedName(); PropertyDescriptor pd = findProperty(descriptors, classPropertyName); @@ -447,7 +456,7 @@ else if (descriptors.size() > 1) { } if (pd != null) { - if(isNotMappedToDifferentProperty(property, pd.getName(), relatedMappedBy)) { + if (isNotMappedToDifferentProperty(property, pd.getName(), relatedMappedBy)) { relatedClassPropertyType = pd.getPropertyType(); referencedPropertyName = pd.getName(); } @@ -464,19 +473,16 @@ else if (descriptors.size() > 1) { boolean many = false; if (embedded) { association = propertyFactory.createEmbeddedCollection(entity, context, property); - } - else if (relatedClassPropertyType == null || isInverseSideEntity) { + } else if (relatedClassPropertyType == null || isInverseSideEntity) { // uni or bi-directional one-to-many association = propertyFactory.createOneToMany(entity, context, property); - } - else if (Collection.class.isAssignableFrom(relatedClassPropertyType) || - Map.class.isAssignableFrom(relatedClassPropertyType)) { + } else if (Collection.class.isAssignableFrom(relatedClassPropertyType) || + Map.class.isAssignableFrom(relatedClassPropertyType)) { // many-to-many association = propertyFactory.createManyToMany(entity, context, property); - ((ManyToMany)association).setInversePropertyName(relatedClassPropertyName); + ((ManyToMany) association).setInversePropertyName(relatedClassPropertyName); many = true; - } - else { + } else { // uni-directional one-to-many association = propertyFactory.createOneToMany(entity, context, property); @@ -512,14 +518,16 @@ private List getPropertiesAssignableFromType(Class type, Cla } private String findManyRelatedClassPropertyName(String propertyName, - ClassPropertyFetcher cpf, Map classRelationships, Class classType) { + ClassPropertyFetcher cpf, Map classRelationships, Class classType) { Map mappedBy = getMapStaticProperty(cpf, MAPPED_BY); // retrieve the relationship property for (Object o : classRelationships.keySet()) { String currentKey = (String) o; - String mappedByProperty = (String)mappedBy.get(currentKey); - if (mappedByProperty != null && !mappedByProperty.equals(propertyName)) continue; - Class currentClass = (Class)classRelationships.get(currentKey); + String mappedByProperty = (String) mappedBy.get(currentKey); + if (mappedByProperty != null && !mappedByProperty.equals(propertyName)) { + continue; + } + Class currentClass = (Class) classRelationships.get(currentKey); if (currentClass.isAssignableFrom(classType)) { return currentKey; } @@ -530,21 +538,21 @@ private String findManyRelatedClassPropertyName(String propertyName, /** * Find out if the relationship is a 1-to-many or many-to-many. * - * @param relatedClassType The related type + * @param relatedClassType The related type * @param relatedClassRelationships The related types relationships * @return true if the relationship is a many-to-many */ private boolean isRelationshipToMany(PersistentEntity entity, - Class relatedClassType, Map relatedClassRelationships) { + Class relatedClassType, Map relatedClassRelationships) { return relatedClassRelationships != null && - !relatedClassRelationships.isEmpty() && - !relatedClassType.equals(entity.getJavaClass()); + !relatedClassRelationships.isEmpty() && + !relatedClassType.equals(entity.getJavaClass()); } /** * Finds a property type is an array of descriptors for the given property name * - * @param descriptors The descriptors + * @param descriptors The descriptors * @param propertyName The property name * @return The Class or null */ @@ -561,7 +569,7 @@ private PropertyDescriptor findProperty(List descriptors, St * Establish relationship with related domain class * * @param entity - * @param property Establishes a relationship between this class and the domain class property + * @param property Establishes a relationship between this class and the domain class property * @param context * @param hasOneMap * @param embedded @@ -597,40 +605,38 @@ private ToOne establishDomainClassRelationship(PersistentEntity entity, Property relatedClassPropertyName = findOneToManyThatMatchesType(entity, property, relatedClassRelationships, mappedBy, relatedCpf); Object mappedByValue = relatedClassPropertyName != null ? mappedBy.get(relatedClassPropertyName) : null; - if(mappedByValue != null && property.getName().equals(mappedByValue)) { + if (mappedByValue != null && property.getName().equals(mappedByValue)) { relatedClassPropertyType = relatedCpf.getPropertyType(relatedClassPropertyName, true); - } - else { + } else { // if there is only one property on many-to-one side of the relationship then // try to establish if it is bidirectional - if (descriptors.length == 1 && isNotMappedToDifferentProperty(property,relatedClassPropertyName, mappedBy)) { + if (descriptors.length == 1 && isNotMappedToDifferentProperty(property, relatedClassPropertyName, mappedBy)) { if (StringUtils.hasText(relatedClassPropertyName)) { // get the type of the property PropertyDescriptor potentialProperty = relatedCpf.getPropertyDescriptor(relatedClassPropertyName); // ensure circular links are not possible between one-to-one associations - if(!potentialProperty.equals(property)) { + if (!potentialProperty.equals(property)) { relatedClassPropertyType = potentialProperty.getPropertyType(); } } - } - // if there is more than one property on the many-to-one side then we need to either - // find out if there is a mappedBy property or whether a convention is used to decide - // on the mapping property - else if (descriptors.length > 1) { + } else if (descriptors.length > 1) { + // if there is more than one property on the many-to-one side then we need to either + // find out if there is a mappedBy property or whether a convention is used to decide + // on the mapping property if (mappedBy.containsValue(property.getName())) { for (Object o : mappedBy.keySet()) { String mappedByPropertyName = (String) o; if (property.getName().equals(mappedBy.get(mappedByPropertyName))) { Class mappedByRelatedType = (Class) relatedClassRelationships.get(mappedByPropertyName); - if (mappedByRelatedType != null && propType.isAssignableFrom(mappedByRelatedType)) + if (mappedByRelatedType != null && propType.isAssignableFrom(mappedByRelatedType)) { relatedClassPropertyType = relatedCpf.getPropertyType(mappedByPropertyName); + } } } - } - else if(relatedClassPropertyName != null) { + } else if (relatedClassPropertyName != null) { // in this case no mappedBy is found so check if the the property name is the same as the class name (eg. 'Foo' would be come 'foo') // using this convention we consider this the default property to map to String classNameAsProperty = Introspector.decapitalize(propType.getSimpleName()); @@ -650,16 +656,15 @@ else if(relatedClassPropertyName != null) { if (descriptors.size() == 1) { PropertyDescriptor first = descriptors.get(0); // ensure circular links are not possible between one-to-one associations - if(!first.equals(property)) { + if (!first.equals(property)) { String otherSidePropertyName = first.getName(); - if(mappedBy.containsKey(otherSidePropertyName)) { + if (mappedBy.containsKey(otherSidePropertyName)) { Object mapping = mappedBy.get(otherSidePropertyName); - if(mapping != null && mapping.equals(property.getName())) { + if (mapping != null && mapping.equals(property.getName())) { relatedClassPropertyType = first.getPropertyType(); relatedClassPropertyName = otherSidePropertyName; } - } - else { + } else { relatedClassPropertyType = first.getPropertyType(); relatedClassPropertyName = otherSidePropertyName; } @@ -679,9 +684,8 @@ else if(relatedClassPropertyName != null) { if (hasOneMap.containsKey(property.getName()) && !embedded) { association.setForeignKeyInChild(true); } - } - // bi-directional many-to-one - else if (!embedded && Collection.class.isAssignableFrom(relatedClassPropertyType)||Map.class.isAssignableFrom(relatedClassPropertyType)) { + } else if (!embedded && Collection.class.isAssignableFrom(relatedClassPropertyType) || Map.class.isAssignableFrom(relatedClassPropertyType)) { + // bi-directional many-to-one association = propertyFactory.createManyToOne(entity, context, property); } @@ -699,36 +703,35 @@ else if (!embedded && Collection.class.isAssignableFrom(relatedClassPropertyType /** * check if mappedBy is set explicitly to null for the given property. + * * @param property * @param mappedBy * @return true if mappedBy is set explicitly to null */ private boolean forceUnidirectional(PropertyDescriptor property, Map mappedBy) { - return mappedBy.containsKey(property.getName()) && (mappedBy.get(property.getName())==null); + return mappedBy.containsKey(property.getName()) && (mappedBy.get(property.getName()) == null); } /** * Tries to obtain or create an associated entity. Note that if #canExpandMappingContext is set to false then this method may return null * - * @param entity The main entity - * @param context The context + * @param entity The main entity + * @param context The context * @param propType The associated property type * @return The associated entity or null */ protected PersistentEntity getOrCreateAssociatedEntity(PersistentEntity entity, MappingContext context, Class propType) { PersistentEntity associatedEntity = context.getPersistentEntity(propType.getName()); if (associatedEntity == null) { - if(canExpandMappingContext) { + if (canExpandMappingContext) { if (entity.isExternal()) { associatedEntity = context.addExternalPersistentEntity(propType); - } - else { + } else { associatedEntity = context.addPersistentEntity(propType); } } - } - else { - if(!associatedEntity.isInitialized()) { + } else { + if (!associatedEntity.isInitialized()) { associatedEntity.initialize(); } } @@ -738,9 +741,9 @@ protected PersistentEntity getOrCreateAssociatedEntity(PersistentEntity entity, /** * Tries to obtain or create an embedded entity. Note that if #canExpandMappingContext is set to false then this method may return null * - * @param entity The main entity + * @param entity The main entity * @param context The context - * @param type The associated property type + * @param type The associated property type * @return The associated entity or null */ protected PersistentEntity getOrCreateEmbeddedEntity(PersistentEntity entity, MappingContext context, Class type) { @@ -748,24 +751,21 @@ protected PersistentEntity getOrCreateEmbeddedEntity(PersistentEntity entity, Ma if (associatedEntity == null) { // If this is a persistent entity, add and initialize, otherwise // assume it's embedded - if( isPersistentEntity(type) ) { + if (isPersistentEntity(type)) { if (entity.isExternal()) { associatedEntity = context.addExternalPersistentEntity(type); associatedEntity.initialize(); - } - else { + } else { associatedEntity = context.addPersistentEntity(type); associatedEntity.initialize(); } - } - else { + } else { PersistentEntity embeddedEntity = context.createEmbeddedEntity(type); embeddedEntity.initialize(); return embeddedEntity; } - } - else { - if(!associatedEntity.isInitialized()) { + } else { + if (!associatedEntity.isInitialized()) { associatedEntity.initialize(); } } @@ -773,23 +773,27 @@ protected PersistentEntity getOrCreateEmbeddedEntity(PersistentEntity entity, Ma } private boolean isNotMappedToDifferentProperty(PropertyDescriptor property, - String relatedClassPropertyName, Map mappedBy) { + String relatedClassPropertyName, Map mappedBy) { - String mappedByForRelation = (String)mappedBy.get(relatedClassPropertyName); - if (mappedByForRelation == null) return true; - if (!property.getName().equals(mappedByForRelation)) return false; + String mappedByForRelation = (String) mappedBy.get(relatedClassPropertyName); + if (mappedByForRelation == null) { + return true; + } + if (!property.getName().equals(mappedByForRelation)) { + return false; + } return true; } private String findOneToManyThatMatchesType(PersistentEntity entity, PropertyDescriptor pd, Map relatedClassRelationships, Map mappedBy, ClassPropertyFetcher relatedCpf) { for (Object o : relatedClassRelationships.keySet()) { String currentKey = (String) o; - Class currentClass = (Class)relatedClassRelationships.get(currentKey); + Class currentClass = (Class) relatedClassRelationships.get(currentKey); Object mappedByValue = mappedBy.get(currentKey); if (currentClass.isAssignableFrom(entity.getJavaClass())) { - if(mappedByValue == null || pd.getName().equals(mappedByValue)) { + if (mappedByValue == null || pd.getName().equals(mappedByValue)) { PropertyDescriptor candidate = relatedCpf.getPropertyDescriptor(currentKey); - if(candidate != null && !candidate.equals(pd)) { + if (candidate != null && !candidate.equals(pd)) { return currentKey; } } @@ -806,7 +810,7 @@ protected boolean isCollectionType(Class type) { protected boolean isExcludedProperty(String propertyName, ClassMapping classMapping, Collection transients, boolean includeIdentifiers) { IdentityMapping id = classMapping != null ? classMapping.getIdentifier() : null; String[] identifierName = id != null && !includeIdentifiers ? id.getIdentifierName() : null; - return isExcludeId(propertyName, id, identifierName,includeIdentifiers) || + return isExcludeId(propertyName, id, identifierName, includeIdentifiers) || EXCLUDED_PROPERTIES.contains(propertyName) || transients.contains(propertyName); } @@ -817,13 +821,16 @@ private boolean isExcludeId(String propertyName, IdentityMapping id, String[] id private boolean isIdentifierProperty(String propertyName, String[] identifierName) { for (String n : identifierName) { - if(propertyName.equals(n)) return true; + if (propertyName.equals(n)) { + return true; + } } return false; } /** * Retrieves the association map + * * @param cpf The ClassPropertyFetcher instance * @return The association map */ @@ -833,6 +840,7 @@ public Map getAssociationMap(ClassPropertyFetcher cpf) { /** * Retrieves the association map + * * @param cpf The ClassPropertyFetcher instance * @return The association map */ @@ -873,16 +881,14 @@ public PersistentProperty[] getCompositeIdentity(Class javaClass, MappingContext String name = names[i]; final PersistentProperty p = entity.getPropertyByName(name); - if(p != null) { + if (p != null) { identifiers[i] = p; - } - else { + } else { final PropertyDescriptor pd = cpf.getPropertyDescriptor(name); if (pd != null) { identifiers[i] = propertyFactory.createIdentity(entity, context, pd); - } - else { - throw new IllegalMappingException("Invalid composite id mapping. Could not resolve property ["+name+"] for entity ["+javaClass.getName()+"]"); + } else { + throw new IllegalMappingException("Invalid composite id mapping. Could not resolve property [" + name + "] for entity [" + javaClass.getName() + "]"); } } @@ -908,7 +914,7 @@ public PersistentProperty getIdentity(Class javaClass, MappingContext context) { } if (!entity.isExternal() && isAbstract(entity)) { throw new IllegalMappingException("Mapped identifier [" + names[0] + "] for class [" + - javaClass.getName() + "] is not a valid property"); + javaClass.getName() + "] is not a valid property"); } return null; } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormProperties.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormProperties.java index 7f85eaa1dec..e60a6267f0b 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormProperties.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/GormProperties.java @@ -25,6 +25,7 @@ * @since 1.0 */ public interface GormProperties { + String IDENTITY = "id"; String PROPERTIES = "properties"; String TENANT_IDENTITY = "tenantId"; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/JpaMappingConfigurationStrategy.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/JpaMappingConfigurationStrategy.java index 631839cc648..dac14b37ee7 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/JpaMappingConfigurationStrategy.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/config/JpaMappingConfigurationStrategy.java @@ -16,25 +16,42 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.model.config; import groovy.lang.MetaProperty; +import jakarta.persistence.Embedded; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Transient; import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.engine.internal.MappingUtils; -import org.grails.datastore.mapping.model.*; +import org.grails.datastore.mapping.model.ClassMapping; +import org.grails.datastore.mapping.model.IdentityMapping; +import org.grails.datastore.mapping.model.MappingContext; +import org.grails.datastore.mapping.model.MappingFactory; +import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.model.PersistentProperty; +import org.grails.datastore.mapping.model.ValueGenerator; import org.grails.datastore.mapping.model.types.Association; import org.grails.datastore.mapping.model.types.EmbeddedCollection; import org.grails.datastore.mapping.model.types.Simple; import org.grails.datastore.mapping.model.types.ToOne; import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; + import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.*; -import jakarta.persistence.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; @SuppressWarnings({"rawtypes", "unchecked", "Duplicates"}) public class JpaMappingConfigurationStrategy extends GormMappingConfigurationStrategy { @@ -83,60 +100,54 @@ public List getPersistentProperties(PersistentEntity entity, continue; } - if (isExcludedProperty(propertyName, classMapping, new ArrayList<>(), includeIdentifiers)) continue; + if (isExcludedProperty(propertyName, classMapping, new ArrayList<>(), includeIdentifiers)) { + continue; + } Class propertyType = descriptor.getPropertyType(); - if(hasAnnotation(readMethod, field, Id.class)) { - persistentProperties.add( propertyFactory.createIdentity(entity, context, descriptor)); - } - else if(hasAnnotation(readMethod, field, EmbeddedId.class)) { - persistentProperties.add( propertyFactory.createIdentity(entity, context, descriptor)); - } - else if (hasAnnotation(readMethod, field, Embedded.class)) { + if (hasAnnotation(readMethod, field, Id.class)) { + persistentProperties.add(propertyFactory.createIdentity(entity, context, descriptor)); + } else if (hasAnnotation(readMethod, field, EmbeddedId.class)) { + persistentProperties.add(propertyFactory.createIdentity(entity, context, descriptor)); + } else if (hasAnnotation(readMethod, field, Embedded.class)) { if (isCollectionType(propertyType)) { final Association association = establishRelationshipForCollection(descriptor, field, entity, context, true); if (association != null) { persistentProperties.add(association); } - } - else { + } else { final ToOne association = establishDomainClassRelationship(entity, descriptor, field, context, true); if (association != null) { persistentProperties.add(association); } } - } - else if (isCollectionType(propertyType)) { + } else if (isCollectionType(propertyType)) { final Association association = establishRelationshipForCollection(descriptor, field, entity, context, false); if (association != null) { configureOwningSide(association); persistentProperties.add(association); } - } - // otherwise if the type is a domain class establish relationship - else if (isPersistentEntity(propertyType)) { + } else if (isPersistentEntity(propertyType)) { + // otherwise if the type is a domain class establish relationship final ToOne association = establishDomainClassRelationship(entity, descriptor, field, context, false); if (association != null) { configureOwningSide(association); persistentProperties.add(association); } - } - else if (propertyFactory.isSimpleType(propertyType)) { + } else if (propertyFactory.isSimpleType(propertyType)) { Simple simpleProperty = propertyFactory.createSimple(entity, context, descriptor); - if(hasAnnotation(readMethod, field, GeneratedValue.class)) { + if (hasAnnotation(readMethod, field, GeneratedValue.class)) { simpleProperty.getMapping().getMappedForm().setDerived(true); } persistentProperties.add(simpleProperty); - } - else if (supportsCustomType(propertyType)) { + } else if (supportsCustomType(propertyType)) { persistentProperties.add(propertyFactory.createCustom(entity, context, descriptor)); } } return persistentProperties; } - protected Association establishRelationshipForCollection(PropertyDescriptor property, Field field, PersistentEntity entity, MappingContext context, boolean embedded) { Class javaClass = entity.getJavaClass(); Class genericClass = MappingUtils.getGenericTypeForProperty(javaClass, property.getName()); @@ -152,16 +163,14 @@ protected Association establishRelationshipForCollection(PropertyDescriptor prop if (embedded) { if (propertyFactory.isSimpleType(relatedClassType)) { return propertyFactory.createBasicCollection(entity, context, property, relatedClassType); - } - else { + } else { // no point in setting up bidirectional link here, since target isn't an entity. EmbeddedCollection association = propertyFactory.createEmbeddedCollection(entity, context, property); PersistentEntity associatedEntity = getOrCreateEmbeddedEntity(entity, context, relatedClassType); association.setAssociatedEntity(associatedEntity); return association; } - } - else if (!isPersistentEntity(relatedClassType) && !relatedClassType.equals(entity.getJavaClass())) { + } else if (!isPersistentEntity(relatedClassType) && !relatedClassType.equals(entity.getJavaClass())) { // otherwise set it to not persistent as you can't persist // relationships to non-domain classes return propertyFactory.createBasicCollection(entity, context, property, relatedClassType); @@ -178,7 +187,7 @@ else if (!isPersistentEntity(relatedClassType) && !relatedClassType.equals(entit association = propertyFactory.createManyToMany(entity, context, property); ManyToMany manyToMany = getAnnotation(readMethod, field, ManyToMany.class); if (!manyToMany.mappedBy().equals("")) { - ((org.grails.datastore.mapping.model.types.ManyToMany)association).setInversePropertyName(manyToMany.mappedBy()); + ((org.grails.datastore.mapping.model.types.ManyToMany) association).setInversePropertyName(manyToMany.mappedBy()); referencedPropertyName = manyToMany.mappedBy(); } else { List descriptors = referencedCpf.getPropertiesAssignableToType(Collection.class); @@ -200,8 +209,7 @@ else if (!isPersistentEntity(relatedClassType) && !relatedClassType.equals(entit } } } - } - else if (hasAnnotation(readMethod, field, OneToMany.class)) { + } else if (hasAnnotation(readMethod, field, OneToMany.class)) { association = propertyFactory.createOneToMany(entity, context, property); OneToMany oneToMany = getAnnotation(readMethod, field, OneToMany.class); if (!oneToMany.mappedBy().equals("")) { @@ -240,7 +248,6 @@ private ToOne establishDomainClassRelationship(PersistentEntity entity, Property Method readMethod = property.getReadMethod(); - if (getAnnotation(readMethod, field, ManyToOne.class) != null) { association = propertyFactory.createManyToOne(entity, context, property); @@ -263,8 +270,7 @@ private ToOne establishDomainClassRelationship(PersistentEntity entity, Property } } } - } - else { + } else { OneToOne oneToOne = getAnnotation(readMethod, field, OneToOne.class); if (oneToOne != null) { if (!oneToOne.mappedBy().equals("")) { @@ -291,7 +297,7 @@ private ToOne establishDomainClassRelationship(PersistentEntity entity, Property if (association != null) { PersistentEntity associatedEntity = getOrCreateAssociatedEntity(entity, context, propType); association.setAssociatedEntity(associatedEntity); - if (relatedClassPropertyName != null ) { + if (relatedClassPropertyName != null) { association.setReferencedPropertyName(relatedClassPropertyName); } } @@ -312,7 +318,7 @@ public IdentityMapping getIdentityMapping(final ClassMapping classMapping) { String[] idPropertiesArray; public String[] getIdentifierName() { - if(idPropertiesArray != null) { + if (idPropertiesArray != null) { return idPropertiesArray; } @@ -322,22 +328,21 @@ public String[] getIdentifierName() { for (MetaProperty metaProperty : cpf.getMetaProperties()) { int modifiers = metaProperty.getModifiers(); - if(Modifier.isStatic(modifiers) || Modifier.isAbstract(modifiers)) { + if (Modifier.isStatic(modifiers) || Modifier.isAbstract(modifiers)) { continue; } PropertyDescriptor pd = propertyFactory.createPropertyDescriptor(entity.getJavaClass(), metaProperty); - if(pd != null) { + if (pd != null) { if (hasAnnotation(cpf, pd, Id.class)) { idProperties.add(metaProperty.getName()); - } - else if (hasAnnotation(cpf, pd, EmbeddedId.class)) { + } else if (hasAnnotation(cpf, pd, EmbeddedId.class)) { idProperties.add(metaProperty.getName()); } } } - if(idProperties.isEmpty()) { + if (idProperties.isEmpty()) { // default to just use 'id' idProperties.add(GormProperties.IDENTITY); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/lifecycle/Initializable.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/lifecycle/Initializable.java index 70968cdcbfd..3178759ef34 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/lifecycle/Initializable.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/lifecycle/Initializable.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.model.lifecycle; /** diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Association.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Association.java index dfc983f51ec..d7814fbfa76 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Association.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Association.java @@ -18,17 +18,25 @@ */ package org.grails.datastore.mapping.model.types; -import java.beans.PropertyDescriptor; -import java.util.*; - import jakarta.persistence.CascadeType; import jakarta.persistence.FetchType; - import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.dirty.checking.DirtyCheckable; -import org.grails.datastore.mapping.model.*; +import org.grails.datastore.mapping.model.AbstractPersistentProperty; +import org.grails.datastore.mapping.model.IllegalMappingException; +import org.grails.datastore.mapping.model.MappingContext; +import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.validation.CascadeValidateType; +import java.beans.PropertyDescriptor; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * Models an association between one class and another * @@ -39,7 +47,7 @@ public abstract class Association extends AbstractPersistentProperty { private static final Set DEFAULT_OWNER_CASCADE = Collections.unmodifiableSet(new HashSet<>(Collections.singletonList(CascadeType.ALL))); - + private static final Map CASCADE_TYPE_CONVERSIONS = new LinkedHashMap<>(); private static final Set DEFAULT_CHILD_CASCADE = Collections.unmodifiableSet(new HashSet<>(Collections.singletonList(CascadeType.PERSIST))); private PersistentEntity associatedEntity; @@ -50,17 +58,15 @@ public abstract class Association extends AbstractPersistent private Set cascadeOperations; private CascadeValidateType cascadeValidateType; - private static final Map cascadeTypeConversions = new LinkedHashMap<>(); - static { - cascadeTypeConversions.put("all", CascadeType.ALL); - cascadeTypeConversions.put("all-delete-orphan", CascadeType.ALL); - cascadeTypeConversions.put("merge", CascadeType.MERGE); - cascadeTypeConversions.put("save-update", CascadeType.PERSIST); - cascadeTypeConversions.put("delete", CascadeType.REMOVE); - cascadeTypeConversions.put("remove", CascadeType.REMOVE); - cascadeTypeConversions.put("refresh", CascadeType.REFRESH); - cascadeTypeConversions.put("persist", CascadeType.PERSIST); + CASCADE_TYPE_CONVERSIONS.put("all", CascadeType.ALL); + CASCADE_TYPE_CONVERSIONS.put("all-delete-orphan", CascadeType.ALL); + CASCADE_TYPE_CONVERSIONS.put("merge", CascadeType.MERGE); + CASCADE_TYPE_CONVERSIONS.put("save-update", CascadeType.PERSIST); + CASCADE_TYPE_CONVERSIONS.put("delete", CascadeType.REMOVE); + CASCADE_TYPE_CONVERSIONS.put("remove", CascadeType.REMOVE); + CASCADE_TYPE_CONVERSIONS.put("refresh", CascadeType.REFRESH); + CASCADE_TYPE_CONVERSIONS.put("persist", CascadeType.PERSIST); // Unsupported Types // "all-delete-orphan", "lock", "replicate", "evict", "delete-orphan" } @@ -99,7 +105,9 @@ public boolean isOrphanRemoval() { */ public Association getInverseSide() { final PersistentProperty associatedProperty = associatedEntity.getPropertyByName(referencedPropertyName); - if (associatedProperty == null) return null; + if (associatedProperty == null) { + return null; + } if (associatedProperty instanceof Association) { return (Association) associatedProperty; } @@ -126,12 +134,11 @@ public boolean doesCascade(CascadeType cascadeOperation) { */ public boolean doesCascade(CascadeType... cascadeOperations) { Set cascades = getCascadeOperations(); - if( cascades.contains(CascadeType.ALL) ) { + if (cascades.contains(CascadeType.ALL)) { return true; - } - else if(cascadeOperations != null) { + } else if (cascadeOperations != null) { for (CascadeType cascadeOperation : cascadeOperations) { - if(cascades.contains(cascadeOperation)) { + if (cascades.contains(cascadeOperation)) { return true; } } @@ -164,7 +171,7 @@ public boolean doesCascadeValidate(Object associatedObject) { // Only cascade if the associated object is flagged as dirty. This presumes the object wasn't loaded // from persistence in an invalid state, which is probably a reasonable assumption. if (cascadeValidateType == CascadeValidateType.DIRTY && associatedObject instanceof DirtyCheckable) { - return defaultCascade && ((DirtyCheckable)associatedObject).hasChanged(); + return defaultCascade && ((DirtyCheckable) associatedObject).hasChanged(); } // Default @@ -222,6 +229,7 @@ public PersistentEntity getAssociatedEntity() { /** * Sets the name of the inverse property + * * @param referencedPropertyName The referenced property name */ public void setReferencedPropertyName(String referencedPropertyName) { @@ -280,30 +288,27 @@ private synchronized void buildCascadeOperations() { if (cascade != null) { final String[] specifiedOperations = cascade.toLowerCase().split(","); Set cascadeOperations = new HashSet<>(); - for(final String operation: specifiedOperations) { + for (final String operation : specifiedOperations) { final String key = operation.trim(); - if (cascadeTypeConversions.containsKey(key)) { - cascadeOperations.add(cascadeTypeConversions.get(key)); + if (CASCADE_TYPE_CONVERSIONS.containsKey(key)) { + cascadeOperations.add(CASCADE_TYPE_CONVERSIONS.get(key)); } - if(key.contains("delete-orphan")) { + if (key.contains("delete-orphan")) { this.orphanRemoval = true; } } this.cascadeOperations = Collections.unmodifiableSet(cascadeOperations); } else { List cascades = mappedForm.getCascades(); - if(cascades != null) { + if (cascades != null) { this.cascadeOperations = Collections.unmodifiableSet(new HashSet<>(cascades)); - } - else if (isOwningSide()) { + } else if (isOwningSide()) { this.cascadeOperations = DEFAULT_OWNER_CASCADE; - } - else { - if((this instanceof ManyToOne) && isBidirectional()) { + } else { + if ((this instanceof ManyToOne) && isBidirectional()) { // don't cascade by default to many-to-one that is not owned this.cascadeOperations = Collections.emptySet(); - } - else { + } else { this.cascadeOperations = DEFAULT_CHILD_CASCADE; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Basic.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Basic.java index eeb728b51ac..a4767577033 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Basic.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Basic.java @@ -14,11 +14,6 @@ */ package org.grails.datastore.mapping.model.types; -import java.beans.PropertyDescriptor; -import java.util.Collection; -import java.util.List; -import java.util.Map; - import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.engine.internal.MappingUtils; import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller; @@ -27,6 +22,11 @@ import org.grails.datastore.mapping.model.config.GormProperties; import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; +import java.beans.PropertyDescriptor; +import java.util.Collection; +import java.util.List; +import java.util.Map; + /** * Models a basic collection type such as a list of Strings * @@ -40,7 +40,7 @@ public abstract class Basic extends ToMany { private Class componentType; public Basic(PersistentEntity owner, MappingContext context, - PropertyDescriptor descriptor) { + PropertyDescriptor descriptor) { super(owner, context, descriptor); initializeComponentType(); } @@ -53,29 +53,27 @@ public Basic(PersistentEntity owner, MappingContext context, String name, Class private void initializeComponentType() { final Class type = getType(); final Class ownerClass = getOwner().getJavaClass(); - if(Map.class.isAssignableFrom(type)) { - this.componentType = MappingUtils.getGenericTypeForMapProperty(ownerClass, getName(), false ); - } - else if(Collection.class.isAssignableFrom(type)) { - this.componentType = MappingUtils.getGenericTypeForProperty(ownerClass, getName() ); - } - else if(type.isArray()) { + if (Map.class.isAssignableFrom(type)) { + this.componentType = MappingUtils.getGenericTypeForMapProperty(ownerClass, getName(), false); + } else if (Collection.class.isAssignableFrom(type)) { + this.componentType = MappingUtils.getGenericTypeForProperty(ownerClass, getName()); + } else if (type.isArray()) { this.componentType = type.getComponentType(); } - if(componentType == null) { + if (componentType == null) { List maps = ClassPropertyFetcher.getStaticPropertyValuesFromInheritanceHierarchy(ownerClass, GormProperties.HAS_MANY, Map.class); for (Map map : maps) { - if(map.containsKey(getName())) { + if (map.containsKey(getName())) { final Object o = map.get(getName()); - if(o instanceof Class) { + if (o instanceof Class) { this.componentType = (Class) o; break; } } } - if(componentType == null) { + if (componentType == null) { this.componentType = Object.class; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/BasicTypeConverterRegistrar.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/BasicTypeConverterRegistrar.java index a5b1405a564..c10583ec662 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/BasicTypeConverterRegistrar.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/BasicTypeConverterRegistrar.java @@ -18,13 +18,13 @@ */ package org.grails.datastore.mapping.model.types; +import org.springframework.core.convert.converter.Converter; +import org.springframework.core.convert.converter.ConverterRegistry; + import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; -import org.springframework.core.convert.converter.Converter; -import org.springframework.core.convert.converter.ConverterRegistry; - /** * A registrar that registers basic type converters * @@ -62,10 +62,10 @@ public Long convert(Integer integer) { }); registry.addConverter(new Converter() { - public Integer convert(Long longValue) { - return longValue.intValue(); - } - }); + public Integer convert(Long longValue) { + return longValue.intValue(); + } + }); registry.addConverter(new Converter() { public Double convert(Integer integer) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Custom.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Custom.java index 0270b82c01f..3e202b42204 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Custom.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Custom.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.model.types; import org.grails.datastore.mapping.engine.types.CustomTypeMarshaller; @@ -33,16 +32,17 @@ * @since 1.0 */ public abstract class Custom extends AbstractPersistentProperty { + private CustomTypeMarshaller customTypeMarshaller; public Custom(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor, - CustomTypeMarshaller customTypeMarshaller) { + CustomTypeMarshaller customTypeMarshaller) { super(owner, context, descriptor); this.customTypeMarshaller = customTypeMarshaller; } protected Custom(PersistentEntity owner, MappingContext context, String name, Class type, - CustomTypeMarshaller customTypeMarshaller) { + CustomTypeMarshaller customTypeMarshaller) { super(owner, context, name, type); this.customTypeMarshaller = customTypeMarshaller; } @@ -51,7 +51,7 @@ protected Custom(PersistentEntity owner, MappingContext context, String name, Cl * @return The type converter for this custom type */ @SuppressWarnings("rawtypes") - public CustomTypeMarshaller getCustomTypeMarshaller() { + public CustomTypeMarshaller getCustomTypeMarshaller() { return (CustomTypeMarshaller) customTypeMarshaller; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Embedded.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Embedded.java index bffadaea7fa..279615003d2 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Embedded.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Embedded.java @@ -18,12 +18,12 @@ */ package org.grails.datastore.mapping.model.types; -import java.beans.PropertyDescriptor; - import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; +import java.beans.PropertyDescriptor; + /** * Models an embedded component * diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/EmbeddedCollection.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/EmbeddedCollection.java index 9d13b704606..b2a3fde3ca3 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/EmbeddedCollection.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/EmbeddedCollection.java @@ -18,12 +18,12 @@ */ package org.grails.datastore.mapping.model.types; -import java.beans.PropertyDescriptor; - import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; +import java.beans.PropertyDescriptor; + /** * Models an embedded collection. * diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Identity.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Identity.java index 0ed2a5cab94..2fb77b7bda2 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Identity.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Identity.java @@ -18,13 +18,13 @@ */ package org.grails.datastore.mapping.model.types; -import java.beans.PropertyDescriptor; - import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.model.AbstractPersistentProperty; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; +import java.beans.PropertyDescriptor; + /** * Represents the identity of a persistent entity * @@ -32,9 +32,11 @@ * @since 1.0 */ public abstract class Identity extends AbstractPersistentProperty { + public Identity(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { super(owner, context, descriptor); } + public Identity(PersistentEntity owner, MappingContext context, String name, @SuppressWarnings("rawtypes") Class type) { super(owner, context, name, type); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ManyToOne.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ManyToOne.java index 45c92daebef..f041bbb03a7 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ManyToOne.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ManyToOne.java @@ -18,12 +18,12 @@ */ package org.grails.datastore.mapping.model.types; -import java.beans.PropertyDescriptor; - import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; +import java.beans.PropertyDescriptor; + /** * Models a many-to-one association * @@ -31,6 +31,7 @@ * @since 1.0 */ public abstract class ManyToOne extends ToOne { + public ManyToOne(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { super(owner, context, descriptor); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToMany.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToMany.java index 1d7a00d5ada..bb9e7b12010 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToMany.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToMany.java @@ -18,12 +18,12 @@ */ package org.grails.datastore.mapping.model.types; -import java.beans.PropertyDescriptor; - import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; +import java.beans.PropertyDescriptor; + /** * Models a one-to-many association * @@ -32,6 +32,7 @@ */ @SuppressWarnings("rawtypes") public abstract class OneToMany extends ToMany { + public OneToMany(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { super(owner, context, descriptor); } @@ -42,10 +43,9 @@ public OneToMany(PersistentEntity owner, MappingContext context, String name, Cl @Override public boolean isNullable() { - if(isCircular() && !isBidirectional()) { + if (isCircular() && !isBidirectional()) { return true; - } - else { + } else { return super.isNullable(); } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToOne.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToOne.java index 4a0fa082efa..8bac24f2720 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToOne.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/OneToOne.java @@ -18,12 +18,12 @@ */ package org.grails.datastore.mapping.model.types; -import java.beans.PropertyDescriptor; - import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; +import java.beans.PropertyDescriptor; + /** * Models a one-to-one association * @@ -31,6 +31,7 @@ * @since 1.0 */ public abstract class OneToOne extends ToOne { + public OneToOne(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { super(owner, context, descriptor); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Simple.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Simple.java index 7e0a7018049..77c0675e5d6 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Simple.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Simple.java @@ -32,6 +32,7 @@ * @since 1.0 */ public abstract class Simple extends AbstractPersistentProperty { + public Simple(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { super(owner, context, descriptor); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/TenantId.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/TenantId.java index d0dd5975752..8cc17ab56de 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/TenantId.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/TenantId.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.model.types; import org.grails.datastore.mapping.config.Property; @@ -33,6 +32,7 @@ * @since 6.0 */ public abstract class TenantId extends AbstractPersistentProperty { + public TenantId(PersistentEntity owner, MappingContext context, String name, Class type) { super(owner, context, name, type); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ToMany.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ToMany.java index bc5606b4844..54a9efaaaa0 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ToMany.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ToMany.java @@ -18,11 +18,11 @@ */ package org.grails.datastore.mapping.model.types; +import jakarta.persistence.FetchType; import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; -import jakarta.persistence.FetchType; import java.beans.PropertyDescriptor; /** @@ -33,7 +33,6 @@ */ public abstract class ToMany extends Association { - public ToMany(PersistentEntity owner, MappingContext context, PropertyDescriptor descriptor) { super(owner, context, descriptor); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ToOne.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ToOne.java index d4417ba77aa..14f137ffa25 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ToOne.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/ToOne.java @@ -18,12 +18,12 @@ */ package org.grails.datastore.mapping.model.types; -import java.beans.PropertyDescriptor; - import org.grails.datastore.mapping.config.Property; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; +import java.beans.PropertyDescriptor; + /** * @author Graeme Rocher * @since 1.1 diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/ByteArrayToStringConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/ByteArrayToStringConverter.groovy index 9865ab8db59..1ca44345325 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/ByteArrayToStringConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/ByteArrayToStringConverter.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.model.types.conversion import groovy.transform.CompileStatic - import org.springframework.core.convert.converter.Converter /** @@ -27,6 +26,7 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class ByteArrayToStringConverter implements Converter { + @Override String convert(byte[] source) { source.encodeBase64().toString() diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DefaultConversionService.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DefaultConversionService.java index 13b46f3d06a..d6c653364ba 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DefaultConversionService.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DefaultConversionService.java @@ -16,18 +16,17 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.model.types.conversion; import groovy.lang.GroovyObject; - -import java.io.Serializable; - import org.springframework.core.convert.TypeDescriptor; import org.springframework.format.datetime.DateFormatterRegistrar; +import java.io.Serializable; + /** * Default conversion service th + * * @author Graeme Rocher */ public class DefaultConversionService extends org.springframework.core.convert.support.DefaultConversionService { @@ -54,7 +53,7 @@ public DefaultConversionService() { @Override public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { // force converting GStringImpl & StreamCharBuffer to String before conversion - if(source instanceof CharSequence && source.getClass() != String.class && + if (source instanceof CharSequence && source.getClass() != String.class && targetType != null && targetType.getType() != source.getClass()) { source = source.toString(); sourceType = TypeDescriptor.valueOf(String.class); @@ -70,12 +69,12 @@ public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) && targetType.getType() == String.class && sourceType != null && (sourceType.getType() == GroovyObject.class || - sourceType.getType() == Comparable.class || - sourceType.getType() == Serializable.class)) { + sourceType.getType() == Comparable.class || + sourceType.getType() == Serializable.class)) { return false; } boolean reply = super.canConvert(sourceType, targetType); - if(!reply && sourceType != null && CharSequence.class.isAssignableFrom(sourceType.getType())) { + if (!reply && sourceType != null && CharSequence.class.isAssignableFrom(sourceType.getType())) { reply = super.canConvert(TypeDescriptor.valueOf(String.class), targetType); } return reply; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DoubleToFloatConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DoubleToFloatConverter.groovy index e20eb589441..d7e506a51f9 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DoubleToFloatConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/DoubleToFloatConverter.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.model.types.conversion import groovy.transform.CompileStatic - import org.springframework.core.convert.converter.Converter /** @@ -27,6 +26,7 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class DoubleToFloatConverter implements Converter { + @Override Float convert(Double source) { source as Float diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntArrayToIntegerArrayConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntArrayToIntegerArrayConverter.groovy index fe18be45c7c..6bc0e880aba 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntArrayToIntegerArrayConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntArrayToIntegerArrayConverter.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.model.types.conversion import groovy.transform.CompileStatic - import org.springframework.core.convert.converter.Converter /** @@ -27,6 +26,7 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class IntArrayToIntegerArrayConverter implements Converter { + Integer[] convert(int[] source) { source as Integer[] } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToByteConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToByteConverter.groovy index fdc0de82a1a..0a0504c1f29 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToByteConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToByteConverter.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.model.types.conversion import groovy.transform.CompileStatic - import org.springframework.core.convert.converter.Converter /** @@ -27,6 +26,7 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class IntegerToByteConverter implements Converter { + @Override Byte convert(Integer source) { source as Byte diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToShortConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToShortConverter.groovy index 80856c1b9bc..79cfee61f90 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToShortConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/IntegerToShortConverter.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.model.types.conversion import groovy.transform.CompileStatic - import org.springframework.core.convert.converter.Converter /** @@ -27,6 +26,7 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class IntegerToShortConverter implements Converter { + @Override Short convert(Integer source) { source as Short diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/LongArrayToLongArrayConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/LongArrayToLongArrayConverter.groovy index 8e36edc7e9f..b66c8c86598 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/LongArrayToLongArrayConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/LongArrayToLongArrayConverter.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.model.types.conversion import groovy.transform.CompileStatic - import org.springframework.core.convert.converter.Converter /** @@ -27,6 +26,7 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class LongArrayToLongArrayConverter implements Converter { + Long[] convert(long[] source) { source as Long[] } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigDecimalConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigDecimalConverter.groovy index 42aa1d0a4a9..44e7a6d0431 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigDecimalConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigDecimalConverter.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.model.types.conversion import groovy.transform.CompileStatic - import org.springframework.core.convert.converter.Converter /** @@ -27,6 +26,7 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class StringToBigDecimalConverter implements Converter { + BigDecimal convert(String source) { new BigDecimal(source) } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigIntegerConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigIntegerConverter.groovy index 5690682f030..113399287da 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigIntegerConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToBigIntegerConverter.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.model.types.conversion import groovy.transform.CompileStatic - import org.springframework.core.convert.converter.Converter /** @@ -27,6 +26,7 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class StringToBigIntegerConverter implements Converter { + BigInteger convert(String source) { new BigInteger(source) } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToByteArrayConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToByteArrayConverter.groovy index 3664c74827b..46ba23d1b09 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToByteArrayConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToByteArrayConverter.groovy @@ -26,6 +26,7 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class StringToByteArrayConverter implements Converter { + @Override byte[] convert(String source) { source.decodeBase64() diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToCurrencyConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToCurrencyConverter.groovy index b8e130f5c45..6a02b870da2 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToCurrencyConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToCurrencyConverter.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.model.types.conversion import groovy.transform.CompileStatic - import org.springframework.core.convert.converter.Converter /** @@ -27,6 +26,7 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class StringToCurrencyConverter implements Converter { + Currency convert(String source) { Currency.getInstance(source) } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToLocaleConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToLocaleConverter.groovy index 1b63e26be18..aa3d7f6f020 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToLocaleConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToLocaleConverter.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.model.types.conversion import groovy.transform.CompileStatic - import org.springframework.core.convert.converter.Converter /** @@ -27,12 +26,13 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class StringToLocaleConverter implements Converter { + Locale convert(String source) { String[] parts = source.split("_") switch (parts.length) { case 1: return new Locale(parts[0]) - case 2: return new Locale(parts[0],parts[1]) - case 3: return new Locale(parts[0],parts[1],parts[2]) + case 2: return new Locale(parts[0], parts[1]) + case 3: return new Locale(parts[0], parts[1], parts[2]) default: return new Locale(source) } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToShortConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToShortConverter.groovy index 5be88e6cb30..4fb963d0f00 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToShortConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToShortConverter.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.model.types.conversion import groovy.transform.CompileStatic - import org.springframework.core.convert.converter.Converter /** @@ -27,6 +26,7 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class StringToShortConverter implements Converter { + Short convert(String source) { new Short(source) } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToTimeZoneConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToTimeZoneConverter.groovy index 80847676e5c..40b675144bb 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToTimeZoneConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToTimeZoneConverter.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.model.types.conversion import groovy.transform.CompileStatic - import org.springframework.core.convert.converter.Converter /** @@ -27,6 +26,7 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class StringToTimeZoneConverter implements Converter { + TimeZone convert(String source) { TimeZone.getTimeZone(source) } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToURLConverter.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToURLConverter.groovy index 579575e1715..91f9fad376f 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToURLConverter.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/conversion/StringToURLConverter.groovy @@ -19,7 +19,6 @@ package org.grails.datastore.mapping.model.types.conversion import groovy.transform.CompileStatic - import org.springframework.core.convert.converter.Converter /** @@ -27,6 +26,7 @@ import org.springframework.core.convert.converter.Converter */ @CompileStatic class StringToURLConverter implements Converter { + URL convert(String source) { new URL(source) } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/MultiTenancySettings.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/MultiTenancySettings.groovy index 718a8ae58ad..39c7dee2160 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/MultiTenancySettings.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/MultiTenancySettings.groovy @@ -48,10 +48,9 @@ class MultiTenancySettings { * @return The tenant resolver */ TenantResolver getTenantResolver() { - if(tenantResolver != null) { + if (tenantResolver != null) { return tenantResolver - } - else if(tenantResolverClass != null) { + } else if (tenantResolverClass != null) { return BeanUtils.instantiateClass(tenantResolverClass) } return new NoTenantResolver() @@ -104,10 +103,9 @@ class MultiTenancySettings { * @return */ static String resolveConnectionForTenantId(MultiTenancyMode mode, Serializable tenantId) { - if(mode.isSharedConnection()) { + if (mode.isSharedConnection()) { return ConnectionSource.DEFAULT - } - else { + } else { return tenantId.toString() } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/MultiTenantCapableDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/MultiTenantCapableDatastore.java index ef55fb44ce4..ed97edcf0cb 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/MultiTenantCapableDatastore.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/MultiTenantCapableDatastore.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.multitenancy; import groovy.lang.Closure; @@ -54,15 +53,13 @@ public interface MultiTenantCapableDatastore the return type + * @param the return type * @return The return value of the closure */ T1 withNewSession(Serializable tenantId, Closure callable); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/SchemaMultiTenantCapableDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/SchemaMultiTenantCapableDatastore.java index 0a4aceb1184..a17a22efec8 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/SchemaMultiTenantCapableDatastore.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/SchemaMultiTenantCapableDatastore.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.multitenancy; import org.grails.datastore.mapping.core.connections.ConnectionSourceSettings; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/TenantDataSourceConfig.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/TenantDataSourceConfig.java index 8a4de83480c..fad4456cf3e 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/TenantDataSourceConfig.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/TenantDataSourceConfig.java @@ -18,7 +18,11 @@ */ package org.grails.datastore.mapping.multitenancy; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** *

    An annotation that adds possibility to configure whether a domain should be excluded from particular @@ -35,5 +39,6 @@ @Retention(RetentionPolicy.RUNTIME) @Documented public @interface TenantDataSourceConfig { + String[] dataSourcesToExclude() default ""; } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/exceptions/TenantException.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/exceptions/TenantException.groovy index 24a8e703822..0c8e30dfb47 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/exceptions/TenantException.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/exceptions/TenantException.groovy @@ -20,7 +20,6 @@ package org.grails.datastore.mapping.multitenancy.exceptions import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors import org.grails.datastore.mapping.core.DatastoreException /** @@ -31,6 +30,7 @@ import org.grails.datastore.mapping.core.DatastoreException */ @CompileStatic class TenantException extends DatastoreException { + TenantException(String s) { super(s) } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/exceptions/TenantNotFoundException.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/exceptions/TenantNotFoundException.groovy index 71556a56fb8..bcd89d1a570 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/exceptions/TenantNotFoundException.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/exceptions/TenantNotFoundException.groovy @@ -20,7 +20,6 @@ package org.grails.datastore.mapping.multitenancy.exceptions import groovy.transform.CompileStatic -import org.grails.datastore.mapping.core.DatastoreException /** * Thrown when the tenant cannot be found @@ -30,6 +29,7 @@ import org.grails.datastore.mapping.core.DatastoreException */ @CompileStatic class TenantNotFoundException extends TenantException { + TenantNotFoundException(String s) { super(s) } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/resolvers/FixedTenantResolver.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/resolvers/FixedTenantResolver.groovy index 54ace5d3984..b66c972685b 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/resolvers/FixedTenantResolver.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/resolvers/FixedTenantResolver.groovy @@ -41,7 +41,7 @@ class FixedTenantResolver implements TenantResolver { } FixedTenantResolver(Serializable tenantId) { - if(tenantId == null) { + if (tenantId == null) { throw new IllegalArgumentException("Argument [tenantId] cannot be null") } this.tenantId = tenantId diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/resolvers/NoTenantResolver.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/resolvers/NoTenantResolver.groovy index f486e13acde..5883669c819 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/resolvers/NoTenantResolver.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/resolvers/NoTenantResolver.groovy @@ -31,6 +31,7 @@ import org.grails.datastore.mapping.multitenancy.exceptions.TenantNotFoundExcept */ @CompileStatic class NoTenantResolver implements TenantResolver { + @Override Serializable resolveTenantIdentifier() { throw new TenantNotFoundException() diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/resolvers/SystemPropertyTenantResolver.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/resolvers/SystemPropertyTenantResolver.groovy index ba2acbe6e11..bbd13d7cef2 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/resolvers/SystemPropertyTenantResolver.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/multitenancy/resolvers/SystemPropertyTenantResolver.groovy @@ -34,10 +34,9 @@ class SystemPropertyTenantResolver implements TenantResolver { @Override Serializable resolveTenantIdentifier() throws TenantNotFoundException { def value = System.getProperty(PROPERTY_NAME) - if(value) { + if (value) { return value - } - else { + } else { throw new TenantNotFoundException() } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/AssociationQueryProxyHandler.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/AssociationQueryProxyHandler.java index d087a85d3a1..a5853da326e 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/AssociationQueryProxyHandler.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/AssociationQueryProxyHandler.java @@ -35,7 +35,7 @@ * @author Graeme Rocher * @since 5.0 */ -public class AssociationQueryProxyHandler extends EntityProxyMethodHandler { +public class AssociationQueryProxyHandler extends EntityProxyMethodHandler { protected final Session session; protected final AssociationQueryExecutor executor; @@ -59,26 +59,24 @@ protected Object getProxyKey(Object self) { return associationKey; } - @Override protected Object resolveDelegate(Object self) { if (target == null) { final List results = executor.query(associationKey); - if(executor.doesReturnKeys()) { - if(!results.isEmpty()) { + if (executor.doesReturnKeys()) { + if (!results.isEmpty()) { target = session.retrieve(executor.getIndexedEntity().getJavaClass(), (Serializable) results.get(0)); } - } - else { - if(!results.isEmpty()) { + } else { + if (!results.isEmpty()) { target = results.get(0); } } // This tends to happen during unit testing if the proxy class is not properly mocked // and therefore can't be found in the session. - if( target == null ) { - throw new DataIntegrityViolationException("Proxy for ["+ proxyClass.getName()+"] for association ["+executor.getIndexedEntity().getName()+"] could not be initialized"); + if (target == null) { + throw new DataIntegrityViolationException("Proxy for [" + proxyClass.getName() + "] for association [" + executor.getIndexedEntity().getName() + "] could not be initialized"); } if (target instanceof DirtyCheckable) { ((DirtyCheckable) target).syncChangedProperties(self); @@ -89,16 +87,16 @@ protected Object resolveDelegate(Object self) { protected Object handleInvocationFallback(Object self, Method thisMethod, Object[] args) { Object actualTarget = getProxyTarget(self); - if(!thisMethod.getDeclaringClass().isInstance(actualTarget)) { - if(Modifier.isPublic(thisMethod.getModifiers())) { + if (!thisMethod.getDeclaringClass().isInstance(actualTarget)) { + if (Modifier.isPublic(thisMethod.getModifiers())) { final Method method = ReflectionUtils.findMethod(actualTarget.getClass(), thisMethod.getName(), thisMethod.getParameterTypes()); - if(method != null) { + if (method != null) { ReflectionUtils.makeAccessible(method); thisMethod = method; } } else { final Method method = ReflectionUtils.findMethod(actualTarget.getClass(), thisMethod.getName(), thisMethod.getParameterTypes()); - if(method != null) { + if (method != null) { thisMethod = method; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/EntityProxy.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/EntityProxy.java index aa46e189fae..f0d75e26068 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/EntityProxy.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/EntityProxy.java @@ -33,12 +33,14 @@ public interface EntityProxy { /** * Obtains the target performing initialization if necessary + * * @return The target */ T getTarget(); /** * Checks whether the proxy has been initialized + * * @return True if it has */ boolean isInitialized(); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/EntityProxyMethodHandler.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/EntityProxyMethodHandler.java index 03456ebaf79..825a69e592c 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/EntityProxyMethodHandler.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/EntityProxyMethodHandler.java @@ -25,7 +25,6 @@ /** * Base class for entity proxy handlers that are aware of Groovy * - * * @author Graeme Rocher * @author Lari Hotari * @@ -61,23 +60,23 @@ protected Object getPropertyBeforeResolving(Object self, String property) { return super.getPropertyBeforeResolving(self, property); } } - + @Override public Object invokeMethodBeforeResolving(Object self, String methodName, Object[] args) { Object result = invokeEntityProxyMethods(self, methodName, args); - if(!wasHandled(result)) { + if (!wasHandled(result)) { return super.invokeMethodBeforeResolving(self, methodName, args); - } else { + } else { return result; } } - + @Override public Object handleInvocation(Object self, Method thisMethod, Object[] args) { Object result = invokeEntityProxyMethods(self, thisMethod.getName(), args); - if(!wasHandled(result)) { + if (!wasHandled(result)) { result = super.handleInvocation(self, thisMethod, args); - if(!wasHandled(result)) { + if (!wasHandled(result)) { return handleInvocationFallback(self, thisMethod, args); } } @@ -85,9 +84,9 @@ public Object handleInvocation(Object self, Method thisMethod, Object[] args) { } protected Object handleInvocationFallback(Object self, Method thisMethod, Object[] args) { - return INVOKE_IMPLEMENTATION; - } - + return INVOKE_IMPLEMENTATION; + } + protected Object invokeEntityProxyMethods(Object self, String methodName, Object[] args) { if (methodName.equals(IS_PROXY_METHOD)) { return true; @@ -105,7 +104,6 @@ protected Object invokeEntityProxyMethods(Object self, String methodName, Object } } - protected void initializeProxyTarget(Object self) { getProxyTarget(self); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/GroovyObjectMethodHandler.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/GroovyObjectMethodHandler.java index 87588188cc6..57c1adbd8b3 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/GroovyObjectMethodHandler.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/GroovyObjectMethodHandler.java @@ -19,22 +19,21 @@ package org.grails.datastore.mapping.proxy; import groovy.lang.MetaClass; - -import java.lang.reflect.Method; - import javassist.util.proxy.MethodHandler; - import org.codehaus.groovy.runtime.InvokerHelper; +import java.lang.reflect.Method; + /** * Javassist MethodHandler for handling GroovyObject methods - * + *

    * delegates getProperty, setProperty & invokeMethod to super class's MetaClass * * @author Lari Hotari * @author Graeme Rocher */ public class GroovyObjectMethodHandler implements MethodHandler { + public static final Object INVOKE_IMPLEMENTATION = new Object(); public static final String META_CLASS_PROPERTY = "metaClass"; public static final String GET_META_CLASS = "getMetaClass"; @@ -51,7 +50,7 @@ public GroovyObjectMethodHandler(Class proxyClass) { public Object getProperty(Object self, String property) { Object result = getPropertyBeforeResolving(self, property); - if(!wasHandled(result)) { + if (!wasHandled(result)) { return resolveDelegateAndGetProperty(self, property); } else { return result; @@ -67,7 +66,7 @@ protected Object getPropertyAfterResolving(Object delegate, String property) { } protected Object getPropertyBeforeResolving(Object self, String property) { - if(META_CLASS_PROPERTY.equals(property)) { + if (META_CLASS_PROPERTY.equals(property)) { return getThisMetaClass(); } return INVOKE_IMPLEMENTATION; @@ -78,7 +77,7 @@ protected Object resolveDelegate(Object self) { } public void setProperty(Object self, String property, Object newValue) { - if(setPropertyBeforeResolving(self, property, newValue)) { + if (setPropertyBeforeResolving(self, property, newValue)) { return; } resolveDelegateAndSetProperty(self, property, newValue); @@ -89,20 +88,20 @@ protected void resolveDelegateAndSetProperty(Object self, String property, Objec } protected boolean setPropertyBeforeResolving(Object self, String property, Object newValue) { - if(META_CLASS_PROPERTY.equals(property)) { - setThisMetaClass((MetaClass)newValue); + if (META_CLASS_PROPERTY.equals(property)) { + setThisMetaClass((MetaClass) newValue); return true; } return false; } - + protected void setPropertyAfterResolving(Object delegate, String property, Object newValue) { InvokerHelper.getMetaClass(delegate).setProperty(delegate, property, newValue); } public Object invokeThisMethod(Object self, String name, Object[] args) { Object result = invokeMethodBeforeResolving(self, name, args); - if(!wasHandled(result)) { + if (!wasHandled(result)) { return resolveDelegateAndInvokeThisMethod(self, name, args); } else { return result; @@ -118,11 +117,11 @@ protected Object invokeMethodAfterResolving(Object delegate, String name, Object } public Object invokeMethodBeforeResolving(Object self, String name, Object[] args) { - if(GET_META_CLASS.equals(name) && args.length==0) { + if (GET_META_CLASS.equals(name) && args.length == 0) { return getThisMetaClass(); } - if(SET_META_CLASS.equals(name) && args.length==1) { - setThisMetaClass((MetaClass)args[0]); + if (SET_META_CLASS.equals(name) && args.length == 1) { + setThisMetaClass((MetaClass) args[0]); return Void.class; } return INVOKE_IMPLEMENTATION; @@ -142,7 +141,7 @@ public void setThisMetaClass(MetaClass metaClass) { @Override public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable { Object result = handleInvocation(self, thisMethod, args); - if(!wasHandled(result)) { + if (!wasHandled(result)) { return proceed.invoke(self, args); } else { @@ -160,32 +159,30 @@ public Object handleInvocation(Object self, Method thisMethod, Object[] args) { if (GET_META_CLASS.equals(methodName)) { return getThisMetaClass(); } - } - else if (args.length == 1) { + } else if (args.length == 1) { if (GET_PROPERTY.equals(methodName)) { String name = args[0].toString(); - if(META_CLASS_PROPERTY.equals(name)) { + if (META_CLASS_PROPERTY.equals(name)) { return getThisMetaClass(); } else { return getProperty(self, name); } } else if (SET_META_CLASS.equals(methodName)) { - setThisMetaClass((MetaClass)args[0]); + setThisMetaClass((MetaClass) args[0]); return Void.class; } - } - else if (args.length == 2) { + } else if (args.length == 2) { if (SET_PROPERTY.equals(methodName)) { String name = args[0].toString(); Object value = args[1]; - if(META_CLASS_PROPERTY.equals(name)) { - setThisMetaClass((MetaClass)value); + if (META_CLASS_PROPERTY.equals(name)) { + setThisMetaClass((MetaClass) value); } else { setProperty(self, name, value); } return Void.class; } else if (INVOKE_METHOD.equals(methodName)) { - return invokeThisMethod(self, args[0].toString(), (Object[])args[1]); + return invokeThisMethod(self, args[0].toString(), (Object[]) args[1]); } } return INVOKE_IMPLEMENTATION; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/JavassistProxyFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/JavassistProxyFactory.java index 09d031303cb..225ed34c2af 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/JavassistProxyFactory.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/JavassistProxyFactory.java @@ -43,8 +43,8 @@ @SuppressWarnings({"rawtypes", "unchecked"}) public class JavassistProxyFactory implements org.grails.datastore.mapping.proxy.ProxyFactory { - private static final Map PROXY_FACTORIES = new ConcurrentHashMap(); - private static final Map ID_TYPES = new ConcurrentHashMap(); + private static final Map PROXY_FACTORIES = new ConcurrentHashMap(); + private static final Map ID_TYPES = new ConcurrentHashMap(); private static final Class[] EMPTY_CLASS_ARRAY = {}; private static final Set EXCLUDES = new HashSet(Arrays.asList("$getStaticMetaClass")); @@ -56,17 +56,16 @@ public boolean isProxy(Object object) { } public Serializable getIdentifier(Object obj) { - if(obj instanceof EntityProxy) { - return ((EntityProxy)obj).getProxyKey(); - } - else { + if (obj instanceof EntityProxy) { + return ((EntityProxy) obj).getProxyKey(); + } else { return null; } } @Override public Class getProxiedClass(Object o) { - if(isProxy(o)) { + if (isProxy(o)) { return o.getClass().getSuperclass(); } return o.getClass(); @@ -74,10 +73,9 @@ public Class getProxiedClass(Object o) { @Override public void initialize(Object o) { - if(o instanceof EntityProxy) { - ((EntityProxy)o).initialize(); - } - else if(o instanceof PersistentCollection) { + if (o instanceof EntityProxy) { + ((EntityProxy) o).initialize(); + } else if (o instanceof PersistentCollection) { ((PersistentCollection) o).initialize(); } } @@ -89,13 +87,11 @@ else if(o instanceof PersistentCollection) { * @return True if it is */ public boolean isInitialized(Object object) { - if(!isProxy(object)) { + if (!isProxy(object)) { return true; - } - else if(object instanceof EntityProxy) { + } else if (object instanceof EntityProxy) { return ((EntityProxy) object).isInitialized(); - } - else if(object instanceof PersistentCollection) { + } else if (object instanceof PersistentCollection) { return ((PersistentCollection) object).isInitialized(); } return true; @@ -115,7 +111,7 @@ public boolean isInitialized(Object object, String associationName) { */ public Object unwrap(Object object) { if (isProxy(object) && object instanceof EntityProxy) { - return ((EntityProxy)object).getTarget(); + return ((EntityProxy) object).getTarget(); } return object; } @@ -129,14 +125,14 @@ public T createProxy(Session session, AssociationQue MethodHandler mi = createMethodHandler(session, executor, associationKey); Class proxyClass = getProxyClass(executor.getIndexedEntity().getJavaClass()); Object proxy = ReflectionUtils.instantiate(proxyClass); - ((ProxyObject)proxy).setHandler(mi); + ((ProxyObject) proxy).setHandler(mi); return (T) proxy; } protected Object createProxiedInstance(final Session session, final Class cls, Class proxyClass, final Serializable id) { MethodHandler mi = createMethodHandler(session, cls, proxyClass, id); Object proxy = ReflectionUtils.instantiate(proxyClass); - ((ProxyObject)proxy).setHandler(mi); + ((ProxyObject) proxy).setHandler(mi); return proxy; } @@ -163,10 +159,10 @@ protected Class getProxyClass(Class type) { pf.setFilter(new MethodFilter() { public boolean isHandled(Method method) { Traits.TraitBridge traitBridge = method.getAnnotation(Traits.TraitBridge.class); - if(traitBridge != null) { + if (traitBridge != null) { Class traitClass = traitBridge.traitClass(); // ignore core traits - if(traitClass.getPackage().getName().startsWith(DATASTORE_PACKAGE_PREFIX)) { + if (traitClass.getPackage().getName().startsWith(DATASTORE_PACKAGE_PREFIX)) { return false; } } @@ -185,10 +181,10 @@ public boolean isHandled(Method method) { }); proxyClass = pf.createClass(); PROXY_FACTORIES.put(type, proxyClass); - + Method getIdMethod = org.springframework.util.ReflectionUtils.findMethod(type, "getId", EMPTY_CLASS_ARRAY); Class idType = getIdMethod.getReturnType(); - if(idType != null) { + if (idType != null) { ID_TYPES.put(type, idType); } } @@ -196,7 +192,7 @@ public boolean isHandled(Method method) { } protected Class[] getProxyInterfaces() { - return new Class[]{ EntityProxy.class, GroovyObject.class }; + return new Class[]{EntityProxy.class, GroovyObject.class}; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/ProxyFactory.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/ProxyFactory.java index 4d2fe544fb0..f90a811b86f 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/ProxyFactory.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/ProxyFactory.java @@ -18,11 +18,11 @@ */ package org.grails.datastore.mapping.proxy; -import java.io.Serializable; - import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.engine.AssociationQueryExecutor; +import java.io.Serializable; + /** * The factory used to create proxies * @@ -34,10 +34,10 @@ public interface ProxyFactory extends ProxyHandler { /** * Creates a proxy * - * @param The type of the proxy to create + * @param The type of the proxy to create * @param session The session instance - * @param type The type of the proxy to create - * @param key The key to proxy + * @param type The type of the proxy to create + * @param key The key to proxy * @return A proxy instance */ T createProxy(Session session, Class type, Serializable key); @@ -45,12 +45,12 @@ public interface ProxyFactory extends ProxyHandler { /** * Creates a proxy * - * @param The type of the proxy to create - * @param session The session instance - * @param executor The query executor + * @param The type of the proxy to create + * @param session The session instance + * @param executor The query executor * @param associationKey The key to proxy * @return A proxy instance */ - T createProxy(Session session, AssociationQueryExecutor executor, K associationKey); + T createProxy(Session session, AssociationQueryExecutor executor, K associationKey); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/ProxyHandler.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/ProxyHandler.java index f34b5fb8860..7c0decd7e85 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/ProxyHandler.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/ProxyHandler.java @@ -27,6 +27,7 @@ * @since 5.0 */ public interface ProxyHandler { + /** * Checks whether the specified instance is a proxy * @@ -37,10 +38,12 @@ public interface ProxyHandler { /** * Checks whether a given proxy is initialized + * * @param object The object to check * @return True if it is */ boolean isInitialized(Object object); + /** * Checks whether the given association name of the given object is initialized * @@ -51,6 +54,7 @@ public interface ProxyHandler { /** * Unwraps the given proxy if it is one + * * @param object The object * @return The unwrapped proxy */ @@ -58,6 +62,7 @@ public interface ProxyHandler { /** * Obtains the identifier of an object without initializing the proxy if it is one + * * @param obj The object * @return The identifier */ @@ -65,6 +70,7 @@ public interface ProxyHandler { /** * Get the class being proxied + * * @param o The object * @return The class being proxied */ @@ -72,6 +78,7 @@ public interface ProxyHandler { /** * Initialises the given object + * * @param o The object to initialize */ void initialize(Object o); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/SessionEntityProxyMethodHandler.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/SessionEntityProxyMethodHandler.java index 87d3045a18c..c75ea0f0265 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/SessionEntityProxyMethodHandler.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/proxy/SessionEntityProxyMethodHandler.java @@ -30,18 +30,18 @@ import java.lang.reflect.Modifier; /** -* An {@link EntityProxyMethodHandler} that uses the session to initialize a target for the given id -* -* @author Lari Hotari -* @author Graeme Rocher -*/ + * An {@link EntityProxyMethodHandler} that uses the session to initialize a target for the given id + * + * @author Lari Hotari + * @author Graeme Rocher + */ public class SessionEntityProxyMethodHandler extends EntityProxyMethodHandler { + private static final Logger LOG = LoggerFactory.getLogger(SessionEntityProxyMethodHandler.class); + protected Object target; private final Session session; private final Class cls; private final Serializable id; - protected Object target; - public SessionEntityProxyMethodHandler(Class proxyClass, Session session, Class cls, Serializable id) { super(proxyClass); @@ -57,15 +57,15 @@ protected Object resolveDelegate(Object self) { // This tends to happen during unit testing if the proxy class is not properly mocked // and therefore can't be found in the session. - if( target == null ) { - throw new DataIntegrityViolationException("Proxy for ["+ cls.getName()+":"+ id +"] could not be initialized"); + if (target == null) { + throw new DataIntegrityViolationException("Proxy for [" + cls.getName() + ":" + id + "] could not be initialized"); } } return target; } protected void initializeTarget() { - if(LOG.isDebugEnabled()) { + if (LOG.isDebugEnabled()) { LOG.debug("Lazy loading proxy for class {} with id {}", cls.getName(), id); } target = session.retrieve(cls, id); @@ -90,16 +90,16 @@ protected Object getProxyKey(Object self) { protected Object handleInvocationFallback(Object self, Method thisMethod, Object[] args) { Object actualTarget = getProxyTarget(self); - if(!thisMethod.getDeclaringClass().isInstance(actualTarget)) { - if(Modifier.isPublic(thisMethod.getModifiers())) { + if (!thisMethod.getDeclaringClass().isInstance(actualTarget)) { + if (Modifier.isPublic(thisMethod.getModifiers())) { final Method method = ReflectionUtils.findMethod(actualTarget.getClass(), thisMethod.getName(), thisMethod.getParameterTypes()); - if(method != null) { + if (method != null) { ReflectionUtils.makeAccessible(method); thisMethod = method; } } else { final Method method = ReflectionUtils.findMethod(actualTarget.getClass(), thisMethod.getName(), thisMethod.getParameterTypes()); - if(method != null) { + if (method != null) { thisMethod = method; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/AssociationQuery.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/AssociationQuery.java index 14ba4cef042..2feab78d064 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/AssociationQuery.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/AssociationQuery.java @@ -18,13 +18,13 @@ */ package org.grails.datastore.mapping.query; -import java.util.List; - import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.types.Association; import org.grails.datastore.mapping.query.Query.Criterion; +import java.util.List; + /** * Used to capture the metadata for a query on an associated object. * diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Projections.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Projections.java index e92b98f8117..7107f5987be 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Projections.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Projections.java @@ -25,11 +25,13 @@ * @since 1.0 */ public class Projections { + public static final Query.IdProjection ID_PROJECTION = new Query.IdProjection(); public static final Query.CountProjection COUNT_PROJECTION = new Query.CountProjection(); /** * Projection used to obtain the id of an object + * * @return The IdProjection instance */ public static Query.IdProjection id() { @@ -48,6 +50,7 @@ public static Query.CountProjection count() { /** * A projection that obtains the value of a property of an entity + * * @param name The name of the property * @return The PropertyProjection instance */ @@ -85,7 +88,7 @@ public static Query.MaxProjection max(String name) { return new Query.MaxProjection(name); } - /** + /** * Computes the average value of a property * * @param name The name of the property @@ -128,7 +131,6 @@ public static Query.CountDistinctProjection countDistinct(String property) { * Defines a group by projection for datastores that support it * * @param property The property name - * * @return The projection list */ public static Query.GroupPropertyProjection groupProperty(String property) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Query.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Query.java index dfd69c44a9c..8887813a3f9 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Query.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Query.java @@ -18,6 +18,10 @@ */ package org.grails.datastore.mapping.query; +import jakarta.persistence.FetchType; +import jakarta.persistence.FlushModeType; +import jakarta.persistence.LockModeType; +import jakarta.persistence.criteria.JoinType; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.model.MappingContext; import org.grails.datastore.mapping.model.PersistentEntity; @@ -33,12 +37,13 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; -import jakarta.persistence.FetchType; -import jakarta.persistence.FlushModeType; -import jakarta.persistence.LockModeType; -import jakarta.persistence.criteria.JoinType; import java.io.Serializable; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.regex.Pattern; /** @@ -48,7 +53,7 @@ * @since 1.0 */ @SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class Query implements Cloneable{ +public abstract class Query implements Cloneable { protected final PersistentEntity entity; protected final Session session; @@ -72,7 +77,9 @@ protected Query(Session session, PersistentEntity entity) { @Override public Object clone() { Session session = getSession(); - if(session == null) throw new IllegalStateException("Cannot clone a stateless query"); + if (session == null) { + throw new IllegalStateException("Cannot clone a stateless query"); + } Query newQuery = session.createQuery(entity.getJavaClass()); for (Criterion criterion : criteria.getCriteria()) { newQuery.add(criterion); @@ -172,7 +179,7 @@ public void add(Criterion criterion) { * Adds the specified criterion instance to the given junction * * @param currentJunction The junction to add the criterion to - * @param criterion The criterion instance + * @param criterion The criterion instance */ public void add(Junction currentJunction, Criterion criterion) { addToJunction(currentJunction, criterion); @@ -194,6 +201,7 @@ public PersistentEntity getEntity() { /** * Creates a disjunction (OR) query + * * @return The Junction instance */ public Junction disjunction() { @@ -203,6 +211,7 @@ public Junction disjunction() { /** * Creates a conjunction (AND) query + * * @return The Junction instance */ public Junction conjunction() { @@ -212,6 +221,7 @@ public Junction conjunction() { /** * Creates a negation of several criterion + * * @return The negation */ public Junction negation() { @@ -227,6 +237,7 @@ private Junction negation(Junction currentJunction) { /** * Defines the maximum number of results to return + * * @param max The max results * @return This query instance */ @@ -237,6 +248,7 @@ public Query max(int max) { /** * Defines the maximum number of results to return + * * @param max The max results * @return This query instance */ @@ -246,6 +258,7 @@ public Query maxResults(int max) { /** * Defines the offset (the first result index) of the query + * * @param offset The offset * @return This query instance */ @@ -256,6 +269,7 @@ public Query offset(int offset) { /** * Defines the offset (the first result index) of the query + * * @param offset The offset * @return This query instance */ @@ -265,6 +279,7 @@ public Query firstResult(int offset) { /** * Specifies the order of results + * * @param order The order object * @return The Query instance */ @@ -277,6 +292,7 @@ public Query order(Order order) { /** * Gets the Order entries for this query + * * @return The order entries */ public List getOrderBy() { @@ -287,16 +303,15 @@ public List getOrderBy() { * Restricts the results by the given properties value * * @param property The name of the property - * @param value The value to restrict by + * @param value The value to restrict by * @return This query instance */ public Query eq(String property, Object value) { Object resolved = resolvePropertyValue(entity, property, value); if (resolved == value) { - criteria.add(Restrictions.eq(property, value)); - } - else { - criteria.add(Restrictions.eq(property,resolved)); + criteria.add(Restrictions.eq(property, value)); + } else { + criteria.add(Restrictions.eq(property, resolved)); } return this; } @@ -304,10 +319,9 @@ public Query eq(String property, Object value) { Object resolvePropertyValue(PersistentEntity entity, String property, Object value) { PersistentProperty persistentProperty = entity.getPropertyByName(property); Object resolved; - if(persistentProperty instanceof Embedded) { + if (persistentProperty instanceof Embedded) { resolved = value; - } - else { + } else { resolved = resolveIdIfEntity(value); } return resolved; @@ -333,7 +347,7 @@ public Query allEq(Map values) { * Used to restrict a value to be empty (such as a blank string or an empty collection) * * @param property The property name - */ + */ public Query isEmpty(String property) { criteria.add(Restrictions.isEmpty(property)); return this; @@ -343,7 +357,7 @@ public Query isEmpty(String property) { * Used to restrict a value to be not empty (such as a blank string or an empty collection) * * @param property The property name - */ + */ public Query isNotEmpty(String property) { criteria.add(Restrictions.isNotEmpty(property)); return this; @@ -353,7 +367,7 @@ public Query isNotEmpty(String property) { * Used to restrict a property to be null * * @param property The property name - */ + */ public Query isNull(String property) { criteria.add(Restrictions.isNull(property)); return this; @@ -363,7 +377,7 @@ public Query isNull(String property) { * Used to restrict a property to be not null * * @param property The property name - */ + */ public Query isNotNull(String property) { criteria.add(Restrictions.isNotNull(property)); return this; @@ -379,8 +393,8 @@ public AssociationQuery createQuery(String associationName) { final PersistentProperty property = entity.getPropertyByName(associationName); if (property == null || !(property instanceof Association)) { throw new InvalidDataAccessResourceUsageException("Cannot query association [" + - associationName + "] of class [" + entity + - "]. The specified property is not an association."); + associationName + "] of class [" + entity + + "]. The specified property is not an association."); } Association association = (Association) property; @@ -407,7 +421,7 @@ public Query idEq(Object value) { * Used to restrict a value to be greater than the given value * * @param property The name of the property - * @param value The value to restrict by + * @param value The value to restrict by * @return This query instance */ public Query gt(String property, Object value) { @@ -419,7 +433,7 @@ public Query gt(String property, Object value) { * Used to restrict a value to be greater than or equal to the given value * * @param property The name of the property - * @param value The value to restrict by + * @param value The value to restrict by * @return This query instance */ public Query gte(String property, Object value) { @@ -431,7 +445,7 @@ public Query gte(String property, Object value) { * Used to restrict a value to be less than or equal to the given value * * @param property The name of the property - * @param value The value to restrict by + * @param value The value to restrict by * @return This query instance */ public Query lte(String property, Object value) { @@ -443,7 +457,7 @@ public Query lte(String property, Object value) { * Used to restrict a value to be greater than or equal to the given value * * @param property The name of the property - * @param value The value to restrict by + * @param value The value to restrict by * @return This query instance */ public Query ge(String property, Object value) { @@ -454,7 +468,7 @@ public Query ge(String property, Object value) { * Used to restrict a value to be less than or equal to the given value * * @param property The name of the property - * @param value The value to restrict by + * @param value The value to restrict by * @return This query instance */ public Query le(String property, Object value) { @@ -465,7 +479,7 @@ public Query le(String property, Object value) { * Used to restrict a value to be less than the given value * * @param property The name of the property - * @param value The value to restrict by + * @param value The value to restrict by * @return This query instance */ public Query lt(String property, Object value) { @@ -477,7 +491,7 @@ public Query lt(String property, Object value) { * Restricts the results by the given property values * * @param property The name of the property - * @param values The values to restrict by + * @param values The values to restrict by * @return This query instance */ public Query in(String property, List values) { @@ -489,8 +503,8 @@ public Query in(String property, List values) { * Restricts the results by the given property value range * * @param property The name of the property - * @param start The start of the range - * @param end The end of the range + * @param start The start of the range + * @param end The end of the range * @return This query instance */ public Query between(String property, Object start, Object end) { @@ -502,7 +516,7 @@ public Query between(String property, Object start, Object end) { * Restricts the results by the given properties value * * @param property The name of the property - * @param expr The expression to restrict by + * @param expr The expression to restrict by * @return This query instance */ public Query like(String property, String expr) { @@ -514,7 +528,7 @@ public Query like(String property, String expr) { * Restricts the results by the given properties value * * @param property The name of the property - * @param expr The expression to restrict by + * @param expr The expression to restrict by * @return This query instance */ public Query ilike(String property, String expr) { @@ -526,7 +540,7 @@ public Query ilike(String property, String expr) { * Restricts the results by the given properties value * * @param property The name of the property - * @param expr The expression to restrict by + * @param expr The expression to restrict by * @return This query instance */ public Query rlike(String property, String expr) { @@ -541,7 +555,7 @@ public Query rlike(String property, String expr) { * @param b The right hand side * @return This query instance */ - public Query and( Criterion a, Criterion b) { + public Query and(Criterion a, Criterion b) { Assert.notNull(a, "Left hand side of AND cannot be null"); Assert.notNull(b, "Right hand side of AND cannot be null"); criteria.add(Restrictions.and(a, b)); @@ -555,7 +569,7 @@ public Query and( Criterion a, Criterion b) { * @param b The right hand side * @return This query instance */ - public Query or( Criterion a, Criterion b) { + public Query or(Criterion a, Criterion b) { Assert.notNull(a, "Left hand side of AND cannot be null"); Assert.notNull(b, "Right hand side of AND cannot be null"); criteria.add(Restrictions.or(a, b)); @@ -574,6 +588,7 @@ public List list() { /** * Executes the query returning a single result or null + * * @return The result */ public Object singleResult() { @@ -586,19 +601,18 @@ private List doList() { flushBeforeQuery(); ApplicationEventPublisher publisher = session.getDatastore().getApplicationEventPublisher(); - if(publisher != null) { + if (publisher != null) { publisher.publishEvent(new PreQueryEvent(this)); } List results = executeQuery(entity, criteria); - if(publisher != null) { + if (publisher != null) { PostQueryEvent postQueryEvent = new PostQueryEvent(this, results); publisher.publishEvent(postQueryEvent); results = postQueryEvent.getResults(); } - return results; } @@ -621,12 +635,11 @@ public void setUniqueResult(boolean uniqueResult) { */ protected FetchType fetchStrategy(String property) { final FetchType fetchType = fetchStrategies.get(property); - if(fetchType != null) { + if (fetchType != null) { return fetchType; - } - else { + } else { final PersistentProperty prop = entity.getPropertyByName(property); - if(prop != null) { + if (prop != null) { return prop.getMapping().getMappedForm().getFetchStrategy(); } } @@ -637,7 +650,7 @@ protected FetchType fetchStrategy(String property) { * Subclasses should implement this to provide the concrete implementation * of querying * - * @param entity The entity + * @param entity The entity * @param criteria The criteria * @return The results */ @@ -677,7 +690,9 @@ private Junction conjunction(Junction currentJunction) { * @return The pattern */ public static String patternToRegex(Object value) { - if (value == null) value = "null"; + if (value == null) { + value = "null"; + } String[] array = value.toString().split("%", -1); for (int i = 0; i < array.length; i++) { @@ -721,23 +736,20 @@ private void addToJunction(Junction currentJunction, Criterion criterion) { associationQuery.add(associationCriterion); } currentJunction.add(associationQuery); - } - else if (criterion instanceof Junction) { + } else if (criterion instanceof Junction) { Junction j = (Junction) criterion; Junction newj; if (j instanceof Disjunction) { - newj= disjunction(currentJunction); + newj = disjunction(currentJunction); } else if (j instanceof Negation) { - newj= negation(currentJunction); - } - else { - newj= conjunction(currentJunction); + newj = negation(currentJunction); + } else { + newj = conjunction(currentJunction); } for (Criterion c : j.getCriteria()) { addToJunction(newj, c); } - } - else { + } else { currentJunction.add(criterion); } } @@ -745,12 +757,15 @@ else if (criterion instanceof Junction) { /** * Represents a criterion to be used in a criteria query */ - public static interface Criterion {} + public static interface Criterion { + + } /** * The ordering of results. */ public static class Order { + private Direction direction = Direction.ASC; private String property; private boolean ignoreCase = false; @@ -824,6 +839,7 @@ public static enum Direction { * Restricts a property to be null */ public static class IsNull extends PropertyNameCriterion { + public IsNull(String name) { super(name); } @@ -833,6 +849,7 @@ public IsNull(String name) { * Restricts a property to be empty (such as a blank string) */ public static class IsEmpty extends PropertyNameCriterion { + public IsEmpty(String name) { super(name); } @@ -842,6 +859,7 @@ public IsEmpty(String name) { * Restricts a property to be empty (such as a blank string) */ public static class IsNotEmpty extends PropertyNameCriterion { + public IsNotEmpty(String name) { super(name); } @@ -851,6 +869,7 @@ public IsNotEmpty(String name) { * Restricts a property to be not null */ public static class IsNotNull extends PropertyNameCriterion { + public IsNotNull(String name) { super(name); } @@ -860,6 +879,7 @@ public IsNotNull(String name) { * A Criterion that applies to a property */ public static class PropertyNameCriterion implements Criterion { + protected String name; public PropertyNameCriterion(String name) { @@ -874,7 +894,8 @@ public String getProperty() { /** * A Criterion that compares to properties */ - public static class PropertyComparisonCriterion extends PropertyNameCriterion{ + public static class PropertyComparisonCriterion extends PropertyNameCriterion { + protected String otherProperty; public PropertyComparisonCriterion(String property, String otherProperty) { @@ -888,36 +909,42 @@ public String getOtherProperty() { } public static class EqualsProperty extends PropertyComparisonCriterion { + public EqualsProperty(String property, String otherProperty) { super(property, otherProperty); } } public static class NotEqualsProperty extends PropertyComparisonCriterion { + public NotEqualsProperty(String property, String otherProperty) { super(property, otherProperty); } } public static class GreaterThanProperty extends PropertyComparisonCriterion { + public GreaterThanProperty(String property, String otherProperty) { super(property, otherProperty); } } public static class GreaterThanEqualsProperty extends PropertyComparisonCriterion { + public GreaterThanEqualsProperty(String property, String otherProperty) { super(property, otherProperty); } } public static class LessThanProperty extends PropertyComparisonCriterion { + public LessThanProperty(String property, String otherProperty) { super(property, otherProperty); } } public static class LessThanEqualsProperty extends PropertyComparisonCriterion { + public LessThanEqualsProperty(String property, String otherProperty) { super(property, otherProperty); } @@ -948,20 +975,22 @@ public void setValue(Object v) { * Used to differentiate criterion that require a subquery */ public static class SubqueryCriterion extends PropertyCriterion { + public SubqueryCriterion(String name, QueryableCriteria value) { super(name, value); } @Override public QueryableCriteria getValue() { - return (QueryableCriteria)super.getValue(); + return (QueryableCriteria) super.getValue(); } } /** * Restricts a value to be equal to all the given values */ - public static class EqualsAll extends SubqueryCriterion{ + public static class EqualsAll extends SubqueryCriterion { + public EqualsAll(String name, QueryableCriteria value) { super(name, value); } @@ -970,7 +999,8 @@ public EqualsAll(String name, QueryableCriteria value) { /** * Restricts a value to be not equal to all the given values */ - public static class NotEqualsAll extends SubqueryCriterion{ + public static class NotEqualsAll extends SubqueryCriterion { + public NotEqualsAll(String name, QueryableCriteria value) { super(name, value); } @@ -979,7 +1009,8 @@ public NotEqualsAll(String name, QueryableCriteria value) { /** * Restricts a value to be greater than all the given values */ - public static class GreaterThanAll extends SubqueryCriterion{ + public static class GreaterThanAll extends SubqueryCriterion { + public GreaterThanAll(String name, QueryableCriteria value) { super(name, value); } @@ -988,7 +1019,8 @@ public GreaterThanAll(String name, QueryableCriteria value) { /** * Restricts a value to be greater than some of the given values */ - public static class GreaterThanSome extends SubqueryCriterion{ + public static class GreaterThanSome extends SubqueryCriterion { + public GreaterThanSome(String name, QueryableCriteria value) { super(name, value); } @@ -997,7 +1029,8 @@ public GreaterThanSome(String name, QueryableCriteria value) { /** * Restricts a value to be greater than some of the given values */ - public static class GreaterThanEqualsSome extends SubqueryCriterion{ + public static class GreaterThanEqualsSome extends SubqueryCriterion { + public GreaterThanEqualsSome(String name, QueryableCriteria value) { super(name, value); } @@ -1006,7 +1039,8 @@ public GreaterThanEqualsSome(String name, QueryableCriteria value) { /** * Restricts a value to be less than some of the given values */ - public static class LessThanSome extends SubqueryCriterion{ + public static class LessThanSome extends SubqueryCriterion { + public LessThanSome(String name, QueryableCriteria value) { super(name, value); } @@ -1015,7 +1049,8 @@ public LessThanSome(String name, QueryableCriteria value) { /** * Restricts a value to be less than some of the given values */ - public static class LessThanEqualsSome extends SubqueryCriterion{ + public static class LessThanEqualsSome extends SubqueryCriterion { + public LessThanEqualsSome(String name, QueryableCriteria value) { super(name, value); } @@ -1024,7 +1059,8 @@ public LessThanEqualsSome(String name, QueryableCriteria value) { /** * Restricts a value to be less than all the given values */ - public static class LessThanAll extends SubqueryCriterion{ + public static class LessThanAll extends SubqueryCriterion { + public LessThanAll(String name, QueryableCriteria value) { super(name, value); } @@ -1033,7 +1069,8 @@ public LessThanAll(String name, QueryableCriteria value) { /** * Restricts a value to be greater than or equal to all the given values */ - public static class GreaterThanEqualsAll extends SubqueryCriterion{ + public static class GreaterThanEqualsAll extends SubqueryCriterion { + public GreaterThanEqualsAll(String name, QueryableCriteria value) { super(name, value); } @@ -1042,7 +1079,8 @@ public GreaterThanEqualsAll(String name, QueryableCriteria value) { /** * Restricts a value to be less than or equal to all the given values */ - public static class LessThanEqualsAll extends SubqueryCriterion{ + public static class LessThanEqualsAll extends SubqueryCriterion { + public LessThanEqualsAll(String name, QueryableCriteria value) { super(name, value); } @@ -1063,37 +1101,43 @@ public void setValue(Object value) { } } - public static class SizeEquals extends PropertyCriterion{ + public static class SizeEquals extends PropertyCriterion { + public SizeEquals(String name, int value) { super(name, value); } } - public static class SizeNotEquals extends PropertyCriterion{ + public static class SizeNotEquals extends PropertyCriterion { + public SizeNotEquals(String name, int value) { super(name, value); } } - public static class SizeGreaterThan extends PropertyCriterion{ + public static class SizeGreaterThan extends PropertyCriterion { + public SizeGreaterThan(String name, int value) { super(name, value); } } - public static class SizeGreaterThanEquals extends PropertyCriterion{ + public static class SizeGreaterThanEquals extends PropertyCriterion { + public SizeGreaterThanEquals(String name, int value) { super(name, value); } } - public static class SizeLessThanEquals extends PropertyCriterion{ + public static class SizeLessThanEquals extends PropertyCriterion { + public SizeLessThanEquals(String name, int value) { super(name, value); } } - public static class SizeLessThan extends PropertyCriterion{ + public static class SizeLessThan extends PropertyCriterion { + public SizeLessThan(String name, int value) { super(name, value); } @@ -1135,6 +1179,7 @@ public void setValue(Object value) { * Criterion used to restrict the results based on a list of values */ public static class In extends PropertyCriterion { + private Collection values = Collections.emptyList(); private QueryableCriteria subquery; @@ -1143,11 +1188,16 @@ public In(String name, Collection values) { this.values = convertCharSequenceValuesIfNecessary(values); } + public In(String name, QueryableCriteria subquery) { + super(name, subquery); + this.subquery = subquery; + } + private static Collection convertCharSequenceValuesIfNecessary(Collection values) { - boolean requiresConversion=false; + boolean requiresConversion = false; for (Object val : values) { if (!(val instanceof String) && val instanceof CharSequence) { - requiresConversion=true; + requiresConversion = true; break; } } @@ -1157,16 +1207,11 @@ private static Collection convertCharSequenceValuesIfNecessary(Collection values newList.add(val instanceof CharSequence ? val.toString() : val); } return newList; - } else { + } else { return values; } } - public In(String name, QueryableCriteria subquery) { - super(name, subquery); - this.subquery = subquery; - } - public String getName() { return getProperty(); } @@ -1184,8 +1229,8 @@ public QueryableCriteria getSubquery() { * Criterion used to restrict the results based on a list of values */ public static class NotIn extends SubqueryCriterion { - private QueryableCriteria subquery; + private QueryableCriteria subquery; public NotIn(String name, QueryableCriteria subquery) { super(name, subquery); @@ -1205,6 +1250,7 @@ public QueryableCriteria getSubquery() { * Used for exists subquery */ public static class Exists implements Criterion { + private QueryableCriteria subquery; public Exists(QueryableCriteria subquery) { @@ -1220,6 +1266,7 @@ public QueryableCriteria getSubquery() { * Used for exists subquery */ public static class NotExists implements Criterion { + private QueryableCriteria subquery; public NotExists(QueryableCriteria subquery) { @@ -1235,6 +1282,7 @@ public QueryableCriteria getSubquery() { * Used to restrict a value to be greater than the given value */ public static class GreaterThan extends PropertyCriterion { + public GreaterThan(String name, Object value) { super(name, value); } @@ -1244,6 +1292,7 @@ public GreaterThan(String name, Object value) { * Used to restrict a value to be greater than or equal to the given value */ public static class GreaterThanEquals extends PropertyCriterion { + public GreaterThanEquals(String name, Object value) { super(name, value); } @@ -1253,6 +1302,7 @@ public GreaterThanEquals(String name, Object value) { * Used to restrict a value to be less than the given value */ public static class LessThan extends PropertyCriterion { + public LessThan(String name, Object value) { super(name, value); } @@ -1262,6 +1312,7 @@ public LessThan(String name, Object value) { * Used to restrict a value to be less than the given value */ public static class LessThanEquals extends PropertyCriterion { + public LessThanEquals(String name, Object value) { super(name, value); } @@ -1271,6 +1322,7 @@ public LessThanEquals(String name, Object value) { * Criterion used to restrict the result to be between values (range query) */ public static class Between extends PropertyCriterion { + private String property; private Object from; private Object to; @@ -1300,6 +1352,7 @@ public Object getTo() { * Criterion used to restrict the results based on a pattern (likeness) */ public static class Like extends PropertyCriterion { + public Like(String name, String expression) { super(name, expression); } @@ -1313,6 +1366,7 @@ public String getPattern() { * Criterion used to restrict the results based on a pattern (likeness) */ public static class ILike extends Like { + public ILike(String name, String expression) { super(name, expression); } @@ -1322,6 +1376,7 @@ public ILike(String name, String expression) { * Criterion used to restrict the results based on a regular expression pattern */ public static class RLike extends Like { + public RLike(String name, String expression) { super(name, expression); } @@ -1332,7 +1387,8 @@ public String getPattern() { } } - public static abstract class Junction implements Criterion { + public abstract static class Junction implements Criterion { + private List criteria = new ArrayList(); protected Junction() { @@ -1362,6 +1418,7 @@ public boolean isEmpty() { * A Criterion used to combine to criterion in a logical AND */ public static class Conjunction extends Junction { + public Conjunction() { } @@ -1374,6 +1431,7 @@ public Conjunction(List criteria) { * A Criterion used to combine to criterion in a logical OR */ public static class Disjunction extends Junction { + public Disjunction() { } @@ -1385,29 +1443,40 @@ public Disjunction(List criteria) { /** * A criterion used to negate several other criterion */ - public static class Negation extends Junction {} + public static class Negation extends Junction { + + } /** * A projection */ - public static class Projection {} + public static class Projection { + + } /** * A projection used to obtain the identifier of an object */ - public static class IdProjection extends Projection {} + public static class IdProjection extends Projection { + + } /** * Used to count the results of a query */ - public static class CountProjection extends Projection {} + public static class CountProjection extends Projection { - public static class DistinctProjection extends Projection {} + } + + public static class DistinctProjection extends Projection { + + } /** * A projection that obtains the value of a property of an entity */ public static class PropertyProjection extends Projection { + private String propertyName; protected PropertyProjection(String propertyName) { @@ -1419,19 +1488,22 @@ public String getPropertyName() { } } - public static class DistinctPropertyProjection extends PropertyProjection{ + public static class DistinctPropertyProjection extends PropertyProjection { + protected DistinctPropertyProjection(String propertyName) { super(propertyName); } } - public static class CountDistinctProjection extends PropertyProjection{ + public static class CountDistinctProjection extends PropertyProjection { + public CountDistinctProjection(String property) { super(property); } } - public static class GroupPropertyProjection extends PropertyProjection{ + public static class GroupPropertyProjection extends PropertyProjection { + public GroupPropertyProjection(String property) { super(property); } @@ -1441,6 +1513,7 @@ public GroupPropertyProjection(String property) { * Computes the average value of a property */ public static class AvgProjection extends PropertyProjection { + protected AvgProjection(String propertyName) { super(propertyName); } @@ -1450,6 +1523,7 @@ protected AvgProjection(String propertyName) { * Computes the max value of a property */ public static class MaxProjection extends PropertyProjection { + protected MaxProjection(String propertyName) { super(propertyName); } @@ -1459,6 +1533,7 @@ protected MaxProjection(String propertyName) { * Computes the min value of a property */ public static class MinProjection extends PropertyProjection { + protected MinProjection(String propertyName) { super(propertyName); } @@ -1468,12 +1543,12 @@ protected MinProjection(String propertyName) { * Computes the sum of a property */ public static class SumProjection extends PropertyProjection { + protected SumProjection(String propertyName) { super(propertyName); } } - /** * A list of projections */ @@ -1530,6 +1605,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList rowCount() { /** * A projection that obtains the value of a property of an entity + * * @param name The name of the property * @return The PropertyProjection instance */ diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/QueryCreator.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/QueryCreator.java index 4170a0d68fc..dec758880a4 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/QueryCreator.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/QueryCreator.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.query; /** @@ -26,6 +25,7 @@ * @since 6.0 */ public interface QueryCreator { + /** * Creates a query instance for the give type * diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/QueryException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/QueryException.java index bf42cabc721..80d73a208c1 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/QueryException.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/QueryException.java @@ -17,6 +17,7 @@ * under the License. */ package org.grails.datastore.mapping.query; + import org.grails.datastore.mapping.core.DatastoreException; /** @@ -26,6 +27,7 @@ * @since 5.0 */ public class QueryException extends DatastoreException { + public QueryException(String s) { super(s); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Restrictions.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Restrictions.java index 4b8c3d89a09..66a82a376af 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Restrictions.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/Restrictions.java @@ -29,8 +29,9 @@ public class Restrictions { /** * Restricts the property to be equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return An instance of Query.Equals */ public static Query.Equals eq(String property, Object value) { @@ -39,6 +40,7 @@ public static Query.Equals eq(String property, Object value) { /** * Restricts the property to be equal to the given value + * * @param value The value * @return An instance of Query.Equals */ @@ -48,8 +50,9 @@ public static Query.IdEquals idEq(Object value) { /** * Restricts the property to be not equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return An instance of Query.Equals */ @@ -59,8 +62,9 @@ public static Query.NotEquals ne(String property, Object value) { /** * Restricts the property to be in the list of given values + * * @param property The property - * @param values The values + * @param values The values * @return An instance of Query.In */ public static Query.In in(String property, Collection values) { @@ -69,6 +73,7 @@ public static Query.In in(String property, Collection values) { /** * Restricts the property to be in the list of given values + * * @param property The property * @param subquery The subquery * @return An instance of Query.In @@ -77,9 +82,9 @@ public static Query.In in(String property, QueryableCriteria subquery) { return new Query.In(property, subquery); } - /** * Restricts the property to be in the list of given values + * * @param property The property * @param subquery The subquery * @return An instance of Query.In @@ -90,7 +95,8 @@ public static Query.NotIn notIn(String property, QueryableCriteria subquery) { /** * Restricts the property match the given String expressions. Expressions use SQL-like % to denote wildcards - * @param property The property name + * + * @param property The property name * @param expression The expression * @return An instance of Query.Like */ @@ -101,7 +107,7 @@ public static Query.Like like(String property, String expression) { /** * Case insensitive like * - * @param property The property + * @param property The property * @param expression The expression * @return An ILike expression */ @@ -112,7 +118,7 @@ public static Query.ILike ilike(String property, String expression) { /** * Restricts the property match the given regular expressions. * - * @param property The property name + * @param property The property name * @param expression The expression * @return An instance of Query.RLike */ @@ -132,8 +138,8 @@ public static Query.Criterion or(Query.Criterion a, Query.Criterion b) { * Restricts the results by the given property value range * * @param property The name of the property - * @param start The start of the range - * @param end The end of the range + * @param start The start of the range + * @param end The end of the range * @return The Between instance */ public static Query.Between between(String property, Object start, Object end) { @@ -142,8 +148,9 @@ public static Query.Between between(String property, Object start, Object end) { /** * Used to restrict a value to be greater than the given value + * * @param property The property - * @param value The value + * @param value The value * @return The GreaterThan instance */ public static Query.GreaterThan gt(String property, Object value) { @@ -152,8 +159,9 @@ public static Query.GreaterThan gt(String property, Object value) { /** * Used to restrict a value to be less than the given value + * * @param property The property - * @param value The value + * @param value The value * @return The LessThan instance */ public static Query.LessThan lt(String property, Object value) { @@ -162,8 +170,9 @@ public static Query.LessThan lt(String property, Object value) { /** * Used to restrict a value to be greater than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The LessThan instance */ public static Query.GreaterThanEquals gte(String property, Object value) { @@ -172,8 +181,9 @@ public static Query.GreaterThanEquals gte(String property, Object value) { /** * Used to restrict a value to be less than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The LessThan instance */ public static Query.LessThanEquals lte(String property, Object value) { @@ -224,7 +234,7 @@ public static Query.IsNotNull isNotNull(String property) { * Used to restrict the size of a collection property * * @param property The property - * @param size The size to restrict + * @param size The size to restrict * @return The result */ public static Query.SizeEquals sizeEq(String property, int size) { @@ -235,7 +245,7 @@ public static Query.SizeEquals sizeEq(String property, int size) { * Used to restrict the size of a collection property to be greater than the given value * * @param property The property - * @param size The size to restrict + * @param size The size to restrict * @return The result */ public static Query.SizeGreaterThan sizeGt(String property, int size) { @@ -246,7 +256,7 @@ public static Query.SizeGreaterThan sizeGt(String property, int size) { * Used to restrict the size of a collection property to be greater than or equal to the given value * * @param property The property - * @param size The size to restrict + * @param size The size to restrict * @return The result */ public static Query.SizeGreaterThanEquals sizeGe(String property, int size) { @@ -257,8 +267,7 @@ public static Query.SizeGreaterThanEquals sizeGe(String property, int size) { * Creates a Criterion that contrains a collection property to be less than or equal to the given size * * @param property The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return A Criterion instance */ public static Query.SizeLessThanEquals sizeLe(String property, int size) { @@ -269,8 +278,7 @@ public static Query.SizeLessThanEquals sizeLe(String property, int size) { * Creates a Criterion that contrains a collection property to be less than to the given size * * @param property The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return A Criterion instance */ public static Query.SizeLessThan sizeLt(String property, int size) { @@ -281,8 +289,7 @@ public static Query.SizeLessThan sizeLt(String property, int size) { * Creates a Criterion that contrains a collection property to be not equal to the given size * * @param property The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return A Criterion instance */ public static Query.SizeNotEquals sizeNe(String property, int size) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/BuildableCriteria.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/BuildableCriteria.java index de3fc094d60..0504bfbc65c 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/BuildableCriteria.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/BuildableCriteria.java @@ -20,19 +20,18 @@ import groovy.lang.Closure; import groovy.lang.DelegatesTo; - import jakarta.persistence.criteria.JoinType; + import java.util.Map; /** - * + * * @author Jeff Brown * @since 3.1.2 * */ public interface BuildableCriteria extends Criteria { - /** * @return The class the criteria applies to */ @@ -70,6 +69,7 @@ public interface BuildableCriteria extends Criteria { * @return This criteria */ BuildableCriteria join(String property, JoinType joinType); + /** * Whether to select on an association * @@ -80,44 +80,41 @@ public interface BuildableCriteria extends Criteria { /** * Defines and executes a list query in a single call. Example: Foo.createCriteria().list { } - * @param closure The closure to execute * + * @param closure The closure to execute * @return The result */ Object list(@DelegatesTo(Criteria.class) Closure closure); /** * Defines and executes a list query in a single call. Example: Foo.createCriteria().list { } - * - * @param params pagination parameters (max, offset, etc...) - * @param closure The closure to execute * + * @param params pagination parameters (max, offset, etc...) + * @param closure The closure to execute * @return The result */ Object list(Map params, @DelegatesTo(Criteria.class) Closure closure); - + /** * Defines and executes a list distinct query in a single call. Example: Foo.createCriteria().listDistinct { } - * @param closure The closure to execute * - * @return The result + * @param closure The closure to execute + * @return The result */ Object listDistinct(@DelegatesTo(Criteria.class) Closure closure); - + /** * Defines and executes a scroll query in a single call. Example: Foo.createCriteria().scroll { } - * - * @param closure The closure to execute * + * @param closure The closure to execute * @return A scrollable result set */ Object scroll(@DelegatesTo(Criteria.class) Closure closure); - + /** * Defines and executes a get query ( a single result) in a single call. Example: Foo.createCriteria().get { } * * @param closure The closure to execute - * * @return A single result */ Object get(@DelegatesTo(Criteria.class) Closure closure); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/Criteria.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/Criteria.java index ef5ffc6fa45..b3f0f2eefa4 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/Criteria.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/Criteria.java @@ -32,7 +32,7 @@ * @since 1.0 */ @SuppressWarnings("rawtypes") -public interface Criteria { +public interface Criteria { /** * Executes an exists subquery @@ -52,6 +52,7 @@ public interface Criteria { /** * Creates a criterion that restricts the id to the given value + * * @param value The value * @return The criteria */ @@ -92,9 +93,8 @@ public interface Criteria { /** * Creates an "equals" Criterion based on the specified property name and value * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return The criteria */ Criteria eq(String propertyName, Object propertyValue); @@ -103,7 +103,6 @@ public interface Criteria { * Creates an "equals" Criterion based on the specified property name and value * * @param propertyValue The property value - * * @return The criteria */ Criteria idEq(Object propertyValue); @@ -111,9 +110,8 @@ public interface Criteria { /** * Creates a "not equals" Criterion based on the specified property name and value * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return The criteria */ Criteria ne(String propertyName, Object propertyValue); @@ -122,57 +120,62 @@ public interface Criteria { * Restricts the results by the given property value range (inclusive) * * @param propertyName The property name - * - * @param start The start of the range - * @param finish The end of the range + * @param start The start of the range + * @param finish The end of the range * @return The criteria */ Criteria between(String propertyName, Object start, Object finish); /** * Used to restrict a value to be greater than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The Criterion instance */ Criteria gte(String property, Object value); /** * Used to restrict a value to be greater than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The Criterion instance */ Criteria ge(String property, Object value); /** * Used to restrict a value to be greater than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The Criterion instance */ Criteria gt(String property, Object value); /** * Used to restrict a value to be less than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The Criterion instance */ Criteria lte(String property, Object value); /** * Used to restrict a value to be less than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The Criterion instance */ Criteria le(String property, Object value); /** * Used to restrict a value to be less than or equal to the given value + * * @param property The property - * @param value The value + * @param value The value * @return The Criterion instance */ Criteria lt(String property, Object value); @@ -180,9 +183,8 @@ public interface Criteria { /** * Creates a like Criterion based on the specified property name and value * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return The criteria */ Criteria like(String propertyName, Object propertyValue); @@ -190,9 +192,8 @@ public interface Criteria { /** * Creates an ilike Criterion based on the specified property name and value. Unlike a like condition, ilike is case insensitive * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return The criteria */ Criteria ilike(String propertyName, Object propertyValue); @@ -200,23 +201,23 @@ public interface Criteria { /** * Creates an rlike Criterion based on the specified property name and value * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return The criteria */ Criteria rlike(String propertyName, Object propertyValue); /** * Creates a logical conjunction - * @param callable The closure * + * @param callable The closure * @return This criteria */ Criteria and(@DelegatesTo(Criteria.class) Closure callable); /** * Creates a logical disjunction + * * @param callable The closure * @return This criteria */ @@ -224,6 +225,7 @@ public interface Criteria { /** * Creates a logical negation + * * @param callable The closure * @return This criteria */ @@ -233,8 +235,7 @@ public interface Criteria { * Creates an "in" Criterion based on the specified property name and list of values * * @param propertyName The property name - * @param values The values - * + * @param values The values * @return The criteria */ Criteria in(String propertyName, Collection values); @@ -243,19 +244,16 @@ public interface Criteria { * Creates an "in" Criterion using a subquery * * @param propertyName The property name - * @param subquery The subquery - * + * @param subquery The subquery * @return The criteria */ Criteria in(String propertyName, QueryableCriteria subquery); - /** * Creates an "in" Criterion using a subquery * * @param propertyName The property name - * @param subquery The subquery - * + * @param subquery The subquery * @return The criteria */ Criteria inList(String propertyName, QueryableCriteria subquery); @@ -264,8 +262,7 @@ public interface Criteria { * Creates an "in" Criterion using a subquery * * @param propertyName The property name - * @param subquery The subquery - * + * @param subquery The subquery * @return The criteria */ Criteria in(String propertyName, Closure subquery); @@ -274,8 +271,7 @@ public interface Criteria { * Creates an "in" Criterion using a subquery * * @param propertyName The property name - * @param subquery The subquery - * + * @param subquery The subquery * @return The criteria */ Criteria inList(String propertyName, Closure subquery); @@ -284,8 +280,7 @@ public interface Criteria { * Creates an "in" Criterion based on the specified property name and list of values * * @param propertyName The property name - * @param values The values - * + * @param values The values * @return The criteria */ Criteria inList(String propertyName, Collection values); @@ -294,28 +289,25 @@ public interface Criteria { * Creates an "in" Criterion based on the specified property name and list of values * * @param propertyName The property name - * @param values The values - * + * @param values The values * @return The criteria */ Criteria inList(String propertyName, Object[] values); /** - * Creates an "in" Criterion based on the specified property name and list of values - * - * @param propertyName The property name - * @param values The values - * - * @return The criteria - */ + * Creates an "in" Criterion based on the specified property name and list of values + * + * @param propertyName The property name + * @param values The values + * @return The criteria + */ Criteria in(String propertyName, Object[] values); /** * Creates a negated "in" Criterion using a subquery * * @param propertyName The property name - * @param subquery The subquery - * + * @param subquery The subquery * @return The criteria */ Criteria notIn(String propertyName, QueryableCriteria subquery); @@ -324,8 +316,7 @@ public interface Criteria { * Creates a negated "in" Criterion using a subquery * * @param propertyName The property name - * @param subquery The subquery - * + * @param subquery The subquery * @return The criteria */ Criteria notIn(String propertyName, Closure subquery); @@ -350,8 +341,7 @@ public interface Criteria { * Orders by the specified property name and direction * * @param propertyName The property name to order by - * @param direction Either "asc" for ascending or "desc" for descending - * + * @param direction Either "asc" for ascending or "desc" for descending * @return This criteria */ Criteria order(String propertyName, String direction); @@ -360,18 +350,16 @@ public interface Criteria { * Creates a Criterion that constrains a collection property by size * * @param propertyName The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return This criteria */ - Criteria sizeEq(String propertyName, int size) ; + Criteria sizeEq(String propertyName, int size); /** * Creates a Criterion that constrains a collection property to be greater than the given size * * @param propertyName The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return This criteria */ Criteria sizeGt(String propertyName, int size); @@ -380,8 +368,7 @@ public interface Criteria { * Creates a Criterion that constrains a collection property to be greater than or equal to the given size * * @param propertyName The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return This criteria */ Criteria sizeGe(String propertyName, int size); @@ -390,8 +377,7 @@ public interface Criteria { * Creates a Criterion that constrains a collection property to be less than or equal to the given size * * @param propertyName The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return This criteria */ Criteria sizeLe(String propertyName, int size); @@ -400,8 +386,7 @@ public interface Criteria { * Creates a Criterion that constrains a collection property to be less than to the given size * * @param propertyName The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return This criteria */ Criteria sizeLt(String propertyName, int size); @@ -410,8 +395,7 @@ public interface Criteria { * Creates a Criterion that constrains a collection property to be not equal to the given size * * @param propertyName The property name - * @param size The size to constrain by - * + * @param size The size to constrain by * @return This criteria */ Criteria sizeNe(String propertyName, int size); @@ -419,7 +403,7 @@ public interface Criteria { /** * Constrains a property to be equal to a specified other property * - * @param propertyName The property + * @param propertyName The property * @param otherPropertyName The other property * @return This criteria */ @@ -428,7 +412,7 @@ public interface Criteria { /** * Constrains a property to be not equal to a specified other property * - * @param propertyName The property + * @param propertyName The property * @param otherPropertyName The other property * @return This criteria */ @@ -437,7 +421,7 @@ public interface Criteria { /** * Constrains a property to be greater than a specified other property * - * @param propertyName The property + * @param propertyName The property * @param otherPropertyName The other property * @return This criteria */ @@ -446,7 +430,7 @@ public interface Criteria { /** * Constrains a property to be greater than or equal to a specified other property * - * @param propertyName The property + * @param propertyName The property * @param otherPropertyName The other property * @return This criteria */ @@ -455,7 +439,7 @@ public interface Criteria { /** * Constrains a property to be less than a specified other property * - * @param propertyName The property + * @param propertyName The property * @param otherPropertyName The other property * @return This criteria */ @@ -464,7 +448,7 @@ public interface Criteria { /** * Constrains a property to be less than or equal to a specified other property * - * @param propertyName The property + * @param propertyName The property * @param otherPropertyName The other property * @return This criteria */ @@ -474,20 +458,17 @@ public interface Criteria { * Apply an "equals" constraint to each property in the key set of a Map * * @param propertyValues a map from property names to values - * * @return Criterion - * * @see org.grails.datastore.mapping.query.Query.Conjunction */ Criteria allEq(Map propertyValues); - //===== Subquery methods /** * Creates a subquery criterion that ensures the given property is equals to all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue A closure that is converted to a {@link org.grails.datastore.mapping.query.api.QueryableCriteria} * @return This criterion instance */ @@ -496,7 +477,7 @@ public interface Criteria { /** * Creates a subquery criterion that ensures the given property is greater than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue A closure that is converted to a {@link org.grails.datastore.mapping.query.api.QueryableCriteria} * @return This criterion instance */ @@ -505,23 +486,25 @@ public interface Criteria { /** * Creates a subquery criterion that ensures the given property is less than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue A closure that is converted to a {@link org.grails.datastore.mapping.query.api.QueryableCriteria} * @return This criterion instance */ Criteria ltAll(String propertyName, Closure propertyValue); + /** * Creates a subquery criterion that ensures the given property is greater than or equals to all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue A closure that is converted to a {@link org.grails.datastore.mapping.query.api.QueryableCriteria} * @return This criterion instance */ Criteria geAll(String propertyName, Closure propertyValue); + /** * Creates a subquery criterion that ensures the given property is less than or equal to all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue A closure that is converted to a {@link org.grails.datastore.mapping.query.api.QueryableCriteria} * @return This criterion instance */ @@ -530,9 +513,8 @@ public interface Criteria { /** * Creates a subquery criterion that ensures the given property is equal to all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return This Criteria instance */ Criteria eqAll(String propertyName, QueryableCriteria propertyValue); @@ -540,9 +522,8 @@ public interface Criteria { /** * Creates a subquery criterion that ensures the given property is greater than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return This Criteria instance */ Criteria gtAll(String propertyName, QueryableCriteria propertyValue); @@ -550,9 +531,8 @@ public interface Criteria { /** * Creates a subquery criterion that ensures the given property is less than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return This Criteria instance */ Criteria ltAll(String propertyName, QueryableCriteria propertyValue); @@ -560,9 +540,8 @@ public interface Criteria { /** * Creates a subquery criterion that ensures the given property is greater than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return This Criteria instance */ Criteria geAll(String propertyName, QueryableCriteria propertyValue); @@ -570,20 +549,17 @@ public interface Criteria { /** * Creates a subquery criterion that ensures the given property is less than all the given returned values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return This Criteria instance */ Criteria leAll(String propertyName, QueryableCriteria propertyValue); - /** * Creates a subquery criterion that ensures the given property is greater than some of the given values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return This Criteria instance */ Criteria gtSome(String propertyName, QueryableCriteria propertyValue); @@ -591,9 +567,8 @@ public interface Criteria { /** * Creates a subquery criterion that ensures the given property is greater than some of the given values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return This Criteria instance */ Criteria gtSome(String propertyName, Closure propertyValue); @@ -601,9 +576,8 @@ public interface Criteria { /** * Creates a subquery criterion that ensures the given property is greater than or equal to some of the given values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return This Criteria instance */ Criteria geSome(String propertyName, QueryableCriteria propertyValue); @@ -611,20 +585,17 @@ public interface Criteria { /** * Creates a subquery criterion that ensures the given property is greater than or equal to some of the given values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return This Criteria instance */ Criteria geSome(String propertyName, Closure propertyValue); - /** * Creates a subquery criterion that ensures the given property is less than some of the given values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return This Criteria instance */ Criteria ltSome(String propertyName, QueryableCriteria propertyValue); @@ -632,9 +603,8 @@ public interface Criteria { /** * Creates a subquery criterion that ensures the given property is less than some of the given values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return This Criteria instance */ Criteria ltSome(String propertyName, Closure propertyValue); @@ -642,9 +612,8 @@ public interface Criteria { /** * Creates a subquery criterion that ensures the given property is less than or equal to some of the given values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return This Criteria instance */ Criteria leSome(String propertyName, QueryableCriteria propertyValue); @@ -652,21 +621,19 @@ public interface Criteria { /** * Creates a subquery criterion that ensures the given property is less than or equal to some of the given values * - * @param propertyName The property name + * @param propertyName The property name * @param propertyValue The property value - * * @return This Criteria instance */ Criteria leSome(String propertyName, Closure propertyValue); /** *

    Configures the second-level cache with the default usage of 'read-write' and the default include of 'all' if - * the passed argument is true + * the passed argument is true * * { cache true } * * @param shouldCache True if the default cache configuration should be applied - * * @return This Criteria instance */ Criteria cache(boolean shouldCache); @@ -677,8 +644,7 @@ public interface Criteria { * { readOnly true } * * @param readOnly True to disable dirty checking - * - * @return This Criteria instance + * @return This Criteria instance */ Criteria readOnly(boolean readOnly); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/ProjectionList.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/ProjectionList.java index 9c8fb87e90d..4cbb0c49a69 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/ProjectionList.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/ProjectionList.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.query.api; /** @@ -26,20 +25,24 @@ * @since 1.0 */ public interface ProjectionList { + /** - * A Projection that obtains the id of an object - * @return The projection list - */ + * A Projection that obtains the id of an object + * + * @return The projection list + */ ProjectionList id(); /** * Count the number of records returned + * * @return The projection list */ ProjectionList count(); /** * Count the number of records returned + * * @param property The property name to count * @return The projection list */ @@ -49,7 +52,6 @@ public interface ProjectionList { * Defines a group by projection for datastores that support it * * @param property The property name - * * @return The projection list */ ProjectionList groupProperty(String property); @@ -65,19 +67,20 @@ public interface ProjectionList { * Projection to return only distinct properties * * @param property The property name to use - * * @return The projection list */ ProjectionList distinct(String property); /** * Count the number of records returned + * * @return The projection list */ ProjectionList rowCount(); /** * A projection that obtains the value of a property of an entity + * * @param name The name of the property * @return The PropertyProjection instance */ diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryAliasAwareSession.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryAliasAwareSession.java index f6a78115fb6..54a4cf4b4f1 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryAliasAwareSession.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryAliasAwareSession.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.query.api; import org.grails.datastore.mapping.core.Session; @@ -31,7 +30,7 @@ public interface QueryAliasAwareSession extends Session { /** * Creates a query instance for the give type * - * @param type The type + * @param type The type * @param alias The alias to use in the query * @return The query */ diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryArgumentsAware.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryArgumentsAware.java index 5a0568d817e..9c7a9032e4c 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryArgumentsAware.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryArgumentsAware.java @@ -1,18 +1,17 @@ /* Copyright (C) 2011 SpringSource -* -* Licensed 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. -*/ - + * + * Licensed 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.datastore.mapping.query.api; import java.util.Map; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryableCriteria.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryableCriteria.java index f03256324ae..1d803aa8ab5 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryableCriteria.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/QueryableCriteria.java @@ -33,6 +33,7 @@ public interface QueryableCriteria extends Criteria { * @return The target entity */ PersistentEntity getPersistentEntity(); + /** * @return A list of all criteria */ @@ -47,6 +48,7 @@ public interface QueryableCriteria extends Criteria { /** * List all results + * * @return All results */ List list(); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/criteria/FunctionCallingCriterion.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/criteria/FunctionCallingCriterion.java index 350aefad40a..8b327512275 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/criteria/FunctionCallingCriterion.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/criteria/FunctionCallingCriterion.java @@ -22,7 +22,7 @@ /** * This criterion calls a function on the property before apply the appropriate comparison. - * + *

    * Example in SQL: year(date) == 2007 where the function is 'year', the property 'date' and the value is '2007' */ public class FunctionCallingCriterion extends Query.PropertyNameCriterion { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/AbstractQueryEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/AbstractQueryEvent.java index c0eb33927a4..93476b37754 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/AbstractQueryEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/AbstractQueryEvent.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.query.event; import org.grails.datastore.mapping.query.Query; @@ -26,6 +25,7 @@ * Base class for query events. */ public abstract class AbstractQueryEvent extends ApplicationEvent { + /** * The query. */ @@ -48,6 +48,7 @@ public AbstractQueryEvent(Object source, Query query) { /** * Get the query from the event. + * * @return The query. */ public Query getQuery() { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PostQueryEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PostQueryEvent.java index 3889e2bac41..715e87fd466 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PostQueryEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PostQueryEvent.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.query.event; import org.grails.datastore.mapping.query.Query; @@ -27,6 +26,7 @@ * Query fired after a query has run. */ public class PostQueryEvent extends AbstractQueryEvent { + /** * The results of the query. */ @@ -51,6 +51,7 @@ public List getResults() { /** * Reset the list of results to a new list. This allows an event handler to modify the results of a query. + * * @param results The replacement results. */ public void setResults(List results) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PreQueryEvent.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PreQueryEvent.java index e0cd8ccdb9a..de4e9022ec4 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PreQueryEvent.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/PreQueryEvent.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.query.event; import org.grails.datastore.mapping.query.Query; @@ -25,6 +24,7 @@ * Event fired immediately before a query is executed. */ public class PreQueryEvent extends AbstractQueryEvent { + public PreQueryEvent(Query query) { super(query); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/QueryEventType.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/QueryEventType.java index aad3e153bc9..59e74bbfe78 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/QueryEventType.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/event/QueryEventType.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.query.event; /** diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryBuilder.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryBuilder.java index 30ebc64ba76..873bdab3e98 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryBuilder.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryBuilder.java @@ -18,15 +18,6 @@ */ package org.grails.datastore.mapping.query.jpa; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - import org.grails.datastore.mapping.model.AbstractPersistentEntity; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; @@ -40,6 +31,15 @@ import org.springframework.core.convert.support.GenericConversionService; import org.springframework.dao.InvalidDataAccessResourceUsageException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + /** * Builds JPA 1.0 String-based queries from the Query model * @@ -48,6 +48,13 @@ */ @SuppressWarnings({"rawtypes", "unchecked"}) public class JpaQueryBuilder { + + public static final String DELETE_CLAUSE = "DELETE "; + public static final String LOGICAL_AND = " AND "; + public static final String LOGICAL_OR = " OR "; + public static final String NOT_CLAUSE = " NOT"; + public static final String PARAMETER_NAME_PREFIX = "p"; + public static final String UPDATE_CLAUSE = "UPDATE "; private static final String DISTINCT_CLAUSE = "DISTINCT "; private static final String SELECT_CLAUSE = "SELECT "; private static final String AS_CLAUSE = " AS "; @@ -60,19 +67,12 @@ public class JpaQueryBuilder { private static final char SPACE = ' '; private static final char QUESTIONMARK = '?'; private static final char DOT = '.'; - public static final String NOT_CLAUSE = " NOT"; - public static final String LOGICAL_AND = " AND "; - public static final String UPDATE_CLAUSE = "UPDATE "; - public static final String DELETE_CLAUSE = "DELETE "; - - public static final String LOGICAL_OR = " OR "; - private static final Map queryHandlers = new HashMap<>(); - public static final String PARAMETER_NAME_PREFIX = "p"; + private static final Map QUERY_HANDLERS = new HashMap<>(); private static final String PARAMETER_PREFIX = ":p"; private PersistentEntity entity; private Query.Junction criteria; private Query.ProjectionList projectionList = new Query.ProjectionList(); - private List orders= Collections.emptyList(); + private List orders = Collections.emptyList(); private String logicalName; private ConversionService conversionService = new GenericConversionService(); private boolean hibernateCompatible; @@ -85,7 +85,7 @@ public JpaQueryBuilder(PersistentEntity entity, List criteria) this(entity, new Query.Conjunction(criteria)); } - public JpaQueryBuilder(PersistentEntity entity,List criteria, Query.ProjectionList projectionList) { + public JpaQueryBuilder(PersistentEntity entity, List criteria, Query.ProjectionList projectionList) { this(entity, new Query.Conjunction(criteria), projectionList); } @@ -158,10 +158,10 @@ public JpaQueryInfo buildSelect() { buildSelectClause(queryString); - StringBuilder whereClause= new StringBuilder(); + StringBuilder whereClause = new StringBuilder(); List parameters = null; if (!criteria.isEmpty()) { - parameters = buildWhereClause(entity, criteria, queryString, whereClause,logicalName, true); + parameters = buildWhereClause(entity, criteria, queryString, whereClause, logicalName, true); } appendOrder(queryString, logicalName); @@ -176,7 +176,7 @@ private void buildSelectClause(StringBuilder queryString) { queryString.append(FROM_CLAUSE) .append(entity.getName()) - .append(AS_CLAUSE ) + .append(AS_CLAUSE) .append(logicalName); } @@ -184,21 +184,18 @@ private static void buildSelect(StringBuilder queryString, List ", hibernateCompatible); - parameters.add(conversionService.convert( eq.getValue(), propType )); + parameters.add(conversionService.convert(eq.getValue(), propType)); return position; } }); - queryHandlers.put(Query.LessThanEquals.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.LessThanEquals.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.LessThanEquals eq = (Query.LessThanEquals) criterion; final String name = eq.getProperty(); PersistentProperty prop = validateProperty(entity, name, Query.LessThanEquals.class); Class propType = prop.getType(); position = appendCriteriaForOperator(whereClause, logicalName, name, position, " <= ", hibernateCompatible); - parameters.add(conversionService.convert( eq.getValue(), propType )); + parameters.add(conversionService.convert(eq.getValue(), propType)); return position; } }); - queryHandlers.put(Query.GreaterThanEquals.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.GreaterThanEquals.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.GreaterThanEquals eq = (Query.GreaterThanEquals) criterion; final String name = eq.getProperty(); PersistentProperty prop = validateProperty(entity, name, Query.GreaterThanEquals.class); Class propType = prop.getType(); position = appendCriteriaForOperator(whereClause, logicalName, name, position, " >= ", hibernateCompatible); - parameters.add(conversionService.convert( eq.getValue(), propType )); + parameters.add(conversionService.convert(eq.getValue(), propType)); return position; } }); - queryHandlers.put(Query.Between.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.Between.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.Between between = (Query.Between) criterion; final Object from = between.getFrom(); @@ -553,83 +545,82 @@ public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuil Class propType = prop.getType(); final String qualifiedName = logicalName + DOT + name; whereClause.append(OPEN_BRACKET) - .append(qualifiedName) - .append(" >= ") - .append(PARAMETER_PREFIX) - .append(++position); + .append(qualifiedName) + .append(" >= ") + .append(PARAMETER_PREFIX) + .append(++position); whereClause.append(" AND ") - .append(qualifiedName) - .append(" <= ") - .append(PARAMETER_PREFIX) - .append(++position) - .append(CLOSE_BRACKET); - - parameters.add(conversionService.convert( from, propType )); - parameters.add(conversionService.convert( to, propType )); + .append(qualifiedName) + .append(" <= ") + .append(PARAMETER_PREFIX) + .append(++position) + .append(CLOSE_BRACKET); + + parameters.add(conversionService.convert(from, propType)); + parameters.add(conversionService.convert(to, propType)); return position; } }); - queryHandlers.put(Query.LessThan.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.LessThan.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.LessThan eq = (Query.LessThan) criterion; final String name = eq.getProperty(); PersistentProperty prop = validateProperty(entity, name, Query.LessThan.class); Class propType = prop.getType(); position = appendCriteriaForOperator(whereClause, logicalName, name, position, " < ", hibernateCompatible); - parameters.add(conversionService.convert( eq.getValue(), propType )); + parameters.add(conversionService.convert(eq.getValue(), propType)); return position; } }); - queryHandlers.put(Query.Like.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.Like.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.Like eq = (Query.Like) criterion; final String name = eq.getProperty(); PersistentProperty prop = validateProperty(entity, name, Query.Like.class); Class propType = prop.getType(); position = appendCriteriaForOperator(whereClause, logicalName, name, position, " like ", hibernateCompatible); - parameters.add(conversionService.convert( eq.getValue(), propType )); + parameters.add(conversionService.convert(eq.getValue(), propType)); return position; } }); - queryHandlers.put(Query.ILike.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.ILike.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.ILike eq = (Query.ILike) criterion; final String name = eq.getProperty(); PersistentProperty prop = validateProperty(entity, name, Query.ILike.class); Class propType = prop.getType(); whereClause.append("lower(") - .append(logicalName) - .append(DOT) - .append(name) - .append(")") - .append(" like lower(") - .append(PARAMETER_PREFIX) - .append(++position) - .append(")"); - parameters.add(conversionService.convert( eq.getValue(), propType )); + .append(logicalName) + .append(DOT) + .append(name) + .append(")") + .append(" like lower(") + .append(PARAMETER_PREFIX) + .append(++position) + .append(")"); + parameters.add(conversionService.convert(eq.getValue(), propType)); return position; } }); - queryHandlers.put(Query.In.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.In.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.In inQuery = (Query.In) criterion; final String name = inQuery.getProperty(); PersistentProperty prop = validateProperty(entity, name, Query.In.class); Class propType = prop.getType(); whereClause.append(logicalName) - .append(DOT) - .append(name) - .append(" IN ("); + .append(DOT) + .append(name) + .append(" IN ("); QueryableCriteria subquery = inQuery.getSubquery(); - if(subquery != null) { + if (subquery != null) { buildSubQuery(q, whereClause, position, parameters, conversionService, allowJoins, hibernateCompatible, subquery); - } - else { - for (Iterator i = inQuery.getValues().iterator(); i.hasNext();) { + } else { + for (Iterator i = inQuery.getValues().iterator(); i.hasNext(); ) { Object val = i.next(); whereClause.append(PARAMETER_PREFIX); whereClause.append(++position); @@ -645,7 +636,7 @@ public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuil } }); - queryHandlers.put(Query.NotIn.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.NotIn.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.NotIn notIn = (Query.NotIn) criterion; String comparisonExpression = " NOT IN ("; @@ -653,7 +644,7 @@ public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuil } }); - queryHandlers.put(Query.EqualsAll.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.EqualsAll.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.EqualsAll equalsAll = (Query.EqualsAll) criterion; String comparisonExpression = " = ALL ("; @@ -661,7 +652,7 @@ public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuil } }); - queryHandlers.put(Query.NotEqualsAll.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.NotEqualsAll.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.SubqueryCriterion equalsAll = (Query.SubqueryCriterion) criterion; String comparisonExpression = " != ALL ("; @@ -669,7 +660,7 @@ public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuil } }); - queryHandlers.put(Query.GreaterThanAll.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.GreaterThanAll.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.SubqueryCriterion equalsAll = (Query.SubqueryCriterion) criterion; String comparisonExpression = " > ALL ("; @@ -677,7 +668,7 @@ public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuil } }); - queryHandlers.put(Query.GreaterThanSome.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.GreaterThanSome.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.SubqueryCriterion equalsAll = (Query.SubqueryCriterion) criterion; String comparisonExpression = " > SOME ("; @@ -685,7 +676,7 @@ public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuil } }); - queryHandlers.put(Query.GreaterThanEqualsAll.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.GreaterThanEqualsAll.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.SubqueryCriterion equalsAll = (Query.SubqueryCriterion) criterion; String comparisonExpression = " >= ALL ("; @@ -693,7 +684,7 @@ public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuil } }); - queryHandlers.put(Query.GreaterThanEqualsSome.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.GreaterThanEqualsSome.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.SubqueryCriterion equalsAll = (Query.SubqueryCriterion) criterion; String comparisonExpression = " >= SOME ("; @@ -701,7 +692,7 @@ public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuil } }); - queryHandlers.put(Query.LessThanAll.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.LessThanAll.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.SubqueryCriterion subqueryCriterion = (Query.SubqueryCriterion) criterion; String comparisonExpression = " < ALL ("; @@ -709,7 +700,7 @@ public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuil } }); - queryHandlers.put(Query.LessThanSome.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.LessThanSome.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.SubqueryCriterion subqueryCriterion = (Query.SubqueryCriterion) criterion; String comparisonExpression = " < SOME ("; @@ -717,7 +708,7 @@ public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuil } }); - queryHandlers.put(Query.LessThanEqualsAll.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.LessThanEqualsAll.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.SubqueryCriterion subqueryCriterion = (Query.SubqueryCriterion) criterion; String comparisonExpression = " <= ALL ("; @@ -725,7 +716,7 @@ public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuil } }); - queryHandlers.put(Query.LessThanEqualsSome.class, new QueryHandler() { + QUERY_HANDLERS.put(Query.LessThanEqualsSome.class, new QueryHandler() { public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { Query.SubqueryCriterion subqueryCriterion = (Query.SubqueryCriterion) criterion; String comparisonExpression = " <= SOME ("; @@ -761,7 +752,7 @@ protected static void buildSubQuery(StringBuilder q, StringBuilder whereClause, .append(" WHERE "); List criteria = subquery.getCriteria(); for (Query.Criterion subCriteria : criteria) { - QueryHandler queryHandler = queryHandlers.get(subCriteria.getClass()); + QueryHandler queryHandler = QUERY_HANDLERS.get(subCriteria.getClass()); queryHandler.handle(associatedEntity, subCriteria, q, whereClause, associatedEntityLogicalName, position, parameters, conversionService, allowJoins, hibernateCompatible); } } @@ -778,11 +769,11 @@ private static int handleAssociationCriteria(StringBuilder query, StringBuilder // TODO: Allow customization of join strategy! String joinType = " INNER JOIN "; query.append(joinType) - .append(logicalName) - .append(DOT) - .append(associationName) - .append(SPACE) - .append(associationName); + .append(logicalName) + .append(DOT) + .append(associationName) + .append(SPACE) + .append(associationName); return buildWhereClauseForCriterion(association.getAssociatedEntity(), associationCriteria, query, whereClause, associationName, associationCriteriaList, position, parameters, conversionService, allowJoins, hibernateCompatible); } @@ -800,7 +791,9 @@ private void buildUpdateStatement(StringBuilder queryString, Map while (iterator.hasNext()) { String propertyName = iterator.next(); PersistentProperty prop = entity.getPropertyByName(propertyName); - if (prop == null) throw new InvalidDataAccessResourceUsageException("Property '"+propertyName+"' of class '"+entity.getName()+"' specified in update does not exist"); + if (prop == null) { + throw new InvalidDataAccessResourceUsageException("Property '" + propertyName + "' of class '" + entity.getName() + "' specified in update does not exist"); + } parameters.add(propertiesToUpdate.get(propertyName)); queryString.append(SPACE).append(logicalName).append(DOT).append(propertyName).append('='); @@ -813,12 +806,12 @@ private void buildUpdateStatement(StringBuilder queryString, Map private static void appendPropertyComparison(StringBuilder q, String logicalName, String propertyName, String otherProperty, String operator) { q.append(logicalName) - .append(DOT) - .append(propertyName) - .append(operator) - .append(logicalName) - .append(DOT) - .append(otherProperty); + .append(DOT) + .append(propertyName) + .append(operator) + .append(logicalName) + .append(DOT) + .append(otherProperty); } private static PersistentProperty validateProperty(PersistentEntity entity, String name, Class criterionType) { @@ -827,9 +820,9 @@ private static PersistentProperty validateProperty(PersistentEntity entity, Stri return identity; } PersistentProperty[] compositeIdentity = ((AbstractPersistentEntity) entity).getCompositeIdentity(); - if(compositeIdentity != null) { + if (compositeIdentity != null) { for (PersistentProperty property : compositeIdentity) { - if(property.getName().equals(name)) { + if (property.getName().equals(name)) { return property; } } @@ -837,15 +830,11 @@ private static PersistentProperty validateProperty(PersistentEntity entity, Stri PersistentProperty prop = entity.getPropertyByName(name); if (prop == null) { throw new InvalidDataAccessResourceUsageException("Cannot use [" + - criterionType.getSimpleName() + "] criterion on non-existent property: " + name); + criterionType.getSimpleName() + "] criterion on non-existent property: " + name); } return prop; } - private static interface QueryHandler { - public int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible); - } - private List buildWhereClause(PersistentEntity entity, Query.Junction criteria, StringBuilder q, StringBuilder whereClause, String logicalName, boolean allowJoins) { List parameters = new ArrayList(); return buildWhereClause(entity, criteria, q, whereClause, logicalName, allowJoins, parameters); @@ -871,14 +860,14 @@ private List buildWhereClause(PersistentEntity entity, Query.Junction criteria, protected void appendOrder(StringBuilder queryString, String logicalName) { if (!orders.isEmpty()) { - queryString.append( ORDER_BY_CLAUSE); + queryString.append(ORDER_BY_CLAUSE); for (Query.Order order : orders) { queryString.append(logicalName) - .append(DOT) - .append(order.getProperty()) - .append(SPACE) - .append(order.getDirection().toString()) - .append(SPACE); + .append(DOT) + .append(order.getProperty()) + .append(SPACE) + .append(order.getDirection().toString()) + .append(SPACE); } } } @@ -886,17 +875,16 @@ protected void appendOrder(StringBuilder queryString, String logicalName) { static int buildWhereClauseForCriterion(PersistentEntity entity, Query.Junction criteria, StringBuilder q, StringBuilder whereClause, String logicalName, final List criterionList, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible) { - for (Iterator iterator = criterionList.iterator(); iterator.hasNext();) { + for (Iterator iterator = criterionList.iterator(); iterator.hasNext(); ) { Query.Criterion criterion = iterator.next(); final String operator = criteria instanceof Query.Conjunction ? LOGICAL_AND : LOGICAL_OR; - QueryHandler qh = queryHandlers.get(criterion.getClass()); + QueryHandler qh = QUERY_HANDLERS.get(criterion.getClass()); if (qh != null) { position = qh.handle(entity, criterion, q, whereClause, logicalName, position, parameters, conversionService, allowJoins, hibernateCompatible); - } - else if (criterion instanceof AssociationCriteria) { + } else if (criterion instanceof AssociationCriteria) { if (!allowJoins) { throw new InvalidDataAccessResourceUsageException("Joins cannot be used in a DELETE or UPDATE operation"); @@ -905,9 +893,8 @@ else if (criterion instanceof AssociationCriteria) { Association association = ac.getAssociation(); List associationCriteriaList = ac.getCriteria(); handleAssociationCriteria(q, whereClause, logicalName, position, parameters, conversionService, allowJoins, association, new Query.Conjunction(), associationCriteriaList, hibernateCompatible); - } - else { - throw new InvalidDataAccessResourceUsageException("Queries of type "+criterion.getClass().getSimpleName()+" are not supported by this implementation"); + } else { + throw new InvalidDataAccessResourceUsageException("Queries of type " + criterion.getClass().getSimpleName() + " are not supported by this implementation"); } if (iterator.hasNext()) { @@ -917,4 +904,9 @@ else if (criterion instanceof AssociationCriteria) { return position; } + + private interface QueryHandler { + + int handle(PersistentEntity entity, Query.Criterion criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int position, List parameters, ConversionService conversionService, boolean allowJoins, boolean hibernateCompatible); + } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryInfo.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryInfo.java index f278ccbefbc..d512a8ce0a5 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryInfo.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryInfo.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.query.jpa; import java.util.List; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/order/ManualEntityOrdering.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/order/ManualEntityOrdering.java index 0cb0ef6ebb6..b02adf74345 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/order/ManualEntityOrdering.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/order/ManualEntityOrdering.java @@ -18,6 +18,13 @@ */ package org.grails.datastore.mapping.query.order; +import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.datastore.mapping.model.PersistentProperty; +import org.grails.datastore.mapping.query.Query; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.PropertyAccessorFactory; +import org.springframework.util.ReflectionUtils; + import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.util.ArrayList; @@ -28,13 +35,6 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.PersistentProperty; -import org.grails.datastore.mapping.query.Query; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.PropertyAccessorFactory; -import org.springframework.util.ReflectionUtils; - /** * Manual implementation of query ordering for datastores that don't support native ordering. Not all * NoSQL datastores support the SQL equivalent of ORDER BY, hence manual in-memory ordering is the @@ -46,8 +46,8 @@ @SuppressWarnings({"rawtypes", "unchecked"}) public class ManualEntityOrdering { - PersistentEntity entity; private static Map cachedReadMethods = new ConcurrentHashMap(); + PersistentEntity entity; public ManualEntityOrdering(PersistentEntity entity) { this.entity = entity; @@ -58,8 +58,12 @@ public PersistentEntity getEntity() { } public List applyOrder(List results, List orderDefinition) { - if (results == null) return null; - if (orderDefinition == null) return results; + if (results == null) { + return null; + } + if (orderDefinition == null) { + return results; + } for (Query.Order order : orderDefinition) { results = applyOrder(results, order); } @@ -84,7 +88,7 @@ private static List reverse(List list) { } public List applyOrder(List results, Query.Order order) { - final String name = order.getProperty(); + final String name = order.getProperty(); final PersistentEntity entity = getEntity(); PersistentProperty property = entity.getPropertyByName(name); @@ -122,11 +126,17 @@ public int compare(Object o1, Object o2) { Object left = ReflectionUtils.invokeMethod(readMethod, o1); Object right = ReflectionUtils.invokeMethod(readMethod, o2); - if (left == null && right == null) return 0; - if (left != null && right == null) return 1; - if (left == null) return -1; + if (left == null && right == null) { + return 0; + } + if (left != null && right == null) { + return 1; + } + if (left == null) { + return -1; + } if ((left instanceof Comparable) && (right instanceof Comparable)) { - return ((Comparable)left).compareTo(right); + return ((Comparable) left).compareTo(right); } } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/projections/ManualProjections.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/projections/ManualProjections.java index c6f20561a1b..3b11e09a0d5 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/projections/ManualProjections.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/projections/ManualProjections.java @@ -14,10 +14,6 @@ */ package org.grails.datastore.mapping.query.projections; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.query.Query; @@ -25,6 +21,10 @@ import org.grails.datastore.mapping.reflect.EntityReflector; import org.grails.datastore.mapping.reflect.FieldEntityAccess; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + /** * Implements common projections in-memory given a set of results. Not all * NoSQL datastores support projections like SQL min(..), max(..) etc. @@ -44,7 +44,7 @@ public ManualProjections(PersistentEntity entity) { /** * Calculates the minimum value of a property * - * @param results The results + * @param results The results * @param property The property to calculate * @return The minimum value or null if there are no results */ @@ -64,7 +64,7 @@ public Object min(Collection results, String property) { /** * Counts the number of distinct values * - * @param results The results + * @param results The results * @param property The property * @return A count of the distinct values */ @@ -82,7 +82,7 @@ public Collection distinct(Collection results, String property) { /** * Calculates the maximum value of a property * - * @param results The results + * @param results The results * @param property The property to calculate * @return The maximum value or null if there are no results */ @@ -92,7 +92,7 @@ public Object max(Collection results, String property) { } final List sorted = order.applyOrder(new ArrayList(results), Query.Order.asc(property)); - final Object o = sorted.get(results.size()-1); + final Object o = sorted.get(results.size() - 1); if (entity.isInstance(o)) { return FieldEntityAccess.getOrIntializeReflector(entity).getProperty(o, property); } @@ -102,7 +102,7 @@ public Object max(Collection results, String property) { /** * Obtains a properties value from the results * - * @param results The results + * @param results The results * @param property The property * @return A list of results */ @@ -117,8 +117,7 @@ public List property(Collection results, String property) { EntityReflector ea = FieldEntityAccess.getOrIntializeReflector(entity); if (entity.isInstance(o)) { projectedResults.add(ea.getProperty(o, property)); - } - else { + } else { projectedResults.add(null); } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/rdbms/RelationalDatastore.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/rdbms/RelationalDatastore.java index ac2b8df8c79..be20140972c 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/rdbms/RelationalDatastore.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/rdbms/RelationalDatastore.java @@ -23,4 +23,6 @@ /** * @author Guillaume Laforge */ -public interface RelationalDatastore extends Datastore {} \ No newline at end of file +public interface RelationalDatastore extends Datastore { + +} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/AstAnnotationUtils.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/AstAnnotationUtils.groovy index 322506a21be..f77c7c55040 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/AstAnnotationUtils.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/AstAnnotationUtils.groovy @@ -27,7 +27,6 @@ import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.MethodNode import org.codehaus.groovy.ast.expr.ConstantExpression import org.codehaus.groovy.ast.expr.Expression -import org.codehaus.groovy.ast.expr.VariableExpression import java.lang.annotation.Annotation @@ -39,11 +38,12 @@ import java.lang.annotation.Annotation */ @CompileStatic class AstAnnotationUtils { + private static final Set JUNIT_ANNOTATION_NAMES = new HashSet(Arrays.asList("org.junit.jupiter.api.BeforeEach", "org.junit.jupiter.api.AfterEach")) static AnnotationNode findAnnotation(AnnotatedNode classNode, Class type) { List annotations = classNode.getAnnotations() - return annotations == null ? null : findAnnotation(new ClassNode(type),annotations) + return annotations == null ? null : findAnnotation(new ClassNode(type), annotations) } static AnnotationNode findAnnotation(AnnotatedNode annotationClassNode, List annotations) { @@ -78,14 +78,13 @@ class AstAnnotationUtils { */ static boolean hasJunitAnnotation(MethodNode md) { for (AnnotationNode annotation in md.getAnnotations()) { - if(JUNIT_ANNOTATION_NAMES.contains(annotation.getClassNode().getName())) { + if (JUNIT_ANNOTATION_NAMES.contains(annotation.getClassNode().getName())) { return true } } return false } - /** * Returns true if MethodNode is marked with annotationClass * @param methodNode A MethodNode to inspect @@ -94,8 +93,8 @@ class AstAnnotationUtils { */ static boolean hasAnnotation(final MethodNode methodNode, String annotationClassName) { List annos = methodNode.getAnnotations() - for(ann in annos) { - if(ann.classNode.name == annotationClassName) return true + for (ann in annos) { + if (ann.classNode.name == annotationClassName) return true } return false } @@ -106,7 +105,6 @@ class AstAnnotationUtils { } } - /** * @param classNode a ClassNode to search * @param annotationsToLookFor Annotations to look for @@ -114,7 +112,7 @@ class AstAnnotationUtils { */ static boolean hasAnyAnnotations(final ClassNode classNode, final Class... annotationsToLookFor) { for (Class annotationClass : annotationsToLookFor) { - if(hasAnnotation(classNode, annotationClass)) { + if (hasAnnotation(classNode, annotationClass)) { return true } } @@ -138,7 +136,7 @@ class AstAnnotationUtils { * @param annotationClass The annotation class */ static AnnotationNode addAnnotationOrGetExisting(AnnotatedNode classNode, Class annotationClass) { - return addAnnotationOrGetExisting(classNode, annotationClass, Collections.emptyMap()) + return addAnnotationOrGetExisting(classNode, annotationClass, Collections. emptyMap()) } /** @@ -163,7 +161,7 @@ class AstAnnotationUtils { } static AnnotationNode addAnnotationOrGetExisting(AnnotatedNode annotatedNode, ClassNode annotationClassNode) { - return addAnnotationOrGetExisting(annotatedNode, annotationClassNode, Collections.emptyMap()) + return addAnnotationOrGetExisting(annotatedNode, annotationClassNode, Collections. emptyMap()) } static AnnotationNode addAnnotationOrGetExisting(AnnotatedNode annotatedNode, ClassNode annotationClassNode, Map members) { @@ -171,21 +169,19 @@ class AstAnnotationUtils { AnnotationNode annotationToAdd = new AnnotationNode(annotationClassNode) if (annotations.isEmpty()) { annotatedNode.addAnnotation(annotationToAdd) - } - else { + } else { AnnotationNode existing = findAnnotation(annotationClassNode, annotations) - if (existing != null){ + if (existing != null) { annotationToAdd = existing - } - else { + } else { annotatedNode.addAnnotation(annotationToAdd) } } - if(members != null && !members.isEmpty()) { + if (members != null && !members.isEmpty()) { for (Map.Entry memberEntry : members.entrySet()) { Object value = memberEntry.getValue() - annotationToAdd.setMember( memberEntry.getKey(), value instanceof Expression ? (Expression)value : new ConstantExpression(value)) + annotationToAdd.setMember(memberEntry.getKey(), value instanceof Expression ? (Expression) value : new ConstantExpression(value)) } } return annotationToAdd diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/AstGenericsUtils.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/AstGenericsUtils.groovy index d9d86987216..40464c0be40 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/AstGenericsUtils.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/AstGenericsUtils.groovy @@ -38,14 +38,13 @@ class AstGenericsUtils extends GenericsUtils { * @return The generic type */ static ClassNode resolveSingleGenericType(ClassNode classNode) { - if(classNode.isArray()) { + if (classNode.isArray()) { return classNode.componentType.plainNodeReference } GenericsType[] genericsTypes = classNode.genericsTypes - if(genericsTypes) { + if (genericsTypes) { return genericsTypes[0].type.plainNodeReference - } - else { + } else { return ClassHelper.OBJECT_TYPE } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/AstUtils.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/AstUtils.groovy index 4c3b0ba1264..51126fd62f6 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/AstUtils.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/AstUtils.groovy @@ -21,6 +21,7 @@ package org.grails.datastore.mapping.reflect import groovy.transform.CompileStatic import groovy.transform.Memoized import groovy.transform.TypeChecked +import jakarta.persistence.Entity import org.codehaus.groovy.ast.ASTNode import org.codehaus.groovy.ast.AnnotatedNode import org.codehaus.groovy.ast.AnnotationNode @@ -35,7 +36,6 @@ import org.codehaus.groovy.ast.PropertyNode import org.codehaus.groovy.ast.VariableScope import org.codehaus.groovy.ast.expr.ArgumentListExpression import org.codehaus.groovy.ast.expr.ClosureExpression -import org.codehaus.groovy.ast.expr.ConstantExpression import org.codehaus.groovy.ast.expr.Expression import org.codehaus.groovy.ast.expr.MapEntryExpression import org.codehaus.groovy.ast.expr.MapExpression @@ -53,18 +53,14 @@ import org.codehaus.groovy.syntax.Token import org.codehaus.groovy.syntax.Types import org.codehaus.groovy.transform.trait.Traits import org.springframework.util.StringUtils -import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse -import jakarta.persistence.Entity import java.lang.annotation.Annotation import java.lang.reflect.Modifier import java.util.regex.Pattern -import static org.codehaus.groovy.ast.ClassHelper.int_TYPE import static org.codehaus.groovy.ast.ClassHelper.make import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse - /** * Utility methods for dealing with Groovy ASTs * @@ -73,6 +69,7 @@ import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecR */ @CompileStatic class AstUtils { + private static final String SPEC_CLASS = "spock.lang.Specification" private static final Class[] EMPTY_JAVA_CLASS_ARRAY = [] private static final Class[] OBJECT_CLASS_ARG = [Object.class] @@ -94,7 +91,7 @@ class AstUtils { * @return The names of the transformed entities for this context */ static Collection getKnownEntityNames() { - return Collections.unmodifiableCollection( TRANSFORMED_CLASSES ) + return Collections.unmodifiableCollection(TRANSFORMED_CLASSES) } /** @@ -167,30 +164,29 @@ class AstUtils { } protected static void findAbstractMethodsInternal(ClassNode classNode, List methods, boolean includeProtected) { - if(classNode == null || classNode == ClassHelper.GROOVY_OBJECT_TYPE || Traits.isTrait(classNode) || classNode.name.indexOf('$') > -1) { + if (classNode == null || classNode == ClassHelper.GROOVY_OBJECT_TYPE || Traits.isTrait(classNode) || classNode.name.indexOf('$') > -1) { return } if (classNode.isInterface()) { methods.addAll(classNode.methods) - } - else { - for(MethodNode m in classNode.getMethods()) { + } else { + for (MethodNode m in classNode.getMethods()) { int modifiers = m.modifiers def traitBridge = findAnnotation(m, Traits.TraitBridge) boolean isInternal = m.name.indexOf('$') > -1 - if(traitBridge != null || isInternal) { + if (traitBridge != null || isInternal) { continue } - if(Modifier.isAbstract(modifiers) && (Modifier.isPublic(modifiers) || (Modifier.isProtected(modifiers) && includeProtected)) && !m.isSynthetic()) { + if (Modifier.isAbstract(modifiers) && (Modifier.isPublic(modifiers) || (Modifier.isProtected(modifiers) && includeProtected)) && !m.isSynthetic()) { methods.add(m) } } ClassNode superClass = classNode.getSuperClass() - if(superClass != ClassHelper.OBJECT_TYPE) { + if (superClass != ClassHelper.OBJECT_TYPE) { findAbstractMethodsInternal(superClass, methods, includeProtected) } } - for(i in classNode.getInterfaces()) { + for (i in classNode.getInterfaces()) { findAbstractMethodsInternal(i, methods, includeProtected) } } @@ -220,7 +216,7 @@ class AstUtils { String methodName = (useBooleanGetter ? "is" : "get") + MetaClassHelper.capitalize(propertyName) MethodCallExpression methodCallExpression = new MethodCallExpression(objectExpression, methodName, MethodCallExpression.NO_ARGUMENTS) MethodNode getterMethod = targetClassNode.getGetterMethod(methodName) - if(getterMethod != null) { + if (getterMethod != null) { methodCallExpression.setMethodTarget(getterMethod) } return methodCallExpression @@ -239,7 +235,7 @@ class AstUtils { String methodName = "set" + MetaClassHelper.capitalize(propertyName) MethodCallExpression methodCallExpression = new MethodCallExpression(objectExpression, methodName, new ArgumentListExpression(valueExpression)) MethodNode setterMethod = targetClassNode.getSetterMethod(methodName) - if(setterMethod != null) { + if (setterMethod != null) { methodCallExpression.setMethodTarget(setterMethod) } return methodCallExpression @@ -247,7 +243,7 @@ class AstUtils { static void processVariableScopes(SourceUnit source, ClassNode classNode, MethodNode methodNode) { VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(source) - if(methodNode == null) { + if (methodNode == null) { scopeVisitor.visitClass(classNode) } else { scopeVisitor.prepareVisit(classNode) @@ -289,7 +285,6 @@ class AstUtils { AstAnnotationUtils.hasJunitAnnotation(md) } - /** * Returns true if MethodNode is marked with annotationClass * @param methodNode A MethodNode to inspect @@ -304,7 +299,6 @@ class AstUtils { AstAnnotationUtils.hasAnnotation(annotationNodes, annotationNode) } - /** * @param classNode a ClassNode to search * @param annotationsToLookFor Annotations to look for @@ -357,10 +351,10 @@ class AstUtils { static void copyAnnotations(final AnnotatedNode from, final AnnotatedNode to, final Set included, final Set excluded) { final List annotationsToCopy = from.getAnnotations() - for(final AnnotationNode node : annotationsToCopy) { + for (final AnnotationNode node : annotationsToCopy) { String annotationClassName = node.getClassNode().getName() - if((excluded==null || !excluded.contains(annotationClassName)) && - (included==null || included.contains(annotationClassName))) { + if ((excluded == null || !excluded.contains(annotationClassName)) && + (included == null || included.contains(annotationClassName))) { final AnnotationNode copyOfAnnotationNode = cloneAnnotation(node) to.addAnnotation(copyOfAnnotationNode) } @@ -370,7 +364,7 @@ class AstUtils { static AnnotationNode cloneAnnotation(final AnnotationNode node) { final AnnotationNode copyOfAnnotationNode = new AnnotationNode(node.getClassNode()) final Map members = node.getMembers() - for(final Map.Entry entry : members.entrySet()) { + for (final Map.Entry entry : members.entrySet()) { copyOfAnnotationNode.addMember(entry.getKey(), entry.getValue()) } return copyOfAnnotationNode @@ -397,7 +391,7 @@ class AstUtils { * @return True if it is */ static boolean isNumberType(ClassNode classNode) { - if(classNode != null) { + if (classNode != null) { return ClassHelper.isNumberType(classNode) || isSubclassOfOrImplementsInterface(classNode, Number.name) } return false @@ -413,18 +407,19 @@ class AstUtils { static PropertyNode getPropertyFromHierarchy(ClassNode cn, String name) { PropertyNode pn = cn.getProperty(name) ClassNode superClass = cn.getSuperClass() - while(pn == null && superClass != null) { + while (pn == null && superClass != null) { pn = superClass.getProperty(name) - if(pn != null) return pn + if (pn != null) return pn superClass = superClass.getSuperClass() } return pn } + @Memoized static boolean isDomainClass(ClassNode classNode) { if (classNode == null) return false if (classNode.isArray()) return false - if(implementsInterface(classNode, "org.grails.datastore.gorm.GormEntity")) { + if (implementsInterface(classNode, "org.grails.datastore.gorm.GormEntity")) { return true } String filePath = classNode.getModule() != null ? classNode.getModule().getDescription() : null @@ -441,7 +436,7 @@ class AstUtils { if (annotations != null && !annotations.isEmpty()) { for (AnnotationNode annotation : annotations) { String className = annotation.getClassNode().getName() - if( ENTITY_ANNOTATIONS.any() { String ann -> ann.equals(className)} ) { + if (ENTITY_ANNOTATIONS.any() { String ann -> ann.equals(className) }) { return true } } @@ -471,14 +466,14 @@ class AstUtils { return type.getPlainNodeReference() } - if(type.isGenericsPlaceHolder() && genericsPlaceholders != null) { + if (type.isGenericsPlaceHolder() && genericsPlaceholders != null) { final ClassNode placeHolderType - if(genericsPlaceholders.containsKey(type.getUnresolvedName())) { + if (genericsPlaceholders.containsKey(type.getUnresolvedName())) { placeHolderType = genericsPlaceholders.get(type.getUnresolvedName()) } else { placeHolderType = defaultPlaceholder } - if(placeHolderType != null) { + if (placeHolderType != null) { return placeHolderType.getPlainNodeReference() } else { return ClassHelper.make(Object.class).getPlainNodeReference() @@ -487,12 +482,12 @@ class AstUtils { final ClassNode nonGen = type.getPlainNodeReference() - if("java.lang.Object".equals(type.getName())) { + if ("java.lang.Object".equals(type.getName())) { nonGen.setGenericsPlaceHolder(false) nonGen.setGenericsTypes(null) nonGen.setUsingGenerics(false) } else { - if(type.isUsingGenerics()) { + if (type.isUsingGenerics()) { GenericsType[] parameterized = type.getGenericsTypes() if (parameterized != null && parameterized.length > 0) { GenericsType[] copiedGenericsTypes = new GenericsType[parameterized.length] @@ -501,7 +496,7 @@ class AstUtils { GenericsType copiedGenericsType = null if (parameterizedType.isPlaceholder() && genericsPlaceholders != null) { ClassNode placeHolderType = genericsPlaceholders.get(parameterizedType.getName()) - if(placeHolderType != null) { + if (placeHolderType != null) { copiedGenericsType = new GenericsType(placeHolderType.getPlainNodeReference()) } else { copiedGenericsType = new GenericsType(ClassHelper.make(Object.class).getPlainNodeReference()) @@ -532,8 +527,8 @@ class AstUtils { if (!implementsTrait && !traitNotLoaded) { final GenericsType[] genericsTypes = traitClassNode.getGenericsTypes() final Map parameterNameToParameterValue = new LinkedHashMap() - if(genericsTypes != null) { - for(GenericsType gt : genericsTypes) { + if (genericsTypes != null) { + for (GenericsType gt : genericsTypes) { parameterNameToParameterValue.put(gt.getName(), classNode) } } @@ -560,7 +555,7 @@ class AstUtils { /** * Returns whether a classNode has the specified property or not * - * @param classNode The ClassNode + * @param classNode The ClassNode * @param propertyName The name of the property * @return true if the property exists in the ClassNode */ @@ -573,7 +568,7 @@ class AstUtils { if (method != null) return true // check read-only field with setter - if( classNode.getField(propertyName) != null && !classNode.getMethods(NameUtils.getSetterName(propertyName)).isEmpty()) { + if (classNode.getField(propertyName) != null && !classNode.getMethods(NameUtils.getSetterName(propertyName)).isEmpty()) { return true } @@ -589,7 +584,7 @@ class AstUtils { /** * Returns the property type if it exists * - * @param classNode The ClassNode + * @param classNode The ClassNode * @param propertyName The name of the property * @return true if the property exists in the ClassNode */ @@ -676,7 +671,7 @@ class AstUtils { /** * Tests whether the ClasNode implements the specified method name. * - * @param classNode The ClassNode + * @param classNode The ClassNode * @param methodName The method name * @return true if it does implement the method */ @@ -701,7 +696,6 @@ class AstUtils { return false } - static boolean isSubclassOfOrImplementsInterface(ClassNode childClass, ClassNode superClass) { String superClassName = superClass.getName() return isSubclassOfOrImplementsInterface(childClass, superClassName) @@ -719,17 +713,16 @@ class AstUtils { * @return True if it is a subclass */ static boolean isSubclassOf(ClassNode classNode, String parentClassName) { - if(classNode.name == parentClassName) return true + if (classNode.name == parentClassName) return true ClassNode currentSuper = classNode.getSuperClass() - while (currentSuper != null ) { + while (currentSuper != null) { if (currentSuper.getName() == parentClassName) { return true } - if(currentSuper.getName() == OBJECT_CLASS_NODE.getName()) { + if (currentSuper.getName() == OBJECT_CLASS_NODE.getName()) { break - } - else { + } else { currentSuper = currentSuper.getSuperClass() } @@ -780,7 +773,7 @@ class AstUtils { static ClassNode findInterface(ClassNode classNode, String interfaceName) { ClassNode currentClassNode = classNode - if(currentClassNode.name == interfaceName) return classNode + if (currentClassNode.name == interfaceName) return classNode while (currentClassNode != null && !currentClassNode.getName().equals(OBJECT_CLASS_NODE.getName())) { ClassNode[] interfaces = currentClassNode.getInterfaces() @@ -795,12 +788,12 @@ class AstUtils { private static ClassNode implementsInterfaceInternal(ClassNode[] interfaces, String interfaceName) { for (ClassNode anInterface : interfaces) { - if(anInterface.getName().equals(interfaceName)) { + if (anInterface.getName().equals(interfaceName)) { return anInterface } ClassNode[] childInterfaces = anInterface.getInterfaces() - if(childInterfaces != null && childInterfaces.length>0) { - return implementsInterfaceInternal(childInterfaces,interfaceName ) + if (childInterfaces != null && childInterfaces.length > 0) { + return implementsInterfaceInternal(childInterfaces, interfaceName) } } @@ -820,7 +813,6 @@ class AstUtils { ) } - static boolean isSetter(MethodNode declaredMethod) { return declaredMethod.getParameters().length == 1 && ReflectionUtils.isSetter(declaredMethod.getName(), OBJECT_CLASS_ARG) } @@ -855,7 +847,7 @@ class AstUtils { */ static MapExpression mapX(Map map) { def me = new MapExpression() - for(entry in map) { + for (entry in map) { me.addMapEntryExpression(new MapEntryExpression(GeneralUtils.constX(entry.key), entry.value)) } return me @@ -883,6 +875,7 @@ class AstUtils { } CodeVisitorSupport variableTransformer = new ClassCodeExpressionTransformer() { + @Override protected SourceUnit getSourceUnit() { methodNode.declaringClass.module.context diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClassPropertyFetcher.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClassPropertyFetcher.java index b1328ae7d90..4574eae9011 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClassPropertyFetcher.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClassPropertyFetcher.java @@ -18,7 +18,11 @@ */ package org.grails.datastore.mapping.reflect; -import groovy.lang.*; +import groovy.lang.GroovySystem; +import groovy.lang.MetaBeanProperty; +import groovy.lang.MetaClass; +import groovy.lang.MetaMethod; +import groovy.lang.MetaProperty; import org.codehaus.groovy.reflection.CachedClass; import org.codehaus.groovy.reflection.CachedField; import org.codehaus.groovy.reflection.CachedMethod; @@ -33,8 +37,13 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.*; - +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; /** * Reads the properties of a class in an optimized manner avoiding exceptions. @@ -45,23 +54,11 @@ @SuppressWarnings("rawtypes") public class ClassPropertyFetcher { + public static final Set EXCLUDED_PROPERTIES = new HashSet(Arrays.asList("class", "metaClass", "properties")); private final Class clazz; private final ClassInfo classInfo; private final MetaClass theMetaClass; private final List metaProperties; - public static final Set EXCLUDED_PROPERTIES = new HashSet(Arrays.asList("class", "metaClass", "properties")); - - public static ClassPropertyFetcher forClass(final Class c) { - return new ClassPropertyFetcher(c); - } - - /** - * @deprecated Does nothing, no longer needed - */ - @Deprecated - public static void clearCache() { - // no-op - } ClassPropertyFetcher(final Class clazz) { this.clazz = clazz; @@ -72,29 +69,28 @@ public static void clearCache() { for (MetaProperty property : properties) { int modifiers = property.getModifiers(); String propertyName = property.getName(); - if(!Modifier.isPublic(modifiers) || Modifier.isStatic(modifiers) || EXCLUDED_PROPERTIES.contains(propertyName)) { + if (!Modifier.isPublic(modifiers) || Modifier.isStatic(modifiers) || EXCLUDED_PROPERTIES.contains(propertyName)) { continue; } - if(property instanceof MetaBeanProperty) { + if (property instanceof MetaBeanProperty) { MetaBeanProperty beanProperty = (MetaBeanProperty) property; MetaMethod getter = beanProperty.getGetter(); - if(getter instanceof CachedMethod) { + if (getter instanceof CachedMethod) { this.metaProperties.add(property); } - } - else if(property instanceof MultipleSetterProperty) { + } else if (property instanceof MultipleSetterProperty) { MultipleSetterProperty msp = (MultipleSetterProperty) property; MetaMethod getter = msp.getGetter(); - if(getter instanceof CachedMethod) { + if (getter instanceof CachedMethod) { try { CachedClass cachedClass = classInfo.getCachedClass(); Method foundGetter = clazz.getDeclaredMethod(NameUtils.getGetterName(propertyName)); - if(foundGetter != null) { + if (foundGetter != null) { getter = new CachedMethod(cachedClass, foundGetter); Method foundSetter = clazz.getDeclaredMethod(NameUtils.getSetterName(propertyName), getter.getReturnType()); - if(foundSetter != null) { + if (foundSetter != null) { MetaMethod setter = new CachedMethod(cachedClass, foundSetter); this.metaProperties.add(new MetaBeanProperty(msp.getName(), getter.getReturnType(), getter, setter)); } @@ -107,6 +103,18 @@ else if(property instanceof MultipleSetterProperty) { } } + public static ClassPropertyFetcher forClass(final Class c) { + return new ClassPropertyFetcher(c); + } + + /** + * @deprecated Does nothing, no longer needed + */ + @Deprecated + public static void clearCache() { + // no-op + } + /** * @return The Java that this ClassPropertyFetcher was constructor for */ @@ -123,7 +131,7 @@ public Object getReference() { } /** - * @deprecated Use getMetaProperties instead + * @deprecated Use getMetaProperties instead */ @Deprecated public PropertyDescriptor[] getPropertyDescriptors() { @@ -143,7 +151,7 @@ public List getMetaProperties() { public boolean isReadableProperty(String name) { MetaProperty metaProperty = theMetaClass.getMetaProperty(name); - if(metaProperty instanceof MetaBeanProperty) { + if (metaProperty instanceof MetaBeanProperty) { MetaBeanProperty metaBeanProperty = (MetaBeanProperty) metaProperty; return metaBeanProperty.getField() != null || metaBeanProperty.getGetter() != null; } @@ -157,7 +165,7 @@ public Object getPropertyValue(String name) { private static Object getStaticPropertyValue(MetaClass theMetaClass, String name) { MetaProperty metaProperty = theMetaClass.getMetaProperty(name); - if(metaProperty != null && Modifier.isStatic(metaProperty.getModifiers())) { + if (metaProperty != null && Modifier.isStatic(metaProperty.getModifiers())) { return metaProperty.getProperty(theMetaClass.getTheClass()); } return null; @@ -185,9 +193,10 @@ public static T getStaticPropertyValue(Class clazz, String name, Class re * from the most derived version of the property ending with the base class. There are entries for each extant * version of the property in turn, so if you have a 10-deep inheritance hierarchy, you may get 0+ values returned, * one per class in the hierarchy that has the property declared (and of the correct type). + * * @param name Name of the property. - * @param c Required type of the property (including derived types) - * @param Required type of the property. + * @param c Required type of the property (including derived types) + * @param Required type of the property. * @return The list, with 0+ values (never null). Do not modify the returned list. */ public List getStaticPropertyValuesFromInheritanceHierarchy(String name, Class c) { @@ -200,9 +209,10 @@ public List getStaticPropertyValuesFromInheritanceHierarchy(String name, * from the most derived version of the property ending with the base class. There are entries for each extant * version of the property in turn, so if you have a 10-deep inheritance hierarchy, you may get 0+ values returned, * one per class in the hierarchy that has the property declared (and of the correct type). - * @param name Name of the property. + * + * @param name Name of the property. * @param requiredTyped Required type of the property (including derived types) - * @param Required type of the property. + * @param Required type of the property. * @return The list, with 0+ values (never null). Do not modify the returned list. */ public static List getStaticPropertyValuesFromInheritanceHierarchy(Class theClass, String name, Class requiredTyped) { @@ -215,43 +225,43 @@ private static List getStaticPropertyValuesFromInheritanceHierarchy(Class Class javaClass = cachedClass.getTheClass(); List values = new ArrayList<>(hierarchy.size()); for (ClassInfo current : hierarchy) { - if(cachedClass.isInterface()) continue; + if (cachedClass.isInterface()) { + continue; + } MetaProperty metaProperty = current.getMetaClass().getMetaProperty(name); - if(metaProperty != null && Modifier.isStatic(metaProperty.getModifiers())) { + if (metaProperty != null && Modifier.isStatic(metaProperty.getModifiers())) { Class type = metaProperty.getType(); - if(type == Object.class || c.isAssignableFrom(type)) { - if(metaProperty instanceof MetaBeanProperty) { + if (type == Object.class || c.isAssignableFrom(type)) { + if (metaProperty instanceof MetaBeanProperty) { MetaBeanProperty beanProperty = (MetaBeanProperty) metaProperty; CachedField field = beanProperty.getField(); // try the field - if(field != null) { + if (field != null) { Object val = field.getProperty(javaClass); - if(c.isInstance(val)) { + if (c.isInstance(val)) { values.add((T) val); } - } - else { + } else { Object val = metaProperty.getProperty(javaClass); - if(c.isInstance(val)) { + if (c.isInstance(val)) { values.add((T) val); } } - } - else { + } else { Object val = metaProperty.getProperty(javaClass); - if(c.isInstance(val)) { + if (c.isInstance(val)) { values.add((T) val); } } - } - else { + } else { // try the field Field field = org.springframework.util.ReflectionUtils.findField(javaClass, name); if (field != null && c.isAssignableFrom(field.getType())) { org.springframework.util.ReflectionUtils.makeAccessible(field); try { values.add((T) field.get(javaClass)); - } catch (IllegalAccessException ignored) {} + } catch (IllegalAccessException ignored) { + } } return null; } @@ -271,12 +281,11 @@ public Class getPropertyType(String name) { public Class getPropertyType(String name, boolean onlyInstanceProperties) { MetaProperty metaProperty = theMetaClass.getMetaProperty(name); - if(metaProperty != null) { + if (metaProperty != null) { boolean isStatic = Modifier.isStatic(metaProperty.getModifiers()); - if(onlyInstanceProperties && isStatic) { + if (onlyInstanceProperties && isStatic) { return null; - } - else { + } else { // Avoid any proxy handling that might be wrapped around the getters and setters Field field = getDeclaredField(name); return field != null ? field.getType() : metaProperty.getType(); @@ -287,7 +296,7 @@ public Class getPropertyType(String name, boolean onlyInstanceProperties) { public PropertyDescriptor getPropertyDescriptor(String name) { MetaProperty property = theMetaClass.getMetaProperty(name); - if(property != null) { + if (property != null) { return createPropertyDescriptor(clazz, property); } return null; @@ -301,20 +310,19 @@ public PropertyDescriptor getPropertyDescriptor(String name) { */ public static PropertyDescriptor createPropertyDescriptor(Class declaringClass, MetaProperty property) { int modifiers = property.getModifiers(); - if(!Modifier.isStatic(modifiers)) { + if (!Modifier.isStatic(modifiers)) { String propertyName = property.getName(); - if(property instanceof MetaBeanProperty) { + if (property instanceof MetaBeanProperty) { MetaBeanProperty beanProperty = (MetaBeanProperty) property; MetaMethod getter = beanProperty.getGetter(); MetaMethod setter = beanProperty.getSetter(); - if(getter instanceof CachedMethod && setter instanceof CachedMethod) { + if (getter instanceof CachedMethod && setter instanceof CachedMethod) { try { Method getterMethod = ((CachedMethod) getter).getCachedMethod(); Method setterMethod = ((CachedMethod) setter).getCachedMethod(); - if(getterMethod.getReturnType().equals(setterMethod.getParameterTypes()[0])) { + if (getterMethod.getReturnType().equals(setterMethod.getParameterTypes()[0])) { return new PropertyDescriptor(propertyName, getterMethod, setterMethod); - } - else { + } else { String getterName = NameUtils.getGetterName(propertyName); String setterName = NameUtils.getSetterName(propertyName); getterMethod = declaringClass.getMethod(getterName); @@ -326,33 +334,30 @@ public static PropertyDescriptor createPropertyDescriptor(Class declaringClass, } catch (NoSuchMethodException e) { return null; } - } - else if(getter instanceof CachedMethod) { + } else if (getter instanceof CachedMethod) { try { return new PropertyDescriptor(propertyName, ((CachedMethod) getter).getCachedMethod(), null); } catch (IntrospectionException e) { return null; } } - } - else if(property instanceof MultipleSetterProperty) { + } else if (property instanceof MultipleSetterProperty) { MultipleSetterProperty msp = (MultipleSetterProperty) property; MetaMethod getter = msp.getGetter(); - if(getter instanceof CachedMethod) { + if (getter instanceof CachedMethod) { try { Method foundGetter = declaringClass.getDeclaredMethod(NameUtils.getGetterName(propertyName)); - if(foundGetter != null) { + if (foundGetter != null) { Method foundSetter = declaringClass.getDeclaredMethod(NameUtils.getSetterName(propertyName), foundGetter.getReturnType()); - if(foundSetter != null) { + if (foundSetter != null) { try { return new PropertyDescriptor(propertyName, foundGetter, foundSetter); } catch (IntrospectionException e) { return null; } - } - else { + } else { try { return new PropertyDescriptor(propertyName, foundGetter, null); } catch (IntrospectionException e) { @@ -375,7 +380,9 @@ public List getPropertiesOfType(Class javaClass) { for (MetaProperty property : properties) { int modifiers = property.getModifiers(); - if(Modifier.isStatic(modifiers) || property.getName().contains("$") || !property.getType().equals(javaClass)) continue; + if (Modifier.isStatic(modifiers) || property.getName().contains("$") || !property.getType().equals(javaClass)) { + continue; + } addBeanProperty(propertyDescriptors, property); } @@ -388,7 +395,7 @@ public List getPropertiesAssignableToType(Class assignableTy List propertyDescriptors = new ArrayList<>(2); for (MetaProperty property : properties) { int modifiers = property.getModifiers(); - if(Modifier.isStatic(modifiers) || property.getName().contains("$") || !assignableType.isAssignableFrom(property.getType())) { + if (Modifier.isStatic(modifiers) || property.getName().contains("$") || !assignableType.isAssignableFrom(property.getType())) { continue; } @@ -403,7 +410,9 @@ public List getPropertiesAssignableFromType(Class assignable List propertyDescriptors = new ArrayList<>(2); for (MetaProperty property : properties) { int modifiers = property.getModifiers(); - if(Modifier.isStatic(modifiers) || property.getName().contains("$") || !property.getType().isAssignableFrom( assignableType )) continue; + if (Modifier.isStatic(modifiers) || property.getName().contains("$") || !property.getType().isAssignableFrom(assignableType)) { + continue; + } addBeanProperty(propertyDescriptors, property); } return propertyDescriptors; @@ -411,7 +420,7 @@ public List getPropertiesAssignableFromType(Class assignable public static Class getPropertyType(Class cls, String propertyName) { MetaProperty metaProperty = GroovySystem.getMetaClassRegistry().getMetaClass(cls).getMetaProperty(propertyName); - if(metaProperty != null) { + if (metaProperty != null) { return metaProperty.getType(); } return null; @@ -419,16 +428,15 @@ public static Class getPropertyType(Class cls, String propertyName) { public Field getDeclaredField(String name) { MetaProperty metaProperty = theMetaClass.getMetaProperty(name); - if(metaProperty instanceof MetaBeanProperty) { + if (metaProperty instanceof MetaBeanProperty) { CachedField field = ((MetaBeanProperty) metaProperty).getField(); - if(field != null) { + if (field != null) { return field.getCachedField(); } - } - else if(metaProperty instanceof MultipleSetterProperty) { + } else if (metaProperty instanceof MultipleSetterProperty) { MultipleSetterProperty msp = (MultipleSetterProperty) metaProperty; CachedField field = msp.getField(); - if(field != null) { + if (field != null) { return field.getCachedField(); } } @@ -436,12 +444,12 @@ else if(metaProperty instanceof MultipleSetterProperty) { } protected void addBeanProperty(List propertyDescriptors, MetaProperty property) { - if(property instanceof MetaBeanProperty) { + if (property instanceof MetaBeanProperty) { MetaBeanProperty beanProperty = (MetaBeanProperty) property; MetaMethod getter = beanProperty.getGetter(); MetaMethod setter = beanProperty.getSetter(); boolean isGetterCachedMethod = getter instanceof CachedMethod; - if(isGetterCachedMethod && setter instanceof CachedMethod) { + if (isGetterCachedMethod && setter instanceof CachedMethod) { CachedMethod cachedGetter = (CachedMethod) getter; CachedMethod cachedSetter = (CachedMethod) setter; try { @@ -449,8 +457,7 @@ protected void addBeanProperty(List propertyDescriptors, Met } catch (IntrospectionException e) { // ignore } - } - else if(isGetterCachedMethod) { + } else if (isGetterCachedMethod) { CachedMethod cachedGetter = (CachedMethod) getter; try { propertyDescriptors.add(new PropertyDescriptor(beanProperty.getName(), cachedGetter.getCachedMethod(), null)); @@ -465,29 +472,31 @@ else if(isGetterCachedMethod) { @SuppressWarnings("unchecked") private static T returnOnlyIfInstanceOf(Object value, Class type) { if (value != null && (type == Object.class || ReflectionUtils.isAssignableFrom(type, value.getClass()))) { - return (T)value; + return (T) value; } return null; } private static Object getInstancePropertyValue(Object instance, String name, MetaClass metaClass) { MetaProperty metaProperty = metaClass.getMetaProperty(name); - if(metaProperty != null && !Modifier.isStatic(metaProperty.getModifiers())) { - if(metaProperty instanceof MetaBeanProperty) { + if (metaProperty != null && !Modifier.isStatic(metaProperty.getModifiers())) { + if (metaProperty instanceof MetaBeanProperty) { MetaBeanProperty beanProperty = (MetaBeanProperty) metaProperty; CachedField field = beanProperty.getField(); MetaMethod getter = beanProperty.getGetter(); Object result = getPropertyWithFieldOrGetter(instance, name, field, getter); - if (result != null) return result; - } - else if(metaProperty instanceof MultipleSetterProperty) { + if (result != null) { + return result; + } + } else if (metaProperty instanceof MultipleSetterProperty) { MultipleSetterProperty msp = (MultipleSetterProperty) metaProperty; CachedField field = msp.getField(); MetaMethod getter = msp.getGetter(); Object result = getPropertyWithFieldOrGetter(instance, name, field, getter); - if (result != null) return result; - } - else { + if (result != null) { + return result; + } + } else { return metaProperty.getProperty(instance); } } @@ -495,17 +504,15 @@ else if(metaProperty instanceof MultipleSetterProperty) { } private static Object getPropertyWithFieldOrGetter(Object instance, String name, CachedField field, MetaMethod getter) { - if(field != null) { + if (field != null) { return field.getProperty(instance); - } - else { - if(getter instanceof CachedMethod) { + } else { + if (getter instanceof CachedMethod) { return getter.invoke(instance, MetaClassHelper.EMPTY_ARRAY); - } - else { + } else { // take the slow path and reflect Method method = org.springframework.util.ReflectionUtils.findMethod(instance.getClass(), NameUtils.getGetterName(name)); - if(method != null) { + if (method != null) { org.springframework.util.ReflectionUtils.makeAccessible(method); return org.springframework.util.ReflectionUtils.invokeMethod(method, instance); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClassUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClassUtils.java index 077e1560093..ce46657b782 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClassUtils.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClassUtils.java @@ -29,14 +29,16 @@ * @since 5.0 */ public class ClassUtils { + public static final Map, Class> PRIMITIVE_TYPE_COMPATIBLE_CLASSES = new HashMap, Class>(); /** * Just add two entries to the class compatibility map + * * @param left * @param right */ - private static final void registerPrimitiveClassPair(Class left, Class right) { + private static void registerPrimitiveClassPair(Class left, Class right) { PRIMITIVE_TYPE_COMPATIBLE_CLASSES.put(left, right); PRIMITIVE_TYPE_COMPATIBLE_CLASSES.put(right, left); } @@ -56,16 +58,16 @@ private static final void registerPrimitiveClassPair(Class left, Class rig * Determine whether the {@link Class} identified by the supplied name is present * and can be loaded. Will return {@code false} if either the class or * one of its dependencies is not present or cannot be loaded. + * * @param className the name of the class to check - * (may be {@code null}, which indicates the default class loader) + * (may be {@code null}, which indicates the default class loader) * @return whether the specified class is present */ public static boolean isPresent(String className) { try { Class.forName(className, false, ClassUtils.class.getClassLoader()); return true; - } - catch (Throwable ex) { + } catch (Throwable ex) { // Class or one of its dependencies is not present... return false; } @@ -92,27 +94,27 @@ public static boolean isAssignableOrConvertibleFrom(Class clazz, Class typ return false; } return clazz.isAssignableFrom(primitiveClass); - } - else if(type.isArray() && Iterable.class.isAssignableFrom(clazz)) { + } else if (type.isArray() && Iterable.class.isAssignableFrom(clazz)) { return true; } return clazz.isAssignableFrom(type); } + /** * Determine whether the {@link Class} identified by the supplied name is present * and can be loaded. Will return {@code false} if either the class or * one of its dependencies is not present or cannot be loaded. - * @param className the name of the class to check + * + * @param className the name of the class to check * @param classLoader the class loader to use - * (may be {@code null}, which indicates the default class loader) + * (may be {@code null}, which indicates the default class loader) * @return whether the specified class is present */ public static boolean isPresent(String className, ClassLoader classLoader) { try { Class.forName(className, false, classLoader); return true; - } - catch (Throwable ex) { + } catch (Throwable ex) { // Class or one of its dependencies is not present... return false; } @@ -126,12 +128,16 @@ public static boolean isPresent(String className, ClassLoader classLoader) { * @return A boolean value which will be false if the map is null, the map doesn't contain the key or the value is false */ public static boolean getBooleanFromMap(String key, Map map) { - if (map == null) return false; + if (map == null) { + return false; + } if (map.containsKey(key)) { Object o = map.get(key); - if (o == null)return false; + if (o == null) { + return false; + } if (o instanceof Boolean) { - return (Boolean)o; + return (Boolean) o; } return Boolean.valueOf(o.toString()); } @@ -160,7 +166,7 @@ public static boolean isClassBelowPackage(Class domainClazz, List packageList public static boolean isMultiTenant(Class clazz) { Class[] allInterfacesForClass = org.springframework.util.ClassUtils.getAllInterfacesForClass(clazz); for (Class anInterface : allInterfacesForClass) { - if(anInterface.getSimpleName().equals("MultiTenant")) { + if (anInterface.getSimpleName().equals("MultiTenant")) { return true; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClosureToMapPopulator.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClosureToMapPopulator.java index 5ae0004b108..2a9cec2d67b 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClosureToMapPopulator.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ClosureToMapPopulator.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.reflect; import groovy.lang.Closure; @@ -33,7 +32,7 @@ * @author Graeme Rocher * @since 6.0 */ -@SuppressWarnings({"unchecked","rawtypes"}) +@SuppressWarnings({"unchecked", "rawtypes"}) public class ClosureToMapPopulator extends GroovyObjectSupport { private Map map; @@ -64,16 +63,14 @@ public void setProperty(String name, Object o) { public Object invokeMethod(String name, Object o) { if (o != null) { if (o.getClass().isArray()) { - Object[] args = (Object[])o; + Object[] args = (Object[]) o; if (args.length == 1) { map.put(name, args[0]); - } - else { + } else { map.put(name, Arrays.asList(args)); } - } - else { - map.put(name,o); + } else { + map.put(name, o); } } return null; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/EntityReflector.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/EntityReflector.java index 09ad2f8e330..b8efaf8919d 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/EntityReflector.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/EntityReflector.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.reflect; import org.grails.datastore.mapping.model.PersistentEntity; @@ -44,16 +43,19 @@ public interface EntityReflector { * @return Obtains the dirty checking state for the given entity */ Map getDirtyCheckingState(Object entity); + /** * @return The fast class * @deprecated Do not use */ @Deprecated FastClass fastClass(); + /** * @return The identity type */ Class identifierType(); + /** * @return The name of the identifier */ @@ -80,7 +82,7 @@ public interface EntityReflector { * Get a property for the specified index * * @param object The object - * @param index The index + * @param index The index * @return The value */ Object getProperty(Object object, int index); @@ -89,7 +91,7 @@ public interface EntityReflector { * Set a property for the specified index * * @param object The object - * @param index The index + * @param index The index * @param value The value */ void setProperty(Object object, int index, Object value); @@ -98,7 +100,7 @@ public interface EntityReflector { * Get a property for the specified index * * @param object The object - * @param name The index + * @param name The index * @return The value */ Object getProperty(Object object, String name); @@ -107,14 +109,13 @@ public interface EntityReflector { * Set a property for the specified index * * @param object The object - * @param name The index + * @param name The index * @param value The value */ void setProperty(Object object, String name, Object value); /** * @param name Obtains the property reader for the given property - * * @return The name of the property */ PropertyReader getPropertyReader(String name); @@ -152,6 +153,7 @@ interface PropertyReader { } interface PropertyWriter { + /** * @return The field or null if the field cannot be resolved */ @@ -161,16 +163,18 @@ interface PropertyWriter { * @return The getter */ Method setter(); + /** * @return The property type */ Class propertyType(); + /** * Writes the property * * @param object the object - * @param value The value + * @param value The value */ void write(Object object, Object value); } -} \ No newline at end of file +} diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/FieldEntityAccess.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/FieldEntityAccess.java index 0a091c64f0a..0e71dfcadf6 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/FieldEntityAccess.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/FieldEntityAccess.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.reflect; import org.codehaus.groovy.transform.trait.Traits; @@ -47,7 +46,7 @@ */ public class FieldEntityAccess implements EntityAccess { - private static Map REFLECTORS = new ConcurrentHashMap<>(); + private static final Map REFLECTORS = new ConcurrentHashMap<>(); private final PersistentEntity persistentEntity; private final Object entity; @@ -68,7 +67,7 @@ public static void clearReflectors() { public static EntityReflector getOrIntializeReflector(PersistentEntity persistentEntity) { String entityName = persistentEntity.getName(); EntityReflector entityReflector = REFLECTORS.get(entityName); - if(entityReflector == null) { + if (entityReflector == null) { entityReflector = new FieldEntityReflector(persistentEntity); REFLECTORS.put(entityName, entityReflector); } @@ -98,7 +97,7 @@ public Object getPropertyValue(String name) { @Override public Class getPropertyType(String name) { PersistentProperty property = persistentEntity.getPropertyByName(name); - if(property != null) { + if (property != null) { return property.getType(); } return null; @@ -111,9 +110,9 @@ public void setProperty(String name, Object value) { try { converted = conversionService.convert(value, writer.propertyType()); } catch (ConversionException e) { - throw new IllegalArgumentException("Cannot assign value ["+value+"] to property ["+name+"] of type ["+writer.propertyType().getName()+"] of class ["+persistentEntity.getName()+"]. The value could not be converted to the appropriate type: " + e.getMessage(), e); + throw new IllegalArgumentException("Cannot assign value [" + value + "] to property [" + name + "] of type [" + writer.propertyType().getName() + "] of class [" + persistentEntity.getName() + "]. The value could not be converted to the appropriate type: " + e.getMessage(), e); } catch (Exception e) { - throw new IllegalArgumentException("Cannot assign value ["+value+"] to property ["+name+"] of type ["+writer.propertyType().getName()+"] of class ["+persistentEntity.getName()+"]. The value is not an acceptable type: " + e.getMessage(), e); + throw new IllegalArgumentException("Cannot assign value [" + value + "] to property [" + name + "] of type [" + writer.propertyType().getName() + "] of class [" + persistentEntity.getName() + "]. The value is not an acceptable type: " + e.getMessage(), e); } writer.write(entity, converted); } @@ -129,9 +128,9 @@ public void setIdentifier(Object id) { try { converted = conversionService.convert(id, reflector.identifierType()); } catch (ConversionException e) { - throw new IllegalArgumentException("Cannot assign identifier ["+id+"] to property ["+reflector.getIdentifierName()+"] of type ["+reflector.identifierType().getName()+"] of class ["+persistentEntity.getName()+"]. The value could not be converted to the appropriate type: " + e.getMessage(), e); + throw new IllegalArgumentException("Cannot assign identifier [" + id + "] to property [" + reflector.getIdentifierName() + "] of type [" + reflector.identifierType().getName() + "] of class [" + persistentEntity.getName() + "]. The value could not be converted to the appropriate type: " + e.getMessage(), e); } catch (Exception e) { - throw new IllegalArgumentException("Cannot assign identifier ["+id+"] to property ["+reflector.getIdentifierName()+"] of type ["+reflector.identifierType().getName()+"] of class ["+persistentEntity.getName()+"]. The identifier is not an compatible type: " + e.getMessage(), e); + throw new IllegalArgumentException("Cannot assign identifier [" + id + "] to property [" + reflector.getIdentifierName() + "] of type [" + reflector.identifierType().getName() + "] of class [" + persistentEntity.getName() + "]. The identifier is not an compatible type: " + e.getMessage(), e); } reflector.setIdentifier(entity, converted); @@ -142,7 +141,7 @@ public void setIdentifierNoConversion(Object id) { try { reflector.setIdentifier(entity, id); } catch (Exception e) { - throw new IllegalArgumentException("Cannot assign identifier ["+id+"] to property ["+reflector.getIdentifierName()+"] of type ["+reflector.identifierType().getName()+"] of class ["+persistentEntity.getName()+"]. The identifier is not an compatible type: " + e.getMessage(), e); + throw new IllegalArgumentException("Cannot assign identifier [" + id + "] to property [" + reflector.getIdentifierName() + "] of type [" + reflector.identifierType().getName() + "] of class [" + persistentEntity.getName() + "]. The identifier is not an compatible type: " + e.getMessage(), e); } } @@ -168,13 +167,21 @@ public void setPropertyNoConversion(String name, Object value) { reflector.setProperty(entity, name, value); } catch (Exception e) { String valueType = value != null ? value.getClass().getName() : null; - throw new IllegalArgumentException("Cannot assign value ["+value+"] with type ["+valueType+"] to property ["+name+"] of class ["+persistentEntity.getName()+"]. The value is not an acceptable type: " + e.getMessage(), e); + throw new IllegalArgumentException("Cannot assign value [" + value + "] with type [" + valueType + "] to property [" + name + "] of class [" + persistentEntity.getName() + "]. The value is not an acceptable type: " + e.getMessage(), e); } } - + private static Object unwrapIfProxy(PersistentEntity entity, Object object) { + if (entity != null) { + final ProxyHandler proxyHandler = entity.getMappingContext().getProxyHandler(); + return proxyHandler.unwrap(object); + } else { + return object; + } + } static class FieldEntityReflector implements EntityReflector { + final PersistentEntity entity; final PropertyReader[] readers; final PropertyWriter[] writers; @@ -191,11 +198,11 @@ public FieldEntityReflector(PersistentEntity entity) { this.entity = entity; PersistentProperty identity = entity.getIdentity(); dirtyCheckingStateField = ReflectionUtils.findField(entity.getJavaClass(), getTraitFieldName(DirtyCheckable.class, "$changedProperties")); - if(dirtyCheckingStateField != null) { + if (dirtyCheckingStateField != null) { ReflectionUtils.makeAccessible(dirtyCheckingStateField); } ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity.getJavaClass()); - if(identity != null) { + if (identity != null) { String identityName = identity.getName(); this.identifierName = identityName; this.identifierType = identity.getType(); @@ -205,11 +212,10 @@ public FieldEntityReflector(PersistentEntity entity) { identifierWriter = readerAndWriterMaker.getPropertyWriter(); readerMap.put(identifierName, identifierReader); - if(identifierWriter != null) { + if (identifierWriter != null) { writerMap.put(identifierName, identifierWriter); } - } - else { + } else { this.identifierName = null; this.identifierReader = null; this.identifierWriter = null; @@ -217,7 +223,7 @@ public FieldEntityReflector(PersistentEntity entity) { } PersistentProperty[] composite = entity.getCompositeIdentity(); - if(composite != null) { + if (composite != null) { for (PersistentProperty property : composite) { String propertyName = property.getName(); ReaderAndWriterMaker readerAndWriterMaker = new ReaderAndWriterMaker(cpf, propertyName).make(); @@ -249,10 +255,9 @@ protected String getTraitFieldName(Traits.TraitBridge traitBridge, String fieldN } private String getTraitFieldName(Class traitClass, String fieldName) { - return traitClass.getName().replace('.','_') + "__" + fieldName; + return traitClass.getName().replace('.', '_') + "__" + fieldName; } - @Override public PersistentEntity getPersitentEntity() { return this.entity; @@ -260,7 +265,7 @@ public PersistentEntity getPersitentEntity() { @Override public Map getDirtyCheckingState(Object entity) { - if(dirtyCheckingStateField != null) { + if (dirtyCheckingStateField != null) { try { return (Map) dirtyCheckingStateField.get(entity); } catch (Throwable e) { @@ -272,7 +277,7 @@ public Map getDirtyCheckingState(Object entity) { @Override public FastClass fastClass() { - if(fastClass == null) { + if (fastClass == null) { fastClass = FastClass.create(entity.getJavaClass()); } return fastClass; @@ -281,21 +286,20 @@ public FastClass fastClass() { @Override public PropertyReader getPropertyReader(String name) { final PropertyReader reader = readerMap.get(name); - if(reader != null) { + if (reader != null) { return reader; } - throw new IllegalArgumentException("Property ["+name+"] is not a valid property of " + entity.getJavaClass()); + throw new IllegalArgumentException("Property [" + name + "] is not a valid property of " + entity.getJavaClass()); } @Override public PropertyWriter getPropertyWriter(String name) { final PropertyWriter writer = writerMap.get(name); - if(writer != null) { + if (writer != null) { return writer; - } - else { - throw new IllegalArgumentException("Property ["+name+"] is not a valid property of " + entity.getJavaClass()); + } else { + throw new IllegalArgumentException("Property [" + name + "] is not a valid property of " + entity.getJavaClass()); } } @@ -317,7 +321,7 @@ public Class identifierType() { @Override public Serializable getIdentifier(Object object) { - if(identifierReader != null && object != null) { + if (identifierReader != null && object != null) { return (Serializable) identifierReader.read(object); } return null; @@ -325,7 +329,7 @@ public Serializable getIdentifier(Object object) { @Override public void setIdentifier(Object object, Object value) { - if(identifierWriter != null) { + if (identifierWriter != null) { identifierWriter.write(object, value); } } @@ -347,12 +351,11 @@ public Object getProperty(Object object, int index) { @Override public void setProperty(Object object, int index, Object value) { - writers[index].write(object,value); + writers[index].write(object, value); } - - static class ReflectMethodReader implements PropertyReader { + final Method method; public ReflectMethodReader(Method method) { @@ -382,6 +385,7 @@ public Object read(Object object) { } static class ReflectionMethodWriter implements PropertyWriter { + final Method method; final Class propertyType; @@ -413,6 +417,7 @@ public void write(Object object, Object value) { } static class FieldReader implements PropertyReader { + final Field field; final Method getter; @@ -443,12 +448,13 @@ public Object read(Object object) { object = unwrapIfProxy(null, object); return field.get(object); } catch (Throwable e) { - throw new IllegalArgumentException("Cannot read field ["+field+"] from object ["+object+"] of type ["+object.getClass()+"]", e); + throw new IllegalArgumentException("Cannot read field [" + field + "] from object [" + object + "] of type [" + object.getClass() + "]", e); } } } static class FieldWriter implements PropertyWriter { + final Field field; final Method setter; @@ -478,12 +484,13 @@ public void write(Object object, Object value) { try { field.set(object, value); } catch (Throwable e) { - throw new IllegalArgumentException("Cannot set field ["+field.getName()+"] of object ["+object+"] for value ["+value+"] of type ["+value.getClass().getName()+"]", e); + throw new IllegalArgumentException("Cannot set field [" + field.getName() + "] of object [" + object + "] for value [" + value + "] of type [" + value.getClass().getName() + "]", e); } } } private class ReaderAndWriterMaker { + private ClassPropertyFetcher cpf; private String propertyName; private PropertyReader propertyReader; @@ -505,47 +512,42 @@ public PropertyWriter getPropertyWriter() { public ReaderAndWriterMaker make() { Class javaClass = cpf.getJavaClass(); Field field = ReflectionUtils.findField(javaClass, propertyName); - if(field != null) { + if (field != null) { ReflectionUtils.makeAccessible(field); propertyReader = new FieldReader(field, ReflectionUtils.findMethod(javaClass, NameUtils.getGetterName(propertyName))); propertyWriter = new FieldWriter(field, ReflectionUtils.findMethod(javaClass, NameUtils.getSetterName(propertyName), field.getType())); - } - else { + } else { PropertyDescriptor descriptor = cpf.getPropertyDescriptor(propertyName); Method readMethod = descriptor.getReadMethod(); Traits.TraitBridge traitBridge = readMethod.getAnnotation(Traits.TraitBridge.class); String traitFieldName; - if(traitBridge != null) { + if (traitBridge != null) { traitFieldName = getTraitFieldName(traitBridge, propertyName); - } - else { + } else { Traits.Implemented traitImplemented = readMethod.getAnnotation(Traits.Implemented.class); - if(traitImplemented != null) { + if (traitImplemented != null) { traitFieldName = getTraitFieldName(readMethod.getDeclaringClass(), propertyName); - } - else { + } else { traitFieldName = null; } } - if(traitFieldName != null) { + if (traitFieldName != null) { field = ReflectionUtils.findField(javaClass, traitFieldName); - if(field != null) { + if (field != null) { ReflectionUtils.makeAccessible(field); propertyReader = new FieldReader(field, readMethod); propertyWriter = new FieldWriter(field, descriptor.getWriteMethod()); - } - else { + } else { Method writeMethod = descriptor.getWriteMethod(); propertyReader = new ReflectMethodReader(readMethod); propertyWriter = new ReflectionMethodWriter(writeMethod, descriptor.getPropertyType()); } - } - else { + } else { propertyReader = new ReflectMethodReader(readMethod); Method writeMethod = descriptor.getWriteMethod(); - if(writeMethod != null) { + if (writeMethod != null) { propertyWriter = new ReflectionMethodWriter(writeMethod, descriptor.getPropertyType()); } } @@ -554,14 +556,4 @@ public ReaderAndWriterMaker make() { } } } - - - private static Object unwrapIfProxy(PersistentEntity entity, Object object) { - if (entity != null) { - final ProxyHandler proxyHandler = entity.getMappingContext().getProxyHandler(); - return proxyHandler.unwrap(object); - } else { - return object; - } - } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/MetaClassUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/MetaClassUtils.java index 67276369798..70a0670d296 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/MetaClassUtils.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/MetaClassUtils.java @@ -45,7 +45,7 @@ public static ExpandoMetaClass getExpandoMetaClass(Class aClass) { registry.removeMetaClass(aClass); mc = registry.getMetaClass(aClass); if (mc instanceof ExpandoMetaClass) { - return (ExpandoMetaClass)mc; + return (ExpandoMetaClass) mc; } ExpandoMetaClass emc = new ExpandoMetaClass(aClass, true, true); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/NameUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/NameUtils.java index 1a056cafe99..60978ec9e36 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/NameUtils.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/NameUtils.java @@ -14,30 +14,29 @@ */ package org.grails.datastore.mapping.reflect; +import org.codehaus.groovy.runtime.MetaClassHelper; +import org.grails.datastore.mapping.model.config.GormProperties; + import java.beans.Introspector; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.codehaus.groovy.runtime.MetaClassHelper; -import org.grails.datastore.mapping.model.config.GormProperties; - /** * @author Graeme Rocher * @since 1.0 */ public class NameUtils { + public static final String DOLLAR_SEPARATOR = "$"; private static final String PROPERTY_SET_PREFIX = "set"; private static final String PROPERTY_GET_PREFIX = "get"; private static final String PROPERTY_IS_PREFIX = "is"; - private static final Set CONFIGURATIONAL_PROPERTIES; - public static final String DOLLAR_SEPARATOR = "$"; static { - Set configurational = new HashSet( Arrays.asList( + Set configurational = new HashSet(Arrays.asList( GormProperties.META_CLASS, GormProperties.CLASS, GormProperties.TRANSIENT, @@ -55,7 +54,7 @@ public class NameUtils { "sessionFactory", "messageSource", "applicationContext", - "properties") ); + "properties")); CONFIGURATIONAL_PROPERTIES = Collections.unmodifiableSet(configurational); } @@ -69,15 +68,17 @@ public static boolean isNotConfigurational(String name) { /** * Retrieves the name of a setter for the specified property name + * * @param propertyName The property name * @return The setter equivalent */ public static String getSetterName(String propertyName) { return PROPERTY_SET_PREFIX + capitalize(propertyName); } - + /** * Retrieves the name of a setter for the specified property name + * * @param propertyName The property name * @return The getter equivalent */ @@ -87,7 +88,8 @@ public static String getGetterName(String propertyName) { /** * Retrieves the name of a setter for the specified property name - * @param propertyName The property name + * + * @param propertyName The property name * @param useBooleanPrefix true if property is type of boolean * @return The getter equivalent */ @@ -104,7 +106,7 @@ public static String getGetterName(String propertyName, boolean useBooleanPrefix */ public static String getClassName(Class clazz) { final String sn = clazz.getSimpleName(); - if(sn.contains(DOLLAR_SEPARATOR)) { + if (sn.contains(DOLLAR_SEPARATOR)) { return clazz.getSuperclass().getName(); } return clazz.getName(); @@ -112,11 +114,14 @@ public static String getClassName(Class clazz) { /** * Returns the property name for a getter or setter + * * @param getterOrSetterName The getter or setter name * @return The property name */ public static String getPropertyNameForGetterOrSetter(String getterOrSetterName) { - if (getterOrSetterName == null || getterOrSetterName.length() == 0) return null; + if (getterOrSetterName == null || getterOrSetterName.length() == 0) { + return null; + } if (getterOrSetterName.startsWith(PROPERTY_GET_PREFIX) || getterOrSetterName.startsWith(PROPERTY_SET_PREFIX)) { return decapitalize(getterOrSetterName.substring(3)); @@ -138,14 +143,15 @@ public static String decapitalize(String name) { /** * Transforms the first character of a string into a lowercase letter + * * @param name String to be transformed * @return Original string with the first char as a lowercase letter */ public static String decapitalizeFirstChar(String name) { - if (name == null || name.length() == 0) { + if (name == null || name.isEmpty()) { return name; } - char chars[] = name.toCharArray(); + char[] chars = name.toCharArray(); chars[0] = Character.toLowerCase(chars[0]); return new String(chars); } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ReflectionUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ReflectionUtils.java index 0acad57cde8..dc681bf85ab 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ReflectionUtils.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/ReflectionUtils.java @@ -18,6 +18,10 @@ */ package org.grails.datastore.mapping.reflect; +import org.grails.datastore.mapping.model.DatastoreConfigurationException; +import org.springframework.beans.BeanUtils; +import org.springframework.util.StringUtils; + import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -28,10 +32,6 @@ import java.util.Map; import java.util.Set; -import org.grails.datastore.mapping.model.DatastoreConfigurationException; -import org.springframework.beans.BeanUtils; -import org.springframework.util.StringUtils; - /** * Provides methods to help with reflective operations * @@ -46,6 +46,7 @@ public class ReflectionUtils { /** * Just add two entries to the class compatibility map + * * @param left * @param right */ @@ -65,28 +66,28 @@ private static void registerPrimitiveClassPair(Class left, Class right) { registerPrimitiveClassPair(Double.class, double.class); } - /** - * Make the given field accessible, explicitly setting it accessible if necessary. - * The setAccessible(true) method is only called when actually necessary, - * to avoid unnecessary conflicts with a JVM SecurityManager (if active). - * - * Based on the same method in Spring core. - * - * @param field the field to make accessible - * @see java.lang.reflect.Field#setAccessible - */ - public static void makeAccessible(Field field) { - if (!Modifier.isPublic(field.getModifiers()) || - !Modifier.isPublic(field.getDeclaringClass().getModifiers())) { - field.setAccessible(true); - } - } + /** + * Make the given field accessible, explicitly setting it accessible if necessary. + * The setAccessible(true) method is only called when actually necessary, + * to avoid unnecessary conflicts with a JVM SecurityManager (if active). + *

    + * Based on the same method in Spring core. + * + * @param field the field to make accessible + * @see java.lang.reflect.Field#setAccessible + */ + public static void makeAccessible(Field field) { + if (!Modifier.isPublic(field.getModifiers()) || + !Modifier.isPublic(field.getDeclaringClass().getModifiers())) { + field.setAccessible(true); + } + } /** * Make the given method accessible, explicitly setting it accessible if necessary. * The setAccessible(true) method is only called when actually necessary, * to avoid unnecessary conflicts with a JVM SecurityManager (if active). - * + *

    * Based on the same method in Spring core. * * @param method the method to make accessible @@ -106,7 +107,7 @@ public static void makeAccessible(Method method) { * with a bit of magic for native types and polymorphism i.e. Number assigned an int. * If either parameter is null an exception is thrown

    * - * @param leftType The type of the left hand part of a notional assignment + * @param leftType The type of the left hand part of a notional assignment * @param rightType The type of the right hand part of a notional assignment * @return True if values of the right hand type can be assigned in Groovy to variables of the left hand type. */ @@ -136,8 +137,7 @@ public static boolean isAssignableFrom(final Class leftType, final Class r if (r != null) { result = leftType.isAssignableFrom(r); } - } - else { + } else { // Otherwise it may just be assignable using normal Java polymorphism result = leftType.isAssignableFrom(rightType); } @@ -151,28 +151,29 @@ public static boolean isAssignableFrom(final Class leftType, final Class r * @param clazz The class * @return The instantiated object or null if the class parameter was null */ - @SuppressWarnings({ "rawtypes", "unchecked" }) + @SuppressWarnings({"rawtypes", "unchecked"}) public static T instantiate(Class clazz) { - if (clazz == null) return null; + if (clazz == null) { + return null; + } try { return clazz.getConstructor(EMPTY_CLASS_ARRAY).newInstance(); } catch (IllegalAccessException e) { - throw new InstantiationException(e.getClass().getName() + " error creating instance of class ["+e.getMessage()+"]: " + e.getMessage(), e); + throw new InstantiationException(e.getClass().getName() + " error creating instance of class [" + e.getMessage() + "]: " + e.getMessage(), e); } catch (InvocationTargetException e) { - throw new InstantiationException(e.getClass().getName() + " error creating instance of class ["+e.getMessage()+"]: " + e.getMessage(), e); + throw new InstantiationException(e.getClass().getName() + " error creating instance of class [" + e.getMessage() + "]: " + e.getMessage(), e); } catch (NoSuchMethodException e) { - throw new InstantiationException(e.getClass().getName() + " error creating instance of class ["+e.getMessage()+"]: " + e.getMessage(), e); + throw new InstantiationException(e.getClass().getName() + " error creating instance of class [" + e.getMessage() + "]: " + e.getMessage(), e); } catch (java.lang.InstantiationException e) { - throw new InstantiationException(e.getClass().getName() + " error creating instance of class ["+e.getMessage()+"]: " + e.getMessage(), e); + throw new InstantiationException(e.getClass().getName() + " error creating instance of class [" + e.getMessage() + "]: " + e.getMessage(), e); } } /** * Retrieves all the properties of the given class for the given type * - * @param clazz The class to retrieve the properties from + * @param clazz The class to retrieve the properties from * @param propertyType The type of the properties you wish to retrieve - * * @return An array of PropertyDescriptor instances */ public static PropertyDescriptor[] getPropertiesOfType(Class clazz, Class propertyType) { @@ -188,8 +189,7 @@ public static PropertyDescriptor[] getPropertiesOfType(Class clazz, Class properties.add(descriptor); } } - } - catch (Exception e) { + } catch (Exception e) { // if there are any errors in instantiating just return null for the moment return new PropertyDescriptor[0]; } @@ -208,28 +208,41 @@ private static boolean isTypeInstanceOfPropertyType(Class type, Class prop * @return true if it is a javabean property method */ public static boolean isGetter(String name, Class[] args) { - if (!StringUtils.hasText(name) || args == null)return false; - if (args.length != 0)return false; + if (!StringUtils.hasText(name) || args == null) { + return false; + } + if (args.length != 0) { + return false; + } if (name.startsWith("get")) { name = name.substring(3); - if (name.length() > 0 && Character.isUpperCase(name.charAt(0))) return true; - } - else if (name.startsWith("is")) { + if (name.length() > 0 && Character.isUpperCase(name.charAt(0))) { + return true; + } + } else if (name.startsWith("is")) { name = name.substring(2); - if (name.length() > 0 && Character.isUpperCase(name.charAt(0))) return true; + if (name.length() > 0 && Character.isUpperCase(name.charAt(0))) { + return true; + } } return false; } @SuppressWarnings("rawtypes") public static boolean isSetter(String name, Class[] args) { - if (!StringUtils.hasText(name) || args == null)return false; + if (!StringUtils.hasText(name) || args == null) { + return false; + } if (name.startsWith("set")) { - if (args.length != 1) return false; + if (args.length != 1) { + return false; + } name = name.substring(3); - if (name.length() > 0 && Character.isUpperCase(name.charAt(0))) return true; + if (name.length() > 0 && Character.isUpperCase(name.charAt(0))) { + return true; + } } return false; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/DefaultServiceDefinition.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/DefaultServiceDefinition.java index e5f52161722..802e9089c66 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/DefaultServiceDefinition.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/DefaultServiceDefinition.java @@ -33,6 +33,7 @@ */ @Internal class DefaultServiceDefinition implements ServiceDefinition { + private final String name; private final Optional> loadedClass; @@ -51,7 +52,9 @@ public String getName() { } @Override - public Class getType() { return loadedClass.orElseThrow(() -> new ServiceConfigurationError("Call to load() when class '" + name + "' is not present")); } + public Class getType() { + return loadedClass.orElseThrow(() -> new ServiceConfigurationError("Call to load() when class '" + name + "' is not present")); + } @Override public boolean isPresent() { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/DefaultServiceRegistry.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/DefaultServiceRegistry.groovy index c5043f0a449..48c8c808d93 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/DefaultServiceRegistry.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/DefaultServiceRegistry.groovy @@ -23,13 +23,8 @@ import groovy.transform.CompileStatic import groovy.util.logging.Slf4j import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.model.lifecycle.Initializable -import org.grails.datastore.mapping.reflect.NameUtils -import org.springframework.beans.factory.BeanFactory -import org.springframework.beans.factory.BeanFactoryAware -import org.springframework.beans.factory.config.ConfigurableBeanFactory import org.springframework.util.ClassUtils -import java.beans.Introspector import java.lang.reflect.Modifier /** @@ -46,7 +41,7 @@ class DefaultServiceRegistry implements ServiceRegistry, Initializable { */ final Datastore datastore - protected final Map servicesByInterface + protected final Map servicesByInterface protected final Collection services = [] private boolean initialized @@ -55,36 +50,36 @@ class DefaultServiceRegistry implements ServiceRegistry, Initializable { Iterable services = loadServices() Map serviceMap = [:] Iterator serviceIterator = services.iterator() - while(serviceIterator.hasNext()) { + while (serviceIterator.hasNext()) { try { Service service = serviceIterator.next() this.services.add(service) Class[] allInterfaces = ClassUtils.getAllInterfaces(service) Class theClass = service.getClass() serviceMap.put(theClass.name, service) - if( theClass.simpleName.startsWith('$') ) { + if (theClass.simpleName.startsWith('$')) { // handle automatically implemented abstract service implementations Class superClass = theClass.getSuperclass() - if(superClass != null && superClass != Object.class && Modifier.isAbstract(superClass.modifiers)) { + if (superClass != null && superClass != Object.class && Modifier.isAbstract(superClass.modifiers)) { serviceMap.put(superClass.name, service) } } - for(Class i in allInterfaces) { - if(isValidInterface(i)) { + for (Class i in allInterfaces) { + if (isValidInterface(i)) { serviceMap.put(i.name, service) } } } catch (Throwable e) { log.error("Could not load GORM service: ${e.message}", e) - if(exceptionOnLoadError) { + if (exceptionOnLoadError) { throw e } } } servicesByInterface = Collections.unmodifiableMap( - serviceMap + serviceMap ) } @@ -96,7 +91,7 @@ class DefaultServiceRegistry implements ServiceRegistry, Initializable { @Override def T getService(Class interfaceType) throws ServiceNotFoundException { final Service s = servicesByInterface.get(interfaceType.name) - if(s == null) { + if (s == null) { throw new ServiceNotFoundException("No service found for type $interfaceType") } return (T) s @@ -112,7 +107,7 @@ class DefaultServiceRegistry implements ServiceRegistry, Initializable { @Override void initialize() { - for(s in services) { + for (s in services) { s.datastore = datastore } this.initialized = true diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/ServiceNotFoundException.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/ServiceNotFoundException.groovy index 6223da9fa46..4bba8a33728 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/ServiceNotFoundException.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/ServiceNotFoundException.groovy @@ -20,7 +20,6 @@ package org.grails.datastore.mapping.services import groovy.transform.CompileStatic -import groovy.transform.InheritConstructors import org.grails.datastore.mapping.core.DatastoreException /** @@ -31,6 +30,7 @@ import org.grails.datastore.mapping.core.DatastoreException */ @CompileStatic class ServiceNotFoundException extends DatastoreException { + ServiceNotFoundException(String s) { super(s) } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/SoftServiceLoader.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/SoftServiceLoader.java index 881749ea8f9..f40654a9f59 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/SoftServiceLoader.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/SoftServiceLoader.java @@ -27,7 +27,14 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; -import java.util.*; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.ServiceConfigurationError; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -40,13 +47,13 @@ * @since 1.0 */ public final class SoftServiceLoader implements Iterable> { + public static final String PROPERTY_GRAILS_CLASSLOADER_LOGGING = "grails.classloader.logging"; public static final String META_INF_SERVICES = "META-INF/services"; public static final Logger REFLECTION_LOGGER; private static final boolean ENABLE_CLASS_LOADER_LOGGING = Boolean.getBoolean(PROPERTY_GRAILS_CLASSLOADER_LOGGING); - private final Class serviceType; private final ClassLoader classLoader; private final Map> loadedServices = new LinkedHashMap<>(); @@ -57,7 +64,6 @@ public final class SoftServiceLoader implements Iterable REFLECTION_LOGGER = getLogger(ClassUtils.class); } - private SoftServiceLoader(Class serviceType, ClassLoader classLoader) { this(serviceType, classLoader, (String name) -> true); } @@ -211,6 +217,7 @@ protected ServiceDefinition newService(String name, Optional loadedCla * A service loader iterator implementation. */ private final class ServiceLoaderIterator implements Iterator> { + private Enumeration serviceConfigs = null; private Iterator unprocessed = null; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/CustomizableRollbackTransactionAttribute.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/CustomizableRollbackTransactionAttribute.java index 1c7333349b5..cb7ac73108b 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/CustomizableRollbackTransactionAttribute.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/CustomizableRollbackTransactionAttribute.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.transactions; import org.slf4j.Logger; @@ -36,7 +35,7 @@ */ public class CustomizableRollbackTransactionAttribute extends RuleBasedTransactionAttribute { - private static final Logger log = LoggerFactory.getLogger(CustomizableRollbackTransactionAttribute.class); + private static final Logger LOG = LoggerFactory.getLogger(CustomizableRollbackTransactionAttribute.class); private static final long serialVersionUID = 1L; private boolean inheritRollbackOnly = true; @@ -69,19 +68,19 @@ public CustomizableRollbackTransactionAttribute(TransactionDefinition other) { } public CustomizableRollbackTransactionAttribute(CustomizableRollbackTransactionAttribute other) { - this((RuleBasedTransactionAttribute)other); + this((RuleBasedTransactionAttribute) other); } public CustomizableRollbackTransactionAttribute(RuleBasedTransactionAttribute other) { - if(other instanceof CustomizableRollbackTransactionAttribute) { - this.inheritRollbackOnly = ((CustomizableRollbackTransactionAttribute)other).inheritRollbackOnly; + if (other instanceof CustomizableRollbackTransactionAttribute) { + this.inheritRollbackOnly = ((CustomizableRollbackTransactionAttribute) other).inheritRollbackOnly; } } @Override public boolean rollbackOn(Throwable ex) { - if (log.isTraceEnabled()) { - log.trace("Applying rules to determine whether transaction should rollback on $ex"); + if (LOG.isTraceEnabled()) { + LOG.trace("Applying rules to determine whether transaction should rollback on $ex"); } RollbackRuleAttribute winner = null; @@ -98,13 +97,13 @@ public boolean rollbackOn(Throwable ex) { } } - if (log.isTraceEnabled()) { - log.trace("Winning rollback rule is: $winner" ); + if (LOG.isTraceEnabled()) { + LOG.trace("Winning rollback rule is: $winner"); } // User superclass behavior (rollback on unchecked) if no rule matches. if (winner == null) { - log.trace("No relevant rollback rule found: applying default rules"); + LOG.trace("No relevant rollback rule found: applying default rules"); // always rollback regardless if it is a checked or unchecked exception since Groovy doesn't differentiate those return true; @@ -112,6 +111,7 @@ public boolean rollbackOn(Throwable ex) { return !(winner instanceof NoRollbackRuleAttribute); } + public boolean isInheritRollbackOnly() { return inheritRollbackOnly; } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/DatastoreTransactionManager.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/DatastoreTransactionManager.java index 028f92a2633..8b31e07a5ed 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/DatastoreTransactionManager.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/DatastoreTransactionManager.java @@ -19,13 +19,12 @@ package org.grails.datastore.mapping.transactions; import jakarta.persistence.FlushModeType; - -import org.springframework.dao.DataAccessException; -import org.springframework.dao.DataAccessResourceFailureException; import org.grails.datastore.mapping.core.ConnectionNotFoundException; import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.DatastoreUtils; import org.grails.datastore.mapping.core.Session; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.transaction.CannotCreateTransactionException; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionException; @@ -79,15 +78,14 @@ protected Object doGetTransaction() throws TransactionException { TransactionObject txObject = new TransactionObject(); SessionHolder sessionHolder = - (SessionHolder) TransactionSynchronizationManager.getResource(getDatastore()); + (SessionHolder) TransactionSynchronizationManager.getResource(getDatastore()); if (sessionHolder != null) { if (logger.isDebugEnabled()) { logger.debug("Found thread-bound Session [" + sessionHolder.getSession() + "] for Datastore transaction"); } txObject.setSessionHolder(sessionHolder); - } - else if (datastoreManagedSession) { + } else if (datastoreManagedSession) { try { Session session = getDatastore().getCurrentSession(); if (logger.isDebugEnabled()) { @@ -95,13 +93,11 @@ else if (datastoreManagedSession) { session + "] for Spring-managed transaction"); } txObject.setExistingSession(session); - } - catch (ConnectionNotFoundException ex) { + } catch (ConnectionNotFoundException ex) { throw new DataAccessResourceFailureException( "Could not obtain Datastore-managed Session for Spring-managed transaction", ex); } - } - else { + } else { Session session = getDatastore().connect(); txObject.setSession(session); } @@ -134,21 +130,18 @@ protected void doBegin(Object o, TransactionDefinition definition) throws Transa TransactionSynchronizationManager.bindResource(getDatastore(), txObject.getSessionHolder()); } txObject.getSessionHolder().setSynchronizedWithTransaction(true); - } - catch (Exception ex) { + } catch (Exception ex) { if (txObject.isNewSession()) { try { if (session != null) { Transaction transaction = session.getTransaction(); - if(transaction != null && transaction.isActive()) { + if (transaction != null && transaction.isActive()) { transaction.rollback(); } } - } - catch (Throwable ex2) { + } catch (Throwable ex2) { logger.debug("Could not rollback Session after failed transaction begin", ex); - } - finally { + } finally { DatastoreUtils.closeSession(session); } } @@ -162,9 +155,9 @@ protected void doCommit(DefaultTransactionStatus status) throws TransactionExcep final SessionHolder sessionHolder = txObject.getSessionHolder(); try { Transaction transaction = txObject.getTransaction(); - if(transaction != null && transaction.isActive() ) { + if (transaction != null && transaction.isActive()) { Session session = sessionHolder.getSession(); - if(!status.isReadOnly()) { + if (!status.isReadOnly()) { if (session != null) { if (status.isDebug()) { logger.debug("Flushing Session prior to transaction commit [" + session + "]"); @@ -177,8 +170,7 @@ protected void doCommit(DefaultTransactionStatus status) throws TransactionExcep } transaction.commit(); } - } - catch (DataAccessException ex) { + } catch (DataAccessException ex) { throw new TransactionSystemException("Could not commit Datastore transaction", ex); } } @@ -189,18 +181,16 @@ protected void doRollback(DefaultTransactionStatus status) throws TransactionExc final SessionHolder sessionHolder = txObject.getSessionHolder(); try { Transaction transaction = txObject.getTransaction(); - if(transaction != null && transaction.isActive()) { + if (transaction != null && transaction.isActive()) { if (status.isDebug()) { logger.debug("Rolling back Datastore transaction on Session [" + sessionHolder.getSession() + "]"); } transaction.rollback(); } - } - catch (DataAccessException ex) { + } catch (DataAccessException ex) { throw new TransactionSystemException("Could not rollback Datastore transaction", ex); - } - finally { + } finally { // Clear all pending inserts/updates/deletes in the Session. // Necessary for pre-bound Sessions, to avoid inconsistent state. if (sessionHolder.getSession() != null) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionHolder.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionHolder.java index 5512096ecd8..495b05bad69 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionHolder.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionHolder.java @@ -18,12 +18,12 @@ */ package org.grails.datastore.mapping.transactions; -import java.util.Deque; -import java.util.concurrent.LinkedBlockingDeque; - import org.grails.datastore.mapping.core.Session; import org.springframework.transaction.support.ResourceHolderSupport; +import java.util.Deque; +import java.util.concurrent.LinkedBlockingDeque; + /** * Holds a reference to one or more sessions. * @@ -50,7 +50,7 @@ public Object getCreator() { public Transaction getTransaction() { final Session session = getSession(); - if(session != null && session.hasTransaction()) { + if (session != null && session.hasTransaction()) { return session.getTransaction(); } return null; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionOnlyTransaction.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionOnlyTransaction.java index d0a69616da5..5105c739324 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionOnlyTransaction.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/SessionOnlyTransaction.java @@ -29,9 +29,8 @@ * No other resource level transaction management is provided. *

    * - * @author graemerocher - * * @param + * @author graemerocher */ public class SessionOnlyTransaction implements Transaction { @@ -48,8 +47,7 @@ public void commit() { if (active) { try { session.flush(); - } - finally { + } finally { active = false; } } @@ -59,8 +57,7 @@ public void rollback() { if (active) { try { session.clear(); - } - finally { + } finally { active = false; } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/Transaction.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/Transaction.java index 5aacc43f466..307b2615e89 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/Transaction.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/Transaction.java @@ -45,12 +45,14 @@ public interface Transaction { /** * Whether the transaction is active + * * @return True if it is */ boolean isActive(); /** * Sets the transaction timeout period + * * @param timeout The timeout */ void setTimeout(int timeout); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionObject.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionObject.java index 005cf533019..fbbf2b3f857 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionObject.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionObject.java @@ -28,6 +28,7 @@ * @since 1.0 */ public class TransactionObject implements SmartTransactionObject { + private SessionHolder sessionHolder; private boolean newSessionHolder; private boolean newSession; @@ -41,8 +42,8 @@ public Transaction getTransaction() { } /** - * @deprecated Here for binary compatibility, doesn't actually do anything * @param transaction + * @deprecated Here for binary compatibility, doesn't actually do anything */ @Deprecated public void setTransaction(Transaction transaction) { @@ -74,7 +75,6 @@ public boolean isNewSession() { return newSession; } - @Override public boolean isRollbackOnly() { return sessionHolder.isRollbackOnly(); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionUtils.java index 0f190364c28..ffba458e17e 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionUtils.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/TransactionUtils.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.transactions; import org.grails.datastore.mapping.core.Datastore; diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/support/SpringSessionSynchronization.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/support/SpringSessionSynchronization.java index c855fd0e6bd..031032d21f1 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/support/SpringSessionSynchronization.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/transactions/support/SpringSessionSynchronization.java @@ -18,11 +18,11 @@ */ package org.grails.datastore.mapping.transactions.support; -import org.springframework.dao.DataAccessException; import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.core.DatastoreUtils; import org.grails.datastore.mapping.core.Session; import org.grails.datastore.mapping.transactions.SessionHolder; +import org.springframework.dao.DataAccessException; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; @@ -41,7 +41,7 @@ public class SpringSessionSynchronization implements TransactionSynchronization private boolean holderActive = true; public SpringSessionSynchronization(SessionHolder sessionHolder, - Datastore datastore, boolean newSession) { + Datastore datastore, boolean newSession) { this.sessionHolder = sessionHolder; this.datastore = datastore; this.newSession = newSession; @@ -96,8 +96,7 @@ public void afterCompletion(int status) { // (closed in beforeCompletion in case of TransactionManagerLookup). if (newSession) { DatastoreUtils.closeSessionOrRegisterDeferredClose(session, datastore); - } - else { + } else { session.disconnect(); } if (sessionHolder.doesNotHoldNonDefaultSession()) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/BeanFactoryValidatorRegistry.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/BeanFactoryValidatorRegistry.java index 44b18c3eddd..d52c881f89f 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/BeanFactoryValidatorRegistry.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/BeanFactoryValidatorRegistry.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.validation; import org.grails.datastore.mapping.model.PersistentEntity; @@ -32,6 +31,7 @@ * @since 6.0 */ public class BeanFactoryValidatorRegistry implements ValidatorRegistry { + private final BeanFactory beanFactory; public BeanFactoryValidatorRegistry(BeanFactory beanFactory) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/CascadeValidateType.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/CascadeValidateType.java index 963c33a2d9d..c193d6792e1 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/CascadeValidateType.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/CascadeValidateType.java @@ -22,16 +22,24 @@ * Defines a set of cascade validation options that are propagated to the associated entity. */ public enum CascadeValidateType { - /** By default, cascade for any owned association or with a JPA cascade of PERSIST or MERGE **/ + /** + * By default, cascade for any owned association or with a JPA cascade of PERSIST or MERGE + **/ DEFAULT, - /** Don't cascade validations at all, only entities that are actually flushed will be validated (similar to deepValidate: false) **/ + /** + * Don't cascade validations at all, only entities that are actually flushed will be validated (similar to deepValidate: false) + **/ NONE, - /** Only cascade validation for associations which are owned by the parent entity, regardless of the JPA cascade behavior **/ + /** + * Only cascade validation for associations which are owned by the parent entity, regardless of the JPA cascade behavior + **/ OWNED, - /** In addition to the default cascade requirement, only cascade to entities that are DirtyCheckable and hasChanged **/ + /** + * In addition to the default cascade requirement, only cascade to entities that are DirtyCheckable and hasChanged + **/ DIRTY; public static CascadeValidateType fromMappedName(String name) { diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationErrors.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationErrors.java index 540b87cfd39..5407a4d1349 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationErrors.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationErrors.java @@ -27,6 +27,7 @@ * @since 2.0 */ public class ValidationErrors extends BeanPropertyBindingResult { + private static final long serialVersionUID = 1; /** @@ -38,10 +39,11 @@ public class ValidationErrors extends BeanPropertyBindingResult { public ValidationErrors(Object target, String objectName) { super(target, objectName); } + /** * Creates a new instance of the {@link org.springframework.validation.BeanPropertyBindingResult} class. * - * @param target the target bean to bind onto + * @param target the target bean to bind onto */ public ValidationErrors(Object target) { super(target, target.getClass().getName()); diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationException.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationException.java index f2eee4915b2..d7178dc2a4d 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationException.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidationException.java @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.grails.datastore.mapping.validation; import org.codehaus.groovy.runtime.DefaultGroovyMethods; @@ -28,13 +27,12 @@ */ public class ValidationException extends DataIntegrityViolationException { - private static final long serialVersionUID = 1; - public static final Class VALIDATION_EXCEPTION_TYPE; + private static final long serialVersionUID = 1; static { ClassLoader cl = Thread.currentThread().getContextClassLoader(); - if(ClassUtils.isPresent("grails.validation.ValidationException", cl)) { + if (ClassUtils.isPresent("grails.validation.ValidationException", cl)) { Class validationExceptionType; try { validationExceptionType = (Class) ClassUtils.forName("grails.validation.ValidationException", cl); @@ -43,13 +41,11 @@ public class ValidationException extends DataIntegrityViolationException { } VALIDATION_EXCEPTION_TYPE = validationExceptionType; - } - else { + } else { VALIDATION_EXCEPTION_TYPE = ValidationException.class; } } - private final String fullMessage; private final Errors errors; @@ -72,7 +68,7 @@ public String getMessage() { return fullMessage; } - public static String formatErrors(Errors errors, String msg ) { + public static String formatErrors(Errors errors, String msg) { String ls = System.getProperty("line.separator"); StringBuilder b = new StringBuilder(); if (msg != null) { @@ -81,14 +77,14 @@ public static String formatErrors(Errors errors, String msg ) { for (ObjectError error : errors.getAllErrors()) { b.append(ls) - .append(" - ") - .append(error) - .append(ls); + .append(" - ") + .append(error) + .append(ls); } return b.toString(); } public static RuntimeException newInstance(String message, Errors errors) { - return DefaultGroovyMethods.newInstance(VALIDATION_EXCEPTION_TYPE, new Object[]{ message, errors }); + return DefaultGroovyMethods.newInstance(VALIDATION_EXCEPTION_TYPE, new Object[]{message, errors}); } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidatorRegistry.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidatorRegistry.java index c684b7a0e03..04864963f52 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidatorRegistry.java +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/validation/ValidatorRegistry.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.validation; import org.grails.datastore.mapping.model.PersistentEntity; diff --git a/grails-datastore-web/build.gradle b/grails-datastore-web/build.gradle index a177a1fb389..28b7091b60b 100644 --- a/grails-datastore-web/build.gradle +++ b/grails-datastore-web/build.gradle @@ -91,5 +91,6 @@ apply { from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/CookieTenantResolver.groovy b/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/CookieTenantResolver.groovy index 2ae3105f5f1..5236c24c7e7 100644 --- a/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/CookieTenantResolver.groovy +++ b/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/CookieTenantResolver.groovy @@ -20,16 +20,14 @@ package org.grails.datastore.mapping.multitenancy.web import groovy.transform.CompileStatic -import org.grails.datastore.mapping.core.connections.ConnectionSource +import jakarta.servlet.http.Cookie +import jakarta.servlet.http.HttpServletRequest import org.grails.datastore.mapping.multitenancy.TenantResolver import org.grails.datastore.mapping.multitenancy.exceptions.TenantNotFoundException import org.springframework.web.context.request.RequestAttributes import org.springframework.web.context.request.RequestContextHolder import org.springframework.web.context.request.ServletWebRequest -import jakarta.servlet.http.Cookie -import jakarta.servlet.http.HttpServletRequest - /** * Resolves the tenant id from a cookie * @@ -49,14 +47,14 @@ class CookieTenantResolver implements TenantResolver { @Override Serializable resolveTenantIdentifier() throws TenantNotFoundException { RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes() - if(requestAttributes instanceof ServletWebRequest) { + if (requestAttributes instanceof ServletWebRequest) { HttpServletRequest servletRequest = ((ServletWebRequest) requestAttributes).getRequest() Cookie[] cookies = servletRequest.getCookies() - if(cookies != null) { + if (cookies != null) { for (Cookie cookie : cookies) { - if( cookieName.equals( cookie.name ) ) { + if (cookieName.equals(cookie.name)) { return cookie.getValue() } } diff --git a/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/HttpHeaderTenantResolver.groovy b/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/HttpHeaderTenantResolver.groovy index 58ff9bfd5ce..25663345d0c 100644 --- a/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/HttpHeaderTenantResolver.groovy +++ b/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/HttpHeaderTenantResolver.groovy @@ -20,14 +20,13 @@ package org.grails.datastore.mapping.multitenancy.web import groovy.transform.CompileStatic +import jakarta.servlet.http.HttpServletRequest import org.grails.datastore.mapping.multitenancy.TenantResolver import org.grails.datastore.mapping.multitenancy.exceptions.TenantNotFoundException import org.springframework.web.context.request.RequestAttributes import org.springframework.web.context.request.RequestContextHolder import org.springframework.web.context.request.ServletWebRequest -import jakarta.servlet.http.HttpServletRequest - /** * A tenant resolver that resolves the tenant from the request HTTP Header * @@ -36,6 +35,7 @@ import jakarta.servlet.http.HttpServletRequest */ @CompileStatic class HttpHeaderTenantResolver implements TenantResolver { + public static final String HEADER_NAME = "gorm.tenantId" /** @@ -47,12 +47,12 @@ class HttpHeaderTenantResolver implements TenantResolver { Serializable resolveTenantIdentifier() { RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes() - if(requestAttributes instanceof ServletWebRequest) { + if (requestAttributes instanceof ServletWebRequest) { HttpServletRequest httpServletRequest = ((ServletWebRequest) requestAttributes).getRequest() String tenantId = httpServletRequest.getHeader(headerName.toLowerCase()) - if ( tenantId ) { + if (tenantId) { return tenantId } throw new TenantNotFoundException("Tenant could not be resolved from HTTP Header: ${headerName}") diff --git a/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/SessionTenantResolver.groovy b/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/SessionTenantResolver.groovy index 7b67361b662..aa98372f64b 100644 --- a/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/SessionTenantResolver.groovy +++ b/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/SessionTenantResolver.groovy @@ -20,12 +20,10 @@ package org.grails.datastore.mapping.multitenancy.web import groovy.transform.CompileStatic -import org.grails.datastore.mapping.core.connections.ConnectionSource import org.grails.datastore.mapping.multitenancy.TenantResolver import org.grails.datastore.mapping.multitenancy.exceptions.TenantNotFoundException import org.springframework.web.context.request.RequestAttributes import org.springframework.web.context.request.RequestContextHolder -import org.springframework.web.context.request.ServletWebRequest /** * Resolves the tenant id from the user HTTP session @@ -45,13 +43,12 @@ class SessionTenantResolver implements TenantResolver { @Override Serializable resolveTenantIdentifier() throws TenantNotFoundException { RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes() - if(requestAttributes != null) { + if (requestAttributes != null) { def tenantId = requestAttributes.getAttribute(attributeName, RequestAttributes.SCOPE_SESSION) - if(tenantId instanceof Serializable) { - return (Serializable)tenantId - } - else { + if (tenantId instanceof Serializable) { + return (Serializable) tenantId + } else { throw new TenantNotFoundException() } } diff --git a/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/SubDomainTenantResolver.groovy b/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/SubDomainTenantResolver.groovy index 3883bbda485..7e410c2357d 100644 --- a/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/SubDomainTenantResolver.groovy +++ b/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/multitenancy/web/SubDomainTenantResolver.groovy @@ -20,6 +20,7 @@ package org.grails.datastore.mapping.multitenancy.web import groovy.transform.CompileStatic +import jakarta.servlet.http.HttpServletRequest import org.grails.datastore.mapping.core.connections.ConnectionSource import org.grails.datastore.mapping.multitenancy.TenantResolver import org.grails.datastore.mapping.multitenancy.exceptions.TenantNotFoundException @@ -27,8 +28,6 @@ import org.springframework.web.context.request.RequestAttributes import org.springframework.web.context.request.RequestContextHolder import org.springframework.web.context.request.ServletWebRequest -import jakarta.servlet.http.HttpServletRequest - /** * A tenant resolver that resolves the tenant from the Subdomain * @@ -36,26 +35,25 @@ import jakarta.servlet.http.HttpServletRequest * @since 6.0 */ @CompileStatic -class SubDomainTenantResolver implements TenantResolver{ +class SubDomainTenantResolver implements TenantResolver { @Override Serializable resolveTenantIdentifier() { RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes() - if(requestAttributes instanceof ServletWebRequest) { + if (requestAttributes instanceof ServletWebRequest) { HttpServletRequest httpServletRequest = ((ServletWebRequest) requestAttributes).getRequest() String subdomain = httpServletRequest.getRequestURL().toString() String requestURI = httpServletRequest.getRequestURI() def i = requestURI.length() - if(i > 0) { - subdomain = subdomain.substring(0, subdomain.length()-i) + if (i > 0) { + subdomain = subdomain.substring(0, subdomain.length() - i) } subdomain = subdomain.substring(subdomain.indexOf("/") + 2); - if( subdomain.indexOf(".") > -1 ) { + if (subdomain.indexOf(".") > -1) { return subdomain.substring(0, subdomain.indexOf(".")) - } - else { + } else { return ConnectionSource.DEFAULT } } diff --git a/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/web/support/OpenSessionInViewInterceptor.java b/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/web/support/OpenSessionInViewInterceptor.java index a05de361fe0..9cac775f6cf 100644 --- a/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/web/support/OpenSessionInViewInterceptor.java +++ b/grails-datastore-web/src/main/groovy/org/grails/datastore/mapping/web/support/OpenSessionInViewInterceptor.java @@ -16,11 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.datastore.mapping.web.support; import jakarta.persistence.FlushModeType; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.grails.datastore.mapping.core.Datastore; @@ -78,7 +76,7 @@ public void postHandle(WebRequest webRequest, ModelMap modelMap) throws Exceptio final Session session = sessionHolder.getSession(); if (session.getFlushMode() == FlushModeType.AUTO) { - if(session.hasTransaction()) { + if (session.hasTransaction()) { session.flush(); } } diff --git a/grails-doc/build.gradle b/grails-doc/build.gradle index bb59665b350..73f14a2fcd1 100644 --- a/grails-doc/build.gradle +++ b/grails-doc/build.gradle @@ -17,8 +17,8 @@ * under the License. */ -import grails.doc.git.FetchTagsTask import grails.doc.dropdown.CreateReleaseDropDownTask +import grails.doc.git.FetchTagsTask import grails.doc.gradle.PublishGuideTask plugins { @@ -117,7 +117,7 @@ String getVersion(String artifact) { def generateBomDocumentation = tasks.register('generateBomDocumentation') generateBomDocumentation.configure { Task it -> - it.dependsOn(':grails-bom:extractConstraints') + it.dependsOn(':grails-bom:extractConstraints', ':grails-bom:checkstyleNohttp', ':grails-bom:spotlessJava', ':grails-bom:spotlessGroovy', ':grails-bom:spotlessJavaMisc') it.description = 'Generates an AsciiDoc table listing Group, Artifact, and Version for project dependencies.' it.group = 'documentation' diff --git a/grails-doc/resources/doc.properties b/grails-doc/resources/doc.properties index 1a8eaea3b98..4832cd072a4 100644 --- a/grails-doc/resources/doc.properties +++ b/grails-doc/resources/doc.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-doc/resources/log4j.properties b/grails-doc/resources/log4j.properties index 2ad54fae729..3375f3224b9 100644 --- a/grails-doc/resources/log4j.properties +++ b/grails-doc/resources/log4j.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-doc/src/en/guide/REST/hypermedia.adoc b/grails-doc/src/en/guide/REST/hypermedia.adoc index d2044753a45..c3b49721251 100644 --- a/grails-doc/src/en/guide/REST/hypermedia.adoc +++ b/grails-doc/src/en/guide/REST/hypermedia.adoc @@ -17,6 +17,6 @@ specific language governing permissions and limitations under the License. //// -http://en.wikipedia.org/wiki/HATEOAS[HATEOAS], an abbreviation for Hypermedia as the Engine of Application State, is a common pattern applied to REST architectures that uses hypermedia and linking to define the REST API. +https://en.wikipedia.org/wiki/HATEOAS[HATEOAS], an abbreviation for Hypermedia as the Engine of Application State, is a common pattern applied to REST architectures that uses hypermedia and linking to define the REST API. -Hypermedia (also called Mime or Media Types) are used to describe the state of a REST resource, and links tell clients how to transition to the next state. The format of the response is typically JSON or XML, although standard formats such as http://tools.ietf.org/html/rfc4287[Atom] and/or http://stateless.co/hal_specification.html[HAL] are frequently used. +Hypermedia (also called Mime or Media Types) are used to describe the state of a REST resource, and links tell clients how to transition to the next state. The format of the response is typically JSON or XML, although standard formats such as https://tools.ietf.org/html/rfc4287[Atom] and/or http://stateless.co/hal_specification.html[HAL] are frequently used. diff --git a/grails-doc/src/en/guide/REST/hypermedia/atom.adoc b/grails-doc/src/en/guide/REST/hypermedia/atom.adoc index 367bacf0174..dbcc0d787f4 100644 --- a/grails-doc/src/en/guide/REST/hypermedia/atom.adoc +++ b/grails-doc/src/en/guide/REST/hypermedia/atom.adoc @@ -17,15 +17,15 @@ specific language governing permissions and limitations under the License. //// -http://tools.ietf.org/html/rfc4287[Atom] is another standard interchange format used to implement REST APIs. An example of Atom output can be seen below: +https://tools.ietf.org/html/rfc4287[Atom] is another standard interchange format used to implement REST APIs. An example of Atom output can be seen below: [source,xml] ---- - + Example Feed - + 2003-12-13T18:30:02Z John Doe @@ -34,7 +34,7 @@ http://tools.ietf.org/html/rfc4287[Atom] is another standard interchange format Atom-Powered Robots Run Amok - + urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2003-12-13T18:30:02Z Some text. diff --git a/grails-doc/src/en/guide/REST/hypermedia/hal.adoc b/grails-doc/src/en/guide/REST/hypermedia/hal.adoc index 941d9a2bdf3..af6d3f1b951 100644 --- a/grails-doc/src/en/guide/REST/hypermedia/hal.adoc +++ b/grails-doc/src/en/guide/REST/hypermedia/hal.adoc @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. //// -http://stateless.co/hal_specification.html[HAL] is a standard exchange format commonly used when developing REST APIs that follow HATEOAS principals. An example HAL document representing a list of orders can be seen below: +https://stateless.co/hal_specification.html[HAL] is a standard exchange format commonly used when developing REST APIs that follow HATEOAS principals. An example HAL document representing a list of orders can be seen below: [source,javascript] ---- diff --git a/grails-doc/src/en/guide/REST/jsonViews.adoc b/grails-doc/src/en/guide/REST/jsonViews.adoc index a098bce1ce6..95d0c32dd10 100644 --- a/grails-doc/src/en/guide/REST/jsonViews.adoc +++ b/grails-doc/src/en/guide/REST/jsonViews.adoc @@ -23,4 +23,4 @@ You can continue to separate your application in terms of MVC, with the logic of JSON views also provide the flexibility to easily customize the JSON presented to clients without having to resort to relatively complex marshalling libraries like Jackson or Grails' marshaller API. -NOTE: Since Grails 3.1, JSON views are considered by the Grails team the best way to present JSON output for the client, the section on writing custom marshallers has been removed from the user guide. If you are looking for information on that topic, see http://grails.github.io/grails-doc/3.0.x/guide/webServices.html#objectMarshallers[the Grails 3.0.x guide]. \ No newline at end of file +NOTE: Since Grails 3.1, JSON views are considered by the Grails team the best way to present JSON output for the client, the section on writing custom marshallers has been removed from the user guide. If you are looking for information on that topic, see https://grails.github.io/grails-doc/3.0.x/guide/webServices.html#objectMarshallers[the Grails 3.0.x guide]. \ No newline at end of file diff --git a/grails-doc/src/en/guide/REST/jsonViews/jsonViewsCreating.adoc b/grails-doc/src/en/guide/REST/jsonViews/jsonViewsCreating.adoc index 51560d1c0f5..09c061ae87b 100644 --- a/grails-doc/src/en/guide/REST/jsonViews/jsonViewsCreating.adoc +++ b/grails-doc/src/en/guide/REST/jsonViews/jsonViewsCreating.adoc @@ -37,7 +37,7 @@ The above JSON view produces: {"person":{"name":"bob"}} ---- -There is an implicit `json` variable which is an instance of http://docs.groovy-lang.org/latest/html/api/groovy/json/StreamingJsonBuilder.html[StreamingJsonBuilder]. +There is an implicit `json` variable which is an instance of https://docs.groovy-lang.org/latest/html/api/groovy/json/StreamingJsonBuilder.html[StreamingJsonBuilder]. Example usages: @@ -48,4 +48,4 @@ json { name "Bob" } == '{"name":"Bob"}' json([1,2,3]) { n it } == '[{"n":1},{"n":2},{"n":3}]' ---- -Refer to the API documentation on http://docs.groovy-lang.org/latest/html/api/groovy/json/StreamingJsonBuilder.html[StreamingJsonBuilder] for more information about what is possible. +Refer to the API documentation on https://docs.groovy-lang.org/latest/html/api/groovy/json/StreamingJsonBuilder.html[StreamingJsonBuilder] for more information about what is possible. diff --git a/grails-doc/src/en/guide/REST/jsonViews/jsonViewsTemplatesAndConventions.adoc b/grails-doc/src/en/guide/REST/jsonViews/jsonViewsTemplatesAndConventions.adoc index e4692ec0b28..8516782918d 100644 --- a/grails-doc/src/en/guide/REST/jsonViews/jsonViewsTemplatesAndConventions.adoc +++ b/grails-doc/src/en/guide/REST/jsonViews/jsonViewsTemplatesAndConventions.adoc @@ -46,4 +46,4 @@ def save(Book book) { If a validation error occurs in the above example the `grails-app/views/book/_errors.gson` template will be rendered. -For more information on JSON views (and Markup views), see the http://views.grails.org/latest/[JSON Views user guide]. +For more information on JSON views (and Markup views), see the https://views.grails.org/latest/[JSON Views user guide]. diff --git a/grails-doc/src/en/guide/async.adoc b/grails-doc/src/en/guide/async.adoc index 82113bc8a4e..97983f2e489 100644 --- a/grails-doc/src/en/guide/async.adoc +++ b/grails-doc/src/en/guide/async.adoc @@ -22,7 +22,7 @@ With modern hardware featuring multiple cores, many programming languages have b Popular asynchronous libraries include: * RxJava - https://reactivex.io -* GPars - http://gpars.org +* GPars - https://gpars.org * Reactor - https://projectreactor.io By building on top of these various libraries the Async features of Grails aim to simplify concurrent programming within the framework, include the concept of Promises, and a unified event model. diff --git a/grails-doc/src/en/guide/async/asyncRequests.adoc b/grails-doc/src/en/guide/async/asyncRequests.adoc index 3988871a4d8..b383615a119 100644 --- a/grails-doc/src/en/guide/async/asyncRequests.adoc +++ b/grails-doc/src/en/guide/async/asyncRequests.adoc @@ -96,7 +96,7 @@ class StockController { def stock(String ticker) { task { ticker = ticker ?: 'GOOG' - def url = new URL("http://download.finance.yahoo.com/d/quotes.csv?s=${ticker}&f=nsl1op&e=.csv") + def url = new URL("https://download.finance.yahoo.com/d/quotes.csv?s=${ticker}&f=nsl1op&e=.csv") Double price = url.text.split(',')[-1] as Double render "ticker: $ticker, price: \$price" } diff --git a/grails-doc/src/en/guide/commandLine/creatingCustomCommands.adoc b/grails-doc/src/en/guide/commandLine/creatingCustomCommands.adoc index 75d3870e3d5..0985470ca22 100644 --- a/grails-doc/src/en/guide/commandLine/creatingCustomCommands.adoc +++ b/grails-doc/src/en/guide/commandLine/creatingCustomCommands.adoc @@ -31,14 +31,14 @@ Since Grails 3.2.0, commands have similar abilities as scripts in regards to ret If you created a command in a previous version of grails, you can update your command to have those abilities by changing which trait you are implementing. -Commands created in Grails 3.1.x or lower implement the http://docs.grails.org/latest/api/grails/dev/commands/ApplicationCommand.html[ApplicationCommand] trait by default which requires your command to implement the following method: +Commands created in Grails 3.1.x or lower implement the https://docs.grails.org/latest/api/grails/dev/commands/ApplicationCommand.html[ApplicationCommand] trait by default which requires your command to implement the following method: [source,groovy] ---- boolean handle(ExecutionContext executionContext) ---- -Commands created in Grails 3.2.0 or higher implement the http://docs.grails.org/latest/api/grails/dev/commands/GrailsApplicationCommand.html[GrailsApplicationCommand] trait by default which requires your command to implement the following method: +Commands created in Grails 3.2.0 or higher implement the https://docs.grails.org/latest/api/grails/dev/commands/GrailsApplicationCommand.html[GrailsApplicationCommand] trait by default which requires your command to implement the following method: [source,groovy] ---- diff --git a/grails-doc/src/en/guide/commandLine/gradleBuild.adoc b/grails-doc/src/en/guide/commandLine/gradleBuild.adoc index 1b244ab26db..0344cf228e7 100644 --- a/grails-doc/src/en/guide/commandLine/gradleBuild.adoc +++ b/grails-doc/src/en/guide/commandLine/gradleBuild.adoc @@ -17,12 +17,12 @@ specific language governing permissions and limitations under the License. //// -The http://gradle.org[Gradle Build System] is used for build related tasks such as compilation, running tests and producing binary distributions of your Grails project. +The https://gradle.org[Gradle Build System] is used for build related tasks such as compilation, running tests and producing binary distributions of your Grails project. It is recommended to use Gradle {GradleVersion} or above with Grails. The build is defined by the `build.gradle` file which specifies the version of your project, the dependencies of the project and the repositories where to find those dependencies (amongst other things). -When you invoke the `grails` command the version of Gradle that ships with Grails (currently {GradleVersion}) is invoked by the `grails` process via the http://www.gradle.org/docs/current/userguide/embedding.html[Gradle Tooling API]: +When you invoke the `grails` command the version of Gradle that ships with Grails (currently {GradleVersion}) is invoked by the `grails` process via the https://www.gradle.org/docs/current/userguide/embedding.html[Gradle Tooling API]: [source,bash] ---- diff --git a/grails-doc/src/en/guide/commandLine/gradleBuild/gradleDependencies.adoc b/grails-doc/src/en/guide/commandLine/gradleBuild/gradleDependencies.adoc index 3358704236d..80309327c35 100644 --- a/grails-doc/src/en/guide/commandLine/gradleBuild/gradleDependencies.adoc +++ b/grails-doc/src/en/guide/commandLine/gradleBuild/gradleDependencies.adoc @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. //// -Dependencies for your project are defined in the `dependencies` block. In general, you can follow the http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html[Gradle documentation on dependency management] to understand how to configure additional dependencies. +Dependencies for your project are defined in the `dependencies` block. In general, you can follow the https://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html[Gradle documentation on dependency management] to understand how to configure additional dependencies. The default dependencies for the Grails Web application can be seen below: diff --git a/grails-doc/src/en/guide/commandLine/gradleBuild/gradlePlugins.adoc b/grails-doc/src/en/guide/commandLine/gradleBuild/gradlePlugins.adoc index 603d4d4df8d..5896ecce9ab 100644 --- a/grails-doc/src/en/guide/commandLine/gradleBuild/gradlePlugins.adoc +++ b/grails-doc/src/en/guide/commandLine/gradleBuild/gradlePlugins.adoc @@ -44,8 +44,8 @@ The default plugins are as follows: * `groovy` - The Groovy plugin adds support for Groovy projects. It can handle Groovy code mixed with Java. Read More: https://docs.gradle.org/{gradleVersion}/userguide/groovy_plugin.html[The Groovy Plugin] * `war` - The https://docs.gradle.org/{gradleVersion}/userguide/war_plugin.html[WAR plugin] changes the packaging so that Gradle creates a WAR file. You can comment out this plugin to build a runnable JAR file for standalone deployment. -* `idea` - The IDEA plugin generates files used by http://www.jetbrains.com/idea/[IntelliJ IDEA], allowing the project to be opened from IDEA. Read More: https://docs.gradle.org/{gradleVersion}/userguide/idea_plugin.html[The IDEA Plugin] -* `eclipse` - The Eclipse plugins generate files for the http://eclipse.org/[Eclipse IDE], enabling project import (File - Import... - Existing Projects into Workspace). Read More: https://docs.gradle.org/{gradleVersion}/userguide/eclipse_plugin.html[The Eclipse Plugin] +* `idea` - The IDEA plugin generates files used by https://www.jetbrains.com/idea/[IntelliJ IDEA], allowing the project to be opened from IDEA. Read More: https://docs.gradle.org/{gradleVersion}/userguide/idea_plugin.html[The IDEA Plugin] +* `eclipse` - The Eclipse plugins generate files for the https://eclipse.org/[Eclipse IDE], enabling project import (File - Import... - Existing Projects into Workspace). Read More: https://docs.gradle.org/{gradleVersion}/userguide/eclipse_plugin.html[The Eclipse Plugin] * `asset-pipeline` - The https://github.com/wondrify/asset-pipeline[Asset Pipeline] plugin enables compilation of static assets (JavaScript, CSS, etc.) Many of these are built-in plugins provided by Gradle or third-party plugins. The Gradle plugins that Grails provides are as follows: diff --git a/grails-doc/src/en/guide/conf/config.adoc b/grails-doc/src/en/guide/conf/config.adoc index 4748016cfca..751f14775b7 100644 --- a/grails-doc/src/en/guide/conf/config.adoc +++ b/grails-doc/src/en/guide/conf/config.adoc @@ -21,7 +21,7 @@ Configuration in Grails is generally split across 2 areas: build configuration a Build configuration is generally done via Gradle and the `build.gradle` file. Runtime configuration is by default specified in YAML in the `grails-app/conf/application.yml` file. -If you prefer to use Grails 2.0-style Groovy configuration then it is possible to specify configuration using Groovy's http://docs.groovy-lang.org/latest/html/documentation/#_configslurper[ConfigSlurper] syntax. Two Groovy configuration files are available: `grails-app/conf/application.groovy` and `grails-app/conf/runtime.groovy`: +If you prefer to use Grails 2.0-style Groovy configuration then it is possible to specify configuration using Groovy's https://docs.groovy-lang.org/latest/html/documentation/#_configslurper[ConfigSlurper] syntax. Two Groovy configuration files are available: `grails-app/conf/application.groovy` and `grails-app/conf/runtime.groovy`: . Use `application.groovy` for configuration that doesn't depend on application classes . Use `runtime.groovy` for configuration that does depend on application classes diff --git a/grails-doc/src/en/guide/conf/config/builtInOptions.adoc b/grails-doc/src/en/guide/conf/config/builtInOptions.adoc index 5cbc2b7799d..671c6574cfa 100644 --- a/grails-doc/src/en/guide/conf/config/builtInOptions.adoc +++ b/grails-doc/src/en/guide/conf/config/builtInOptions.adoc @@ -31,7 +31,7 @@ On the runtime front, i.e. `grails-app/conf/application.yml`, there are quite a * `grails.views.gsp.encoding` - The file encoding used for GSP source files (default: 'utf-8'). * `grails.mime.file.extensions` - Whether to use the file extension to dictate the mime type in link:theWebLayer.html#contentNegotiation[Content Negotiation] (default: true). * `grails.mime.types` - A map of supported mime types used for link:theWebLayer.html#contentNegotiation[Content Negotiation]. -* `grails.serverURL` - A string specifying the server URL portion of absolute links, including server name e.g. grails.serverURL="http://my.yourportal.com". See link:{gspdocs}/ref/Tags/createLink.html[createLink]. Also used by redirects. +* `grails.serverURL` - A string specifying the server URL portion of absolute links, including server name e.g. grails.serverURL="https://my.yourportal.com". See link:{gspdocs}/ref/Tags/createLink.html[createLink]. Also used by redirects. * `grails.views.gsp.layout.preprocess` - Determines whether layout preprocessing happens. Disabling this slows down page rendering, but if you need Grails' layout implementation to parse the generated HTML from a GSP view, then disabling it is the right option. Don't worry if you don't understand this advanced property: leave it set to true. * `grails.reload.excludes` and `grails.reload.includes` - Configuring these directives determines the reload behavior for project specific source files. Each directive takes a list of strings that are the class names for project source files that should be excluded from reloading behavior or included accordingly when running the application in development with the `bootRun` task. If the `grails.reload.includes` directive is configured, then only the classes in that list will be reloaded. diff --git a/grails-doc/src/en/guide/conf/config/logging/loggerName.adoc b/grails-doc/src/en/guide/conf/config/logging/loggerName.adoc index 125fbf076ba..78301757dc6 100644 --- a/grails-doc/src/en/guide/conf/config/logging/loggerName.adoc +++ b/grails-doc/src/en/guide/conf/config/logging/loggerName.adoc @@ -26,7 +26,7 @@ qualified name of the artifact. Grails 3.3.x simplifies logger names. The next examples illustrate the changes: -`BookController.groovy` located at `grails-app/controllers/com/company` NOT annotated with `http://docs.groovy-lang.org/latest/html/gapi/groovy/util/logging/Slf4j.html[@Slf4j]` +`BookController.groovy` located at `grails-app/controllers/com/company` NOT annotated with `https://docs.groovy-lang.org/latest/html/gapi/groovy/util/logging/Slf4j.html[@Slf4j]` [cols="2*"] |=== @@ -37,7 +37,7 @@ Grails 3.3.x simplifies logger names. The next examples illustrate the changes: |=== -`BookController.groovy` located at `grails-app/controllers/com/company` annotated with `http://docs.groovy-lang.org/latest/html/gapi/groovy/util/logging/Slf4j.html[@Slf4j]` +`BookController.groovy` located at `grails-app/controllers/com/company` annotated with `https://docs.groovy-lang.org/latest/html/gapi/groovy/util/logging/Slf4j.html[@Slf4j]` [cols="2*"] |=== @@ -48,7 +48,7 @@ Grails 3.3.x simplifies logger names. The next examples illustrate the changes: |=== -`BookService.groovy` located at `grails-app/services/com/company` NOT annotated with `http://docs.groovy-lang.org/latest/html/gapi/groovy/util/logging/Slf4j.html[@Slf4j]` +`BookService.groovy` located at `grails-app/services/com/company` NOT annotated with `https://docs.groovy-lang.org/latest/html/gapi/groovy/util/logging/Slf4j.html[@Slf4j]` [cols="2*"] |=== @@ -58,7 +58,7 @@ Grails 3.3.x simplifies logger names. The next examples illustrate the changes: |`grails.app.services.com.company.BookService` |=== -`BookService.groovy` located at `grails-app/services/com/company` annotated with `http://docs.groovy-lang.org/latest/html/gapi/groovy/util/logging/Slf4j.html[@Slf4j]` +`BookService.groovy` located at `grails-app/services/com/company` annotated with `https://docs.groovy-lang.org/latest/html/gapi/groovy/util/logging/Slf4j.html[@Slf4j]` [cols="2*"] |=== @@ -68,7 +68,7 @@ Grails 3.3.x simplifies logger names. The next examples illustrate the changes: |`com.company.BookService` |=== -`BookDetail.groovy` located at `src/main/groovy/com/company` annotated with `http://docs.groovy-lang.org/latest/html/gapi/groovy/util/logging/Slf4j.html[@Slf4j]` +`BookDetail.groovy` located at `src/main/groovy/com/company` annotated with `https://docs.groovy-lang.org/latest/html/gapi/groovy/util/logging/Slf4j.html[@Slf4j]` [cols="2*"] |=== diff --git a/grails-doc/src/en/guide/conf/dataSource.adoc b/grails-doc/src/en/guide/conf/dataSource.adoc index c3c9cbe79b8..b88ed9b4463 100644 --- a/grails-doc/src/en/guide/conf/dataSource.adoc +++ b/grails-doc/src/en/guide/conf/dataSource.adoc @@ -44,7 +44,7 @@ Once you have the JAR resolved you need to get familiar with how Grails manages * `readOnly` - If `true` makes the DataSource read-only, which results in the connection pool calling `setReadOnly(true)` on each `Connection` * `transactional` - If `false` leaves the DataSource's transactionManager bean outside the chained BE1PC transaction manager implementation. This only applies to additional datasources. * `persistenceInterceptor` - The default datasource is automatically wired up to the persistence interceptor, other datasources are not wired up automatically unless this is set to `true` -* `properties` - Extra properties to set on the DataSource bean. See the http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#Common_Attributes[Tomcat Pool] documentation. There is also a Javadoc format https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/tomcat/jdbc/pool/PoolConfiguration.html[documentation of the properties]. +* `properties` - Extra properties to set on the DataSource bean. See the https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#Common_Attributes[Tomcat Pool] documentation. There is also a Javadoc format https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/tomcat/jdbc/pool/PoolConfiguration.html[documentation of the properties]. * `jmxExport` - If `false`, will disable registration of JMX MBeans for all DataSources. By default JMX MBeans are added for DataSources with `jmxEnabled = true` in properties. * `type` - The connection pool class if you want to force Grails to use it when there are more than one available. @@ -107,7 +107,7 @@ dataSource { type = "com.zaxxer.hikari.HikariDataSource" properties { // Documentation for Tomcat JDBC Pool - // http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#Common_Attributes + // https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#Common_Attributes // https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/tomcat/jdbc/pool/PoolConfiguration.html jmxEnabled = true initialSize = 5 @@ -125,7 +125,7 @@ dataSource { testWhileIdle = true testOnReturn = false ignoreExceptionOnPreLoad = true - // http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#JDBC_interceptors + // https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#JDBC_interceptors jdbcInterceptors = "ConnectionState;StatementCache(max=200)" defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED // safe default // controls for leaked connections @@ -138,7 +138,7 @@ dataSource { // Mysql as example dbProperties { // Mysql specific driver properties - // http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html + // https://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html // let Tomcat JDBC Pool handle reconnecting autoReconnect=false // truncation behaviour @@ -183,4 +183,4 @@ Hibernate can automatically create the database tables required for your domain * *validate* - Makes no changes to your database. Compares the configuration with the existing database schema and reports warnings. * any other value - does nothing -Setting the `dbCreate` setting to "none" is recommended once your schema is relatively stable and definitely when your application and database are deployed in production. Database changes are then managed through proper migrations, either with SQL scripts or a migration tool like https://flywaydb.org/[Flyway] or http://www.liquibase.org/[Liquibase]. The link:{hibernate5Guide}/manual/index.html#databaseMigration[Database Migration] plugin uses Liquibase. +Setting the `dbCreate` setting to "none" is recommended once your schema is relatively stable and definitely when your application and database are deployed in production. Database changes are then managed through proper migrations, either with SQL scripts or a migration tool like https://flywaydb.org/[Flyway] or https://www.liquibase.org/[Liquibase]. The link:{hibernate5Guide}/manual/index.html#databaseMigration[Database Migration] plugin uses Liquibase. diff --git a/grails-doc/src/en/guide/conf/dataSource/databaseConsole.adoc b/grails-doc/src/en/guide/conf/dataSource/databaseConsole.adoc index ac04b4640c6..2fbabab16a7 100644 --- a/grails-doc/src/en/guide/conf/dataSource/databaseConsole.adoc +++ b/grails-doc/src/en/guide/conf/dataSource/databaseConsole.adoc @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. //// -The http://h2database.com/html/quickstart.html#h2_console[H2 database console] is a convenient feature of H2 that provides a web-based interface to any database that you have a JDBC driver for, and it's very useful to view the database you're developing against. It's especially useful when running against an in-memory database. +The https://h2database.com/html/quickstart.html#h2_console[H2 database console] is a convenient feature of H2 that provides a web-based interface to any database that you have a JDBC driver for, and it's very useful to view the database you're developing against. It's especially useful when running against an in-memory database. You can access the console by navigating to http://localhost:8080/h2-console in a browser. See the {springBootReference}/htmlsingle/#data.sql.h2-web-console[Spring Boot H2 Console Documentation] for more information on the options available. diff --git a/grails-doc/src/en/guide/conf/dataSource/multipleDatasources.adoc b/grails-doc/src/en/guide/conf/dataSource/multipleDatasources.adoc index 7b5944e8b20..c09dfc4f8f7 100644 --- a/grails-doc/src/en/guide/conf/dataSource/multipleDatasources.adoc +++ b/grails-doc/src/en/guide/conf/dataSource/multipleDatasources.adoc @@ -211,7 +211,7 @@ For example if the `Book` class is in the default datasource, you would register + 'https://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd'> @@ -226,7 +226,7 @@ and if the `Library` class is in the "ds2" datasource, you would register that i + 'https://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd'> diff --git a/grails-doc/src/en/guide/conf/docengine.adoc b/grails-doc/src/en/guide/conf/docengine.adoc index 911422ef38f..5dc652bae74 100644 --- a/grails-doc/src/en/guide/conf/docengine.adoc +++ b/grails-doc/src/en/guide/conf/docengine.adoc @@ -39,7 +39,7 @@ To use the engine you need to follow a few conventions. First, you need to creat Note that you can have all your gdoc files in the top-level directory if you want, but you can also put sub-sections in sub-directories named after the parent section - as the above example shows. -Once you have your source files, you still need to tell the documentation engine what the structure of your user guide is going to be. To do that, you add a `src/docs/guide/toc.yml` file that contains the structure and titles for each section. This file is in http://www.yaml.org/[YAML] format and basically represents the structure of the user guide in tree form. For example, the above files could be represented as: +Once you have your source files, you still need to tell the documentation engine what the structure of your user guide is going to be. To do that, you add a `src/docs/guide/toc.yml` file that contains the structure and titles for each section. This file is in https://www.yaml.org/[YAML] format and basically represents the structure of the user guide in tree form. For example, the above files could be represented as: [source,yaml] ---- @@ -142,11 +142,11 @@ Bold: *bold* ---- Image: -image::http://grails.org/images/new/grailslogo_topNav.png[] +image::https://grails.org/images/new/grailslogo_topNav.png[] [source,xml] ---- -\!http://grails.org/images/new/grailslogo_topNav.png\! +\!https://grails.org/images/new/grailslogo_topNav.png\! ---- You can also link to internal images like so: @@ -173,14 +173,14 @@ There are several ways to create links with the documentation generator. A basic [source,groovy] ---- -http://www.pivotal.io/oss[Pivotal] +https://www.pivotal.io/oss[Pivotal] ---- or [source,groovy] ---- -http://www.pivotal.io/oss[Pivotal] ---- +https://www.pivotal.io/oss[Pivotal] ---- For links to other sections inside the user guide you can use the `guide:` prefix with the name of the section you want to link to: @@ -212,7 +212,7 @@ The documentation engine will automatically create the appropriate javadoc link [source,groovy] ---- grails.doc.api.org.hibernate= - "http://docs.jboss.org/hibernate/stable/core/javadocs" + "https://docs.jboss.org/hibernate/stable/core/javadocs" ---- The above example configures classes within the `org.hibernate` package to link to the Hibernate website's API docs. diff --git a/grails-doc/src/en/guide/contributing/build.adoc b/grails-doc/src/en/guide/contributing/build.adoc index 5c5f98c551d..f7bff5c13c3 100644 --- a/grails-doc/src/en/guide/contributing/build.adoc +++ b/grails-doc/src/en/guide/contributing/build.adoc @@ -22,13 +22,13 @@ If you're interested in contributing fixes and features to any part of grails, y * A JDK (17 or above) * A git client -Once you have all the pre-requisite packages installed, the next step is to download the Grails source code, which is hosted at http://github.com/apache/grails-core[GitHub]. +Once you have all the pre-requisite packages installed, the next step is to download the Grails source code, which is hosted at https://github.com/apache/grails-core[GitHub]. This is a simple case of cloning the repository you're interested in. For example, to get the core framework run: [source,groovy] ---- -git clone http://github.com/apache/grails-core.git +git clone https://github.com/apache/grails-core.git ---- This will create a "grails-core" directory in your current working directory containing all the project source files. The next step is to get a Grails installation from the source. @@ -49,7 +49,7 @@ Under the extracted location is a `bin` directory. Add it to your path. When you next type `grails-shell-cli` command to run, you'll be using the version you just built. -If you are using http://sdkman.io[SDKMAN] then that can also be used to work with this local installation via the following: +If you are using https://sdkman.io[SDKMAN] then that can also be used to work with this local installation via the following: [source,groovy] ---- diff --git a/grails-doc/src/en/guide/gettingStarted/conventionOverConfiguration.adoc b/grails-doc/src/en/guide/gettingStarted/conventionOverConfiguration.adoc index 173b7587b20..2909b587fb5 100644 --- a/grails-doc/src/en/guide/gettingStarted/conventionOverConfiguration.adoc +++ b/grails-doc/src/en/guide/gettingStarted/conventionOverConfiguration.adoc @@ -28,7 +28,7 @@ Grails adopts the "convention over configuration" approach to configure itself. * `services` - The link:services.html[Service Layer]. * `taglib` - link:theWebLayer.html#taglibs[Tag Libraries]. * `utils` - Houses Grails-specific utilities. -* `views` - link:theWebLayer.html#gsp[Groovy Server Pages (GSP)] or http://views.grails.org/latest[JSON Views] - Responsible for the "V" in MVC. +* `views` - link:theWebLayer.html#gsp[Groovy Server Pages (GSP)] or https://views.grails.org/latest[JSON Views] - Responsible for the "V" in MVC. * `commands` - link:commandLine.html#customCommands[Custom Grails Commands] - Create your own Grails CLI commands. 2. `src/main/groovy` - Supporting Sources diff --git a/grails-doc/src/en/guide/gettingStarted/deployingAnApplication.adoc b/grails-doc/src/en/guide/gettingStarted/deployingAnApplication.adoc index 95a8f69f02a..2ab4fcb064f 100644 --- a/grails-doc/src/en/guide/gettingStarted/deployingAnApplication.adoc +++ b/grails-doc/src/en/guide/gettingStarted/deployingAnApplication.adoc @@ -41,7 +41,7 @@ To target a Tomcat 7 container, insert a line to `build.gradle` above the `depen ---- ext['tomcat.version'] = '7.0.59' ---- -WARNING: Grails 5 contains dependencies that _require_ `javax.el-api:3.0` (eg.: `datastore-gorm:7.x`, `spring-boot:2.x`) which is only supported starting from Tomcat 8.x+, based on the http://tomcat.apache.org/whichversion.html[tomcat version table]! +WARNING: Grails 5 contains dependencies that _require_ `javax.el-api:3.0` (eg.: `datastore-gorm:7.x`, `spring-boot:2.x`) which is only supported starting from Tomcat 8.x+, based on the https://tomcat.apache.org/whichversion.html[tomcat version table]! Unlike most scripts which default to the `development` environment unless overridden, the `war` command runs in the `production` environment by default. You can override this like any script by specifying the environment name, for example: diff --git a/grails-doc/src/en/guide/gettingStarted/ide.adoc b/grails-doc/src/en/guide/gettingStarted/ide.adoc index 4d3c48edd60..0ecc2c09878 100644 --- a/grails-doc/src/en/guide/gettingStarted/ide.adoc +++ b/grails-doc/src/en/guide/gettingStarted/ide.adoc @@ -55,9 +55,9 @@ Apache https://netbeans.apache.org[Netbeans] does not offer specific support for There are several excellent text editors that work nicely with Groovy and Grails. Here are some references: -* A https://github.com/textmate/groovy-grails.tmbundle[bundle] is available for Groovy / Grails support in http://macromates.com[Textmate]. -* A https://packagecontrol.io/packages/Grails[plugin] can be installed via Sublime Package Control for the http://www.sublimetext.com[Sublime Text Editor]. +* A https://github.com/textmate/groovy-grails.tmbundle[bundle] is available for Groovy / Grails support in https://macromates.com[Textmate]. +* A https://packagecontrol.io/packages/Grails[plugin] can be installed via Sublime Package Control for the https://www.sublimetext.com[Sublime Text Editor]. * The https://github.com/lifeisfoo/emacs-grails[emacs-grails] extension offers basic support for Grails development in Emacs. -* See http://www.objectpartners.com/2012/02/21/using-vim-as-your-grails-ide-part-1-navigating-your-project/[this post] for some helpful tips on how to set up VIM as your Grails editor of choice. +* See https://www.objectpartners.com/2012/02/21/using-vim-as-your-grails-ide-part-1-navigating-your-project/[this post] for some helpful tips on how to set up VIM as your Grails editor of choice. These text editors, along with the provided extensions and configurations, can enhance your Groovy and Grails development experience, offering flexibility and customization to meet your coding preferences. diff --git a/grails-doc/src/en/guide/gettingStarted/requirements.adoc b/grails-doc/src/en/guide/gettingStarted/requirements.adoc index b0cbdccfdac..1fc5f96eb66 100644 --- a/grails-doc/src/en/guide/gettingStarted/requirements.adoc +++ b/grails-doc/src/en/guide/gettingStarted/requirements.adoc @@ -30,7 +30,7 @@ We recommend https://bell-sw.com/pages/downloads/#jdk-17-lts[Liberica JDK 17 LTS | 5 | 8 |=== -To automate the installation of Grails we recommend http://sdkman.io[SDKMAN] which greatly simplifies installing and managing multiple Grails versions. +To automate the installation of Grails we recommend https://sdkman.io[SDKMAN] which greatly simplifies installing and managing multiple Grails versions. On some platforms (for example macOS) the Java installation is automatically detected. However in many cases you will want to manually configure the location of Java. For example, if you're using bash or another variant of the Bourne Shell: diff --git a/grails-doc/src/en/guide/hibernate/mappingWithHibernateAnnotations.adoc b/grails-doc/src/en/guide/hibernate/mappingWithHibernateAnnotations.adoc index 6fab7273748..289bf997cb4 100644 --- a/grails-doc/src/en/guide/hibernate/mappingWithHibernateAnnotations.adoc +++ b/grails-doc/src/en/guide/hibernate/mappingWithHibernateAnnotations.adoc @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. //// -To map a domain class with annotations, create a new class in `src/main/groovy/` and use the annotations defined as part of the EJB 3.0 spec (for more info on this see the http://annotations.hibernate.org/[Hibernate Annotations Docs]): +To map a domain class with annotations, create a new class in `src/main/groovy/` and use the annotations defined as part of the EJB 3.0 spec (for more info on this see the https://annotations.hibernate.org/[Hibernate Annotations Docs]): [source,groovy] ---- @@ -67,7 +67,7 @@ Then register the class with the Hibernate `sessionFactory` by adding relevant e [source,xml] ---- + "https://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> diff --git a/grails-doc/src/en/guide/i18n.adoc b/grails-doc/src/en/guide/i18n.adoc index b37cf1ceaef..0f9e4a04597 100644 --- a/grails-doc/src/en/guide/i18n.adoc +++ b/grails-doc/src/en/guide/i18n.adoc @@ -23,4 +23,4 @@ ____ A Locale object represents a specific geographical, political, or cultural region. An operation that requires a Locale to perform its task is called locale-sensitive and uses the Locale to tailor information for the user. For example, displaying a number is a locale-sensitive operation--the number should be formatted according to the customs/conventions of the user's native country, region, or culture. ____ -A Locale is made up of a https://www.loc.gov/standards/iso639-2/php/English_list.php[language code] and a http://www.iso.org/iso/country_codes/iso_3166_code_lists/country_names_and_code_elements.htm[country code]. For example "en_US" is the code for US English, whilst "en_GB" is the code for British English. +A Locale is made up of a https://www.loc.gov/standards/iso639-2/php/English_list.php[language code] and a https://www.iso.org/iso/country_codes/iso_3166_code_lists/country_names_and_code_elements.htm[country code]. For example "en_US" is the code for US English, whilst "en_GB" is the code for British English. diff --git a/grails-doc/src/en/guide/i18n/readingMessages.adoc b/grails-doc/src/en/guide/i18n/readingMessages.adoc index 01564474925..143bf62b868 100644 --- a/grails-doc/src/en/guide/i18n/readingMessages.adoc +++ b/grails-doc/src/en/guide/i18n/readingMessages.adoc @@ -69,7 +69,7 @@ class MyappController { ==== Reading Messages in Controllers and Tag Libraries with the Message Tag -Additionally, you can read a message inside Controllers and Tag Libraries with the link:http://gsp.grails.org/latest/ref/Tags/message.html[Message Tag]. However, using the message tag relies on GSP support which a Grails application may not necessarily have; e.g. a rest application. +Additionally, you can read a message inside Controllers and Tag Libraries with the link:https://gsp.grails.org/latest/ref/Tags/message.html[Message Tag]. However, using the message tag relies on GSP support which a Grails application may not necessarily have; e.g. a rest application. In a controller, you can invoke tags as methods. diff --git a/grails-doc/src/en/guide/introduction.adoc b/grails-doc/src/en/guide/introduction.adoc index cb7cbd1f0b5..84e65b82ece 100644 --- a/grails-doc/src/en/guide/introduction.adoc +++ b/grails-doc/src/en/guide/introduction.adoc @@ -24,18 +24,18 @@ Dynamic frameworks like Rails and Django helped pave the way to a more modern wa Grails is a full stack framework and attempts to solve as many pieces of the web development puzzle through the core technology and its associated plugins. Included out the box are things like: * link:{gormWebsite}[GORM] - An easy-to-use Object Mapping library with support for link:{hibernate5Guide}[SQL], link:{mongodbGuide}[MongoDB], https://gorm.grails.org/{projectVersion}/neo4j[Neo4j] and link:{gormWebsite}[more]. -* View technologies for https://gsp.grails.org[rendering HTML] as well as http://views.grails.org[JSON] +* View technologies for https://gsp.grails.org[rendering HTML] as well as https://views.grails.org[JSON] * A controller layer built on https://spring.io/projects/spring-boot[Spring Boot] -* A plugin system featuring http://plugins.grails.org[hundreds of plugins]. -* Flexible profiles to http://start.grails.org/#/index[create applications with AngularJS, React and more]. -* An interactive command line environment and build system based on http://gradle.org[Gradle] -* An embedded http://tomcat.apache.org[Tomcat] container which is configured for on the fly reloading +* A plugin system featuring https://plugins.grails.org[hundreds of plugins]. +* Flexible profiles to https://start.grails.org/#/index[create applications with AngularJS, React and more]. +* An interactive command line environment and build system based on https://gradle.org[Gradle] +* An embedded https://tomcat.apache.org[Tomcat] container which is configured for on the fly reloading -All of these are made easy to use through the power of the http://groovy-lang.org[Groovy] language and the extensive use of Domain Specific Languages (DSLs) +All of these are made easy to use through the power of the https://groovy-lang.org[Groovy] language and the extensive use of Domain Specific Languages (DSLs) This documentation will take you through getting started with Grails and building web applications with the Grails framework. -In addition to this documentation there are http://guides.grails.org[comprehensive guides] that walk you through various aspects of the technology. +In addition to this documentation there are https://guides.grails.org[comprehensive guides] that walk you through various aspects of the technology. Finally, Grails is far more than just a web framework and is made up of various sub-projects. The following table summarizes some other key projects in the eco-system with links to documentation. @@ -52,13 +52,13 @@ Finally, Grails is far more than just a web framework and is made up of various |https://gorm.grails.org/{projectVersion}/neo4j[GORM for Neo4j] |An Object Mapping implementation for Neo4j Graph Database -|http://views.grails.org[JSON Views] +|https://views.grails.org[JSON Views] |A View technology for rendering JSON on the server side -|http://gsp.grails.org[Groovy Server Pages] +|https://gsp.grails.org[Groovy Server Pages] |A View technology for rendering HTML and other markup on the server -|http://async.grails.org[Async Framework] +|https://async.grails.org[Async Framework] |Asynchronous programming abstraction with support for RxJava, GPars and more diff --git a/grails-doc/src/en/guide/plugins/artefactApi/customArtefacts.adoc b/grails-doc/src/en/guide/plugins/artefactApi/customArtefacts.adoc index f33df9eacc2..3e70e3d4713 100644 --- a/grails-doc/src/en/guide/plugins/artefactApi/customArtefacts.adoc +++ b/grails-doc/src/en/guide/plugins/artefactApi/customArtefacts.adoc @@ -39,4 +39,4 @@ The best way to understand how both the handler and wrapper classes work is to l * https://github.com/apache/grails-quartz/blob/master/src/main/groovy/grails/plugins/quartz/DefaultGrailsJobClass.java[DefaultGrailsJobClass] * https://github.com/apache/grails-quartz/blob/master/src/main/groovy/grails/plugins/quartz/JobArtefactHandler.groovy[JobArtefactHandler] -Another example is the http://github.com/pledbrook/grails-shiro[Shiro plugin] which adds a realm artefact. +Another example is the https://github.com/pledbrook/grails-shiro[Shiro plugin] which adds a realm artefact. diff --git a/grails-doc/src/en/guide/plugins/hookingIntoRuntimeConfiguration.adoc b/grails-doc/src/en/guide/plugins/hookingIntoRuntimeConfiguration.adoc index c0d427bd622..8336155a4c6 100644 --- a/grails-doc/src/en/guide/plugins/hookingIntoRuntimeConfiguration.adoc +++ b/grails-doc/src/en/guide/plugins/hookingIntoRuntimeConfiguration.adoc @@ -71,7 +71,7 @@ Closure doWithSpring() {{-> }} ---- -If you need to customize the servlet you can use Spring Boot's http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/context/embedded/ServletRegistrationBean.html[ServletRegistrationBean]: +If you need to customize the servlet you can use Spring Boot's https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/context/embedded/ServletRegistrationBean.html[ServletRegistrationBean]: [source,groovy] ---- @@ -95,7 +95,7 @@ Closure doWithSpring() {{-> }} ---- -However, if you want to control the order of filter registrations you will need to use Spring Boot's http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/servlet/FilterRegistrationBean.html[FilterRegistrationBean]: +However, if you want to control the order of filter registrations you will need to use Spring Boot's https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/servlet/FilterRegistrationBean.html[FilterRegistrationBean]: [source,groovy] ---- diff --git a/grails-doc/src/en/guide/plugins/repositories.adoc b/grails-doc/src/en/guide/plugins/repositories.adoc index 16e2f4579be..e23633ffb12 100644 --- a/grails-doc/src/en/guide/plugins/repositories.adoc +++ b/grails-doc/src/en/guide/plugins/repositories.adoc @@ -37,4 +37,4 @@ grails plugin-info [plugin-name] which prints extra information about it, such as its description, who wrote, etc. -NOTE: If you have created a Grails plugin and want it to be hosted in the central repository, you'll find instructions for getting an account on the http://plugins.grails.org/[plugin portal] website. +NOTE: If you have created a Grails plugin and want it to be hosted in the central repository, you'll find instructions for getting an account on the https://plugins.grails.org/[plugin portal] website. diff --git a/grails-doc/src/en/guide/profiles.adoc b/grails-doc/src/en/guide/profiles.adoc index 989ee9eebd5..6a92507fcf2 100644 --- a/grails-doc/src/en/guide/profiles.adoc +++ b/grails-doc/src/en/guide/profiles.adoc @@ -62,7 +62,7 @@ grails { profiles { repositories { myRepo { - url = "http://foo.com/repo" + url = "https://foo.com/repo" snapshotsEnabled = true } mavenCentral() @@ -81,7 +81,7 @@ grails { profiles { repositories { myRepo { - url = "http://foo.com/repo" + url = "https://foo.com/repo" snapshotsEnabled = true username = "user" password = "pass" diff --git a/grails-doc/src/en/guide/profiles/publishingProfiles.adoc b/grails-doc/src/en/guide/profiles/publishingProfiles.adoc index 75db721b1ff..30105477981 100644 --- a/grails-doc/src/en/guide/profiles/publishingProfiles.adoc +++ b/grails-doc/src/en/guide/profiles/publishingProfiles.adoc @@ -27,7 +27,7 @@ To mark a profile project for publishing, you need to apply the `grails-profile- apply plugin: "org.apache.grails.gradle.grails-publish-profile" ---- -To publish a profile using this plugin to the Grails central repository first upload the source to https://github.com[Github] (closed source profiles will not be accepted). Then register for an account on http://bintray.com[Bintray] and configure your keys as follows in the profile's `build.gradle` file: +To publish a profile using this plugin to Maven Central first upload the source to https://github.com[Github] (closed source profiles will not be accepted). Then register for an account on https://central.sonatype.com[Maven Cnetral] and configure your keys as follows in the profile's `build.gradle` file: [source,groovy] ---- diff --git a/grails-doc/src/en/guide/testing/functionalTesting.adoc b/grails-doc/src/en/guide/testing/functionalTesting.adoc index c7a6d3a3b11..912bada6b39 100644 --- a/grails-doc/src/en/guide/testing/functionalTesting.adoc +++ b/grails-doc/src/en/guide/testing/functionalTesting.adoc @@ -19,7 +19,7 @@ under the License. Functional tests involve making HTTP requests against the running application and verifying the resultant behaviour. This is useful for end-to-end testing scenarios, such as making REST calls against a JSON API. -Grails by default ships with support for writing functional tests using the http://www.gebish.org[Geb framework]. To create a functional test you can use the `create-functional-test` command which will create a new functional test: +Grails by default ships with support for writing functional tests using the https://www.gebish.org[Geb framework]. To create a functional test you can use the `create-functional-test` command which will create a new functional test: [source,groovy] ---- diff --git a/grails-doc/src/en/guide/theWebLayer/controllers/jsonResponses.adoc b/grails-doc/src/en/guide/theWebLayer/controllers/jsonResponses.adoc index ce1d0b218bb..1e5c316cd04 100644 --- a/grails-doc/src/en/guide/theWebLayer/controllers/jsonResponses.adoc +++ b/grails-doc/src/en/guide/theWebLayer/controllers/jsonResponses.adoc @@ -19,7 +19,7 @@ under the License. ==== Using the respond method to output JSON -The `respond` method is the preferred way to return JSON and integrates with link:theWebLayer.html#contentNegotiation[Content Negotiation] and http://views.grails.org[JSON Views]. +The `respond` method is the preferred way to return JSON and integrates with link:theWebLayer.html#contentNegotiation[Content Negotiation] and https://views.grails.org[JSON Views]. The `respond` method provides content negotiation strategies to intelligently produce an appropriate response for the given client. @@ -79,7 +79,7 @@ In the above example Grails will respond by default with `json` if the media typ ==== Using Views to Output JSON Responses -If you define a view (either a GSP or a http://views.grails.org[JSON View]) then Grails will render the view when using the `respond` method by calculating a model from the argument passed to `respond`. +If you define a view (either a GSP or a https://views.grails.org[JSON View]) then Grails will render the view when using the `respond` method by calculating a model from the argument passed to `respond`. For example, in the previous listing, if you were to define `grails-app/views/index.gson` and `grails-app/views/index.gsp` views, these would be used if the client requested `application/json` or `text/html` media types respectively. Thus allowing you to define a single backend capable of serving responses to a web browser or representing your application's API. diff --git a/grails-doc/src/en/guide/theWebLayer/controllers/moreOnJSONBuilder.adoc b/grails-doc/src/en/guide/theWebLayer/controllers/moreOnJSONBuilder.adoc index 88632f7864c..a7de2fbbe57 100644 --- a/grails-doc/src/en/guide/theWebLayer/controllers/moreOnJSONBuilder.adoc +++ b/grails-doc/src/en/guide/theWebLayer/controllers/moreOnJSONBuilder.adoc @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. //// -The previous section on XML and JSON responses covered simplistic examples of rendering XML and JSON responses. Whilst the XML builder used by Grails is the standard http://groovy-lang.org/processing-xml.html#_xmlparser_and_xmlslurper[XmlSlurper] found in Groovy. +The previous section on XML and JSON responses covered simplistic examples of rendering XML and JSON responses. Whilst the XML builder used by Grails is the standard https://groovy-lang.org/processing-xml.html#_xmlparser_and_xmlslurper[XmlSlurper] found in Groovy. -For JSON, since Grails 3.1, Grails uses Groovy's http://docs.groovy-lang.org/latest/html/documentation/core-domain-specific-languages.html#_streamingjsonbuilder[StreamingJsonBuilder] by default and you can refer to the http://docs.groovy-lang.org/latest/html/documentation/core-domain-specific-languages.html#_streamingjsonbuilder[Groovy documentation] and {groovyapi}groovy/json/StreamingJsonBuilder.html[StreamingJsonBuilder] API documentation on how to use it. +For JSON, since Grails 3.1, Grails uses Groovy's https://docs.groovy-lang.org/latest/html/documentation/core-domain-specific-languages.html#_streamingjsonbuilder[StreamingJsonBuilder] by default and you can refer to the https://docs.groovy-lang.org/latest/html/documentation/core-domain-specific-languages.html#_streamingjsonbuilder[Groovy documentation] and {groovyapi}groovy/json/StreamingJsonBuilder.html[StreamingJsonBuilder] API documentation on how to use it. diff --git a/grails-doc/src/en/guide/theWebLayer/fields/scaffolding/extending/index.adoc b/grails-doc/src/en/guide/theWebLayer/fields/scaffolding/extending/index.adoc index aa614b96cfc..4c96518096f 100644 --- a/grails-doc/src/en/guide/theWebLayer/fields/scaffolding/extending/index.adoc +++ b/grails-doc/src/en/guide/theWebLayer/fields/scaffolding/extending/index.adoc @@ -44,7 +44,7 @@ Input renders must implement the link:api/org/grails/scaffolding/registry/Domain * `Boolean supports(DomainProperty domainProperty)` Return true if your renderer supports the given property. See the link:api/org/grails/scaffolding/model/property/DomainProperty.html[DomainProperty] and link:{gormApiDocs}/org/grails/datastore/mapping/model/PersistentProperty.html[PersistentProperty] interfaces to see what data is available on the domain property instance. * `Closure renderInput(Map defaultAttributes, DomainProperty property)` - Return a closure to be passed to a link:http://docs.groovy-lang.org/latest/html/api/groovy/xml/MarkupBuilder.html[MarkupBuilder] that renders your property + Return a closure to be passed to a link:https://docs.groovy-lang.org/latest/html/api/groovy/xml/MarkupBuilder.html[MarkupBuilder] that renders your property NOTE: The default attributes passed to `renderInput` are created by the link:api/org/grails/scaffolding/markup/PropertyMarkupRenderer.html#getStandardAttributes(org.grails.scaffolding.model.property.DomainProperty)[PropertyMarkupRenderer#getStandardAttributes] method. @@ -64,9 +64,9 @@ Output renders must implement the link:api/org/grails/scaffolding/registry/Domai * `Boolean supports(DomainProperty domainProperty)` Return true if your renderer supports the given property. See the link:api/org/grails/scaffolding/model/property/DomainProperty.html[DomainProperty] and link:{gormApiDocs}/org/grails/datastore/mapping/model/PersistentProperty.html[PersistentProperty] interfaces to see what data is available on the domain property instance. * `Closure renderListOutput(DomainProperty property)` - Return a closure to be passed to a link:http://docs.groovy-lang.org/latest/html/api/groovy/xml/MarkupBuilder.html[MarkupBuilder] that renders your property in the context of a list of domain class instances + Return a closure to be passed to a link:https://docs.groovy-lang.org/latest/html/api/groovy/xml/MarkupBuilder.html[MarkupBuilder] that renders your property in the context of a list of domain class instances * `Closure renderOutput(DomainProperty property)` - Return a closure to be passed to a link:http://docs.groovy-lang.org/latest/html/api/groovy/xml/MarkupBuilder.html[MarkupBuilder] that renders your property in the context of a single domain class instance + Return a closure to be passed to a link:https://docs.groovy-lang.org/latest/html/api/groovy/xml/MarkupBuilder.html[MarkupBuilder] that renders your property in the context of a single domain class instance To register your renderer, inject the "domainOutputRendererRegistry" bean and execute `registerDomainRenderer`, passing along your renderer and its priority. diff --git a/grails-doc/src/en/guide/theWebLayer/gson.adoc b/grails-doc/src/en/guide/theWebLayer/gson.adoc index 4f930f5905e..247bca5574e 100644 --- a/grails-doc/src/en/guide/theWebLayer/gson.adoc +++ b/grails-doc/src/en/guide/theWebLayer/gson.adoc @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. //// -JSON views are written in Groovy, end with the file extension `gson` and reside in the `grails-app/views` directory. They allow rendering of JSON responses using Groovy's http://docs.groovy-lang.org/latest/html/gapi/groovy/json/StreamingJsonBuilder.html[StreamingJsonBuilder] by providing a DSL for producing output in the JSON format. A hello world example can be seen below: +JSON views are written in Groovy, end with the file extension `gson` and reside in the `grails-app/views` directory. They allow rendering of JSON responses using Groovy's https://docs.groovy-lang.org/latest/html/gapi/groovy/json/StreamingJsonBuilder.html[StreamingJsonBuilder] by providing a DSL for producing output in the JSON format. A hello world example can be seen below: [source,groovy] .`grails-app/views/hello.gson` @@ -30,7 +30,7 @@ The above JSON view results in the output: [source,javascript] {"message":{ "hello":"world"}} -The `json` variable is an instance of {groovyapi}/groovy/json/StreamingJsonBuilder.html[StreamingJsonBuilder]. See the http://docs.groovy-lang.org/latest/html/documentation/core-domain-specific-languages.html#_streamingjsonbuilder[documentation] in the Groovy user guide for more information on `StreamingJsonBuilder`. +The `json` variable is an instance of {groovyapi}/groovy/json/StreamingJsonBuilder.html[StreamingJsonBuilder]. See the https://docs.groovy-lang.org/latest/html/documentation/core-domain-specific-languages.html#_streamingjsonbuilder[documentation] in the Groovy user guide for more information on `StreamingJsonBuilder`. More example usages: diff --git a/grails-doc/src/en/guide/theWebLayer/gson/jsonapi.adoc b/grails-doc/src/en/guide/theWebLayer/gson/jsonapi.adoc index 11af1c97214..94380fc4a0e 100644 --- a/grails-doc/src/en/guide/theWebLayer/gson/jsonapi.adoc +++ b/grails-doc/src/en/guide/theWebLayer/gson/jsonapi.adoc @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. //// -http://jsonapi.org/[JSON API] is a standard format for representing JSON. +https://jsonapi.org/[JSON API] is a standard format for representing JSON. The JSON views plugin for Grails provides JSON API support out-of-the-box. All JSON views have access to the `jsonapi` instance which implements link:{api}/grails/plugin/json/view/api/JsonApiViewHelper.html[JsonApiViewHelper]. @@ -74,7 +74,7 @@ This is what an example `Book` instance rendered with JSON API might look like. == JSON API Object -To include the link:http://jsonapi.org/format/#document-jsonapi-object[JSON API Object] in the response, include a `jsonApiObject` argument to the `render` method. +To include the link:https://jsonapi.org/format/#document-jsonapi-object[JSON API Object] in the response, include a `jsonApiObject` argument to the `render` method. [source,groovy] model { @@ -86,7 +86,7 @@ The response will contain `"jsonapi":{"version":"1.0"}` as the first key in the == Meta Object -To add link:http://jsonapi.org/format/#document-meta[metadata] to your response, the `meta` argument can be passed to render with the value being the object that should be rendered. If this functionality is used in addition to `jsonApiObject: true`, the metadata will be rendered as the "meta" property of the "jsonapi" object. +To add link:https://jsonapi.org/format/#document-meta[metadata] to your response, the `meta` argument can be passed to render with the value being the object that should be rendered. If this functionality is used in addition to `jsonApiObject: true`, the metadata will be rendered as the "meta" property of the "jsonapi" object. [source,groovy] model { @@ -98,7 +98,7 @@ The response will contain `"meta":{"name":"Metadata Information"}` as the first == Rendering Errors -The JSON API specification has link:http://jsonapi.org/format/#errors[instructions on how to render errors]. In the case of the Grails implementation, this applies to both exceptions and validation errors. +The JSON API specification has link:https://jsonapi.org/format/#errors[instructions on how to render errors]. In the case of the Grails implementation, this applies to both exceptions and validation errors. === Exceptions @@ -170,7 +170,7 @@ Currently links are not supported in the case of to many relationships. == Pagination -The JSON API specification has a section which explains http://jsonapi.org/format/#fetching-pagination[pagination]. The Grails implementation follows that specification as it is written. +The JSON API specification has a section which explains https://jsonapi.org/format/#fetching-pagination[pagination]. The Grails implementation follows that specification as it is written. To enable pagination links in your output you must be rendering a collection and also include some arguments in addition to the collection being rendered. There are two required arguments: total and resource. The default offset is 0 and max is 10. @@ -202,7 +202,7 @@ json jsonapi.render(books, [pagination: [total: bookTotal, resource: Book, max: == Associations -The JSON API specification details how relationships should be rendered. The first way is through a relationships object described http://jsonapi.org/format/#document-resource-object-relationships[here]. By default that is now relationships will be rendered in json views. +The JSON API specification details how relationships should be rendered. The first way is through a relationships object described https://jsonapi.org/format/#document-resource-object-relationships[here]. By default that is now relationships will be rendered in json views. If you do not wish to render the relationships at all, the `associations` argument can be passed to `render` with the value of false. @@ -212,7 +212,7 @@ model { } json jsonapi.render(book, [associations: false]) -The specification also has a section that describes http://jsonapi.org/format/#document-compound-documents[compound documents]. If you want one or more of your relationships to be rendered in that manner, you can include the `expand` argument. +The specification also has a section that describes https://jsonapi.org/format/#document-compound-documents[compound documents]. If you want one or more of your relationships to be rendered in that manner, you can include the `expand` argument. [source,groovy] model { diff --git a/grails-doc/src/en/guide/theWebLayer/gson/templateEngine.adoc b/grails-doc/src/en/guide/theWebLayer/gson/templateEngine.adoc index 8eef99666ce..dd3e68eec7a 100644 --- a/grails-doc/src/en/guide/theWebLayer/gson/templateEngine.adoc +++ b/grails-doc/src/en/guide/theWebLayer/gson/templateEngine.adoc @@ -19,7 +19,7 @@ under the License. The JSON Views plugin registers a bean called `jsonTemplateEngine` of type link:{api}/grails/plugin/json/view/JsonViewTemplateEngine.html[JsonViewTemplateEngine]. -This class is a regular Groovy http://docs.groovy-lang.org/latest/html/documentation/template-engines.html[TemplateEngine], and you can use the engine to render JSON views outside the scope of an HTTP request. +This class is a regular Groovy https://docs.groovy-lang.org/latest/html/documentation/template-engines.html[TemplateEngine], and you can use the engine to render JSON views outside the scope of an HTTP request. For example: diff --git a/grails-doc/src/en/guide/theWebLayer/markup.adoc b/grails-doc/src/en/guide/theWebLayer/markup.adoc index 3b986a8a444..d57871702c9 100644 --- a/grails-doc/src/en/guide/theWebLayer/markup.adoc +++ b/grails-doc/src/en/guide/theWebLayer/markup.adoc @@ -19,7 +19,7 @@ under the License. Markup Views are written in Groovy, end with the file extension `gml` and reside in the `grails-app/views` directory. -The Markup Views plugin uses Groovy's http://docs.groovy-lang.org/docs/latest/html/documentation/template-engines.html#_the_markuptemplateengine[MarkupTemplateEngine] and you can mostly use the http://docs.groovy-lang.org/docs/latest/html/documentation/template-engines.html#_the_markuptemplateengine[Groovy user guide] as a reference for the syntax. +The Markup Views plugin uses Groovy's https://docs.groovy-lang.org/docs/latest/html/documentation/template-engines.html#_the_markuptemplateengine[MarkupTemplateEngine] and you can mostly use the https://docs.groovy-lang.org/docs/latest/html/documentation/template-engines.html#_the_markuptemplateengine[Groovy user guide] as a reference for the syntax. Example Markup View: @@ -40,7 +40,7 @@ This produces the following output given a model such as `[cars:[[make:"Audi", m -For further examples see Groovy's http://docs.groovy-lang.org/docs/latest/html/documentation/template-engines.html#_the_markuptemplateengine[MarkupTemplateEngine] documentation. +For further examples see Groovy's https://docs.groovy-lang.org/docs/latest/html/documentation/template-engines.html#_the_markuptemplateengine[MarkupTemplateEngine] documentation. All Markup views subclass the link:api/grails/plugin/markup/view/MarkupViewTemplate.html[MarkupViewTemplate] class by default. diff --git a/grails-doc/src/en/guide/theWebLayer/markup/markupConfiguration.adoc b/grails-doc/src/en/guide/theWebLayer/markup/markupConfiguration.adoc index 0db77038a2d..7f217070eb4 100644 --- a/grails-doc/src/en/guide/theWebLayer/markup/markupConfiguration.adoc +++ b/grails-doc/src/en/guide/theWebLayer/markup/markupConfiguration.adoc @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. //// -Markup views configuration can be altered with `grails-app/conf/application.yml`. Any of the properties within the link:{api}/grails/plugin/markup/view/MarkupViewConfiguration.html[MarkupViewConfiguration] class and Groovy's http://docs.groovy-lang.org/latest/html/api/groovy/text/markup/TemplateConfiguration.html[TemplateConfiguration] class can be set. +Markup views configuration can be altered with `grails-app/conf/application.yml`. Any of the properties within the link:{api}/grails/plugin/markup/view/MarkupViewConfiguration.html[MarkupViewConfiguration] class and Groovy's https://docs.groovy-lang.org/latest/html/api/groovy/text/markup/TemplateConfiguration.html[TemplateConfiguration] class can be set. For example: diff --git a/grails-doc/src/en/guide/upgrading/upgrading33x.adoc b/grails-doc/src/en/guide/upgrading/upgrading33x.adoc index 178627c48ad..056d1a135f1 100644 --- a/grails-doc/src/en/guide/upgrading/upgrading33x.adoc +++ b/grails-doc/src/en/guide/upgrading/upgrading33x.adoc @@ -374,7 +374,7 @@ seleniumSafariDriverVersion=3.14.0 <4> Includes the https://github.com/apache/grails-geb[Grails Geb Plugin dependency] which has a transitive dependency to `geb-spock`. This is the dependency necessary to work with https://www.gebish.org[Geb] and Spock. <5> Selenium and different driver dependencies. -Create also a http://www.gebish.org/manual/current/#configuration[Geb Configuration] file at `src/integration-test/resources/GebConfig.groovy`. +Create also a https://www.gebish.org/manual/current/#configuration[Geb Configuration] file at `src/integration-test/resources/GebConfig.groovy`. [source, groovy] .src/integration-test/resources/GebConfig.groovy diff --git a/grails-domain-class/build.gradle b/grails-domain-class/build.gradle index c53f0d33ddb..787e184d4ca 100644 --- a/grails-domain-class/build.gradle +++ b/grails-domain-class/build.gradle @@ -77,4 +77,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-domain-class/src/main/groovy/grails/artefact/DomainClass.groovy b/grails-domain-class/src/main/groovy/grails/artefact/DomainClass.groovy index 83c6561c7bf..073f811c16e 100644 --- a/grails-domain-class/src/main/groovy/grails/artefact/DomainClass.groovy +++ b/grails-domain-class/src/main/groovy/grails/artefact/DomainClass.groovy @@ -49,7 +49,7 @@ trait DomainClass { if (persistentEntity) { return new DefaultConstrainedDiscovery().findConstrainedProperties(persistentEntity) } else { - return Collections.emptyMap() + return Collections. emptyMap() } } } diff --git a/grails-domain-class/src/main/groovy/grails/compiler/traits/DomainClassTraitInjector.groovy b/grails-domain-class/src/main/groovy/grails/compiler/traits/DomainClassTraitInjector.groovy index fc46becd79b..f3b95ee010e 100644 --- a/grails-domain-class/src/main/groovy/grails/compiler/traits/DomainClassTraitInjector.groovy +++ b/grails-domain-class/src/main/groovy/grails/compiler/traits/DomainClassTraitInjector.groovy @@ -22,7 +22,7 @@ import grails.artefact.DomainClass import org.grails.core.artefact.DomainClassArtefactHandler /** - * + * * @author Jeff Brown * @since 3.0 * @@ -33,7 +33,6 @@ class DomainClassTraitInjector implements TraitInjector { DomainClass } - @Override String[] getArtefactTypes() { [DomainClassArtefactHandler.TYPE] diff --git a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/DomainClassGrailsPlugin.groovy b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/DomainClassGrailsPlugin.groovy index fcf46337f4f..9bb1771b5c2 100644 --- a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/DomainClassGrailsPlugin.groovy +++ b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/DomainClassGrailsPlugin.groovy @@ -39,22 +39,24 @@ class DomainClassGrailsPlugin extends Plugin { "file:./plugins/*/grails-app/domain/**/*.groovy"] def version = GrailsUtil.getGrailsVersion() - def dependsOn = [i18n:version] + def dependsOn = [i18n: version] def loadAfter = ['controllers', 'dataSource'] - Closure doWithSpring() {{-> - GrailsApplication application = grailsApplication - validateableConstraintsEvaluator(DefaultConstraintEvaluatorFactoryBean) { bean -> - bean.lazyInit = true + Closure doWithSpring() { + { -> + GrailsApplication application = grailsApplication + validateableConstraintsEvaluator(DefaultConstraintEvaluatorFactoryBean) { bean -> + bean.lazyInit = true + } + "${ConstraintsEvaluator.BEAN_NAME}"(ConstraintEvaluatorAdapter, ref("validateableConstraintsEvaluator")) { bean -> + bean.lazyInit = true + } + grailsDomainClassMappingContext(DefaultMappingContextFactoryBean, application, applicationContext) { bean -> + bean.lazyInit = true + } + gormValidatorRegistry(ValidatorRegistryFactoryBean) { bean -> + bean.lazyInit = true + } } - "${ConstraintsEvaluator.BEAN_NAME}"(ConstraintEvaluatorAdapter, ref("validateableConstraintsEvaluator")) { bean -> - bean.lazyInit = true - } - grailsDomainClassMappingContext(DefaultMappingContextFactoryBean, application, applicationContext) { bean -> - bean.lazyInit = true - } - gormValidatorRegistry(ValidatorRegistryFactoryBean) { bean -> - bean.lazyInit = true - } - }} + } } diff --git a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/ConstraintEvaluatorAdapter.java b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/ConstraintEvaluatorAdapter.java index 20d5ccd7b0c..9f43fcef877 100644 --- a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/ConstraintEvaluatorAdapter.java +++ b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/ConstraintEvaluatorAdapter.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.plugins.domain.support; import grails.gorm.validation.ConstrainedProperty; diff --git a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/DefaultMappingContextFactoryBean.groovy b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/DefaultMappingContextFactoryBean.groovy index f0f77b374be..916a615b0c0 100644 --- a/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/DefaultMappingContextFactoryBean.groovy +++ b/grails-domain-class/src/main/groovy/org/grails/plugins/domain/support/DefaultMappingContextFactoryBean.groovy @@ -33,7 +33,6 @@ import org.springframework.beans.factory.FactoryBean import org.springframework.beans.factory.InitializingBean import org.springframework.beans.factory.annotation.Autowired import org.springframework.context.ApplicationContext -import org.springframework.context.ConfigurableApplicationContext import org.springframework.context.MessageSource import org.springframework.core.env.PropertyResolver @@ -56,15 +55,13 @@ class DefaultMappingContextFactoryBean implements FactoryBean, I this.configuration = grailsApplication.config this.messageSource = messageSource this.grailsApplication = grailsApplication - if(messageSource instanceof ApplicationContext) { - this.applicationContext = (ApplicationContext)messageSource - } - else { + if (messageSource instanceof ApplicationContext) { + this.applicationContext = (ApplicationContext) messageSource + } else { applicationContext = null } } - @Override MappingContext getObject() throws Exception { return mappingContext @@ -90,7 +87,7 @@ class DefaultMappingContextFactoryBean implements FactoryBean, I this.mappingContext = new KeyValueMappingContext("default", settings) DefaultValidatorRegistry validatorRegistry = new DefaultValidatorRegistry(mappingContext, settings, messageSource) - for(factory in constraintFactories) { + for (factory in constraintFactories) { validatorRegistry.addConstraintFactory(factory) } mappingContext.setValidatorRegistry( @@ -98,6 +95,6 @@ class DefaultMappingContextFactoryBean implements FactoryBean, I ) GrailsClass[] persistentClasses = grailsApplication.getArtefacts(DomainClassArtefactHandler.TYPE) - mappingContext.addPersistentEntities(persistentClasses.collect() { GrailsClass cls -> cls.clazz} as Class[]) + mappingContext.addPersistentEntities(persistentClasses.collect() { GrailsClass cls -> cls.clazz } as Class[]) } } diff --git a/grails-encoder/build.gradle b/grails-encoder/build.gradle index 73504efd32d..8ede4211f86 100644 --- a/grails-encoder/build.gradle +++ b/grails-encoder/build.gradle @@ -61,4 +61,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/CodecPrintWriter.java b/grails-encoder/src/main/groovy/org/grails/buffer/CodecPrintWriter.java index 8cc6900a459..c67b9d60a7d 100644 --- a/grails-encoder/src/main/groovy/org/grails/buffer/CodecPrintWriter.java +++ b/grails-encoder/src/main/groovy/org/grails/buffer/CodecPrintWriter.java @@ -18,15 +18,16 @@ */ package org.grails.buffer; -import java.io.Writer; - import org.grails.encoder.EncodedAppender; import org.grails.encoder.EncodedAppenderFactory; import org.grails.encoder.Encoder; import org.grails.encoder.EncoderAware; import org.grails.encoder.EncodingStateRegistry; +import java.io.Writer; + public class CodecPrintWriter extends GrailsPrintWriter implements EncoderAware, EncodedAppenderFactory { + private final Encoder encoder; private final StreamCharBuffer buffer; private boolean ignoreEncodingState; @@ -34,11 +35,11 @@ public class CodecPrintWriter extends GrailsPrintWriter implements EncoderAware, public CodecPrintWriter(Writer out, Encoder encoder, EncodingStateRegistry encodingStateRegistry) { this(out, encoder, encodingStateRegistry, false); } - + public CodecPrintWriter(Writer out, Encoder encoder, EncodingStateRegistry encodingStateRegistry, boolean ignoreEncodingState) { super(null); this.encoder = encoder; - buffer=new StreamCharBuffer(); + buffer = new StreamCharBuffer(); buffer.setNotifyParentBuffersEnabled(false); allowUnwrappingOut = false; buffer.connectTo(out, false); @@ -54,7 +55,7 @@ public Encoder getEncoder() { } public EncodedAppender getEncodedAppender() { - EncodedAppender encodedAppender = ((EncodedAppenderFactory)buffer.getWriter()).getEncodedAppender(); + EncodedAppender encodedAppender = ((EncodedAppenderFactory) buffer.getWriter()).getEncodedAppender(); encodedAppender.setIgnoreEncodingState(ignoreEncodingState); return encodedAppender; } diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/FastStringPrintWriter.java b/grails-encoder/src/main/groovy/org/grails/buffer/FastStringPrintWriter.java index 16f7b58970a..56485c05324 100644 --- a/grails-encoder/src/main/groovy/org/grails/buffer/FastStringPrintWriter.java +++ b/grails-encoder/src/main/groovy/org/grails/buffer/FastStringPrintWriter.java @@ -18,13 +18,13 @@ */ package org.grails.buffer; -import java.io.Reader; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.objenesis.ObjenesisStd; import org.springframework.objenesis.instantiator.ObjectInstantiator; +import java.io.Reader; + /** * Fast in-memory PrintWriter implementation. * @@ -32,9 +32,11 @@ * @since 2.0 */ public class FastStringPrintWriter extends GrailsPrintWriterAdapter { + private static final Logger LOG = LoggerFactory.getLogger(FastStringPrintWriter.class); private static ObjectInstantiator instantiator; + static { try { instantiator = new ObjenesisStd(false).getInstantiatorOf(FastStringPrintWriter.class); @@ -55,6 +57,11 @@ public FastStringPrintWriter(int initialChunkSize) { streamBuffer = ((StreamCharBuffer.StreamCharBufferWriter) getOut()).getBuffer(); } + protected FastStringPrintWriter(Object o) { + this(); + print(o); + } + public static FastStringPrintWriter newInstance() { return newInstance(0); } @@ -67,7 +74,7 @@ public static FastStringPrintWriter newInstance(int initialChunkSize) { return new FastStringPrintWriter(); } - FastStringPrintWriter instance = (FastStringPrintWriter)instantiator.newInstance(); + FastStringPrintWriter instance = (FastStringPrintWriter) instantiator.newInstance(); if (initialChunkSize > 0) { instance.streamBuffer = new StreamCharBuffer(initialChunkSize); } else { @@ -77,11 +84,6 @@ public static FastStringPrintWriter newInstance(int initialChunkSize) { return instance; } - protected FastStringPrintWriter(Object o) { - this(); - print(o); - } - public StreamCharBuffer getBuffer() { return streamBuffer; } diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsLazyProxyPrintWriter.java b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsLazyProxyPrintWriter.java index e4c944b929d..d5210dee0a6 100644 --- a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsLazyProxyPrintWriter.java +++ b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsLazyProxyPrintWriter.java @@ -22,16 +22,10 @@ import java.io.Writer; public class GrailsLazyProxyPrintWriter extends GrailsPrintWriter { + private DestinationFactory factory; private boolean destinationActivated = false; - /** - * Factory to lazily instantiate the destination. - */ - public static interface DestinationFactory { - Writer activateDestination() throws IOException; - } - public GrailsLazyProxyPrintWriter(DestinationFactory factory) { super(null); this.factory = factory; @@ -42,8 +36,7 @@ public Writer getOut() { if (!destinationActivated) { try { super.setOut(factory.activateDestination()); - } - catch (IOException e) { + } catch (IOException e) { setError(); } destinationActivated = true; @@ -77,4 +70,12 @@ public void setDestinationActivated(boolean destinationActivated) { super.setOut(null); } } + + /** + * Factory to lazily instantiate the destination. + */ + public interface DestinationFactory { + + Writer activateDestination() throws IOException; + } } diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriter.java b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriter.java index df4fb5f60ef..808e5ed78e4 100644 --- a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriter.java +++ b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriter.java @@ -21,13 +21,11 @@ import groovy.lang.GroovyObject; import groovy.lang.MetaClass; import groovy.lang.Writable; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Writer; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.codehaus.groovy.runtime.GStringImpl; +import org.codehaus.groovy.runtime.InvokerHelper; +import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; import org.grails.charsequences.CharSequences; import org.grails.encoder.EncodedAppender; import org.grails.encoder.EncodedAppenderFactory; @@ -37,9 +35,10 @@ import org.grails.encoder.EncodingStateRegistry; import org.grails.encoder.StreamingEncoder; import org.grails.encoder.StreamingEncoderWriter; -import org.codehaus.groovy.runtime.GStringImpl; -import org.codehaus.groovy.runtime.InvokerHelper; -import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; /** * PrintWriter implementation that doesn't have synchronization. null object @@ -48,8 +47,9 @@ * @author Lari Hotari, Sagire Software Oy */ public class GrailsPrintWriter extends Writer implements GrailsWrappedWriter, EncodedAppenderWriterFactory, GroovyObject { + protected static final Log LOG = LogFactory.getLog(GrailsPrintWriter.class); - protected static final char CRLF[] = { '\r', '\n' }; + protected static final char[] CRLF = {'\r', '\n'}; protected boolean trouble = false; protected Writer out; protected boolean allowUnwrappingOut = true; @@ -57,6 +57,9 @@ public class GrailsPrintWriter extends Writer implements GrailsWrappedWriter, En protected Writer streamCharBufferTarget = null; protected Writer previousOut = null; + // GroovyObject interface implementation to speed up metaclass operations + private transient MetaClass metaClass; + public GrailsPrintWriter(Writer out) { this.metaClass = InvokerHelper.getMetaClass(this.getClass()); setOut(out); @@ -89,8 +92,8 @@ public void setOut(Writer newOut) { } protected Writer unwrapWriter(Writer writer) { - if (writer instanceof GrailsWrappedWriter ) { - return ((GrailsWrappedWriter)writer).unwrap(); + if (writer instanceof GrailsWrappedWriter) { + return ((GrailsWrappedWriter) writer).unwrap(); } return writer; } @@ -111,27 +114,21 @@ public GrailsPrintWriter leftShift(Object obj) throws IOException { Class clazz = obj.getClass(); if (clazz == String.class) { - write((String)obj); - } - else if (clazz == StreamCharBuffer.class) { - write((StreamCharBuffer)obj); - } - else if (clazz == GStringImpl.class) { - write((Writable)obj); - } - else if (obj instanceof Writable) { - write((Writable)obj); - } - else if (obj instanceof CharSequence) { + write((String) obj); + } else if (clazz == StreamCharBuffer.class) { + write((StreamCharBuffer) obj); + } else if (clazz == GStringImpl.class) { + write((Writable) obj); + } else if (obj instanceof Writable) { + write((Writable) obj); + } else if (obj instanceof CharSequence) { try { usageFlag = true; CharSequences.writeCharSequence(getOut(), (CharSequence) obj); - } - catch (IOException e) { + } catch (IOException e) { handleIOException(e); } - } - else { + } else { InvokerHelper.write(this, obj); } return this; @@ -148,7 +145,7 @@ public GrailsPrintWriter plus(Object value) throws IOException { * true on all successive calls. * * @return true if the print stream has encountered an error, either on the - * underlying output stream or during a format conversion. + * underlying output stream or during a format conversion. */ public boolean checkError() { return trouble; @@ -172,8 +169,7 @@ public synchronized void flush() { if (isDestinationActivated()) { try { getOut().flush(); - } - catch (IOException e) { + } catch (IOException e) { handleIOException(e); } } @@ -213,27 +209,21 @@ public void print(final Object obj) { Class clazz = obj.getClass(); if (clazz == String.class) { - write((String)obj); - } - else if (clazz == StreamCharBuffer.class) { - write((StreamCharBuffer)obj); - } - else if (clazz == GStringImpl.class) { - write((Writable)obj); - } - else if (obj instanceof Writable) { - write((Writable)obj); - } - else if (obj instanceof CharSequence) { + write((String) obj); + } else if (clazz == StreamCharBuffer.class) { + write((StreamCharBuffer) obj); + } else if (clazz == GStringImpl.class) { + write((Writable) obj); + } else if (obj instanceof Writable) { + write((Writable) obj); + } else if (obj instanceof CharSequence) { try { usageFlag = true; - CharSequences.writeCharSequence(getOut(), (CharSequence)obj); - } - catch (IOException e) { + CharSequences.writeCharSequence(getOut(), (CharSequence) obj); + } catch (IOException e) { handleIOException(e); } - } - else { + } else { write(String.valueOf(obj)); } } @@ -270,8 +260,7 @@ public void write(final String s) { try { getOut().write(s); - } - catch (IOException e) { + } catch (IOException e) { handleIOException(e); } } @@ -284,13 +273,13 @@ public void write(final String s) { @Override public void write(final int c) { usageFlag = true; - if (trouble) + if (trouble) { return; + } try { getOut().write(c); - } - catch (IOException e) { + } catch (IOException e) { handleIOException(e); } } @@ -303,14 +292,14 @@ public void write(final int c) { * @param len Number of characters to write */ @Override - public void write(final char buf[], final int off, final int len) { + public void write(final char[] buf, final int off, final int len) { usageFlag = true; - if (trouble || buf == null || len == 0) + if (trouble || buf == null || len == 0) { return; + } try { getOut().write(buf, off, len); - } - catch (IOException e) { + } catch (IOException e) { handleIOException(e); } } @@ -318,36 +307,37 @@ public void write(final char buf[], final int off, final int len) { /** * Write a portion of a string. * - * @param s A String + * @param s A String * @param off Offset from which to start writing characters * @param len Number of characters to write */ @Override public void write(final String s, final int off, final int len) { usageFlag = true; - if (trouble || s == null || s.length() == 0) + if (trouble || s == null || s.length() == 0) { return; + } try { getOut().write(s, off, len); - } - catch (IOException e) { + } catch (IOException e) { handleIOException(e); } } @Override - public void write(final char buf[]) { + public void write(final char[] buf) { write(buf, 0, buf.length); } - /** delegate methods, not synchronized **/ + /** + * delegate methods, not synchronized + **/ public void print(final boolean b) { if (b) { write("true"); - } - else { + } else { write("false"); } } @@ -372,7 +362,7 @@ public void print(final double d) { write(String.valueOf(d)); } - public void print(final char s[]) { + public void print(final char[] s) { write(s); } @@ -411,7 +401,7 @@ public void println(final double d) { println(); } - public void println(final char c[]) { + public void println(final char[] c) { print(c); println(); } @@ -431,8 +421,7 @@ public GrailsPrintWriter append(final char c) { try { usageFlag = true; getOut().append(c); - } - catch (IOException e) { + } catch (IOException e) { handleIOException(e); } return this; @@ -442,12 +431,12 @@ public GrailsPrintWriter append(final char c) { public GrailsPrintWriter append(final CharSequence csq, final int start, final int end) { try { usageFlag = true; - if (csq == null) + if (csq == null) { appendNullCharSequence(); - else + } else { CharSequences.writeCharSequence(getOut(), csq, start, end); - } - catch (IOException e) { + } + } catch (IOException e) { handleIOException(e); } return this; @@ -461,12 +450,12 @@ protected void appendNullCharSequence() throws IOException { public GrailsPrintWriter append(final CharSequence csq) { try { usageFlag = true; - if (csq == null) + if (csq == null) { appendNullCharSequence(); - else + } else { CharSequences.writeCharSequence(getOut(), csq); - } - catch (IOException e) { + } + } catch (IOException e) { handleIOException(e); } return this; @@ -484,13 +473,13 @@ protected Object clone() throws CloneNotSupportedException { public void write(final StreamCharBuffer otherBuffer) { usageFlag = true; - if (trouble) + if (trouble) { return; + } try { otherBuffer.writeTo(findStreamCharBufferTarget(true)); - } - catch (IOException e) { + } catch (IOException e) { handleIOException(e); } } @@ -505,14 +494,13 @@ protected Writer findStreamCharBufferTarget(boolean markUsed) { Writer target = currentOut; while (target instanceof GrailsWrappedWriter) { - GrailsWrappedWriter gpr = ((GrailsWrappedWriter)target); + GrailsWrappedWriter gpr = ((GrailsWrappedWriter) target); if (gpr.isAllowUnwrappingOut()) { if (markUsed) { gpr.markUsed(); } target = gpr.unwrap(); - } - else { + } else { break; } } @@ -520,8 +508,7 @@ protected Writer findStreamCharBufferTarget(boolean markUsed) { Writer result; if (target instanceof StreamCharBuffer.StreamCharBufferWriter) { result = target; - } - else { + } else { result = currentOut; } @@ -558,19 +545,19 @@ public void write(final Writable writable) { } protected void writeWritable(final Writable writable) { - if(writable.getClass() == StreamCharBuffer.class) { - write((StreamCharBuffer)writable); + if (writable.getClass() == StreamCharBuffer.class) { + write((StreamCharBuffer) writable); return; } - + usageFlag = true; - if (trouble) + if (trouble) { return; + } try { writable.writeTo(getOut()); - } - catch (IOException e) { + } catch (IOException e) { handleIOException(e); } } @@ -605,7 +592,7 @@ public boolean isUsed() { Writer target = findStreamCharBufferTarget(false); if (target instanceof StreamCharBuffer.StreamCharBufferWriter) { - StreamCharBuffer buffer = ((StreamCharBuffer.StreamCharBufferWriter)target).getBuffer(); + StreamCharBuffer buffer = ((StreamCharBuffer.StreamCharBufferWriter) target).getBuffer(); if (!buffer.isEmpty()) { return true; } @@ -628,8 +615,7 @@ public void close() { if (isDestinationActivated()) { try { getOut().close(); - } - catch (IOException e) { + } catch (IOException e) { handleIOException(e); } } @@ -661,16 +647,16 @@ public Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodin target = findStreamCharBufferTarget(false); } if (target instanceof EncodedAppenderWriterFactory && target != this) { - return ((EncodedAppenderWriterFactory)target).getWriterForEncoder(encoder, encodingStateRegistry); + return ((EncodedAppenderWriterFactory) target).getWriterForEncoder(encoder, encodingStateRegistry); } else if (target instanceof EncodedAppenderFactory) { - EncodedAppender encodedAppender=((EncodedAppenderFactory)target).getEncodedAppender(); + EncodedAppender encodedAppender = ((EncodedAppenderFactory) target).getEncodedAppender(); if (encodedAppender != null) { return new EncodedAppenderWriter(encodedAppender, encoder, encodingStateRegistry); } } if (target != null) { if (encoder instanceof StreamingEncoder) { - return new StreamingEncoderWriter(target, (StreamingEncoder)encoder, encodingStateRegistry); + return new StreamingEncoderWriter(target, (StreamingEncoder) encoder, encodingStateRegistry); } else { return new CodecPrintWriter(target, encoder, encodingStateRegistry); } @@ -679,9 +665,6 @@ public Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodin } } - // GroovyObject interface implementation to speed up metaclass operations - private transient MetaClass metaClass; - public Object getProperty(String property) { return getMetaClass().getProperty(this, property); } diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriterAdapter.java b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriterAdapter.java index bf4d6b6987d..28740d7cd6c 100644 --- a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriterAdapter.java +++ b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriterAdapter.java @@ -19,25 +19,25 @@ package org.grails.buffer; import groovy.lang.Writable; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Writer; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.objenesis.ObjenesisStd; import org.springframework.objenesis.instantiator.ObjectInstantiator; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; + /** * @author Lari Hotari * @since 2.0 */ public class GrailsPrintWriterAdapter extends PrintWriter implements GrailsWrappedWriter { + private static final Logger LOG = LoggerFactory.getLogger(GrailsPrintWriterAdapter.class); + private static ObjectInstantiator instantiator; protected GrailsPrintWriter target; - private static ObjectInstantiator instantiator; static { try { instantiator = new ObjenesisStd(false).getInstantiatorOf(GrailsPrintWriterAdapter.class); @@ -68,7 +68,7 @@ public void close() throws IOException { public static GrailsPrintWriterAdapter newInstance(Writer wrapped) { if (instantiator != null) { - GrailsPrintWriterAdapter instance = (GrailsPrintWriterAdapter)instantiator.newInstance(); + GrailsPrintWriterAdapter instance = (GrailsPrintWriterAdapter) instantiator.newInstance(); instance.setTarget(wrapped); return instance; } @@ -77,9 +77,8 @@ public static GrailsPrintWriterAdapter newInstance(Writer wrapped) { public void setTarget(Writer wrapped) { if (wrapped instanceof GrailsPrintWriter) { - this.target = ((GrailsPrintWriter)wrapped); - } - else { + this.target = ((GrailsPrintWriter) wrapped); + } else { this.target = new GrailsPrintWriter(wrapped); } this.out = this.target; diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsRoutablePrintWriter.java b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsRoutablePrintWriter.java index 6ad2067f263..2be07a456b2 100644 --- a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsRoutablePrintWriter.java +++ b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsRoutablePrintWriter.java @@ -19,23 +19,24 @@ package org.grails.buffer; import groovy.lang.Writable; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Writer; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.objenesis.ObjenesisStd; import org.springframework.objenesis.instantiator.ObjectInstantiator; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; + public class GrailsRoutablePrintWriter extends GrailsPrintWriterAdapter { + private static final Logger LOG = LoggerFactory.getLogger(GrailsRoutablePrintWriter.class); + private static ObjectInstantiator instantiator = null; private DestinationFactory factory; private boolean blockFlush = true; private boolean blockClose = true; private boolean destinationActivated = false; - private static ObjectInstantiator instantiator=null; + static { try { instantiator = new ObjenesisStd(false).getInstantiatorOf(GrailsRoutablePrintWriter.class); @@ -44,13 +45,6 @@ public class GrailsRoutablePrintWriter extends GrailsPrintWriterAdapter { } } - /** - * Factory to lazily instantiate the destination. - */ - public static interface DestinationFactory { - Writer activateDestination() throws IOException; - } - public GrailsRoutablePrintWriter(DestinationFactory factory) { super(new NullWriter()); this.factory = factory; @@ -58,7 +52,7 @@ public GrailsRoutablePrintWriter(DestinationFactory factory) { public static GrailsRoutablePrintWriter newInstance(DestinationFactory factory) { if (instantiator != null) { - GrailsRoutablePrintWriter instance = (GrailsRoutablePrintWriter)instantiator.newInstance(); + GrailsRoutablePrintWriter instance = (GrailsRoutablePrintWriter) instantiator.newInstance(); instance.out = new NullWriter(); instance.factory = factory; instance.blockFlush = true; @@ -73,8 +67,7 @@ protected void activateDestination() { if (!destinationActivated && factory != null) { try { super.setTarget(factory.activateDestination()); - } - catch (IOException e) { + } catch (IOException e) { setError(); } destinationActivated = true; @@ -116,7 +109,7 @@ public void println(String x) { } @Override - public void println(char x[]) { + public void println(char[] x) { activateDestination(); super.println(x); } @@ -176,7 +169,7 @@ public void print(String s) { } @Override - public void print(char s[]) { + public void print(char[] s) { activateDestination(); super.print(s); } @@ -230,13 +223,13 @@ public void write(String s, int off, int len) { } @Override - public void write(char buf[]) { + public void write(char[] buf) { activateDestination(); super.write(buf); } @Override - public void write(char buf[], int off, int len) { + public void write(char[] buf, int off, int len) { activateDestination(); super.write(buf, off, len); } @@ -278,31 +271,6 @@ public PrintWriter append(CharSequence csq) { return super.append(csq); } - /** - * Just to keep super constructor for PrintWriter happy - it's never - * actually used. - */ - private static class NullWriter extends Writer { - protected NullWriter() { - super(); - } - - @Override - public void write(char cbuf[], int off, int len) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public void flush() throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public void close() throws IOException { - throw new UnsupportedOperationException(); - } - } - public boolean isBlockFlush() { return blockFlush; } @@ -357,4 +325,38 @@ public void setDestinationActivated(boolean destinationActivated) { super.setTarget(new NullWriter()); } } + + /** + * Just to keep super constructor for PrintWriter happy - it's never + * actually used. + */ + private static class NullWriter extends Writer { + + protected NullWriter() { + super(); + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void flush() throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void close() throws IOException { + throw new UnsupportedOperationException(); + } + } + + /** + * Factory to lazily instantiate the destination. + */ + public interface DestinationFactory { + + Writer activateDestination() throws IOException; + } } diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsWrappedWriter.java b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsWrappedWriter.java index 07bc3126ebf..f438a979351 100644 --- a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsWrappedWriter.java +++ b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsWrappedWriter.java @@ -21,7 +21,10 @@ import java.io.Writer; public interface GrailsWrappedWriter { - public boolean isAllowUnwrappingOut(); - public Writer unwrap(); - public void markUsed(); + + boolean isAllowUnwrappingOut(); + + Writer unwrap(); + + void markUsed(); } diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/StreamByteBuffer.java b/grails-encoder/src/main/groovy/org/grails/buffer/StreamByteBuffer.java index 4066c40d8c8..381b80fef83 100644 --- a/grails-encoder/src/main/groovy/org/grails/buffer/StreamByteBuffer.java +++ b/grails-encoder/src/main/groovy/org/grails/buffer/StreamByteBuffer.java @@ -33,12 +33,11 @@ import java.util.Iterator; import java.util.LinkedList; - /** * An in-memory buffer that provides OutputStream and InputStream interfaces. - * + *

    * This is more efficient than using ByteArrayOutputStream/ByteArrayInputStream - * + *

    * This is not thread-safe, it is intended to be used by a single Thread. * * @author Lari Hotari, Sagire Software Oy @@ -135,11 +134,10 @@ public String readAsString(Charset charset) throws CharacterCodingException { int len = charbuffer.remaining(); char[] ch = charbuffer.array(); if (len != ch.length) { - ch = (char[])GrailsArrayUtils.subarray(ch, 0, len); + ch = (char[]) GrailsArrayUtils.subarray(ch, 0, len); } str = StringCharArrayAccessor.createString(ch); - } - else { + } else { str = charbuffer.toString(); } return str; @@ -151,8 +149,7 @@ public int totalBytesUnread() { int total = 0; if (readMode == ReadMode.REMOVE_AFTER_READING) { total = totalBytesUnreadInList; - } - else if (readMode == ReadMode.RETAIN_AFTER_READING) { + } else if (readMode == ReadMode.RETAIN_AFTER_READING) { prepareRetainAfterReading(); total = totalBytesUnreadInIterator; } @@ -162,8 +159,7 @@ else if (readMode == ReadMode.RETAIN_AFTER_READING) { if (currentWriteChunk != currentReadChunk && currentWriteChunk != null) { if (readMode == ReadMode.REMOVE_AFTER_READING) { total += currentWriteChunk.bytesUnread(); - } - else if (readMode == ReadMode.RETAIN_AFTER_READING) { + } else if (readMode == ReadMode.RETAIN_AFTER_READING) { total += currentWriteChunk.bytesUsed(); } } @@ -189,18 +185,15 @@ protected int prepareRead() { currentReadChunk = chunks.removeFirst(); bytesUnread = currentReadChunk.bytesUnread(); totalBytesUnreadInList -= bytesUnread; - } - else if (readMode == ReadMode.RETAIN_AFTER_READING && readIterator.hasNext()) { + } else if (readMode == ReadMode.RETAIN_AFTER_READING && readIterator.hasNext()) { currentReadChunk = readIterator.next(); currentReadChunk.reset(); bytesUnread = currentReadChunk.bytesUnread(); totalBytesUnreadInIterator -= bytesUnread; - } - else if (currentReadChunk != currentWriteChunk) { + } else if (currentReadChunk != currentWriteChunk) { currentReadChunk = currentWriteChunk; bytesUnread = currentReadChunk.bytesUnread(); - } - else { + } else { bytesUnread = -1; } } @@ -237,7 +230,17 @@ public void retainAfterReadingMode() { setReadMode(ReadMode.RETAIN_AFTER_READING); } + public void clear() { + chunks.clear(); + currentReadChunk = null; + totalBytesUnreadInList = 0; + totalBytesUnreadInIterator = 0; + currentWriteChunk = new StreamByteBufferChunk(chunkSize); + readIterator = null; + } + class StreamByteBufferChunk { + private int pointer = 0; private byte[] buffer; private int size; @@ -253,8 +256,7 @@ public ByteBuffer readToNioBuffer() { ByteBuffer result; if (pointer > 0 || used < size) { result = ByteBuffer.wrap(buffer, pointer, used - pointer); - } - else { + } else { result = ByteBuffer.wrap(buffer); } pointer = used; @@ -316,6 +318,7 @@ public int spaceLeft() { } class StreamByteBufferOutputStream extends OutputStream { + private boolean closed = false; @Override @@ -365,6 +368,7 @@ public StreamByteBuffer getBuffer() { } class StreamByteBufferInputStream extends InputStream { + @Override public int read() throws IOException { prepareRead(); @@ -411,10 +415,9 @@ int readImpl(byte[] b, int off, int len) { @Override public synchronized void reset() throws IOException { - if (readMode==ReadMode.RETAIN_AFTER_READING) { + if (readMode == ReadMode.RETAIN_AFTER_READING) { StreamByteBuffer.this.reset(); - } - else { + } else { // reset isn't supported in ReadMode.REMOVE_AFTER_READING super.reset(); } @@ -429,13 +432,4 @@ public StreamByteBuffer getBuffer() { return StreamByteBuffer.this; } } - - public void clear() { - chunks.clear(); - currentReadChunk = null; - totalBytesUnreadInList = 0; - totalBytesUnreadInIterator = 0; - currentWriteChunk = new StreamByteBufferChunk(chunkSize); - readIterator = null; - } } diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/StreamCharBuffer.java b/grails-encoder/src/main/groovy/org/grails/buffer/StreamCharBuffer.java index a4cd3ff917d..9a6e7feee94 100644 --- a/grails-encoder/src/main/groovy/org/grails/buffer/StreamCharBuffer.java +++ b/grails-encoder/src/main/groovy/org/grails/buffer/StreamCharBuffer.java @@ -20,38 +20,14 @@ import groovy.lang.GroovyObjectSupport; import groovy.lang.Writable; - -import java.io.EOFException; -import java.io.Externalizable; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Reader; -import java.io.Writer; -import java.lang.ref.SoftReference; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.codehaus.groovy.runtime.InvokerHelper; import org.codehaus.groovy.runtime.StringGroovyMethods; -import org.grails.encoder.AbstractEncodedAppender; -import org.grails.encoder.ChainedEncoders; import org.grails.charsequences.CharArrayAccessible; import org.grails.charsequences.CharSequences; +import org.grails.encoder.AbstractEncodedAppender; +import org.grails.encoder.ChainedEncoders; import org.grails.encoder.CodecIdentifier; import org.grails.encoder.DefaultCodecIdentifier; import org.grails.encoder.Encodeable; @@ -72,6 +48,28 @@ import org.grails.encoder.StreamingEncoderWritable; import org.grails.encoder.WriterEncodedAppender; +import java.io.EOFException; +import java.io.Externalizable; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.lang.ref.SoftReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** *

    * StreamCharBuffer is a multipurpose in-memory buffer that can replace JDK @@ -101,7 +99,7 @@ * the taglib and return it to the caller. The buffer can be appended to it's * parent buffer directly without extra object generation (like converting to * java.lang.String in between). - * + *

    * for example this line of code in a taglib would just append the buffer * returned from the body closure evaluation to the buffer of the taglib:
    * out << body() @@ -241,7 +239,7 @@ * 256 * * - * + *

    * Configuration values can also be changed for each instance of * StreamCharBuffer individually. Default values are defined with System * Properties. @@ -249,18 +247,28 @@ * @author Lari Hotari, Sagire Software Oy */ public class StreamCharBuffer extends GroovyObjectSupport implements Writable, CharSequence, Externalizable, Encodeable, StreamEncodeable, StreamingEncoderWritable, EncodedAppenderWriterFactory, Cloneable { + + private static final Log LOG = LogFactory.getLog(StreamCharBuffer.class); private static final int EXTERNALIZABLE_VERSION = 2; - static final long serialVersionUID = EXTERNALIZABLE_VERSION; - private static final Log log=LogFactory.getLog(StreamCharBuffer.class); + private static final long serialVersionUID = EXTERNALIZABLE_VERSION; private static final int DEFAULT_CHUNK_SIZE = Integer.getInteger("streamcharbuffer.chunksize", 512); - private static final int DEFAULT_MAX_CHUNK_SIZE = Integer.getInteger("streamcharbuffer.maxchunksize", 1024*1024); + private static final int DEFAULT_MAX_CHUNK_SIZE = Integer.getInteger("streamcharbuffer.maxchunksize", 1024 * 1024); private static final int DEFAULT_CHUNK_SIZE_GROW_PROCENT = Integer.getInteger("streamcharbuffer.growprocent", 100); private static final int SUB_BUFFERCHUNK_MIN_SIZE = Integer.getInteger("streamcharbuffer.subbufferchunkminsize", 512); private static final int SUB_STRINGCHUNK_MIN_SIZE = Integer.getInteger("streamcharbuffer.substringchunkminsize", 512); private static final int WRITE_DIRECT_MIN_SIZE = Integer.getInteger("streamcharbuffer.writedirectminsize", 1024); private static final int CHUNK_MIN_SIZE = Integer.getInteger("streamcharbuffer.chunkminsize", 256); + boolean preferSubChunkWhenWritingToOtherBuffer = false; + int allocatedBufferIdSequence = 0; + int readerCount = 0; + boolean hasReaders = false; + int bufferChangesCounter = 0; + + boolean notifyParentBuffersEnabled = true; + boolean subBuffersEnabled = true; + private final int firstChunkSize; private final int growProcent; private final int maxChunkSize; @@ -275,9 +283,7 @@ public class StreamCharBuffer extends GroovyObjectSupport implements Writable, C private final StreamCharBufferWriter writer; private List connectToWriters; private ConnectedWritersWriter connectedWritersWriter; - private Boolean notConnectedToEncodeAwareWriters=null; - - boolean preferSubChunkWhenWritingToOtherBuffer=false; + private Boolean notConnectedToEncodeAwareWriters = null; private AllocatedBuffer allocBuffer; private AbstractChunk firstChunk; @@ -289,13 +295,6 @@ public class StreamCharBuffer extends GroovyObjectSupport implements Writable, C private Map dynamicChunkMap; private Set> parentBuffers; - int allocatedBufferIdSequence = 0; - int readerCount = 0; - boolean hasReaders = false; - int bufferChangesCounter = 0; - - boolean notifyParentBuffersEnabled = true; - boolean subBuffersEnabled = true; public StreamCharBuffer() { this(DEFAULT_CHUNK_SIZE, DEFAULT_CHUNK_SIZE_GROW_PROCENT, DEFAULT_MAX_CHUNK_SIZE); @@ -317,10 +316,6 @@ public StreamCharBuffer(int chunkSize, int growProcent, int maxChunkSize) { reset(true); } - private class StreamCharBufferKey { - StreamCharBuffer getBuffer() { return StreamCharBuffer.this; } - } - public boolean isPreferSubChunkWhenWritingToOtherBuffer() { return preferSubChunkWhenWritingToOtherBuffer; } @@ -331,9 +326,9 @@ public void setPreferSubChunkWhenWritingToOtherBuffer(boolean prefer) { } protected void notifyPreferSubChunkEnabled() { - if(isPreferSubChunkWhenWritingToOtherBuffer() && parentBuffers != null && isNotifyParentBuffersEnabled()) { - for(StreamCharBuffer parentBuffer : getCurrentParentBuffers()) { - if(!parentBuffer.isPreferSubChunkWhenWritingToOtherBuffer()) { + if (isPreferSubChunkWhenWritingToOtherBuffer() && parentBuffers != null && isNotifyParentBuffersEnabled()) { + for (StreamCharBuffer parentBuffer : getCurrentParentBuffers()) { + if (!parentBuffer.isPreferSubChunkWhenWritingToOtherBuffer()) { parentBuffer.setPreferSubChunkWhenWritingToOtherBuffer(true); } } @@ -382,7 +377,7 @@ public final void clear() { /** * Connect this buffer to a target Writer. - * + *

    * When the buffer (a chunk) get filled up, it will automaticly write it's content to the Writer * * @param w @@ -412,8 +407,8 @@ public final void encodeInStreamingModeTo(final EncoderAware encoderLookup, fina } public LazyInitializingWriter createEncodingInitializer(final EncoderAware encoderLookup, - final EncodingStateRegistryLookup encodingStateRegistryLookup, final LazyInitializingWriter... writers) { - LazyInitializingWriter encodingWriterInitializer=new LazyInitializingMultipleWriter() { + final EncodingStateRegistryLookup encodingStateRegistryLookup, final LazyInitializingWriter... writers) { + LazyInitializingWriter encodingWriterInitializer = new LazyInitializingMultipleWriter() { Writer lazyWriter; public Writer getWriter() throws IOException { @@ -424,10 +419,10 @@ public LazyInitializingWriter[] initializeMultiple(StreamCharBuffer buffer, bool Encoder encoder = encoderLookup.getEncoder(); if (encoder != null) { EncodingStateRegistry encodingStateRegistry = encodingStateRegistryLookup.lookup(); - StreamCharBuffer encodeBuffer=new StreamCharBuffer(chunkSize, growProcent, maxChunkSize); + StreamCharBuffer encodeBuffer = new StreamCharBuffer(chunkSize, growProcent, maxChunkSize); encodeBuffer.setAllowSubBuffers(false); - lazyWriter=encodeBuffer.getWriterForEncoder(encoder, encodingStateRegistry); - for(LazyInitializingWriter w : writers) { + lazyWriter = encodeBuffer.getWriterForEncoder(encoder, encodingStateRegistry); + for (LazyInitializingWriter w : writers) { encodeBuffer.connectTo(w, autoFlushMode); } return new LazyInitializingWriter[]{this}; @@ -447,15 +442,15 @@ private void initConnectedWritersWriter() { private void startUsingConnectedWritersWriter() throws IOException { if (connectedWritersWriter == null) { - List connectedWriters=new ArrayList(); + List connectedWriters = new ArrayList(); - for(ConnectToWriter connectToWriter : connectToWriters) { - for(Writer writer : connectToWriter.getWriters()) { - Writer target=writer; + for (ConnectToWriter connectToWriter : connectToWriters) { + for (Writer writer : connectToWriter.getWriters()) { + Writer target = writer; if (target instanceof GrailsWrappedWriter) { - target = ((GrailsWrappedWriter)target).unwrap(); + target = ((GrailsWrappedWriter) target).unwrap(); } - if (target==null) { + if (target == null) { throw new NullPointerException("target is null"); } connectedWriters.add(new ConnectedWriter(target, connectToWriter.isAutoFlush())); @@ -464,8 +459,7 @@ private void startUsingConnectedWritersWriter() throws IOException { if (connectedWriters.size() > 1) { connectedWritersWriter = new MultiOutputWriter(connectedWriters); - } - else { + } else { connectedWritersWriter = new SingleOutputWriter(connectedWriters.get(0)); } } @@ -582,14 +576,14 @@ public Writer writeTo(Writer target) throws IOException { /** * Writes the buffer content to a target java.io.Writer * - * @param target Writer + * @param target Writer * @param flushTarget calls target.flush() before finishing - * @param emptyAfter empties the buffer if true + * @param emptyAfter empties the buffer if true * @throws IOException */ public void writeTo(Writer target, boolean flushTarget, boolean emptyAfter) throws IOException { if (target instanceof GrailsWrappedWriter) { - GrailsWrappedWriter wrappedWriter = ((GrailsWrappedWriter)target); + GrailsWrappedWriter wrappedWriter = ((GrailsWrappedWriter) target); if (wrappedWriter.isAllowUnwrappingOut()) { target = wrappedWriter.unwrap(); } @@ -598,7 +592,7 @@ public void writeTo(Writer target, boolean flushTarget, boolean emptyAfter) thro throw new IllegalArgumentException("Cannot write buffer to itself."); } if (!emptyAfter && target instanceof StreamCharBufferWriter) { - ((StreamCharBufferWriter)target).write(this, null); + ((StreamCharBufferWriter) target).write(this, null); return; } else if (writeToEncodedAppender(this, target, writer.getEncodedAppender(), true)) { if (emptyAfter) { @@ -614,7 +608,7 @@ public void writeTo(Writer target, boolean flushTarget, boolean emptyAfter) thro private static boolean writeToEncodedAppender(StreamCharBuffer source, Writer target, EncodedAppender notAllowedAppender, boolean flush) throws IOException { if (target instanceof EncodedAppenderFactory) { - EncodedAppenderFactory eaw = (EncodedAppenderFactory)target; + EncodedAppenderFactory eaw = (EncodedAppenderFactory) target; EncodedAppender appender = eaw.getEncodedAppender(); if (appender != null) { if (appender == notAllowedAppender) { @@ -623,22 +617,22 @@ private static boolean writeToEncodedAppender(StreamCharBuffer source, Writer ta Encoder encoder = null; if (target instanceof EncoderAware) { - encoder = ((EncoderAware)target).getEncoder(); + encoder = ((EncoderAware) target).getEncoder(); } if (encoder == null && appender instanceof EncoderAware) { - encoder = ((EncoderAware)appender).getEncoder(); + encoder = ((EncoderAware) appender).getEncoder(); } source.encodeTo(appender, encoder); - if(flush) { - appender.flush(); + if (flush) { + appender.flush(); } return true; - } } - return false; } + return false; + } private void writeToImpl(Writer target, boolean flushTarget, boolean emptyAfter) throws IOException { AbstractChunk current = firstChunk; @@ -667,7 +661,7 @@ protected void emptyAfterReading() { /** * {@inheritDoc} - * + *

    * Reads (and empties) the buffer to a String, but caches the return value for subsequent calls. * If more content has been added between 2 calls, the returned value will be joined from the previously cached value and the data read from the buffer. * @@ -685,8 +679,8 @@ public String toString() { public StringChunk readToSingleStringChunk(boolean registerEncodingState) { if (firstChunk == lastChunk && firstChunk instanceof StringChunk && allocBuffer.charsUsed() == 0 && - ((StringChunk)firstChunk).isSingleBuffer()) { - StringChunk chunk = ((StringChunk)firstChunk); + ((StringChunk) firstChunk).isSingleBuffer()) { + StringChunk chunk = ((StringChunk) firstChunk); if (registerEncodingState) { markEncoded(chunk); } @@ -713,13 +707,14 @@ public StringChunk readToSingleStringChunk(boolean registerEncodingState) { public void markEncoded(StringChunk strChunk) { if (strChunk instanceof MultipartStringChunk) { - MultipartStringChunk stringChunk = (MultipartStringChunk)strChunk; + MultipartStringChunk stringChunk = (MultipartStringChunk) strChunk; if (stringChunk.isSingleEncoding()) { EncodingState encodingState = stringChunk.firstPart.encodingState; if (encodingState != null && encodingState.getEncoders() != null && encodingState.getEncoders().size() > 0) { - Encoder encoder=encodingState.getEncoders().iterator().next(); - if (encoder != null) + Encoder encoder = encodingState.getEncoders().iterator().next(); + if (encoder != null) { encoder.markEncoded(stringChunk.str); + } } } } @@ -727,7 +722,7 @@ public void markEncoded(StringChunk strChunk) { /** * {@inheritDoc} - * + *

    * Uses String's hashCode to support compatibility with String instances in maps, sets, etc. * * @see java.lang.Object#hashCode() @@ -744,9 +739,13 @@ public int hashCode() { */ @Override public boolean equals(Object o) { - if (o==this) return true; + if (o == this) { + return true; + } - if (!(o instanceof CharSequence)) return false; + if (!(o instanceof CharSequence)) { + return false; + } CharSequence other = (CharSequence) o; @@ -763,15 +762,15 @@ public String plus(Object value) { /** * Reads the buffer to a char[]. - * + *

    * Caches the result if there aren't any readers. * * @return the chars */ public char[] toCharArray() { // check if there is a cached single charbuffer - if (firstChunk == lastChunk && firstChunk instanceof CharBufferChunk && allocBuffer.charsUsed()==0 && ((CharBufferChunk)firstChunk).isSingleBuffer()) { - return ((CharBufferChunk)firstChunk).buffer; + if (firstChunk == lastChunk && firstChunk instanceof CharBufferChunk && allocBuffer.charsUsed() == 0 && ((CharBufferChunk) firstChunk).isSingleBuffer()) { + return ((CharBufferChunk) firstChunk).buffer; } int initialReaderCount = readerCount; @@ -783,43 +782,20 @@ public char[] toCharArray() { addChunk(chunk); } } - if(chunk != null) { + if (chunk != null) { return chunk.buffer; } else { return new char[0]; } } - public static final class EncodedPart { - private final EncodingState encodingState; - private final String part; - - public EncodedPart(EncodingState encodingState, String part) { - this.encodingState = encodingState; - this.part = part; - } - - public EncodingState getEncodingState() { - return encodingState; - } - - public String getPart() { - return part; - } - - @Override - public String toString() { - return "EncodedPart [encodingState='" + encodingState + "', part='" + part + "']"; - } - } - public List dumpEncodedParts() { List encodedParts = new ArrayList(); MultipartStringChunk mpStringChunk = readToSingleChunk().asStringChunk(); if (mpStringChunk.firstPart != null) { EncodingStatePart current = mpStringChunk.firstPart; int offset = 0; - char[] buf=StringCharArrayAccessor.getValue(mpStringChunk.str); + char[] buf = StringCharArrayAccessor.getValue(mpStringChunk.str); while (current != null) { encodedParts.add(new EncodedPart(current.encodingState, new String(buf, offset, current.len))); offset += current.len; @@ -835,17 +811,16 @@ private MultipartCharBufferChunk readToSingleChunk() { return null; } - FixedCharArrayEncodedAppender appender=new FixedCharArrayEncodedAppender(currentSize); + FixedCharArrayEncodedAppender appender = new FixedCharArrayEncodedAppender(currentSize); try { encodeTo(appender, null); - } - catch (IOException e) { + } catch (IOException e) { throw new RuntimeException("Unexpected IOException", e); } appender.finish(); return appender.chunk; } - + boolean hasQuicklyCalcutableSize() { return totalCharsInDynamicChunks != -1 || dynamicChunkMap.size() == 0; } @@ -941,8 +916,7 @@ private int appendCharBufferChunk(EncodingState encodingState, boolean flushInCo if (!isChunkSizeResizeable()) { allocBuffer.reuseBuffer(encodingState); } - } - else { + } else { if (allocBuffer.hasChunk()) { addChunk(allocBuffer.createChunk()); } @@ -961,7 +935,7 @@ void appendStringChunk(EncodingState encodingState, String str, int off, int len appendCharBufferChunk(encodingState, false, false); addChunk(new StringChunk(str, off, len)).setEncodingState(encodingState); } - + public void appendStreamCharBufferChunk(StreamCharBuffer subBuffer) throws IOException { appendStreamCharBufferChunk(subBuffer, null); } @@ -984,10 +958,9 @@ AbstractChunk addChunk(AbstractChunk newChunk) { firstChunk = newChunk; } if (newChunk instanceof StreamCharBufferSubChunk) { - StreamCharBufferSubChunk bufSubChunk = (StreamCharBufferSubChunk)newChunk; + StreamCharBufferSubChunk bufSubChunk = (StreamCharBufferSubChunk) newChunk; dynamicChunkMap.put(bufSubChunk.getSourceBuffer().bufferKey, bufSubChunk); - } - else { + } else { totalCharsInList += newChunk.size(); } return newChunk; @@ -999,7 +972,7 @@ public boolean isConnectedMode() { private void flushToConnected(boolean forceFlush) throws IOException { startUsingConnectedWritersWriter(); - if (notConnectedToEncodeAwareWriters==null) { + if (notConnectedToEncodeAwareWriters == null) { notConnectedToEncodeAwareWriters = !connectedWritersWriter.isEncoderAware(); } writeTo(connectedWritersWriter, forceFlush, true); @@ -1017,158 +990,500 @@ protected void resizeChunkSizeAsProcentageOfTotalSize() { return; } - if (growProcent==100) { + if (growProcent == 100) { chunkSize = Math.min(totalChunkSize, maxChunkSize); - } - else if (growProcent == 200) { + } else if (growProcent == 200) { chunkSize = Math.min(totalChunkSize << 1, maxChunkSize); - } - else if (growProcent > 0) { - chunkSize = Math.max(Math.min((totalChunkSize * growProcent)/100, maxChunkSize), firstChunkSize); + } else if (growProcent > 0) { + chunkSize = Math.max(Math.min((totalChunkSize * growProcent) / 100, maxChunkSize), firstChunkSize); } } protected static final void arrayCopy(char[] src, int srcPos, char[] dest, int destPos, int length) { if (length == 1) { - dest[destPos]=src[srcPos]; - } - else { + dest[destPos] = src[srcPos]; + } else { System.arraycopy(src, srcPos, dest, destPos, length); } } - /** - * This is the java.io.Writer implementation for StreamCharBuffer - * - * @author Lari Hotari, Sagire Software Oy - */ - public final class StreamCharBufferWriter extends Writer implements EncodedAppenderFactory, EncodedAppenderWriterFactory { - boolean closed = false; - int writerUsedCounter = 0; - boolean increaseCounter = true; - EncodedAppender encodedAppender; - - @Override - public final void write(final char[] b, final int off, final int len) throws IOException { - write(null, b, off, len); - } + private boolean isNotConnectedToEncoderAwareWriters() { + return notConnectedToEncodeAwareWriters != null && notConnectedToEncodeAwareWriters; + } - private final void write(EncodingState encodingState, final char[] b, final int off, final int len) throws IOException { - if (b == null) { - throw new NullPointerException(); - } + /* Compatibility methods so that StreamCharBuffer will behave more like java.lang.String in groovy code */ - if ((off < 0) || (off > b.length) || (len < 0) || - ((off + len) > b.length) || ((off + len) < 0)) { - throw new IndexOutOfBoundsException(); - } + public char charAt(int index) { + return toString().charAt(index); + } - if (len == 0) { - return; - } + public int length() { + return size(); + } - markUsed(); - if (shouldWriteDirectly(len)) { - appendCharBufferChunk(encodingState,true,true); - startUsingConnectedWritersWriter(); - connectedWritersWriter.write(b, off, len); - } - else { - int charsLeft = len; - int currentOffset = off; - while (charsLeft > 0) { - int spaceLeft = allocateSpace(encodingState); - int writeChars = Math.min(spaceLeft, charsLeft); - allocBuffer.write(b, currentOffset, writeChars); - charsLeft -= writeChars; - currentOffset += writeChars; - } - } - } + public CharSequence subSequence(int start, int end) { + return toString().subSequence(start, end); + } - private final boolean shouldWriteDirectly(final int len) { - if (!isConnectedMode()) { - return false; - } + public boolean asBoolean() { + return isNotEmpty(); + } - if (!(writeDirectlyToConnectedMinSize >= 0 && len >= writeDirectlyToConnectedMinSize)) { - return false; - } + /* methods for notifying child (sub) StreamCharBuffer changes to the parent StreamCharBuffer */ - return isNextChunkBigEnough(len); + void addParentBuffer(StreamCharBuffer parent) { + if (!notifyParentBuffersEnabled) { + return; } - private final boolean isNextChunkBigEnough(final int len) { - return (len > getNewChunkMinSize()); + if (parentBuffers == null) { + parentBuffers = new HashSet>(); } + parentBuffers.add(new SoftReference(parent.bufferKey)); + } - private final int getDirectChunkMinSize() { - if (!isConnectedMode()) { - return -1; - } - if (writeDirectlyToConnectedMinSize >= 0) { - return writeDirectlyToConnectedMinSize; - } + protected boolean bufferChanged(StreamCharBuffer buffer) { + markBufferChanged(); - return getNewChunkMinSize(); + StreamCharBufferSubChunk subChunk = dynamicChunkMap.get(buffer.bufferKey); + if (subChunk == null) { + // buffer isn't a subchunk in this buffer any more + return false; + } + // reset cached size; + if (subChunk.resetSubBuffer()) { + totalCharsInDynamicChunks = -1; + sizeAtLeast = -1; + // notify parents too + notifyBufferChange(); } + return true; + } - private final int getNewChunkMinSize() { - if (chunkMinSize <= 0 || allocBuffer.charsUsed() == 0 || allocBuffer.charsUsed() >= chunkMinSize) { - return 0; + protected List getCurrentParentBuffers() { + List currentParentBuffers = new ArrayList(); + if (parentBuffers != null) { + for (Iterator> i = parentBuffers.iterator(); i.hasNext(); ) { + SoftReference ref = i.next(); + final StreamCharBuffer.StreamCharBufferKey parentKey = ref.get(); + if (parentKey != null) { + currentParentBuffers.add(parentKey.getBuffer()); + } } - return allocBuffer.spaceLeft(null); } + return currentParentBuffers; + } - @Override - public final void write(final String str) throws IOException { - write(null, str, 0, str.length()); + protected void notifyBufferChange() { + markBufferChanged(); + + if (!notifyParentBuffersEnabled) { + return; } - @Override - public final void write(final String str, final int off, final int len) throws IOException { - write(null, str, off, len); + if (parentBuffers == null || parentBuffers.isEmpty()) { + return; } - private final void write(EncodingState encodingState, final String str, final int off, final int len) throws IOException { - if (len==0) return; - markUsed(); - if (shouldWriteDirectly(len)) { - appendCharBufferChunk(encodingState,true,false); - startUsingConnectedWritersWriter(); - connectedWritersWriter.write(str, off, len); + List> parentBuffersList = new ArrayList<>(parentBuffers); + for (SoftReference ref : parentBuffersList) { + final StreamCharBuffer.StreamCharBufferKey parentKey = ref.get(); + boolean removeIt = true; + if (parentKey != null) { + StreamCharBuffer parent = parentKey.getBuffer(); + removeIt = !parent.bufferChanged(this); } - else if (len >= subStringChunkMinSize && isNextChunkBigEnough(len)) { - appendStringChunk(encodingState, str, off, len); + if (removeIt) { + parentBuffers.remove(ref); } - else { - int charsLeft = len; - int currentOffset = off; - while (charsLeft > 0) { - int spaceLeft = allocateSpace(encodingState); - int writeChars = Math.min(spaceLeft, charsLeft); - allocBuffer.writeString(str, currentOffset, writeChars); - charsLeft -= writeChars; - currentOffset += writeChars; - } + } + } + + public int getBufferChangesCounter() { + return bufferChangesCounter; + } + + protected int markBufferChanged() { + return bufferChangesCounter++; + } + + @Override + public StreamCharBuffer clone() { + StreamCharBuffer cloned = new StreamCharBuffer(); + cloned.setNotifyParentBuffersEnabled(false); + cloned.setAllowSubBuffers(false); + if (this.size() > 0) { + cloned.addChunk(readToSingleChunk()); + } + cloned.setAllowSubBuffers(true); + return cloned; + } + + public void readExternal(ObjectInput in) throws IOException, + ClassNotFoundException { + int version = in.readInt(); + if (version != EXTERNALIZABLE_VERSION) { + throw new IOException("Uncompatible version in serialization stream."); + } + reset(); + int len = in.readInt(); + if (len > 0) { + char[] buf = new char[len]; + Reader reader = new InputStreamReader((InputStream) in, "UTF-8"); + reader.read(buf); + String str = StringCharArrayAccessor.createString(buf); + MultipartStringChunk mpStringChunk = new MultipartStringChunk(str); + int partCount = in.readInt(); + for (int i = 0; i < partCount; i++) { + EncodingStatePart current = new EncodingStatePart(); + mpStringChunk.appendEncodingStatePart(current); + current.len = in.readInt(); + int encodersSize = in.readInt(); + Set encoders = null; + if (encodersSize > 0) { + encoders = new LinkedHashSet(); + for (int j = 0; j < encodersSize; j++) { + String codecName = in.readUTF(); + boolean safe = in.readBoolean(); + encoders.add(new SavedEncoder(codecName, safe)); + } + } + current.encodingState = new EncodingStateImpl(encoders, null); + } + addChunk(mpStringChunk); + } + } + + public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(EXTERNALIZABLE_VERSION); + StringChunk stringChunk = readToSingleStringChunk(false); + if (stringChunk != null && stringChunk.str.length() > 0) { + char[] buf = StringCharArrayAccessor.getValue(stringChunk.str); + out.writeInt(buf.length); + Writer writer = new OutputStreamWriter((OutputStream) out, "UTF-8"); + writer.write(buf); + writer.flush(); + if (stringChunk instanceof MultipartStringChunk) { + MultipartStringChunk mpStringChunk = (MultipartStringChunk) stringChunk; + out.writeInt(mpStringChunk.partCount()); + EncodingStatePart current = mpStringChunk.firstPart; + while (current != null) { + out.writeInt(current.len); + if (current.encodingState != null && current.encodingState.getEncoders() != null && current.encodingState.getEncoders().size() > 0) { + out.writeInt(current.encodingState.getEncoders().size()); + for (Encoder encoder : current.encodingState.getEncoders()) { + out.writeUTF(encoder.getCodecIdentifier().getCodecName()); + out.writeBoolean(encoder.isSafe()); + } + } else { + out.writeInt(0); + } + current = current.next; + } + } else { + out.writeInt(0); + } + } else { + out.writeInt(0); + } + } + + public StreamCharBuffer encodeToBuffer(Encoder encoder) { + return encodeToBuffer(encoder, isAllowSubBuffers(), isNotifyParentBuffersEnabled()); + } + + public StreamCharBuffer encodeToBuffer(Encoder encoder, boolean allowSubBuffers, boolean notifyParentBuffersEnabled) { + StreamCharBuffer coded = new StreamCharBuffer(Math.min(Math.max(totalChunkSize, chunkSize) * 12 / 10, maxChunkSize)); + coded.setAllowSubBuffers(allowSubBuffers); + coded.setNotifyParentBuffersEnabled(notifyParentBuffersEnabled); + EncodedAppender codedWriter = coded.writer.getEncodedAppender(); + try { + encodeTo(codedWriter, encoder); + } catch (IOException e) { + // Should not ever happen + LOG.error("IOException in StreamCharBuffer.encodeToBuffer", e); + } + return coded; + } + + public StreamCharBuffer encodeToBuffer(List encoders) { + return encodeToBuffer(encoders, isAllowSubBuffers(), isNotifyParentBuffersEnabled()); + } + + public StreamCharBuffer encodeToBuffer(List encoders, boolean allowSubBuffers, boolean notifyParentBuffersEnabled) { + StreamCharBuffer currentBuffer = this; + for (Encoder encoder : encoders) { + currentBuffer = currentBuffer.encodeToBuffer(encoder, allowSubBuffers, notifyParentBuffersEnabled); + } + return currentBuffer; + } + + public void encodeTo(EncodedAppender appender, Encoder encoder) throws IOException { + if (isPreferSubChunkWhenWritingToOtherBuffer() && appender instanceof StreamCharBufferEncodedAppender) { + StreamCharBufferWriter writer = ((StreamCharBufferEncodedAppender) appender).getWriter(); + if (writer.appendSubBuffer(this, encoder != null ? Collections.singletonList(encoder) : null)) { + // subbuffer was appended, so return + return; + } + } + AbstractChunk current = firstChunk; + while (current != null) { + current.encodeTo(appender, encoder); + current = current.next; + } + allocBuffer.encodeTo(appender, encoder); + } + + public boolean isAllowSubBuffers() { + return subBuffersEnabled && !isConnectedMode(); + } + + public void setAllowSubBuffers(boolean allowSubBuffers) { + this.subBuffersEnabled = allowSubBuffers; + } + + public CharSequence encode(Encoder encoder) { + return encodeToBuffer(encoder); + } + + public Writer getWriterForEncoder() { + return getWriterForEncoder(null); + } + + public Writer getWriterForEncoder(Encoder encoder) { + return getWriterForEncoder(encoder, lookupDefaultEncodingStateRegistry()); + } + + protected EncodingStateRegistry lookupDefaultEncodingStateRegistry() { + EncodingStateRegistryLookup encodingStateRegistryLookup = EncodingStateRegistryLookupHolder.getEncodingStateRegistryLookup(); + return encodingStateRegistryLookup != null ? encodingStateRegistryLookup.lookup() : null; + } + + public Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodingStateRegistry) { + return getWriterForEncoder(encoder, encodingStateRegistry, false); + } + + public Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodingStateRegistry, boolean ignoreEncodingState) { + EncodedAppender encodedAppender = writer.getEncodedAppender(); + encodedAppender.setIgnoreEncodingState(ignoreEncodingState); + return new EncodedAppenderWriter(encodedAppender, encoder, encodingStateRegistry); + } + + public boolean isNotifyParentBuffersEnabled() { + return notifyParentBuffersEnabled; + } + + /** + * By default the parent buffers (a buffer where this buffer has been appended to) get notified of changed to this buffer. + *

    + * You can control the notification behavior with this property. + * Setting this property to false will also clear the references to parent buffers if there are any. + * + * @param notifyParentBuffersEnabled + */ + public void setNotifyParentBuffersEnabled(boolean notifyParentBuffersEnabled) { + this.notifyParentBuffersEnabled = notifyParentBuffersEnabled; + if (!notifyParentBuffersEnabled && parentBuffers != null) { + parentBuffers.clear(); + } + } + + @Override + public void encodeTo(Writer writer, EncodesToWriter encoder) throws IOException { + AbstractChunk current = firstChunk; + while (current != null) { + current.encodeTo(writer, encoder); + current = current.next; + } + allocBuffer.encodeTo(writer, encoder); + } + + /** + * Delegates methodMissing to String object + * + * @param name The name of the method + * @param args The arguments + * @return The return value + */ + public Object methodMissing(String name, Object args) { + String str = this.toString(); + return InvokerHelper.invokeMethod(str, name, args); + } + + public Object asType(Class clazz) { + if (clazz == String.class) { + return toString(); + } else if (clazz == char[].class) { + return toCharArray(); + } else if (clazz == Boolean.class || clazz == boolean.class) { + return asBoolean(); + } else { + return StringGroovyMethods.asType(toString(), clazz); + } + } + + private static final class SavedEncoder implements Encoder { + + private CodecIdentifier codecIdentifier; + private boolean safe; + + public SavedEncoder(String codecName, boolean safe) { + this.codecIdentifier = new DefaultCodecIdentifier(codecName); + this.safe = safe; + } + + public CodecIdentifier getCodecIdentifier() { + return codecIdentifier; + } + + public boolean isSafe() { + return safe; + } + + public Object encode(Object o) { + throw new UnsupportedOperationException("encode isn't supported for SavedEncoder"); + } + + public void markEncoded(CharSequence string) { + throw new UnsupportedOperationException("markEncoded isn't supported for SavedEncoder"); + } + + public boolean isApplyToSafelyEncoded() { + return false; + } + } + + /** + * This is the java.io.Writer implementation for StreamCharBuffer + * + * @author Lari Hotari, Sagire Software Oy + */ + public final class StreamCharBufferWriter extends Writer implements EncodedAppenderFactory, EncodedAppenderWriterFactory { + + boolean closed = false; + int writerUsedCounter = 0; + boolean increaseCounter = true; + EncodedAppender encodedAppender; + + @Override + public void write(final char[] b, final int off, final int len) throws IOException { + write(null, b, off, len); + } + + private void write(EncodingState encodingState, final char[] b, final int off, final int len) throws IOException { + if (b == null) { + throw new NullPointerException(); + } + + if ((off < 0) || (off > b.length) || (len < 0) || + ((off + len) > b.length) || ((off + len) < 0)) { + throw new IndexOutOfBoundsException(); + } + + if (len == 0) { + return; + } + + markUsed(); + if (shouldWriteDirectly(len)) { + appendCharBufferChunk(encodingState, true, true); + startUsingConnectedWritersWriter(); + connectedWritersWriter.write(b, off, len); + } else { + int charsLeft = len; + int currentOffset = off; + while (charsLeft > 0) { + int spaceLeft = allocateSpace(encodingState); + int writeChars = Math.min(spaceLeft, charsLeft); + allocBuffer.write(b, currentOffset, writeChars); + charsLeft -= writeChars; + currentOffset += writeChars; + } } } - - public final void write(StreamCharBuffer subBuffer) throws IOException { + + private boolean shouldWriteDirectly(final int len) { + if (!isConnectedMode()) { + return false; + } + + if (!(writeDirectlyToConnectedMinSize >= 0 && len >= writeDirectlyToConnectedMinSize)) { + return false; + } + + return isNextChunkBigEnough(len); + } + + private boolean isNextChunkBigEnough(final int len) { + return (len > getNewChunkMinSize()); + } + + private int getDirectChunkMinSize() { + if (!isConnectedMode()) { + return -1; + } + if (writeDirectlyToConnectedMinSize >= 0) { + return writeDirectlyToConnectedMinSize; + } + + return getNewChunkMinSize(); + } + + private int getNewChunkMinSize() { + if (chunkMinSize <= 0 || allocBuffer.charsUsed() == 0 || allocBuffer.charsUsed() >= chunkMinSize) { + return 0; + } + return allocBuffer.spaceLeft(null); + } + + @Override + public void write(final String str) throws IOException { + write(null, str, 0, str.length()); + } + + @Override + public void write(final String str, final int off, final int len) throws IOException { + write(null, str, off, len); + } + + private void write(EncodingState encodingState, final String str, final int off, final int len) throws IOException { + if (len == 0) { + return; + } + markUsed(); + if (shouldWriteDirectly(len)) { + appendCharBufferChunk(encodingState, true, false); + startUsingConnectedWritersWriter(); + connectedWritersWriter.write(str, off, len); + } else if (len >= subStringChunkMinSize && isNextChunkBigEnough(len)) { + appendStringChunk(encodingState, str, off, len); + } else { + int charsLeft = len; + int currentOffset = off; + while (charsLeft > 0) { + int spaceLeft = allocateSpace(encodingState); + int writeChars = Math.min(spaceLeft, charsLeft); + allocBuffer.writeString(str, currentOffset, writeChars); + charsLeft -= writeChars; + currentOffset += writeChars; + } + } + } + + public void write(StreamCharBuffer subBuffer) throws IOException { write(subBuffer, null); } - public final void write(StreamCharBuffer subBuffer, List encoders) throws IOException { + public void write(StreamCharBuffer subBuffer, List encoders) throws IOException { markUsed(); int directChunkMinSize = getDirectChunkMinSize(); if (encoders == null && (directChunkMinSize == 0 || (directChunkMinSize != -1 && subBuffer - .isSizeLarger(directChunkMinSize)))) { + .isSizeLarger(directChunkMinSize)))) { appendCharBufferChunk(null, true, false); startUsingConnectedWritersWriter(); subBuffer.writeToImpl(connectedWritersWriter, false, false); - } - else if (!appendSubBuffer(subBuffer, encoders)) { + } else if (!appendSubBuffer(subBuffer, encoders)) { ChainedEncoders.chainEncode(subBuffer, this.getEncodedAppender(), encoders); } } @@ -1188,13 +1503,12 @@ boolean appendSubBuffer(StreamCharBuffer subBuffer, List encoders) thro } @Override - public final Writer append(final CharSequence csq, final int start, final int end) + public Writer append(final CharSequence csq, final int start, final int end) throws IOException { markUsed(); if (csq == null) { write("null"); - } - else { + } else { appendCharSequence(null, csq, start, end); } return this; @@ -1203,37 +1517,34 @@ public final Writer append(final CharSequence csq, final int start, final int en protected void appendCharSequence(final EncodingState encodingState, final CharSequence csq, final int start, final int end) throws IOException { final Class csqClass = csq.getClass(); if (csqClass == String.class || csqClass == StringBuffer.class || csqClass == StringBuilder.class || csq instanceof CharArrayAccessible) { - int len = end-start; + int len = end - start; int charsLeft = len; int currentOffset = start; while (charsLeft > 0) { int spaceLeft = allocateSpace(encodingState); int writeChars = Math.min(spaceLeft, charsLeft); if (csqClass == String.class) { - allocBuffer.writeString((String)csq, currentOffset, writeChars); - } - else if (csqClass == StringBuffer.class) { - allocBuffer.writeStringBuffer((StringBuffer)csq, currentOffset, writeChars); - } - else if (csqClass == StringBuilder.class) { - allocBuffer.writeStringBuilder((StringBuilder)csq, currentOffset, writeChars); - } - else if (csq instanceof CharArrayAccessible) { - allocBuffer.writeCharArrayAccessible((CharArrayAccessible)csq, currentOffset, writeChars); + allocBuffer.writeString((String) csq, currentOffset, writeChars); + } else if (csqClass == StringBuffer.class) { + allocBuffer.writeStringBuffer((StringBuffer) csq, currentOffset, writeChars); + } else if (csqClass == StringBuilder.class) { + allocBuffer.writeStringBuilder((StringBuilder) csq, currentOffset, writeChars); + } else if (csq instanceof CharArrayAccessible) { + allocBuffer.writeCharArrayAccessible((CharArrayAccessible) csq, currentOffset, writeChars); } charsLeft -= writeChars; currentOffset += writeChars; } } else { - String str=csq.subSequence(start, end).toString(); + String str = csq.subSequence(start, end).toString(); write(encodingState, str, 0, str.length()); } } @Override - public final Writer append(final CharSequence csq) throws IOException { + public Writer append(final CharSequence csq) throws IOException { markUsed(); - if (csq==null) { + if (csq == null) { write("null"); } else { append(csq, 0, csq.length()); @@ -1256,11 +1567,11 @@ public boolean isUsed() { return writerUsedCounter > 0; } - public final void markUsed() { + public void markUsed() { if (increaseCounter) { writerUsedCounter++; if (!hasReaders) { - increaseCounter=false; + increaseCounter = false; } } } @@ -1286,7 +1597,7 @@ void flushWriter(boolean forceFlush) throws IOException { notifyBufferChange(); } - public final StreamCharBuffer getBuffer() { + public StreamCharBuffer getBuffer() { return StreamCharBuffer.this; } @@ -1301,7 +1612,7 @@ public Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodin } public EncodedAppender getEncodedAppender() { - if (encodedAppender==null) { + if (encodedAppender == null) { encodedAppender = new StreamCharBufferEncodedAppender(this); } return encodedAppender; @@ -1313,14 +1624,12 @@ public void flush() throws IOException { } } - private boolean isNotConnectedToEncoderAwareWriters() { - return notConnectedToEncodeAwareWriters != null && notConnectedToEncodeAwareWriters; - } + private static final class StreamCharBufferEncodedAppender extends AbstractEncodedAppender { - private final static class StreamCharBufferEncodedAppender extends AbstractEncodedAppender { StreamCharBufferWriter writer; + StreamCharBufferEncodedAppender(StreamCharBufferWriter writer) { - this.writer=writer; + this.writer = writer; } public StreamCharBufferWriter getWriter() { @@ -1359,10 +1668,10 @@ public void close() throws IOException { * * @author Lari Hotari, Sagire Software Oy */ + public final class StreamCharBufferReader extends Reader { - final public class StreamCharBufferReader extends Reader { - boolean eofException=false; - int eofReachedCounter=0; + boolean eofException = false; + int eofReachedCounter = 0; ChunkReader chunkReader; ChunkReader lastChunkReader; boolean removeAfterReading; @@ -1385,8 +1694,7 @@ private int prepareRead(int len) { if (removeAfterReading) { firstChunk.subtractFromTotalCount(); } - } - else { + } else { chunkReader = new AllocatedBufferReader(allocBuffer, removeAfterReading); } } @@ -1404,12 +1712,12 @@ private int prepareRead(int len) { } if (chunkReader == null) { if (hasReaders) { - eofReachedCounter=writer.writerUsedCounter; + eofReachedCounter = writer.writerUsedCounter; } else { eofReachedCounter = 1; } } else if (hasReaders) { - lastChunkReader=chunkReader; + lastChunkReader = chunkReader; } return available; } @@ -1418,18 +1726,18 @@ private int prepareRead(int len) { private void repositionChunkReader() { if (lastChunkReader instanceof AllocatedBufferReader) { if (lastChunkReader.isValid()) { - chunkReader=lastChunkReader; + chunkReader = lastChunkReader; } else { - AllocatedBufferReader allocBufferReader = (AllocatedBufferReader)lastChunkReader; + AllocatedBufferReader allocBufferReader = (AllocatedBufferReader) lastChunkReader; // find out what is the CharBufferChunk that was read by the AllocatedBufferReader already int currentPosition = allocBufferReader.position; AbstractChunk chunk = lastChunk; while (chunk != null && chunk.writerUsedCounter >= lastChunkReader.getWriterUsedCounter()) { if (chunk instanceof CharBufferChunk) { - CharBufferChunk charBufChunk = (CharBufferChunk)chunk; + CharBufferChunk charBufChunk = (CharBufferChunk) chunk; if (charBufChunk.allocatedBufferId == allocBufferReader.parent.id) { if (currentPosition >= charBufChunk.offset && currentPosition <= charBufChunk.lastposition) { - CharBufferChunkReader charBufChunkReader = (CharBufferChunkReader)charBufChunk.getChunkReader(removeAfterReading); + CharBufferChunkReader charBufChunkReader = (CharBufferChunkReader) charBufChunk.getChunkReader(removeAfterReading); int oldpointer = charBufChunkReader.pointer; // skip the already chars charBufChunkReader.pointer = currentPosition; @@ -1455,11 +1763,11 @@ public boolean ready() throws IOException { } @Override - public final int read(final char[] b, final int off, final int len) throws IOException { + public int read(final char[] b, final int off, final int len) throws IOException { return readImpl(b, off, len); } - final int readImpl(final char[] b, final int off, final int len) throws IOException { + int readImpl(final char[] b, final int off, final int len) throws IOException { if (b == null) { throw new NullPointerException(); } @@ -1504,7 +1812,7 @@ public void close() throws IOException { // do nothing } - public final StreamCharBuffer getBuffer() { + public StreamCharBuffer getBuffer() { return StreamCharBuffer.this; } @@ -1514,6 +1822,7 @@ public int getReadLenLimit(int askedAmount) { } abstract class AbstractChunk implements StreamEncodeable, StreamingEncoderWritable { + AbstractChunk next; AbstractChunk prev; int writerUsedCounter; @@ -1522,15 +1831,17 @@ abstract class AbstractChunk implements StreamEncodeable, StreamingEncoderWritab public AbstractChunk() { if (hasReaders) { writerUsedCounter = writer.writerUsedCounter; - } - else { + } else { writerUsedCounter = 1; } } public abstract void writeTo(Writer target) throws IOException; + public abstract ChunkReader getChunkReader(boolean removeAfterReading); + public abstract int size(); + public int getWriterUsedCounter() { return writerUsedCounter; } @@ -1549,16 +1860,22 @@ public void setEncodingState(EncodingState encodingState) { } // keep read state in this class - static abstract class ChunkReader { + abstract static class ChunkReader { + public abstract int read(char[] ch, int off, int len) throws IOException; + public abstract int getReadLenLimit(int askedAmount); + public abstract ChunkReader next(); + public abstract int getWriterUsedCounter(); + public abstract boolean isValid(); } final class AllocatedBuffer { - private int id=allocatedBufferIdSequence++; + + private int id = allocatedBufferIdSequence++; private int size; private char[] buffer; private int used = 0; @@ -1576,20 +1893,20 @@ public void clear() { } public int charsUsed() { - return used-chunkStart; + return used - chunkStart; } public void writeTo(Writer target) throws IOException { - if (used-chunkStart > 0) { - target.write(buffer, chunkStart, used-chunkStart); + if (used - chunkStart > 0) { + target.write(buffer, chunkStart, used - chunkStart); } } public void reuseBuffer(EncodingState encodingState) { - used=0; - chunkStart=0; - this.encodingState=null; - this.nextEncoders=encodingState; + used = 0; + chunkStart = 0; + this.encodingState = null; + this.nextEncoders = encodingState; } public int chunkSize() { @@ -1597,7 +1914,7 @@ public int chunkSize() { } public int spaceLeft(EncodingState encodingState) { - if(encodingState == null) { + if (encodingState == null) { encodingState = EncodingStateImpl.UNDEFINED_ENCODING_STATE; } if (this.encodingState != null && (encodingState == null || !this.encodingState.equals(encodingState)) && hasChunk() && !isNotConnectedToEncoderAwareWriters()) { @@ -1608,9 +1925,9 @@ public int spaceLeft(EncodingState encodingState) { return size - used; } - private final void applyEncoders() throws IOException { - if (encodingState==nextEncoders) { - return ; + private void applyEncoders() throws IOException { + if (encodingState == nextEncoders) { + return; } if (encodingState != null && !isNotConnectedToEncoderAwareWriters() && (nextEncoders == null || !encodingState.equals(nextEncoders))) { throw new IOException("Illegal operation in AllocatedBuffer"); @@ -1628,33 +1945,33 @@ public boolean write(final char ch) throws IOException { return false; } - public final void write(final char[] ch, final int off, final int len) throws IOException { + public void write(final char[] ch, final int off, final int len) throws IOException { applyEncoders(); arrayCopy(ch, off, buffer, used, len); used += len; } - public final void writeString(final String str, final int off, final int len) throws IOException { + public void writeString(final String str, final int off, final int len) throws IOException { applyEncoders(); - str.getChars(off, off+len, buffer, used); + str.getChars(off, off + len, buffer, used); used += len; } - public final void writeStringBuilder(final StringBuilder stringBuilder, final int off, final int len) throws IOException { + public void writeStringBuilder(final StringBuilder stringBuilder, final int off, final int len) throws IOException { applyEncoders(); - stringBuilder.getChars(off, off+len, buffer, used); + stringBuilder.getChars(off, off + len, buffer, used); used += len; } - public final void writeStringBuffer(final StringBuffer stringBuffer, final int off, final int len) throws IOException { + public void writeStringBuffer(final StringBuffer stringBuffer, final int off, final int len) throws IOException { applyEncoders(); - stringBuffer.getChars(off, off+len, buffer, used); + stringBuffer.getChars(off, off + len, buffer, used); used += len; } - public final void writeCharArrayAccessible(final CharArrayAccessible charArrayAccessible, final int off, final int len) throws IOException { + public void writeCharArrayAccessible(final CharArrayAccessible charArrayAccessible, final int off, final int len) throws IOException { applyEncoders(); - charArrayAccessible.getChars(off, off+len, buffer, used); + charArrayAccessible.getChars(off, off + len, buffer, used); used += len; } @@ -1664,9 +1981,9 @@ public final void writeCharArrayAccessible(final CharArrayAccessible charArrayAc * @return the chunk */ public CharBufferChunk createChunk() { - CharBufferChunk chunk=new CharBufferChunk(id, buffer, chunkStart, used-chunkStart); + CharBufferChunk chunk = new CharBufferChunk(id, buffer, chunkStart, used - chunkStart); chunk.setEncodingState(encodingState); - chunkStart=used; + chunkStart = used; return chunk; } @@ -1675,8 +1992,8 @@ public boolean hasChunk() { } public void encodeTo(EncodedAppender appender, Encoder encoder) throws IOException { - if (used-chunkStart > 0) { - appender.append(encoder, encodingState, buffer, chunkStart, used-chunkStart); + if (used - chunkStart > 0) { + appender.append(encoder, encodingState, buffer, chunkStart, used - chunkStart); } } @@ -1685,18 +2002,18 @@ public EncodingState getEncodingState() { } public void encodeTo(Writer writer, EncodesToWriter encoder) throws IOException { - if (used-chunkStart > 0) { - encoder.encodeToWriter(buffer, chunkStart, used-chunkStart, writer, getEncodingState()); + if (used - chunkStart > 0) { + encoder.encodeToWriter(buffer, chunkStart, used - chunkStart, writer, getEncodingState()); } } } /** * The data in the buffer is stored in a linked list of StreamCharBufferChunks. - * + *

    * This class contains data & read/write state for the "chunk level". * It contains methods for reading & writing to the chunk level. - * + *

    * Underneath the chunk is one more level, the StringChunkGroup + StringChunk. * StringChunk makes it possible to directly store the java.lang.String objects. * @@ -1704,6 +2021,7 @@ public void encodeTo(Writer writer, EncodesToWriter encoder) throws IOException * */ class CharBufferChunk extends AbstractChunk { + int allocatedBufferId; char[] buffer; int offset; @@ -1750,8 +2068,9 @@ public void encodeTo(Writer writer, EncodesToWriter encoder) throws IOException } class MultipartStringChunk extends StringChunk { - EncodingStatePart firstPart=null; - EncodingStatePart lastPart=null; + + EncodingStatePart firstPart = null; + EncodingStatePart lastPart = null; public MultipartStringChunk(String str) { super(str, 0, str.length()); @@ -1762,7 +2081,7 @@ public void encodeTo(EncodedAppender appender, Encoder encoder) throws IOExcepti if (firstPart != null) { EncodingStatePart current = firstPart; int offset = 0; - char[] buf=StringCharArrayAccessor.getValue(str); + char[] buf = StringCharArrayAccessor.getValue(str); while (current != null) { appender.append(encoder, current.encodingState, buf, offset, current.len); offset += current.len; @@ -1772,13 +2091,13 @@ public void encodeTo(EncodedAppender appender, Encoder encoder) throws IOExcepti super.encodeTo(appender, encoder); } } - + @Override public void encodeTo(Writer writer, EncodesToWriter encoder) throws IOException { if (firstPart != null) { EncodingStatePart current = firstPart; int offset = 0; - char[] buf=StringCharArrayAccessor.getValue(str); + char[] buf = StringCharArrayAccessor.getValue(str); while (current != null) { encoder.encodeToWriter(buf, offset, current.len, writer, current.encodingState); offset += current.len; @@ -1790,11 +2109,11 @@ public void encodeTo(Writer writer, EncodesToWriter encoder) throws IOException } public boolean isSingleEncoding() { - return (firstPart==lastPart); + return (firstPart == lastPart); } public int partCount() { - int partCount=0; + int partCount = 0; EncodingStatePart current = firstPart; while (current != null) { partCount++; @@ -1804,7 +2123,7 @@ public int partCount() { } public void appendEncodingStatePart(EncodingStatePart current) { - if (firstPart==null) { + if (firstPart == null) { firstPart = current; lastPart = current; } else { @@ -1815,8 +2134,9 @@ public void appendEncodingStatePart(EncodingStatePart current) { } class MultipartCharBufferChunk extends CharBufferChunk { - EncodingStatePart firstPart=null; - EncodingStatePart lastPart=null; + + EncodingStatePart firstPart = null; + EncodingStatePart lastPart = null; public MultipartCharBufferChunk(char[] buffer) { super(-1, buffer, 0, buffer.length); @@ -1847,12 +2167,14 @@ public MultipartStringChunk asStringChunk() { } static final class EncodingStatePart { + EncodingStatePart next; EncodingState encodingState; - int len=-1; + int len = -1; } abstract class AbstractChunkReader extends ChunkReader { + private AbstractChunk parentChunk; private boolean removeAfterReading; @@ -1876,16 +2198,16 @@ public ChunkReader next() { lastChunk = null; } } - AbstractChunk nextChunk=parentChunk.next; + AbstractChunk nextChunk = parentChunk.next; if (nextChunk != null) { if (removeAfterReading) { - if (firstChunk==null) { - firstChunk=nextChunk; + if (firstChunk == null) { + firstChunk = nextChunk; } - if (lastChunk==null) { - lastChunk=nextChunk; + if (lastChunk == null) { + lastChunk = nextChunk; } - nextChunk.prev=null; + nextChunk.prev = null; nextChunk.subtractFromTotalCount(); } return nextChunk.getChunkReader(removeAfterReading); @@ -1901,6 +2223,7 @@ public int getWriterUsedCounter() { } final class CharBufferChunkReader extends AbstractChunkReader { + CharBufferChunk parent; int pointer; @@ -1919,21 +2242,22 @@ public int read(final char[] ch, final int off, final int len) throws IOExceptio @Override public int getReadLenLimit(int askedAmount) { - return Math.min(parent.lastposition-pointer, askedAmount); + return Math.min(parent.lastposition - pointer, askedAmount); } } /** * StringChunk is a wrapper for java.lang.String. - * + *

    * It also keeps state of the read offset and the number of unread characters. - * + *

    * There's methods that StringChunkGroup uses for reading data. * * @author Lari Hotari * */ class StringChunk extends AbstractChunk { + String str; int offset; int lastposition; @@ -1962,7 +2286,7 @@ public int size() { } public boolean isSingleBuffer() { - return offset==0 && length==str.length(); + return offset == 0 && length == str.length(); } @Override @@ -1976,7 +2300,7 @@ public void encodeTo(Writer writer, EncodesToWriter encoder) throws IOException } public CharSequence toCharSequence() { - if(isSingleBuffer()) { + if (isSingleBuffer()) { return str; } else { return CharSequences.createCharSequence(str, offset, length); @@ -1985,6 +2309,7 @@ public CharSequence toCharSequence() { } final class StringChunkReader extends AbstractChunkReader { + StringChunk parent; int position; @@ -2008,18 +2333,19 @@ public int getReadLenLimit(int askedAmount) { } final class StreamCharBufferSubChunk extends AbstractChunk { + + int cachedSize; + int encodedSourceChangesCounter = -1; private StreamCharBuffer sourceBuffer; private List encoders; private StreamCharBuffer encodedBuffer; - int cachedSize; - int encodedSourceChangesCounter = -1; public StreamCharBufferSubChunk(StreamCharBuffer sourceBuffer, List encoders) { this.sourceBuffer = sourceBuffer; this.encoders = encoders; if (encoders == null && hasQuicklyCalcutableSize() && sourceBuffer.hasQuicklyCalcutableSize()) { cachedSize = sourceBuffer.size(); - if(totalCharsInDynamicChunks == -1) { + if (totalCharsInDynamicChunks == -1) { totalCharsInDynamicChunks = 0; } totalCharsInDynamicChunks += cachedSize; @@ -2058,15 +2384,13 @@ public StreamCharBuffer getSourceBuffer() { public void writeTo(Writer target) throws IOException { if (encoders == null || hasEncodedBufferAvailable() || !hasOnlyStreamingEncoders()) { getEncodedBuffer().writeTo(target); - } - else { + } else { EncodedAppender appender; if (target instanceof EncodedAppender) { - appender = ((EncodedAppender)target); + appender = ((EncodedAppender) target); } else if (target instanceof EncodedAppenderFactory) { - appender = ((EncodedAppenderFactory)target).getEncodedAppender(); - } - else { + appender = ((EncodedAppenderFactory) target).getEncodedAppender(); + } else { appender = new WriterEncodedAppender(target); } ChainedEncoders.chainEncode(getSourceBuffer(), appender, encoders); @@ -2076,27 +2400,25 @@ public void writeTo(Writer target) throws IOException { @Override public void encodeTo(EncodedAppender appender, Encoder encodeToEncoder) throws IOException { if (appender instanceof StreamCharBufferEncodedAppender - && getSourceBuffer().isPreferSubChunkWhenWritingToOtherBuffer() - && ((StreamCharBufferEncodedAppender)appender).getWriter().getBuffer().isAllowSubBuffers() ) { + && getSourceBuffer().isPreferSubChunkWhenWritingToOtherBuffer() + && ((StreamCharBufferEncodedAppender) appender).getWriter().getBuffer().isAllowSubBuffers()) { List nextEncoders = ChainedEncoders.appendEncoder(encoders, encodeToEncoder); - ((StreamCharBufferEncodedAppender)appender).getWriter().write(getSourceBuffer(), nextEncoders); - } - else { + ((StreamCharBufferEncodedAppender) appender).getWriter().write(getSourceBuffer(), nextEncoders); + } else { if (hasEncodedBufferAvailable() || !hasOnlyStreamingEncoders()) { appender.append(encodeToEncoder, getEncodedBuffer()); - } - else { + } else { ChainedEncoders.chainEncode(getSourceBuffer(), appender, ChainedEncoders.appendEncoder(encoders, encodeToEncoder)); } } } - + protected boolean hasOnlyStreamingEncoders() { - if(encoders == null || encoders.isEmpty()) { + if (encoders == null || encoders.isEmpty()) { return false; } - for(Encoder encoder : encoders) { - if(!(encoder instanceof StreamingEncoder)) { + for (Encoder encoder : encoders) { + if (!(encoder instanceof StreamingEncoder)) { return false; } } @@ -2108,8 +2430,7 @@ public StreamCharBuffer getEncodedBuffer() { if (encoders == null || sourceBuffer.isEmpty()) { encodedBuffer = sourceBuffer; encodedSourceChangesCounter = sourceBuffer.getBufferChangesCounter(); - } - else { + } else { encodedBuffer = new StreamCharBuffer(chunkSize, growProcent, maxChunkSize); encodedBuffer.setAllowSubBuffers(isAllowSubBuffers()); encodedBuffer.setNotifyParentBuffersEnabled(getSourceBuffer().isNotifyParentBuffersEnabled()); @@ -2125,8 +2446,7 @@ private void encodeToEncodedBuffer() { encodedSourceChangesCounter = sourceBuffer.getBufferChangesCounter(); try { ChainedEncoders.chainEncode(getSourceBuffer(), encodedBuffer.writer.getEncodedAppender(), encoders); - } - catch (IOException e) { + } catch (IOException e) { throw new RuntimeException(e); } encodedBuffer.setAllowSubBuffers(previousAllowSubBuffer); @@ -2142,7 +2462,7 @@ public boolean resetSubBuffer() { if (cachedSize != -1 || encodedBuffer != sourceBuffer) { cachedSize = -1; encodedSourceChangesCounter = -1; - if(encodedBuffer != sourceBuffer && encodedBuffer != null) { + if (encodedBuffer != sourceBuffer && encodedBuffer != null) { encodedBuffer.clear(); encodeToEncodedBuffer(); } @@ -2162,9 +2482,9 @@ public void encodeTo(Writer writer, EncodesToWriter encoder) throws IOException if (hasEncodedBufferAvailable() || !hasOnlyStreamingEncoders() || encoders == null) { getEncodedBuffer().encodeTo(writer, encoder); } else { - List streamingEncoders=new ArrayList(encoders.size()); - for(Encoder e : encoders) { - streamingEncoders.add((StreamingEncoder)e); + List streamingEncoders = new ArrayList(encoders.size()); + for (Encoder e : encoders) { + streamingEncoders.add((StreamingEncoder) e); } getSourceBuffer().encodeTo(writer, encoder.createChainingEncodesToWriter(streamingEncoders, true)); } @@ -2172,13 +2492,14 @@ public void encodeTo(Writer writer, EncodesToWriter encoder) throws IOException } final class StreamCharBufferSubChunkReader extends AbstractChunkReader { + StreamCharBufferSubChunk parent; private StreamCharBufferReader reader; public StreamCharBufferSubChunkReader(StreamCharBufferSubChunk parent, boolean removeAfterReading) { super(parent, removeAfterReading); this.parent = parent; - reader = (StreamCharBufferReader)parent.getEncodedBuffer().getReader(); + reader = (StreamCharBufferReader) parent.getEncodedBuffer().getReader(); } @Override @@ -2193,6 +2514,7 @@ public int read(char[] ch, int off, int len) throws IOException { } final class AllocatedBufferReader extends ChunkReader { + AllocatedBuffer parent; int position; int writerUsedCounter; @@ -2241,7 +2563,8 @@ public boolean isValid() { } private final class FixedCharArrayEncodedAppender extends AbstractEncodedAppender { - char buf[]; + + char[] buf; int count = 0; int currentStart = 0; EncodingState currentState; @@ -2253,13 +2576,13 @@ public FixedCharArrayEncodedAppender(int fixedSize) { } private void checkEncodingChange(EncodingState encodingState) { - if(encodingState == null) { + if (encodingState == null) { encodingState = EncodingStateImpl.UNDEFINED_ENCODING_STATE; } if (currentState != null && !currentState.equals(encodingState)) { addPart(); } - if (currentState==null) { + if (currentState == null) { currentState = encodingState; } } @@ -2273,7 +2596,7 @@ private void addPart() { EncodingStatePart newPart = new EncodingStatePart(); newPart.encodingState = currentState; newPart.len = count - currentStart; - if (chunk.lastPart==null) { + if (chunk.lastPart == null) { chunk.firstPart = newPart; chunk.lastPart = newPart; } else { @@ -2305,22 +2628,18 @@ protected void appendCharSequence(EncodingState encodingState, CharSequence csq, checkEncodingChange(encodingState); final Class csqClass = csq.getClass(); if (csqClass == String.class) { - write(encodingState, (String)csq, start, end-start); - } - else if (csqClass == StringBuffer.class) { - ((StringBuffer)csq).getChars(start, end, buf, count); - count += end-start; - } - else if (csqClass == StringBuilder.class) { - ((StringBuilder)csq).getChars(start, end, buf, count); - count += end-start; - } - else if (csq instanceof CharArrayAccessible) { - ((CharArrayAccessible)csq).getChars(start, end, buf, count); - count += end-start; - } - else { - String str=csq.subSequence(start, end).toString(); + write(encodingState, (String) csq, start, end - start); + } else if (csqClass == StringBuffer.class) { + ((StringBuffer) csq).getChars(start, end, buf, count); + count += end - start; + } else if (csqClass == StringBuilder.class) { + ((StringBuilder) csq).getChars(start, end, buf, count); + count += end - start; + } else if (csq instanceof CharArrayAccessible) { + ((CharArrayAccessible) csq).getChars(start, end, buf, count); + count += end - start; + } else { + String str = csq.subSequence(start, end).toString(); write(encodingState, str, 0, str.length()); } } @@ -2337,20 +2656,23 @@ public void close() throws IOException { * @author Lari Hotari * */ - public static interface LazyInitializingWriter { - public Writer getWriter() throws IOException; + public interface LazyInitializingWriter { + + Writer getWriter() throws IOException; } - public static interface LazyInitializingMultipleWriter extends LazyInitializingWriter { + public interface LazyInitializingMultipleWriter extends LazyInitializingWriter { + /** * initialize underlying writer * * @return false if this writer entry should be removed after calling this callback method */ - public LazyInitializingWriter[] initializeMultiple(StreamCharBuffer buffer, boolean autoFlush) throws IOException; + LazyInitializingWriter[] initializeMultiple(StreamCharBuffer buffer, boolean autoFlush) throws IOException; } final class ConnectToWriter { + final Writer writer; final LazyInitializingWriter lazyInitializingWriter; final boolean autoFlush; @@ -2383,8 +2705,8 @@ private Set resolveLazyInitializers(Set resolved, LazyInitializ if (!resolved.contains(identityHashCode) && lazyInitializingWriter instanceof LazyInitializingMultipleWriter) { resolved.add(identityHashCode); writerList = new LinkedHashSet(); - LazyInitializingWriter[] writers = ((LazyInitializingMultipleWriter)lazyInitializingWriter).initializeMultiple(StreamCharBuffer.this, autoFlush); - for(LazyInitializingWriter writer : writers) { + LazyInitializingWriter[] writers = ((LazyInitializingMultipleWriter) lazyInitializingWriter).initializeMultiple(StreamCharBuffer.this, autoFlush); + for (LazyInitializingWriter writer : writers) { writerList.addAll(resolveLazyInitializers(resolved, writer)); } } else { @@ -2405,6 +2727,7 @@ public boolean isAutoFlush() { * */ static final class ConnectedWriter { + final Writer writer; final boolean autoFlush; final boolean encoderAware; @@ -2431,6 +2754,7 @@ public boolean isEncoderAware() { } static final class SingleOutputWriter extends ConnectedWritersWriter implements GrailsWrappedWriter { + private final ConnectedWriter connectedWriter; private final Writer writer; private final boolean encoderAware; @@ -2452,472 +2776,168 @@ public void flush() throws IOException { } @Override - public void write(final char[] cbuf, final int off, final int len) throws IOException { - writer.write(cbuf, off, len); - } - - @Override - public Writer append(final CharSequence csq, final int start, final int end) - throws IOException { - writer.append(csq, start, end); - return this; - } - - @Override - public void write(String str, int off, int len) throws IOException { - if (!encoderAware) { - StringCharArrayAccessor.writeStringAsCharArray(writer, str, off, len); - } else { - writer.write(str, off, len); - } - } - - @Override - public boolean isEncoderAware() throws IOException { - return encoderAware; - } - - public boolean isAllowUnwrappingOut() { - return true; - } - - public Writer unwrap() { - return writer; - } - - public void markUsed() { - } - - @Override - public void forceFlush() throws IOException { - writer.flush(); - } - } - - static abstract class ConnectedWritersWriter extends Writer { - public abstract boolean isEncoderAware() throws IOException; - public abstract void forceFlush() throws IOException; - } - - /** - * delegates to several writers, used in "connectTo" mode. - */ - static final class MultiOutputWriter extends ConnectedWritersWriter { - final List connectedWriters; - final List writers; - - public MultiOutputWriter(final List connectedWriters) { - this.connectedWriters = connectedWriters; - this.writers = new ArrayList(connectedWriters.size()); - for (ConnectedWriter connectedWriter : connectedWriters) { - writers.add(connectedWriter.getWriter()); - } - } - - @Override - public void close() throws IOException { - // do nothing - } - - @Override - public void flush() throws IOException { - for (ConnectedWriter connectedWriter : connectedWriters) { - connectedWriter.flush(); - } - } - - @Override - public void write(final char[] cbuf, final int off, final int len) throws IOException { - for (Writer writer : writers) { - writer.write(cbuf, off, len); - } - } - - @Override - public Writer append(final CharSequence csq, final int start, final int end) - throws IOException { - for (Writer writer : writers) { - writer.append(csq, start, end); - } - return this; - } - - @Override - public void write(String str, int off, int len) throws IOException { - if (isEncoderAware()) { - for (ConnectedWriter connectedWriter : connectedWriters) { - if (!connectedWriter.isEncoderAware()) { - StringCharArrayAccessor.writeStringAsCharArray(connectedWriter.getWriter(), str, off, len); - } else { - connectedWriter.getWriter().write(str, off, len); - } - } - } else { - for (Writer writer : writers) { - writer.write(str, off, len); - } - } - } - - Boolean encoderAware; - @Override - public boolean isEncoderAware() throws IOException { - if (encoderAware==null) { - encoderAware = false; - for (ConnectedWriter writer : connectedWriters) { - if (writer.isEncoderAware()) { - encoderAware = true; - break; - } - } - } - return encoderAware; - } - - @Override - public void forceFlush() throws IOException { - for (Writer writer : writers) { - writer.flush(); - } - } - } - - /* Compatibility methods so that StreamCharBuffer will behave more like java.lang.String in groovy code */ - - public char charAt(int index) { - return toString().charAt(index); - } - - public int length() { - return size(); - } - - public CharSequence subSequence(int start, int end) { - return toString().subSequence(start, end); - } - - public boolean asBoolean() { - return isNotEmpty(); - } - - /* methods for notifying child (sub) StreamCharBuffer changes to the parent StreamCharBuffer */ - - void addParentBuffer(StreamCharBuffer parent) { - if (!notifyParentBuffersEnabled) return; - - if (parentBuffers==null) { - parentBuffers=new HashSet>(); - } - parentBuffers.add(new SoftReference(parent.bufferKey)); - } - - protected boolean bufferChanged(StreamCharBuffer buffer) { - markBufferChanged(); - - StreamCharBufferSubChunk subChunk=dynamicChunkMap.get(buffer.bufferKey); - if (subChunk==null) { - // buffer isn't a subchunk in this buffer any more - return false; - } - // reset cached size; - if (subChunk.resetSubBuffer()) { - totalCharsInDynamicChunks=-1; - sizeAtLeast=-1; - // notify parents too - notifyBufferChange(); - } - return true; - } - - protected List getCurrentParentBuffers() { - List currentParentBuffers = new ArrayList(); - if(parentBuffers != null) { - for (Iterator> i = parentBuffers.iterator(); i.hasNext();) { - SoftReference ref = i.next(); - final StreamCharBuffer.StreamCharBufferKey parentKey = ref.get(); - if (parentKey != null) { - currentParentBuffers.add(parentKey.getBuffer()); - } - } - } - return currentParentBuffers; - } - - - protected void notifyBufferChange() { - markBufferChanged(); - - if (!notifyParentBuffersEnabled) - return; - - if (parentBuffers == null || parentBuffers.isEmpty()) { - return; - } - - List> parentBuffersList = new ArrayList<>(parentBuffers); - for (SoftReference ref : parentBuffersList) { - final StreamCharBuffer.StreamCharBufferKey parentKey = ref.get(); - boolean removeIt = true; - if (parentKey != null) { - StreamCharBuffer parent = parentKey.getBuffer(); - removeIt = !parent.bufferChanged(this); - } - if (removeIt) { - parentBuffers.remove(ref); - } - } - } - - public int getBufferChangesCounter() { - return bufferChangesCounter; - } - - protected int markBufferChanged() { - return bufferChangesCounter++; - } - - @Override - public StreamCharBuffer clone() { - StreamCharBuffer cloned=new StreamCharBuffer(); - cloned.setNotifyParentBuffersEnabled(false); - cloned.setAllowSubBuffers(false); - if (this.size() > 0) { - cloned.addChunk(readToSingleChunk()); - } - cloned.setAllowSubBuffers(true); - return cloned; - } - - public void readExternal(ObjectInput in) throws IOException, - ClassNotFoundException { - int version = in.readInt(); - if (version != EXTERNALIZABLE_VERSION) { - throw new IOException("Uncompatible version in serialization stream."); - } - reset(); - int len = in.readInt(); - if (len > 0) { - char[] buf=new char[len]; - Reader reader = new InputStreamReader((InputStream)in, "UTF-8"); - reader.read(buf); - String str=StringCharArrayAccessor.createString(buf); - MultipartStringChunk mpStringChunk=new MultipartStringChunk(str); - int partCount = in.readInt(); - for(int i=0;i < partCount;i++) { - EncodingStatePart current = new EncodingStatePart(); - mpStringChunk.appendEncodingStatePart(current); - current.len = in.readInt(); - int encodersSize = in.readInt(); - Set encoders = null; - if (encodersSize > 0) { - encoders = new LinkedHashSet(); - for (int j=0;j < encodersSize;j++) { - String codecName=in.readUTF(); - boolean safe=in.readBoolean(); - encoders.add(new SavedEncoder(codecName, safe)); - } - } - current.encodingState = new EncodingStateImpl(encoders, null); - } - addChunk(mpStringChunk); - } - } - - private static final class SavedEncoder implements Encoder { - private CodecIdentifier codecIdentifier; - private boolean safe; + public void write(final char[] cbuf, final int off, final int len) throws IOException { + writer.write(cbuf, off, len); + } - public SavedEncoder(String codecName, boolean safe) { - this.codecIdentifier=new DefaultCodecIdentifier(codecName); - this.safe=safe; + @Override + public Writer append(final CharSequence csq, final int start, final int end) + throws IOException { + writer.append(csq, start, end); + return this; } - public CodecIdentifier getCodecIdentifier() { - return codecIdentifier; + @Override + public void write(String str, int off, int len) throws IOException { + if (!encoderAware) { + StringCharArrayAccessor.writeStringAsCharArray(writer, str, off, len); + } else { + writer.write(str, off, len); + } } - public boolean isSafe() { - return safe; + @Override + public boolean isEncoderAware() throws IOException { + return encoderAware; } - public Object encode(Object o) { - throw new UnsupportedOperationException("encode isn't supported for SavedEncoder"); + public boolean isAllowUnwrappingOut() { + return true; } - public void markEncoded(CharSequence string) { - throw new UnsupportedOperationException("markEncoded isn't supported for SavedEncoder"); + public Writer unwrap() { + return writer; } - public boolean isApplyToSafelyEncoded() { - return false; + public void markUsed() { } - } - public void writeExternal(ObjectOutput out) throws IOException { - out.writeInt(EXTERNALIZABLE_VERSION); - StringChunk stringChunk = readToSingleStringChunk(false); - if (stringChunk != null && stringChunk.str.length() > 0) { - char[] buf = StringCharArrayAccessor.getValue(stringChunk.str); - out.writeInt(buf.length); - Writer writer = new OutputStreamWriter((OutputStream)out, "UTF-8"); - writer.write(buf); + @Override + public void forceFlush() throws IOException { writer.flush(); - if (stringChunk instanceof MultipartStringChunk) { - MultipartStringChunk mpStringChunk = (MultipartStringChunk)stringChunk; - out.writeInt(mpStringChunk.partCount()); - EncodingStatePart current = mpStringChunk.firstPart; - while (current != null) { - out.writeInt(current.len); - if (current.encodingState != null && current.encodingState.getEncoders() != null && current.encodingState.getEncoders().size() > 0) { - out.writeInt(current.encodingState.getEncoders().size()); - for(Encoder encoder : current.encodingState.getEncoders()) { - out.writeUTF(encoder.getCodecIdentifier().getCodecName()); - out.writeBoolean(encoder.isSafe()); - } - } else { - out.writeInt(0); - } - current = current.next; - } - } else { - out.writeInt(0); - } - } else { - out.writeInt(0); } } - - public StreamCharBuffer encodeToBuffer(Encoder encoder) { - return encodeToBuffer(encoder, isAllowSubBuffers(), isNotifyParentBuffersEnabled()); + + abstract static class ConnectedWritersWriter extends Writer { + + public abstract boolean isEncoderAware() throws IOException; + + public abstract void forceFlush() throws IOException; } - - public StreamCharBuffer encodeToBuffer(Encoder encoder, boolean allowSubBuffers, boolean notifyParentBuffersEnabled) { - StreamCharBuffer coded = new StreamCharBuffer(Math.min(Math.max(totalChunkSize, chunkSize) * 12 / 10, maxChunkSize)); - coded.setAllowSubBuffers(allowSubBuffers); - coded.setNotifyParentBuffersEnabled(notifyParentBuffersEnabled); - EncodedAppender codedWriter = coded.writer.getEncodedAppender(); - try { - encodeTo(codedWriter, encoder); - } catch (IOException e) { - // Should not ever happen - log.error("IOException in StreamCharBuffer.encodeToBuffer", e); + + /** + * delegates to several writers, used in "connectTo" mode. + */ + static final class MultiOutputWriter extends ConnectedWritersWriter { + + final List connectedWriters; + final List writers; + + Boolean encoderAware; + + public MultiOutputWriter(final List connectedWriters) { + this.connectedWriters = connectedWriters; + this.writers = new ArrayList(connectedWriters.size()); + for (ConnectedWriter connectedWriter : connectedWriters) { + writers.add(connectedWriter.getWriter()); + } } - return coded; - } - - public StreamCharBuffer encodeToBuffer(List encoders) { - return encodeToBuffer(encoders, isAllowSubBuffers(), isNotifyParentBuffersEnabled()); - } - - public StreamCharBuffer encodeToBuffer(List encoders, boolean allowSubBuffers, boolean notifyParentBuffersEnabled) { - StreamCharBuffer currentBuffer=this; - for(Encoder encoder : encoders) { - currentBuffer = currentBuffer.encodeToBuffer(encoder, allowSubBuffers, notifyParentBuffersEnabled); + + @Override + public void close() throws IOException { + // do nothing } - return currentBuffer; - } - public void encodeTo(EncodedAppender appender, Encoder encoder) throws IOException { - if(isPreferSubChunkWhenWritingToOtherBuffer() && appender instanceof StreamCharBufferEncodedAppender) { - StreamCharBufferWriter writer = ((StreamCharBufferEncodedAppender)appender).getWriter(); - if(writer.appendSubBuffer(this, encoder != null ? Collections.singletonList(encoder) : null)) { - // subbuffer was appended, so return - return; + @Override + public void flush() throws IOException { + for (ConnectedWriter connectedWriter : connectedWriters) { + connectedWriter.flush(); } } - AbstractChunk current = firstChunk; - while (current != null) { - current.encodeTo(appender, encoder); - current = current.next; + + @Override + public void write(final char[] cbuf, final int off, final int len) throws IOException { + for (Writer writer : writers) { + writer.write(cbuf, off, len); + } } - allocBuffer.encodeTo(appender, encoder); - } - public boolean isAllowSubBuffers() { - return subBuffersEnabled && !isConnectedMode(); - } - - public void setAllowSubBuffers(boolean allowSubBuffers) { - this.subBuffersEnabled = allowSubBuffers; - } + @Override + public Writer append(final CharSequence csq, final int start, final int end) + throws IOException { + for (Writer writer : writers) { + writer.append(csq, start, end); + } + return this; + } - public CharSequence encode(Encoder encoder) { - return encodeToBuffer(encoder); - } + @Override + public void write(String str, int off, int len) throws IOException { + if (isEncoderAware()) { + for (ConnectedWriter connectedWriter : connectedWriters) { + if (!connectedWriter.isEncoderAware()) { + StringCharArrayAccessor.writeStringAsCharArray(connectedWriter.getWriter(), str, off, len); + } else { + connectedWriter.getWriter().write(str, off, len); + } + } + } else { + for (Writer writer : writers) { + writer.write(str, off, len); + } + } + } - public Writer getWriterForEncoder() { - return getWriterForEncoder(null); - } + @Override + public boolean isEncoderAware() throws IOException { + if (encoderAware == null) { + encoderAware = false; + for (ConnectedWriter writer : connectedWriters) { + if (writer.isEncoderAware()) { + encoderAware = true; + break; + } + } + } + return encoderAware; + } - public Writer getWriterForEncoder(Encoder encoder) { - return getWriterForEncoder(encoder, lookupDefaultEncodingStateRegistry()); + @Override + public void forceFlush() throws IOException { + for (Writer writer : writers) { + writer.flush(); + } + } } - protected EncodingStateRegistry lookupDefaultEncodingStateRegistry() { - EncodingStateRegistryLookup encodingStateRegistryLookup = EncodingStateRegistryLookupHolder.getEncodingStateRegistryLookup(); - return encodingStateRegistryLookup != null ? encodingStateRegistryLookup.lookup() : null; - } + public static final class EncodedPart { - public Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodingStateRegistry) { - return getWriterForEncoder(encoder, encodingStateRegistry, false); - } + private final EncodingState encodingState; + private final String part; - public Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodingStateRegistry, boolean ignoreEncodingState) { - EncodedAppender encodedAppender = writer.getEncodedAppender(); - encodedAppender.setIgnoreEncodingState(ignoreEncodingState); - return new EncodedAppenderWriter(encodedAppender, encoder, encodingStateRegistry); - } + public EncodedPart(EncodingState encodingState, String part) { + this.encodingState = encodingState; + this.part = part; + } - public boolean isNotifyParentBuffersEnabled() { - return notifyParentBuffersEnabled; - } + public EncodingState getEncodingState() { + return encodingState; + } - /** - * By default the parent buffers (a buffer where this buffer has been appended to) get notified of changed to this buffer. - * - * You can control the notification behavior with this property. - * Setting this property to false will also clear the references to parent buffers if there are any. - * - * @param notifyParentBuffersEnabled - */ - public void setNotifyParentBuffersEnabled(boolean notifyParentBuffersEnabled) { - this.notifyParentBuffersEnabled = notifyParentBuffersEnabled; - if (!notifyParentBuffersEnabled && parentBuffers != null) { - parentBuffers.clear(); + public String getPart() { + return part; } - } - @Override - public void encodeTo(Writer writer, EncodesToWriter encoder) throws IOException { - AbstractChunk current = firstChunk; - while (current != null) { - current.encodeTo(writer, encoder); - current = current.next; + @Override + public String toString() { + return "EncodedPart [encodingState='" + encodingState + "', part='" + part + "']"; } - allocBuffer.encodeTo(writer, encoder); } - /** - * Delegates methodMissing to String object - * - * @param name The name of the method - * @param args The arguments - * @return The return value - */ - public Object methodMissing(String name, Object args) { - String str = this.toString(); - return InvokerHelper.invokeMethod(str, name, args); - } + private class StreamCharBufferKey { - public Object asType(Class clazz) { - if (clazz == String.class) { - return toString(); - } else if (clazz == char[].class) { - return toCharArray(); - } else if (clazz == Boolean.class || clazz == boolean.class ) { - return asBoolean(); - } else { - return StringGroovyMethods.asType(toString(), clazz); + StreamCharBuffer getBuffer() { + return StreamCharBuffer.this; } } } diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/StreamCharBufferMetaUtils.groovy b/grails-encoder/src/main/groovy/org/grails/buffer/StreamCharBufferMetaUtils.groovy index 2f5792ca321..601a70ff0d8 100644 --- a/grails-encoder/src/main/groovy/org/grails/buffer/StreamCharBufferMetaUtils.groovy +++ b/grails-encoder/src/main/groovy/org/grails/buffer/StreamCharBufferMetaUtils.groovy @@ -20,6 +20,7 @@ package org.grails.buffer class StreamCharBufferMetaUtils { + static registerStreamCharBufferMetaClass() { StreamCharBuffer.metaClass.methodMissing = { String name, args -> def retval = delegate.toString().invokeMethod(name, args) diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/StringCharArrayAccessor.java b/grails-encoder/src/main/groovy/org/grails/buffer/StringCharArrayAccessor.java index 90a5040afaa..6fea4b8d660 100644 --- a/grails-encoder/src/main/groovy/org/grails/buffer/StringCharArrayAccessor.java +++ b/grails-encoder/src/main/groovy/org/grails/buffer/StringCharArrayAccessor.java @@ -24,24 +24,25 @@ /** * Provides optimized access to java.lang.String internals - * + *

    * - Optimized way of creating java.lang.String by reusing a char[] buffer * - Optimized way of writing String to java.io.Writer - * + *

    * java.lang.String creation reusing a char[] buffer requires Java 1.5+ - * + *

    * System property "stringchararrayaccessor.disabled" disables this hack. * -Dstringchararrayaccessor.disabled=true - * + *

    * Read JSR-133, "9.1.1 Post-Construction Modification of Final Fields" - * http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf + * https://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf * * @author Lari Hotari, Sagire Software Oy * */ -public class StringCharArrayAccessor { +public final class StringCharArrayAccessor { + static volatile boolean enabled = Boolean.getBoolean("stringchararrayaccessor.disabled"); - static volatile boolean jdk7_string = false; + static volatile boolean jdk7String = false; // TODO: can't this be removed now since we're always on jdk 7+ static Field valueField; static Field countField; @@ -52,8 +53,7 @@ public class StringCharArrayAccessor { try { valueField = String.class.getDeclaredField("value"); valueField.setAccessible(true); - } - catch (Exception e) { + } catch (Exception e) { enabled = false; handleError(e); } @@ -65,11 +65,9 @@ public class StringCharArrayAccessor { offsetField = String.class.getDeclaredField("offset"); offsetField.setAccessible(true); - } - catch (NoSuchFieldException e) { - jdk7_string = true; - } - catch (Exception e) { + } catch (NoSuchFieldException e) { + jdk7String = true; + } catch (Exception e) { enabled = false; handleError(e); } @@ -82,52 +80,37 @@ private StringCharArrayAccessor() { /** * Writes a portion of a string to a target java.io.Writer with direct access to the char[] of the java.lang.String * - * @param writer - * target java.io.Writer for output - * - * @param str - * A String - * - * @throws IOException - * If an I/O error occurs + * @param writer target java.io.Writer for output + * @param str A String + * @throws IOException If an I/O error occurs */ - static public void writeStringAsCharArray(Writer writer, String str) throws IOException { + public static void writeStringAsCharArray(Writer writer, String str) throws IOException { writeStringAsCharArray(writer, str, 0, str.length()); } /** * Writes a portion of a string to a target java.io.Writer with direct access to the char[] of the java.lang.String * - * @param writer - * target java.io.Writer for output - * - * @param str - * A String - * - * @param off - * Offset from which to start writing characters - * - * @param len - * Number of characters to write - * - * @throws IOException - * If an I/O error occurs + * @param writer target java.io.Writer for output + * @param str A String + * @param off Offset from which to start writing characters + * @param len Number of characters to write + * @throws IOException If an I/O error occurs */ - static public void writeStringAsCharArray(Writer writer, String str, int off, int len) throws IOException { + public static void writeStringAsCharArray(Writer writer, String str, int off, int len) throws IOException { if (!enabled) { writeStringFallback(writer, str, off, len); return; } char[] value; - int internalOffset=0; + int internalOffset = 0; try { - value = (char[])valueField.get(str); - if(!jdk7_string) { + value = (char[]) valueField.get(str); + if (!jdk7String) { internalOffset = offsetField.getInt(str); } - } - catch (Exception e) { + } catch (Exception e) { handleError(e); writeStringFallback(writer, str, off, len); return; @@ -147,15 +130,14 @@ static char[] getValue(String str) { char[] value = null; int internalOffset = 0; try { - value = (char[])valueField.get(str); - if(!jdk7_string) { + value = (char[]) valueField.get(str); + if (!jdk7String) { internalOffset = offsetField.getInt(str); } - } - catch (Exception e) { + } catch (Exception e) { handleError(e); } - if (value != null && internalOffset==0) { + if (value != null && internalOffset == 0) { return value; } @@ -169,8 +151,7 @@ static char[] getValueFallback(String str) { /** * creates a new java.lang.String by setting the char array directly to the String instance with reflection. * - * @param charBuf - * char array to be used as java.lang.String content, don't modify it after passing it. + * @param charBuf char array to be used as java.lang.String content, don't modify it after passing it. * @return new java.lang.String */ public static String createString(char[] charBuf) { @@ -182,20 +163,19 @@ public static String createString(char[] charBuf) { try { // try to prevent possible final field setting execution reordering in JIT (JSR-133/JMM, "9.1.1 Post-Construction Modification of Final Fields") // it was a bit unclear for me if this could ever happen in a single thread - synchronized(str) { + synchronized (str) { valueField.set(str, charBuf); - if(!jdk7_string) { + if (!jdk7String) { countField.set(str, charBuf.length); } } - synchronized(str) { + synchronized (str) { // safety check, just to be sure that setting the final fields went ok if (str.length() != charBuf.length) { throw new IllegalStateException("Fast java.lang.String construction failed."); } } - } - catch (Exception e) { + } catch (Exception e) { handleError(e); str = createStringFallback(charBuf); } @@ -213,7 +193,7 @@ private static synchronized void handleError(Exception e) { offsetField = null; } - static public boolean isEnabled() { + public static boolean isEnabled() { return enabled; } } diff --git a/grails-encoder/src/main/groovy/org/grails/charsequences/CharArrayAccessible.java b/grails-encoder/src/main/groovy/org/grails/charsequences/CharArrayAccessible.java index 883160b8b55..e68bd6cf064 100644 --- a/grails-encoder/src/main/groovy/org/grails/charsequences/CharArrayAccessible.java +++ b/grails-encoder/src/main/groovy/org/grails/charsequences/CharArrayAccessible.java @@ -20,7 +20,7 @@ /** * Marker interface for telling that the underlying char array is directly accessible - * + *

    * This interface is missing from the JVM although String, StringBuffer and StringBuilder all have this method. * * @author Lari Hotari @@ -40,23 +40,23 @@ public interface CharArrayAccessible { * dstbegin + (srcEnd-srcBegin) - 1 * * - * @param srcBegin start copying at this offset. - * @param srcEnd stop copying at this offset. - * @param dst the array to copy the data into. - * @param dstBegin offset into dst. - * @throws NullPointerException if dst is - * null. - * @throws IndexOutOfBoundsException if any of the following is true: - *

      - *
    • srcBegin is negative - *
    • dstBegin is negative - *
    • the srcBegin argument is greater than - * the srcEnd argument. - *
    • srcEnd is greater than - * this.length(). - *
    • dstBegin+srcEnd-srcBegin is greater than - * dst.length - *
    + * @param srcBegin start copying at this offset. + * @param srcEnd stop copying at this offset. + * @param dst the array to copy the data into. + * @param dstBegin offset into dst. + * @throws NullPointerException if dst is + * null. + * @throws IndexOutOfBoundsException if any of the following is true: + *
      + *
    • srcBegin is negative + *
    • dstBegin is negative + *
    • the srcBegin argument is greater than + * the srcEnd argument. + *
    • srcEnd is greater than + * this.length(). + *
    • dstBegin+srcEnd-srcBegin is greater than + * dst.length + *
    */ - void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin); + void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin); } diff --git a/grails-encoder/src/main/groovy/org/grails/charsequences/CharArrayCharSequence.java b/grails-encoder/src/main/groovy/org/grails/charsequences/CharArrayCharSequence.java index e7601fcc916..4c1a8b9b28b 100644 --- a/grails-encoder/src/main/groovy/org/grails/charsequences/CharArrayCharSequence.java +++ b/grails-encoder/src/main/groovy/org/grails/charsequences/CharArrayCharSequence.java @@ -20,28 +20,30 @@ /** * Wraps a char array and implements CharSequence interface - * - * + * * @author Lari Hotari * @since 2.3.10 * */ class CharArrayCharSequence implements CharSequence, CharArrayAccessible { + private final char[] chars; private final int count; private final int start; CharArrayCharSequence(char[] chars, int start, int count) { - if (start + count > chars.length) + if (start + count > chars.length) { throw new StringIndexOutOfBoundsException(start); + } this.chars = chars; this.start = start; this.count = count; } public char charAt(int index) { - if ((index < 0) || (index + start >= chars.length)) + if ((index < 0) || (index + start >= chars.length)) { throw new StringIndexOutOfBoundsException(index); + } return chars[index + start]; } @@ -50,12 +52,15 @@ public int length() { } public CharSequence subSequence(int start, int end) { - if (start < 0) + if (start < 0) { throw new StringIndexOutOfBoundsException(start); - if (end > count) + } + if (end > count) { throw new StringIndexOutOfBoundsException(end); - if (start > end) + } + if (start > end) { throw new StringIndexOutOfBoundsException(end - start); + } if (start == 0 && end == count) { return this; } @@ -68,12 +73,15 @@ public String toString() { } public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { - if (srcBegin < 0) + if (srcBegin < 0) { throw new StringIndexOutOfBoundsException(srcBegin); - if ((srcEnd < 0) || (srcEnd > start+count)) + } + if ((srcEnd < 0) || (srcEnd > start + count)) { throw new StringIndexOutOfBoundsException(srcEnd); - if (srcBegin > srcEnd) + } + if (srcBegin > srcEnd) { throw new StringIndexOutOfBoundsException("srcBegin > srcEnd"); + } System.arraycopy(chars, start + srcBegin, dst, dstBegin, srcEnd - srcBegin); } -} \ No newline at end of file +} diff --git a/grails-encoder/src/main/groovy/org/grails/charsequences/CharSequences.java b/grails-encoder/src/main/groovy/org/grails/charsequences/CharSequences.java index a814e50b7cd..30bd4973f54 100644 --- a/grails-encoder/src/main/groovy/org/grails/charsequences/CharSequences.java +++ b/grails-encoder/src/main/groovy/org/grails/charsequences/CharSequences.java @@ -23,103 +23,100 @@ /** * Utility functions for handling java.lang.CharSequence instances - * - * + * * @author Lari Hotari * @since 2.3.10 * */ -public class CharSequences { +public final class CharSequences { + private CharSequences() { } public static CharSequence createCharSequence(char[] chars) { return new CharArrayCharSequence(chars, 0, chars.length); } - + public static CharSequence createCharSequence(char[] chars, int start, int count) { return new CharArrayCharSequence(chars, start, count); } - + public static CharSequence createCharSequence(CharSequence str, int start, int count) { - if(canUseOriginalForSubSequence(str, start, count)) { + if (canUseOriginalForSubSequence(str, start, count)) { return str; } else { return new SubCharSequence(str, start, count); } } - + /** * Checks if start == 0 and count == length of CharSequence * It does this check only for String, StringBuilder and StringBuffer classes which have a fast way to check length - * + *

    * Calculating length on GStringImpl requires building the result which is costly. * This helper method is to avoid calling length on other that String, StringBuilder and StringBuffer classes * when checking if the input CharSequence instance is already the same as the requested sub sequence * - * @param str CharSequence input + * @param str CharSequence input * @param start start index * @param count length on sub sequence * @return true if input is String, StringBuilder or StringBuffer class, start is 0 and count is length of input sequence */ public static boolean canUseOriginalForSubSequence(CharSequence str, int start, int count) { - if (start != 0) return false; + if (start != 0) { + return false; + } final Class csqClass = str.getClass(); return (csqClass == String.class || csqClass == StringBuilder.class || csqClass == StringBuffer.class) && count == str.length(); } - + public static CharSequence createSingleCharSequence(int c) { return new SingleCharCharSequence(c); } - + public static CharSequence createSingleCharSequence(char ch) { return new SingleCharCharSequence(ch); } - + /** * Writes a CharSequence instance in the most optimal way to the target writer - * - * + * * @param target writer - * @param csq source CharSequence instance - * @param start start/offset index - * @param end end index + 1 + * @param csq source CharSequence instance + * @param start start/offset index + * @param end end index + 1 * @throws IOException */ public static void writeCharSequence(Writer target, CharSequence csq, int start, int end) throws IOException { final Class csqClass = csq.getClass(); if (csqClass == String.class) { - target.write((String)csq, start, end - start); - } - else if (csqClass == StringBuffer.class) { + target.write((String) csq, start, end - start); + } else if (csqClass == StringBuffer.class) { char[] buf = new char[end - start]; - ((StringBuffer)csq).getChars(start, end, buf, 0); + ((StringBuffer) csq).getChars(start, end, buf, 0); target.write(buf); - } - else if (csqClass == StringBuilder.class) { + } else if (csqClass == StringBuilder.class) { char[] buf = new char[end - start]; - ((StringBuilder)csq).getChars(start, end, buf, 0); + ((StringBuilder) csq).getChars(start, end, buf, 0); target.write(buf); - } - else if (csq instanceof CharArrayAccessible) { + } else if (csq instanceof CharArrayAccessible) { char[] buf = new char[end - start]; - ((CharArrayAccessible)csq).getChars(start, end, buf, 0); + ((CharArrayAccessible) csq).getChars(start, end, buf, 0); target.write(buf); - } - else { + } else { String str = csq.subSequence(start, end).toString(); target.write(str, 0, str.length()); } } - + public static void writeCharSequence(Writer target, CharSequence csq) throws IOException { writeCharSequence(target, csq, 0, csq.length()); } - + /** * Provides an optimized way to copy CharSequence content to target array. * Uses getChars method available on String, StringBuilder and StringBuffer classes. - * + *

    * Characters are copied from the source sequence csq into the * destination character array dst. The first character to * be copied is at index srcBegin; the last character to @@ -131,40 +128,36 @@ public static void writeCharSequence(Writer target, CharSequence csq) throws IOE * dstbegin + (srcEnd-srcBegin) - 1 * * - * @param csq the source CharSequence instance. - * @param srcBegin start copying at this offset. - * @param srcEnd stop copying at this offset. - * @param dst the array to copy the data into. - * @param dstBegin offset into dst. - * @throws NullPointerException if dst is - * null. - * @throws IndexOutOfBoundsException if any of the following is true: - *

      - *
    • srcBegin is negative - *
    • dstBegin is negative - *
    • the srcBegin argument is greater than - * the srcEnd argument. - *
    • srcEnd is greater than - * this.length(). - *
    • dstBegin+srcEnd-srcBegin is greater than - * dst.length - *
    - */ - public static void getChars(CharSequence csq, int srcBegin, int srcEnd, char dst[], int dstBegin) { + * @param csq the source CharSequence instance. + * @param srcBegin start copying at this offset. + * @param srcEnd stop copying at this offset. + * @param dst the array to copy the data into. + * @param dstBegin offset into dst. + * @throws NullPointerException if dst is + * null. + * @throws IndexOutOfBoundsException if any of the following is true: + *
      + *
    • srcBegin is negative + *
    • dstBegin is negative + *
    • the srcBegin argument is greater than + * the srcEnd argument. + *
    • srcEnd is greater than + * this.length(). + *
    • dstBegin+srcEnd-srcBegin is greater than + * dst.length + *
    + */ + public static void getChars(CharSequence csq, int srcBegin, int srcEnd, char[] dst, int dstBegin) { final Class csqClass = csq.getClass(); if (csqClass == String.class) { - ((String)csq).getChars(srcBegin, srcEnd, dst, dstBegin); - } - else if (csqClass == StringBuffer.class) { - ((StringBuffer)csq).getChars(srcBegin, srcEnd, dst, dstBegin); - } - else if (csqClass == StringBuilder.class) { - ((StringBuilder)csq).getChars(srcBegin, srcEnd, dst, dstBegin); - } - else if (csq instanceof CharArrayAccessible) { - ((CharArrayAccessible)csq).getChars(srcBegin, srcEnd, dst, dstBegin); - } - else { + ((String) csq).getChars(srcBegin, srcEnd, dst, dstBegin); + } else if (csqClass == StringBuffer.class) { + ((StringBuffer) csq).getChars(srcBegin, srcEnd, dst, dstBegin); + } else if (csqClass == StringBuilder.class) { + ((StringBuilder) csq).getChars(srcBegin, srcEnd, dst, dstBegin); + } else if (csq instanceof CharArrayAccessible) { + ((CharArrayAccessible) csq).getChars(srcBegin, srcEnd, dst, dstBegin); + } else { String str = csq.subSequence(srcBegin, srcEnd).toString(); str.getChars(0, str.length(), dst, dstBegin); } diff --git a/grails-encoder/src/main/groovy/org/grails/charsequences/SingleCharCharSequence.java b/grails-encoder/src/main/groovy/org/grails/charsequences/SingleCharCharSequence.java index aec66a3ed1f..6a4c310110f 100644 --- a/grails-encoder/src/main/groovy/org/grails/charsequences/SingleCharCharSequence.java +++ b/grails-encoder/src/main/groovy/org/grails/charsequences/SingleCharCharSequence.java @@ -20,26 +20,27 @@ /** * Wraps a single char and implements CharSequence interface - * - * + * * @author Lari Hotari * @since 2.3.10 * */ class SingleCharCharSequence implements CharSequence, CharArrayAccessible { + private final char ch; SingleCharCharSequence(int c) { - this((char)c); + this((char) c); } - + SingleCharCharSequence(char ch) { this.ch = ch; } public char charAt(int index) { - if ((index < 0) || (index > 0)) + if ((index < 0) || (index > 0)) { throw new StringIndexOutOfBoundsException(index); + } return ch; } @@ -48,12 +49,15 @@ public int length() { } public CharSequence subSequence(int start, int end) { - if (start < 0) + if (start < 0) { throw new StringIndexOutOfBoundsException(start); - if (end > 1) + } + if (end > 1) { throw new StringIndexOutOfBoundsException(end); - if (start > end) + } + if (start > end) { throw new StringIndexOutOfBoundsException(end - start); + } return this; } @@ -63,12 +67,15 @@ public String toString() { } public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { - if (srcBegin < 0) + if (srcBegin < 0) { throw new StringIndexOutOfBoundsException(srcBegin); - if ((srcEnd < 0) || (srcEnd > 1)) + } + if ((srcEnd < 0) || (srcEnd > 1)) { throw new StringIndexOutOfBoundsException(srcEnd); - if (srcBegin > srcEnd) + } + if (srcBegin > srcEnd) { throw new StringIndexOutOfBoundsException("srcBegin > srcEnd"); + } dst[dstBegin] = ch; } -} \ No newline at end of file +} diff --git a/grails-encoder/src/main/groovy/org/grails/charsequences/SubCharSequence.java b/grails-encoder/src/main/groovy/org/grails/charsequences/SubCharSequence.java index f148e35723e..63c2204f2e2 100644 --- a/grails-encoder/src/main/groovy/org/grails/charsequences/SubCharSequence.java +++ b/grails-encoder/src/main/groovy/org/grails/charsequences/SubCharSequence.java @@ -20,28 +20,30 @@ /** * Wraps a part of a String and implements the CharSequence interface - * - * + * * @author Lari Hotari * @since 2.3.10 * */ class SubCharSequence implements CharSequence, CharArrayAccessible { + private final CharSequence str; private final int count; private final int start; SubCharSequence(CharSequence str, int start, int count) { - if (start + count > str.length()) + if (start + count > str.length()) { throw new StringIndexOutOfBoundsException(start); + } this.str = str; this.start = start; this.count = count; } public char charAt(int index) { - if ((index < 0) || (index + start >= str.length())) + if ((index < 0) || (index + start >= str.length())) { throw new StringIndexOutOfBoundsException(index); + } return str.charAt(index + start); } @@ -50,12 +52,15 @@ public int length() { } public CharSequence subSequence(int start, int end) { - if (start < 0) + if (start < 0) { throw new StringIndexOutOfBoundsException(start); - if (end > count) + } + if (end > count) { throw new StringIndexOutOfBoundsException(end); - if (start > end) + } + if (start > end) { throw new StringIndexOutOfBoundsException(end - start); + } if (start == 0 && end == count) { return this; } @@ -68,12 +73,15 @@ public String toString() { } public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { - if (srcBegin < 0) + if (srcBegin < 0) { throw new StringIndexOutOfBoundsException(srcBegin); - if ((srcEnd < 0) || (srcEnd > start+count)) + } + if ((srcEnd < 0) || (srcEnd > start + count)) { throw new StringIndexOutOfBoundsException(srcEnd); - if (srcBegin > srcEnd) + } + if (srcBegin > srcEnd) { throw new StringIndexOutOfBoundsException("srcBegin > srcEnd"); + } CharSequences.getChars(str, start + srcBegin, start + srcEnd, dst, dstBegin); } -} \ No newline at end of file +} diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/AbstractCharReplacementEncoder.java b/grails-encoder/src/main/groovy/org/grails/encoder/AbstractCharReplacementEncoder.java index aba3b69e307..08b2629c3b5 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/AbstractCharReplacementEncoder.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/AbstractCharReplacementEncoder.java @@ -18,19 +18,12 @@ */ package org.grails.encoder; +import org.grails.charsequences.CharSequences; + import java.io.IOException; import java.io.Writer; import java.util.List; -import org.grails.charsequences.CharSequences; -import org.grails.encoder.CodecIdentifier; -import org.grails.encoder.EncodedAppender; -import org.grails.encoder.Encoder; -import org.grails.encoder.EncodesToWriter; -import org.grails.encoder.EncodesToWriterAdapter; -import org.grails.encoder.EncodingState; -import org.grails.encoder.StreamingEncoder; - /** * Abstract base class for implementing encoders that do character replacements * Implements the {@link StreamingEncoder} interface that enables efficient @@ -40,6 +33,7 @@ * @since 2.3 */ public abstract class AbstractCharReplacementEncoder implements Encoder, StreamingEncoder, EncodesToWriter { + protected CodecIdentifier codecIdentifier; public AbstractCharReplacementEncoder(CodecIdentifier codecIdentifier) { @@ -49,8 +43,8 @@ public AbstractCharReplacementEncoder(CodecIdentifier codecIdentifier) { /** * Escape the character, return null if no replacement has to be made * - * @param ch the character to escape - * @param previousChar the previous char + * @param ch the character to escape + * @param previousChar the previous char * @return the replacement string, null if no replacement has to be made */ protected abstract String escapeCharacter(char ch, char previousChar); @@ -69,18 +63,15 @@ protected final Object doCharReplacementEncoding(Object o) { CharSequence str = null; if (o instanceof CharSequence) { - str = (CharSequence)o; - } - else if (o instanceof Character) { - String escaped = escapeCharacter((Character)o, (char)0); + str = (CharSequence) o; + } else if (o instanceof Character) { + String escaped = escapeCharacter((Character) o, (char) 0); if (escaped != null) { return escaped; - } - else { + } else { return o; } - } - else { + } else { str = convertToString(o); } @@ -99,7 +90,7 @@ protected Object escapeCharSequence(CharSequence str) { StringBuilder sb = null; int n = str.length(), i; int startPos = -1; - char prevChar = (char)0; + char prevChar = (char) 0; for (i = 0; i < n; i++) { char ch = str.charAt(i); if (startPos == -1) { @@ -125,12 +116,11 @@ protected Object escapeCharSequence(CharSequence str) { sb.append(str, startPos, i); } return sb.toString(); - } - else { + } else { return str; } } - + @Override public void encodeToWriter(CharSequence str, int off, int len, Writer writer, EncodingState encodingState) throws IOException { if (str == null || len <= 0) { @@ -139,7 +129,7 @@ public void encodeToWriter(CharSequence str, int off, int len, Writer writer, En int n = Math.min(str.length(), off + len); int i; int startPos = -1; - char prevChar = (char)0; + char prevChar = (char) 0; for (i = off; i < n; i++) { char ch = str.charAt(i); if (startPos == -1) { @@ -161,7 +151,7 @@ public void encodeToWriter(CharSequence str, int off, int len, Writer writer, En CharSequences.writeCharSequence(writer, str, startPos, i); } } - + @Override public void encodeToWriter(char[] buf, int off, int len, Writer writer, EncodingState encodingState) throws IOException { if (buf == null || len <= 0) { @@ -170,7 +160,7 @@ public void encodeToWriter(char[] buf, int off, int len, Writer writer, Encoding int n = Math.min(buf.length, off + len); int i; int startPos = -1; - char prevChar = (char)0; + char prevChar = (char) 0; for (i = off; i < n; i++) { char ch = buf[i]; if (startPos == -1) { @@ -192,7 +182,7 @@ public void encodeToWriter(char[] buf, int off, int len, Writer writer, Encoding writer.write(buf, startPos, i - startPos); } } - + @Override public EncodesToWriter createChainingEncodesToWriter(List encoders, boolean applyAdditionalFirst) { return EncodesToWriterAdapter.createChainingEncodesToWriter(this, encoders, applyAdditionalFirst); @@ -209,7 +199,7 @@ public void encodeToStream(Encoder thisInstance, CharSequence str, int off, int int n = Math.min(str.length(), off + len); int i; int startPos = -1; - char prevChar = (char)0; + char prevChar = (char) 0; for (i = off; i < n; i++) { char ch = str.charAt(i); if (startPos == -1) { diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/AbstractEncodedAppender.java b/grails-encoder/src/main/groovy/org/grails/encoder/AbstractEncodedAppender.java index a97a76043a5..14491efa8c8 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/AbstractEncodedAppender.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/AbstractEncodedAppender.java @@ -29,22 +29,18 @@ * @since 2.3 */ public abstract class AbstractEncodedAppender implements EncodedAppender { + private boolean ignoreEncodingState; - + /** * Append a portion of a char array to the buffer and attach the * encodingState information to it * - * @param encodingState - * the new encoding state of the char array - * @param b - * a char array - * @param off - * Offset from which to start encoding characters - * @param len - * Number of characters to encode - * @throws IOException - * Signals that an I/O exception has occurred. + * @param encodingState the new encoding state of the char array + * @param b a char array + * @param off Offset from which to start encoding characters + * @param len Number of characters to encode + * @throws IOException Signals that an I/O exception has occurred. */ protected abstract void write(EncodingState encodingState, char[] b, int off, int len) throws IOException; @@ -52,16 +48,11 @@ public abstract class AbstractEncodedAppender implements EncodedAppender { * Append a portion of a string to the buffer and attach the encodingState * information to it * - * @param encodingState - * the new encoding state of the string - * @param str - * A String - * @param off - * Offset from which to start encoding characters - * @param len - * Number of characters to encode - * @throws IOException - * Signals that an I/O exception has occurred. + * @param encodingState the new encoding state of the string + * @param str A String + * @param off Offset from which to start encoding characters + * @param len Number of characters to encode + * @throws IOException Signals that an I/O exception has occurred. */ protected abstract void write(EncodingState encodingState, String str, int off, int len) throws IOException; @@ -69,16 +60,11 @@ public abstract class AbstractEncodedAppender implements EncodedAppender { * Append a portion of a CharSequence to the buffer and attach the * encodingState information to it * - * @param encodingState - * the new encoding state of the CharSequence portion - * @param str - * a CharSequence - * @param start - * the start index, inclusive - * @param end - * the end index, exclusive - * @throws IOException - * Signals that an I/O exception has occurred. + * @param encodingState the new encoding state of the CharSequence portion + * @param str a CharSequence + * @param start the start index, inclusive + * @param end the end index, exclusive + * @throws IOException Signals that an I/O exception has occurred. */ protected abstract void appendCharSequence(EncodingState encodingState, CharSequence str, int start, int end) throws IOException; @@ -98,14 +84,12 @@ public void append(Encoder encoder, EncodingState encodingState, char[] b, int o if (shouldEncode(encoder, encodingState)) { EncodingState newEncoders = createNewEncodingState(encoder, encodingState); if (encoder instanceof StreamingEncoder) { - ((StreamingEncoder)encoder).encodeToStream(encoder, CharSequences.createCharSequence(b, off, len), 0, len, this, + ((StreamingEncoder) encoder).encodeToStream(encoder, CharSequences.createCharSequence(b, off, len), 0, len, this, newEncoders); - } - else { + } else { encodeAndWrite(encoder, newEncoders, String.valueOf(b, off, len)); } - } - else { + } else { write(encodingState, b, off, len); } } @@ -133,20 +117,17 @@ public void append(Encoder encoder, EncodingState encodingState, CharSequence st if (shouldEncode(encoder, encodingState)) { EncodingState newEncoders = createNewEncodingState(encoder, encodingState); if (encoder instanceof StreamingEncoder) { - ((StreamingEncoder)encoder).encodeToStream(encoder, str, off, len, this, newEncoders); - } - else { + ((StreamingEncoder) encoder).encodeToStream(encoder, str, off, len, this, newEncoders); + } else { CharSequence source; if (CharSequences.canUseOriginalForSubSequence(str, off, len)) { source = str; - } - else { + } else { source = str.subSequence(off, off + len); } encodeAndWrite(encoder, newEncoders, source); } - } - else { + } else { appendCharSequence(encodingState, str, off, off + len); } } @@ -164,10 +145,8 @@ public void appendEncoded(Encoder encoder, EncodingState encodingState, CharSequ /** * Check if the encoder should be used to a input with certain encodingState * - * @param encoderToApply - * the encoder to apply - * @param encodingState - * the current encoding state + * @param encoderToApply the encoder to apply + * @param encodingState the current encoding state * @return true, if should encode */ public boolean shouldEncode(Encoder encoderToApply, EncodingState encodingState) { @@ -183,14 +162,10 @@ protected boolean shouldEncodeWith(Encoder encoderToApply, EncodingState encodin /** * Encode and write input to buffer using a non-streaming encoder * - * @param encoder - * the encoder to use - * @param newEncodingState - * the new encoding state after encoder has been applied - * @param input - * the input CharSequence - * @throws IOException - * Signals that an I/O exception has occurred. + * @param encoder the encoder to use + * @param newEncodingState the new encoding state after encoder has been applied + * @param input the input CharSequence + * @throws IOException Signals that an I/O exception has occurred. */ protected void encodeAndWrite(Encoder encoder, EncodingState newEncodingState, CharSequence input) throws IOException { diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/ChainedDecoder.java b/grails-encoder/src/main/groovy/org/grails/encoder/ChainedDecoder.java index 434729bb608..5e6e7431560 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/ChainedDecoder.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/ChainedDecoder.java @@ -19,9 +19,10 @@ package org.grails.encoder; public class ChainedDecoder implements Decoder { + protected Decoder[] decoders; protected CodecIdentifier codecIdentifier; - + public ChainedDecoder(Decoder[] decoders) { this.decoders = decoders; this.codecIdentifier = createCodecIdentifier(decoders); @@ -38,7 +39,9 @@ public CodecIdentifier getCodecIdentifier() { @Override public Object decode(Object o) { - if(o==null) return o; + if (o == null) { + return o; + } Object decoded = o; for (Decoder decoder : decoders) { decoded = decoder.decode(decoded); diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/ChainedEncoder.java b/grails-encoder/src/main/groovy/org/grails/encoder/ChainedEncoder.java index fb5134394aa..99850a71f98 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/ChainedEncoder.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/ChainedEncoder.java @@ -23,64 +23,48 @@ import java.util.List; public class ChainedEncoder implements Encoder, StreamingEncoder { + private final StreamingEncoder[] encoders; private final CodecIdentifier combinedCodecIdentifier; private final boolean safe; // this ThreadLocal lives as long as the instance of this ChainedEncoder class, this isn't a static ThreadLocal private final ThreadLocal cacheItemThreadLocal = new ThreadLocal() { - protected ChainedEncoderCacheItem initialValue() { - return new ChainedEncoderCacheItem(); - }; - }; - - private static class ChainedEncoderCacheItem { - EncodedAppender lastAppenderForCached; - boolean lastIgnoreEncodingStateForCached; - EncodedAppender cachedChainedAppender; - - void putInCache(final EncodedAppender appender, EncodedAppender target) { - lastAppenderForCached = appender; - lastIgnoreEncodingStateForCached = appender.isIgnoreEncodingState(); - cachedChainedAppender = target; - } - - EncodedAppender getCached(final EncodedAppender appender) { - if(lastAppenderForCached == appender && lastIgnoreEncodingStateForCached == appender.isIgnoreEncodingState()) { - return cachedChainedAppender; - } - return null; + protected ChainedEncoderCacheItem initialValue() { + return new ChainedEncoderCacheItem(); } - } - + + ; + }; + public ChainedEncoder(List encoders, boolean safe) { this(encoders.toArray(new StreamingEncoder[encoders.size()]), safe); } - + public ChainedEncoder(StreamingEncoder[] encoders, boolean safe) { this.encoders = Arrays.copyOf(encoders, encoders.length); this.combinedCodecIdentifier = createCodecIdentifier(encoders); this.safe = safe; } - + public static StreamingEncoder createFor(StreamingEncoder[] encoders) { return createFor(Arrays.asList(encoders)); } - + public static StreamingEncoder createFor(List encoders) { return createFor(encoders, null); } - + public static StreamingEncoder createFor(List encoders, Boolean safe) { - if(encoders==null) { + if (encoders == null) { return null; - } else if(encoders.size()==0) { + } else if (encoders.size() == 0) { return DefaultEncodingStateRegistry.NONE_ENCODER; - } else if(encoders.size()==1) { + } else if (encoders.size() == 1) { return encoders.get(0); } else { - if(safe == null) { - for(StreamingEncoder encoder : encoders) { - if(encoder.isSafe()) { + if (safe == null) { + for (StreamingEncoder encoder : encoders) { + if (encoder.isSafe()) { safe = true; break; } @@ -93,7 +77,7 @@ public static StreamingEncoder createFor(List encoders, Boolea protected CombinedCodecIdentifier createCodecIdentifier(StreamingEncoder[] encoders) { return new CombinedCodecIdentifier(encoders); } - + @Override public CodecIdentifier getCodecIdentifier() { return combinedCodecIdentifier; @@ -101,10 +85,10 @@ public CodecIdentifier getCodecIdentifier() { @Override public void encodeToStream(Encoder thisInstance, CharSequence source, int offset, int len, - EncodedAppender appender, EncodingState encodingState) throws IOException { + EncodedAppender appender, EncodingState encodingState) throws IOException { EncodedAppender target = chainEncodersAndCachePerThread(appender); - StreamingEncoder encoder=encoders[0]; - if(appender.shouldEncode(encoder, encodingState.getPreviousEncodingState())) { + StreamingEncoder encoder = encoders[0]; + if (appender.shouldEncode(encoder, encodingState.getPreviousEncodingState())) { encoder.encodeToStream(encoder, source, offset, len, target, encodingState.getPreviousEncodingState()); } else { target.appendEncoded(encoder, encodingState.getPreviousEncodingState(), source, offset, len); @@ -113,9 +97,9 @@ public void encodeToStream(Encoder thisInstance, CharSequence source, int offset protected EncodedAppender chainEncodersAndCachePerThread(final EncodedAppender appender) { ChainedEncoderCacheItem cacheItem = cacheItemThreadLocal.get(); - + EncodedAppender target = cacheItem.getCached(appender); - if(target == null) { + if (target == null) { target = doChainEncoders(appender); cacheItem.putInCache(appender, target); } @@ -123,10 +107,10 @@ protected EncodedAppender chainEncodersAndCachePerThread(final EncodedAppender a } protected EncodedAppender doChainEncoders(final EncodedAppender appender) { - EncodedAppender target=appender; - for(int i=encoders.length-1;i >= 1;i--) { - StreamingEncoder encoder=encoders[i]; - target=new StreamingEncoderEncodedAppender(encoder, target); + EncodedAppender target = appender; + for (int i = encoders.length - 1; i >= 1; i--) { + StreamingEncoder encoder = encoders[i]; + target = new StreamingEncoderEncodedAppender(encoder, target); target.setIgnoreEncodingState(appender.isIgnoreEncodingState()); } return target; @@ -134,7 +118,9 @@ protected EncodedAppender doChainEncoders(final EncodedAppender appender) { @Override public Object encode(Object o) { - if(o==null) return o; + if (o == null) { + return o; + } Object encoded = o; for (StreamingEncoder encoder : encoders) { encoded = encoder.encode(encoded); @@ -154,6 +140,27 @@ public boolean isApplyToSafelyEncoded() { @Override public void markEncoded(CharSequence string) { - + + } + + + private static class ChainedEncoderCacheItem { + + EncodedAppender lastAppenderForCached; + boolean lastIgnoreEncodingStateForCached; + EncodedAppender cachedChainedAppender; + + void putInCache(final EncodedAppender appender, EncodedAppender target) { + lastAppenderForCached = appender; + lastIgnoreEncodingStateForCached = appender.isIgnoreEncodingState(); + cachedChainedAppender = target; + } + + EncodedAppender getCached(final EncodedAppender appender) { + if (lastAppenderForCached == appender && lastIgnoreEncodingStateForCached == appender.isIgnoreEncodingState()) { + return cachedChainedAppender; + } + return null; + } } } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/ChainedEncoders.java b/grails-encoder/src/main/groovy/org/grails/encoder/ChainedEncoders.java index 18fb11870a9..e7f31af3ba5 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/ChainedEncoders.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/ChainedEncoders.java @@ -18,29 +18,29 @@ */ package org.grails.encoder; +import org.grails.buffer.StreamCharBuffer; + import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.grails.buffer.StreamCharBuffer; - -public class ChainedEncoders { +public final class ChainedEncoders { private ChainedEncoders() { } public static List toStreamingEncoders(List encoders) { - if(encoders == null || encoders.isEmpty()) { + if (encoders == null || encoders.isEmpty()) { return null; } List streamingEncoders = new ArrayList(); - for(Encoder encoder : encoders) { - if(!(encoder instanceof StreamingEncoder)) { + for (Encoder encoder : encoders) { + if (!(encoder instanceof StreamingEncoder)) { return null; } - StreamingEncoder streamingEncoder = (StreamingEncoder)encoder; - if(shouldApplyEncoder(streamingEncoder)) { + StreamingEncoder streamingEncoder = (StreamingEncoder) encoder; + if (shouldApplyEncoder(streamingEncoder)) { streamingEncoders.add(streamingEncoder); } } @@ -49,7 +49,7 @@ public static List toStreamingEncoders(List encoders) public static void chainEncode(StreamEncodeable streamEncodeable, EncodedAppender appender, List encoders) throws IOException { List streamingEncoders = toStreamingEncoders(encoders); - if(streamingEncoders != null) { + if (streamingEncoders != null) { chainStreamingEncode(streamEncodeable, appender, streamingEncoders); } else { chainMixedEncode(streamEncodeable, appender, encoders); @@ -57,32 +57,32 @@ public static void chainEncode(StreamEncodeable streamEncodeable, EncodedAppende } private static void chainMixedEncode(StreamEncodeable streamEncodeable, EncodedAppender appender, - List encoders) throws IOException { - if(encoders==null || encoders.isEmpty()) { + List encoders) throws IOException { + if (encoders == null || encoders.isEmpty()) { streamEncodeable.encodeTo(appender, null); - } else { + } else { StreamEncodeable lastStreamEncodeable = streamEncodeable; - if(encoders.size() > 1) { + if (encoders.size() > 1) { StreamCharBuffer buffer; - if(streamEncodeable instanceof StreamCharBuffer) { - buffer = (StreamCharBuffer)streamEncodeable; + if (streamEncodeable instanceof StreamCharBuffer) { + buffer = (StreamCharBuffer) streamEncodeable; } else { buffer = new StreamCharBuffer(); - streamEncodeable.encodeTo(((StreamCharBuffer.StreamCharBufferWriter)buffer.getWriter()).getEncodedAppender(), null); + streamEncodeable.encodeTo(((StreamCharBuffer.StreamCharBufferWriter) buffer.getWriter()).getEncodedAppender(), null); } - for(int i=0;i < encoders.size()-1;i++) { + for (int i = 0; i < encoders.size() - 1; i++) { buffer = buffer.encodeToBuffer(encoders.get(i)); } lastStreamEncodeable = buffer; } - lastStreamEncodeable.encodeTo(appender, encoders.get(encoders.size()-1)); + lastStreamEncodeable.encodeTo(appender, encoders.get(encoders.size() - 1)); } } public static void chainStreamingEncode(StreamEncodeable streamEncodeable, EncodedAppender appender, List encoders) throws IOException { EncodedAppender target; Encoder lastEncoder; - if(encoders != null && encoders.size() > 0) { + if (encoders != null && encoders.size() > 0) { target = chainAllButLastEncoders(appender, encoders); lastEncoder = encoders.get(0); } else { @@ -93,28 +93,28 @@ public static void chainStreamingEncode(StreamEncodeable streamEncodeable, Encod } public static EncodedAppender chainAllButLastEncoders(EncodedAppender appender, List encoders) { - EncodedAppender target=appender; - for(int i=encoders.size()-1;i >= 1;i--) { - StreamingEncoder encoder=encoders.get(i); - target=new StreamingEncoderEncodedAppender(encoder, target); + EncodedAppender target = appender; + for (int i = encoders.size() - 1; i >= 1; i--) { + StreamingEncoder encoder = encoders.get(i); + target = new StreamingEncoderEncodedAppender(encoder, target); } return target; } public static EncodedAppender chainAllEncoders(EncodedAppender appender, List encoders) { - EncodedAppender target=appender; - for(int i=encoders.size()-1;i >= 0;i--) { - StreamingEncoder encoder=encoders.get(i); - target=new StreamingEncoderEncodedAppender(encoder, target); + EncodedAppender target = appender; + for (int i = encoders.size() - 1; i >= 0; i--) { + StreamingEncoder encoder = encoders.get(i); + target = new StreamingEncoderEncodedAppender(encoder, target); } return target; } public static List appendEncoder(List encoders, Encoder encodeToEncoder) { List nextEncoders; - if(encodeToEncoder != null) { - if(encoders != null) { - List joined = new ArrayList(encoders.size()+1); + if (encodeToEncoder != null) { + if (encoders != null) { + List joined = new ArrayList(encoders.size() + 1); joined.addAll(encoders); joined.add(encodeToEncoder); nextEncoders = Collections.unmodifiableList(joined); @@ -129,7 +129,7 @@ public static List appendEncoder(List encoders, Encoder encode /** * checks that the encoder isn't a NoneEncoder instance - * + * * @param encoder * @return */ diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/CodecIdentifier.java b/grails-encoder/src/main/groovy/org/grails/encoder/CodecIdentifier.java index 1e846e52e3d..6d738bb398b 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/CodecIdentifier.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/CodecIdentifier.java @@ -46,8 +46,7 @@ public interface CodecIdentifier { /** * Checks if this codec is equivalent to some other codec * - * @param other - * the CodecIdentifier of the other codec + * @param other the CodecIdentifier of the other codec * @return true, if is equivalent */ boolean isEquivalent(CodecIdentifier other); diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/CodecLookup.java b/grails-encoder/src/main/groovy/org/grails/encoder/CodecLookup.java index 05836fe86c6..e232aa0f4f9 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/CodecLookup.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/CodecLookup.java @@ -19,6 +19,8 @@ package org.grails.encoder; public interface CodecLookup { - public Encoder lookupEncoder(String codecName); - public Decoder lookupDecoder(String codecName); + + Encoder lookupEncoder(String codecName); + + Decoder lookupDecoder(String codecName); } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/CodecLookupHelper.java b/grails-encoder/src/main/groovy/org/grails/encoder/CodecLookupHelper.java index eae2f6d0e70..41bd1b0b7af 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/CodecLookupHelper.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/CodecLookupHelper.java @@ -24,8 +24,9 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; -public class CodecLookupHelper { - private static final Logger log = LoggerFactory.getLogger(CodecLookupHelper.class); +public final class CodecLookupHelper { + + private static final Logger LOG = LoggerFactory.getLogger(CodecLookupHelper.class); private CodecLookupHelper() { } @@ -34,18 +35,18 @@ private CodecLookupHelper() { * Lookup encoder. * * @param grailsApplication the grailsApplication instance - * @param codecName the codec name + * @param codecName the codec name * @return the encoder instance */ public static Encoder lookupEncoder(GrailsApplication grailsApplication, String codecName) { ApplicationContext ctx = grailsApplication != null ? grailsApplication.getMainContext() : null; - if(ctx != null) { + if (ctx != null) { try { CodecLookup codecLookup = ctx.getBean("codecLookup", CodecLookup.class); return codecLookup.lookupEncoder(codecName); } catch (NoSuchBeanDefinitionException e) { // ignore missing codecLookup bean in tests - log.debug("codecLookup bean is missing from test context.", e); + LOG.debug("codecLookup bean is missing from test context.", e); } } return null; diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/CodecMetaClassSupport.groovy b/grails-encoder/src/main/groovy/org/grails/encoder/CodecMetaClassSupport.groovy index e3f7429691d..5e1425a2441 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/CodecMetaClassSupport.groovy +++ b/grails-encoder/src/main/groovy/org/grails/encoder/CodecMetaClassSupport.groovy @@ -19,9 +19,8 @@ package org.grails.encoder import grails.util.Environment -import groovy.transform.CompileStatic - import grails.util.GrailsMetaClassUtils +import groovy.transform.CompileStatic import org.codehaus.groovy.runtime.GStringImpl import org.codehaus.groovy.runtime.NullObject import org.springframework.util.Assert @@ -33,10 +32,11 @@ import org.springframework.util.Assert * @since 2.3 */ class CodecMetaClassSupport { + static final Object[] EMPTY_ARGS = [] - static final String ENCODE_AS_PREFIX="encodeAs" - static final String DECODE_PREFIX="decode" - + static final String ENCODE_AS_PREFIX = "encodeAs" + static final String DECODE_PREFIX = "decode" + /** * Adds "encodeAs*" and "decode*" metamethods for given codecClass * @@ -49,7 +49,7 @@ class CodecMetaClassSupport { String codecName = resolveCodecName(codecFactory) Assert.hasText(codecName, "No resolvable codec name") - + String encodeMethodName = encodeMethodNameClosure(codecName) String decodeMethodName = decodeMethodNameClosure(codecName) @@ -82,42 +82,45 @@ class CodecMetaClassSupport { // do what we want here... throw new MissingMethodException(decodeMethodName, delegate.getClass(), EMPTY_ARGS) } - } - else { + } else { // Resolve codec methods once only at startup def encoder = codecFactory.getEncoder() if (encoder) { encoderClosure = { -> encoder.encode(CodecMetaClassSupport.filterNullObject(delegate)) } } else { - encoderClosure = { -> throw new MissingMethodException(encodeMethodName, delegate.getClass(), EMPTY_ARGS) } + encoderClosure = { -> + throw new MissingMethodException(encodeMethodName, delegate.getClass(), EMPTY_ARGS) + } } def decoder = codecFactory.getDecoder() if (decoder) { decoderClosure = { -> decoder.decode(CodecMetaClassSupport.filterNullObject(delegate)) } } else { - decoderClosure = { -> throw new MissingMethodException(decodeMethodName, delegate.getClass(), EMPTY_ARGS) } + decoderClosure = { -> + throw new MissingMethodException(decodeMethodName, delegate.getClass(), EMPTY_ARGS) + } } } addMetaMethod(targetMetaClasses, encodeMethodName, encoderClosure) - if(codecFactory.encoder) { + if (codecFactory.encoder) { addAliasMetaMethods(targetMetaClasses, codecFactory.encoder.codecIdentifier.codecAliases, encodeMethodNameClosure, encoderClosure) } addMetaMethod(targetMetaClasses, decodeMethodName, decoderClosure) - if(codecFactory.decoder) { + if (codecFactory.decoder) { addAliasMetaMethods(targetMetaClasses, codecFactory.decoder.codecIdentifier.codecAliases, decodeMethodNameClosure, decoderClosure) } } /** * returns given parameter if it's not a Groovy NullObject (and is not null) - * + * * The check is made by looking at the Object's class, since NullObject.is & equals give wrong results (Groovy bug?). - * + * * A NullObject get's passed to the closure in delegate perhaps because of a Groovy bug or feature * This happens when a NullObject's MetaMethod is called. - * + * * @param delegate * @return */ @@ -132,26 +135,26 @@ class CodecMetaClassSupport { addMetaMethod(targetMetaClasses, methodNameClosure(aliasName), methodClosure) } } - + private String resolveCodecName(CodecFactory codecFactory) { codecFactory.encoder?.codecIdentifier?.codecName ?: codecFactory.decoder?.codecIdentifier?.codecName } private static List resolveDefaultMetaClasses() { [ - String, - GStringImpl, - StringBuffer, - StringBuilder, - Object + String, + GStringImpl, + StringBuffer, + StringBuilder, + Object ].collect { Class clazz -> GrailsMetaClassUtils.getExpandoMetaClass(clazz) } } - + protected void addMetaMethod(List targetMetaClasses, String methodName, Closure closure) { - targetMetaClasses.each { ExpandoMetaClass emc -> - emc."${methodName}" << closure + targetMetaClasses.each { ExpandoMetaClass emc -> + emc."${methodName}" << closure } } } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/CombinedCodecIdentifier.java b/grails-encoder/src/main/groovy/org/grails/encoder/CombinedCodecIdentifier.java index 77256fa52d8..7bd5191515e 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/CombinedCodecIdentifier.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/CombinedCodecIdentifier.java @@ -18,26 +18,27 @@ */ package org.grails.encoder; +import org.springframework.util.StringUtils; + import java.util.Arrays; import java.util.Collections; import java.util.Set; -import org.springframework.util.StringUtils; - public class CombinedCodecIdentifier implements CodecIdentifier { + private CodecIdentifier[] codecIdentifiers; private String codecName; private String codecAlias; - + CombinedCodecIdentifier(CodecIdentifierProvider[] encodersOrDecoders) { this(encodersOrDecoders, false); } - + CombinedCodecIdentifier(CodecIdentifierProvider[] encodersOrDecoders, boolean reverseOrder) { int size = encodersOrDecoders.length; codecIdentifiers = new CodecIdentifier[size]; String[] encoderNamesArr = new String[size]; - for(int i=0;i < size;i++) { + for (int i = 0; i < size; i++) { int targetIndex = reverseOrder ? (size - 1 - i) : i; codecIdentifiers[targetIndex] = encodersOrDecoders[i].getCodecIdentifier(); encoderNamesArr[targetIndex] = codecIdentifiers[targetIndex].getCodecName(); @@ -58,11 +59,11 @@ public Set getCodecAliases() { @Override public boolean isEquivalent(CodecIdentifier other) { - for(CodecIdentifier codecIdentifier : codecIdentifiers) { - if(codecIdentifier.isEquivalent(other)) { + for (CodecIdentifier codecIdentifier : codecIdentifiers) { + if (codecIdentifier.isEquivalent(other)) { return true; } } return false; } -} \ No newline at end of file +} diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/Decoder.java b/grails-encoder/src/main/groovy/org/grails/encoder/Decoder.java index 3e3e1f11466..cf09700bfd3 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/Decoder.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/Decoder.java @@ -29,8 +29,7 @@ public interface Decoder extends CodecIdentifierProvider { /** * Decode given input object * - * @param o - * the input object + * @param o the input object * @return the decoded object */ Object decode(Object o); diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/DefaultCodecIdentifier.java b/grails-encoder/src/main/groovy/org/grails/encoder/DefaultCodecIdentifier.java index 539182e0734..1ff8f3c9716 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/DefaultCodecIdentifier.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/DefaultCodecIdentifier.java @@ -30,11 +30,12 @@ * @since 2.3 */ public class DefaultCodecIdentifier implements CodecIdentifier { - final private String codecName; - final private Set codecAliases; + + private final String codecName; + private final Set codecAliases; public DefaultCodecIdentifier(String codecName) { - this(codecName, (Set)null); + this(codecName, (Set) null); } public DefaultCodecIdentifier(String codecName, String... codecAliases) { @@ -77,25 +78,30 @@ public int hashCode() { */ @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; - DefaultCodecIdentifier other = (DefaultCodecIdentifier)obj; + } + DefaultCodecIdentifier other = (DefaultCodecIdentifier) obj; if (codecAliases == null) { - if (other.codecAliases != null) + if (other.codecAliases != null) { return false; - } - else if (!codecAliases.equals(other.codecAliases)) + } + } else if (!codecAliases.equals(other.codecAliases)) { return false; + } if (codecName == null) { - if (other.codecName != null) + if (other.codecName != null) { return false; - } - else if (!codecName.equals(other.codecName)) + } + } else if (!codecName.equals(other.codecName)) { return false; + } return true; } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/DefaultEncodingStateRegistry.java b/grails-encoder/src/main/groovy/org/grails/encoder/DefaultEncodingStateRegistry.java index a59ea5fa0ba..e11d642f5b1 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/DefaultEncodingStateRegistry.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/DefaultEncodingStateRegistry.java @@ -37,9 +37,10 @@ * @since 2.3 */ public final class DefaultEncodingStateRegistry implements EncodingStateRegistry { + + public static final StreamingEncoder NONE_ENCODER = BasicCodecLookup.NONE_ENCODER; private static final Logger LOG = LoggerFactory.getLogger(DefaultEncodingStateRegistry.class); private Map>> encodedCharSequencesForEncoder = new HashMap<>(); - public static final StreamingEncoder NONE_ENCODER = BasicCodecLookup.NONE_ENCODER; private long calculateKey(CharSequence charSequence) { int contentHashCode = charSequence.hashCode(); @@ -100,7 +101,9 @@ public void registerEncodedWith(Encoder encoder, CharSequence escaped) { * @see EncodingStateRegistry#shouldEncodeWith(Encoder, java.lang.CharSequence) */ public boolean shouldEncodeWith(Encoder encoderToApply, CharSequence string) { - if (isNoneEncoder(encoderToApply)) return false; + if (isNoneEncoder(encoderToApply)) { + return false; + } EncodingState encodingState = getEncodingStateFor(string); return shouldEncodeWith(encoderToApply, encodingState); } @@ -113,7 +116,9 @@ public boolean shouldEncodeWith(Encoder encoderToApply, CharSequence string) { * @return true, if should encode */ public static boolean shouldEncodeWith(Encoder encoderToApply, EncodingState currentEncodingState) { - if (isNoneEncoder(encoderToApply)) return false; + if (isNoneEncoder(encoderToApply)) { + return false; + } if (currentEncodingState != null && currentEncodingState.getEncoders() != null) { for (Encoder encoder : currentEncodingState.getEncoders()) { if (isPreviousEncoderSafeOrEqual(encoderToApply, encoder)) { diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/Encodeable.java b/grails-encoder/src/main/groovy/org/grails/encoder/Encodeable.java index 4c3b1d0f66e..89b0e8582a7 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/Encodeable.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/Encodeable.java @@ -29,8 +29,7 @@ public interface Encodeable { /** * Encode with given encoder. * - * @param encoder - * the encoder + * @param encoder the encoder * @return the encoded result */ CharSequence encode(Encoder encoder); diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/EncodedAppender.java b/grails-encoder/src/main/groovy/org/grails/encoder/EncodedAppender.java index 0553452c826..c65a25b33d3 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/EncodedAppender.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/EncodedAppender.java @@ -28,39 +28,28 @@ * @since 2.3 */ public interface EncodedAppender { + /** * Encodes a portion of a string and appends it to the buffer. * - * @param encoder - * the encoder to use - * @param encodingState - * the current encoding state of the string - * @param str - * A String - * @param off - * Offset from which to start encoding characters - * @param len - * Number of characters to encode - * @throws IOException - * Signals that an I/O exception has occurred. + * @param encoder the encoder to use + * @param encodingState the current encoding state of the string + * @param str A String + * @param off Offset from which to start encoding characters + * @param len Number of characters to encode + * @throws IOException Signals that an I/O exception has occurred. */ void append(Encoder encoder, EncodingState encodingState, CharSequence str, int off, int len) throws IOException; /** * Appends an encoded portion of a string to the buffer * - * @param encoder - * the encoder that has been applied - * @param encodingState - * the previous encoding state of the string - * @param str - * A String - * @param off - * Offset from which to start encoding characters - * @param len - * Number of characters to encode - * @throws IOException - * Signals that an I/O exception has occurred. + * @param encoder the encoder that has been applied + * @param encodingState the previous encoding state of the string + * @param str A String + * @param off Offset from which to start encoding characters + * @param len Number of characters to encode + * @throws IOException Signals that an I/O exception has occurred. */ void appendEncoded(Encoder encoder, EncodingState encodingState, CharSequence str, int off, int len) throws IOException; @@ -68,43 +57,31 @@ void appendEncoded(Encoder encoder, EncodingState encodingState, CharSequence st /** * Encodes a portion of a char array and appends it to the buffer. * - * @param encoder - * the encoder to use - * @param encodingState - * the current encoding state of the string - * @param b - * a char array - * @param off - * Offset from which to start encoding characters - * @param len - * Number of characters to encode - * @throws IOException - * Signals that an I/O exception has occurred. + * @param encoder the encoder to use + * @param encodingState the current encoding state of the string + * @param b a char array + * @param off Offset from which to start encoding characters + * @param len Number of characters to encode + * @throws IOException Signals that an I/O exception has occurred. */ void append(Encoder encoder, EncodingState encodingState, char[] b, int off, int len) throws IOException; /** * Appends an encoded portion of a char array to the buffer. * - * @param encoder - * the encoder that has been applied - * @param encodingState - * the previous encoding state of the char array - * @param b - * a char array - * @param off - * Offset from which to start encoding characters - * @param len - * Number of characters to encode - * @throws IOException - * Signals that an I/O exception has occurred. + * @param encoder the encoder that has been applied + * @param encodingState the previous encoding state of the char array + * @param b a char array + * @param off Offset from which to start encoding characters + * @param len Number of characters to encode + * @throws IOException Signals that an I/O exception has occurred. */ void appendEncoded(Encoder encoder, EncodingState encodingState, char[] b, int off, int len) throws IOException; /** * Encodes a {@link StreamEncodeable} instance and appends it to the buffer. * - * @param encoder the encoder to use + * @param encoder the encoder to use * @param streamEncodeable the instance to encode * @throws IOException Signals that an I/O exception has occurred. */ @@ -118,30 +95,27 @@ void appendEncoded(Encoder encoder, EncodingState encodingState, CharSequence st */ void flush() throws IOException; - public void close() throws IOException; - - + void close() throws IOException; + /** * When enabled, will encode all input regardless of it's current state * disables double-encoding prevention. - * + * * @param ignoreEncodingState */ void setIgnoreEncodingState(boolean ignoreEncodingState); - + /** * @return current state of ignoreEncodingState setting */ - public boolean isIgnoreEncodingState(); - + boolean isIgnoreEncodingState(); + /** * Check if the encoder should be used to a input with certain encodingState * - * @param encoderToApply - * the encoder to apply - * @param encodingState - * the current encoding state + * @param encoderToApply the encoder to apply + * @param encodingState the current encoding state * @return true, if should encode */ - public boolean shouldEncode(Encoder encoderToApply, EncodingState encodingState); + boolean shouldEncode(Encoder encoderToApply, EncodingState encodingState); } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/EncodedAppenderWriter.java b/grails-encoder/src/main/groovy/org/grails/encoder/EncodedAppenderWriter.java index e9d1f782137..1fb47764139 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/EncodedAppenderWriter.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/EncodedAppenderWriter.java @@ -24,31 +24,29 @@ /** * A java.io.Writer implementation that writes to a {@link EncodedAppender} with * a certain encoder - * + *

    * This class isn't thread-safe. * * @author Lari Hotari * @since 2.3 */ public class EncodedAppenderWriter extends Writer implements EncodedAppenderWriterFactory, EncodedAppenderFactory, EncoderAware { + protected EncodedAppender encodedAppender; protected Encoder encoder; protected EncodingStateRegistry encodingStateRegistry; - private char[] singleCharBuffer=new char[1]; + private char[] singleCharBuffer = new char[1]; /** * Default constructor * - * @param encodedAppender - * the EncodedAppender destination - * @param encoder - * the encoder to use - * @param encodingStateRegistry - * the {@link EncodingStateRegistry} to use to lookup encoding - * state of CharSequence instances + * @param encodedAppender the EncodedAppender destination + * @param encoder the encoder to use + * @param encodingStateRegistry the {@link EncodingStateRegistry} to use to lookup encoding + * state of CharSequence instances */ public EncodedAppenderWriter(EncodedAppender encodedAppender, Encoder encoder, - EncodingStateRegistry encodingStateRegistry) { + EncodingStateRegistry encodingStateRegistry) { this.encodedAppender = encodedAppender; this.encoder = encoder; this.encodingStateRegistry = encodingStateRegistry; @@ -87,7 +85,7 @@ public void close() throws IOException { */ @Override public void write(int c) throws IOException { - append((char)c); + append((char) c); } /* @@ -130,7 +128,7 @@ public Writer append(CharSequence csq, int start, int end) throws IOException { */ @Override public Writer append(char c) throws IOException { - singleCharBuffer[0]=(char)c; + singleCharBuffer[0] = (char) c; encodedAppender.append(encoder, null, singleCharBuffer, 0, 1); return this; } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/EncodedAppenderWriterFactory.java b/grails-encoder/src/main/groovy/org/grails/encoder/EncodedAppenderWriterFactory.java index b02b51d37bb..b7def1a69f7 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/EncodedAppenderWriterFactory.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/EncodedAppenderWriterFactory.java @@ -34,10 +34,8 @@ public interface EncodedAppenderWriterFactory { * Gets the EncodedAppenderWriter instance that is connected to this * instance implementation with a certain encoder fixed. * - * @param encoder - * the encoder to use - * @param encodingStateRegistry - * the current EncodingStateRegistry to use + * @param encoder the encoder to use + * @param encodingStateRegistry the current EncodingStateRegistry to use * @return the java.io.Writer instance */ Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodingStateRegistry); diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/EncodesToWriter.java b/grails-encoder/src/main/groovy/org/grails/encoder/EncodesToWriter.java index c3150a2b9ae..109b05517f2 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/EncodesToWriter.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/EncodesToWriter.java @@ -24,13 +24,16 @@ /** * Marks a class capable of encoding to target Writer - * + * * @author Lari Hotari * @since 2.3.10 * */ public interface EncodesToWriter { - public void encodeToWriter(CharSequence str, int off, int len, Writer writer, EncodingState encodingState) throws IOException; - public void encodeToWriter(char[] buf, int off, int len, Writer writer, EncodingState encodingState) throws IOException; - public EncodesToWriter createChainingEncodesToWriter(List additionalEncoders, boolean applyAdditionalFirst); + + void encodeToWriter(CharSequence str, int off, int len, Writer writer, EncodingState encodingState) throws IOException; + + void encodeToWriter(char[] buf, int off, int len, Writer writer, EncodingState encodingState) throws IOException; + + EncodesToWriter createChainingEncodesToWriter(List additionalEncoders, boolean applyAdditionalFirst); } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/EncodesToWriterAdapter.java b/grails-encoder/src/main/groovy/org/grails/encoder/EncodesToWriterAdapter.java index be65637ae70..d78a670ad8c 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/EncodesToWriterAdapter.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/EncodesToWriterAdapter.java @@ -26,13 +26,14 @@ import java.util.List; public class EncodesToWriterAdapter implements EncodesToWriter { + private final StreamingEncoder encoder; private boolean ignoreEncodingState; - + public EncodesToWriterAdapter(StreamingEncoder encoder) { this(encoder, false); } - + public EncodesToWriterAdapter(StreamingEncoder encoder, boolean ignoreEncodingState) { this.encoder = encoder; this.ignoreEncodingState = ignoreEncodingState; @@ -40,7 +41,7 @@ public EncodesToWriterAdapter(StreamingEncoder encoder, boolean ignoreEncodingSt @Override public void encodeToWriter(CharSequence str, int off, int len, Writer writer, EncodingState encodingState) throws IOException { - if(shouldEncodeWith(encoder, encodingState)) { + if (shouldEncodeWith(encoder, encodingState)) { encoder.encodeToStream(encoder, str, off, len, new WriterEncodedAppender(writer), createNewEncodingState(encoder, encodingState)); } else { CharSequences.writeCharSequence(writer, str, off, len); @@ -49,20 +50,20 @@ public void encodeToWriter(CharSequence str, int off, int len, Writer writer, En @Override public void encodeToWriter(char[] buf, int off, int len, Writer writer, EncodingState encodingState) throws IOException { - if(shouldEncodeWith(encoder, encodingState)) { + if (shouldEncodeWith(encoder, encodingState)) { encoder.encodeToStream(encoder, CharSequences.createCharSequence(buf, off, len), 0, len, new WriterEncodedAppender(writer), createNewEncodingState(encoder, encodingState)); } else { writer.write(buf, off, len); } } - + protected EncodingState createNewEncodingState(Encoder encoder, EncodingState encodingState) { if (encodingState == null) { return new EncodingStateImpl(encoder, null); } return encodingState.appendEncoder(encoder); - } - + } + protected boolean shouldEncodeWith(Encoder encoderToApply, EncodingState encodingState) { return ignoreEncodingState || encodingState == null || DefaultEncodingStateRegistry.shouldEncodeWith(encoderToApply, encodingState); @@ -89,18 +90,18 @@ public EncodesToWriter createChainingEncodesToWriter(List addi public static EncodesToWriterAdapter createChainingEncodesToWriter(StreamingEncoder baseEncoder, List additionalEncoders, boolean applyAdditionalFirst) { boolean baseEncoderShouldBeApplied = ChainedEncoders.shouldApplyEncoder(baseEncoder); - List allEncoders=new ArrayList(additionalEncoders.size()+1); - if(!applyAdditionalFirst && baseEncoderShouldBeApplied) { + List allEncoders = new ArrayList(additionalEncoders.size() + 1); + if (!applyAdditionalFirst && baseEncoderShouldBeApplied) { allEncoders.add(baseEncoder); } - for(StreamingEncoder additional : additionalEncoders) { - if(ChainedEncoders.shouldApplyEncoder(additional)) { + for (StreamingEncoder additional : additionalEncoders) { + if (ChainedEncoders.shouldApplyEncoder(additional)) { allEncoders.add(additional); } } - if(applyAdditionalFirst && baseEncoderShouldBeApplied) { + if (applyAdditionalFirst && baseEncoderShouldBeApplied) { allEncoders.add(baseEncoder); } return new EncodesToWriterAdapter(ChainedEncoder.createFor(allEncoders)); - } + } } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/EncodingState.java b/grails-encoder/src/main/groovy/org/grails/encoder/EncodingState.java index fc63c8eda12..38d2b81be47 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/EncodingState.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/EncodingState.java @@ -36,6 +36,6 @@ public interface EncodingState { Set getEncoders(); EncodingState appendEncoder(Encoder encoder); - + EncodingState getPreviousEncodingState(); } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/EncodingStateImpl.java b/grails-encoder/src/main/groovy/org/grails/encoder/EncodingStateImpl.java index 3ca46380340..4225613efc1 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/EncodingStateImpl.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/EncodingStateImpl.java @@ -29,15 +29,15 @@ * @since 2.3 */ public class EncodingStateImpl implements EncodingState { - public static final EncodingState UNDEFINED_ENCODING_STATE = new EncodingStateImpl((Set)null, null); + + public static final EncodingState UNDEFINED_ENCODING_STATE = new EncodingStateImpl((Set) null, null); private final Set encoders; private final EncodingState previousEncodingState; /** * Default constructor * - * @param encoders - * the encoders + * @param encoders the encoders */ public EncodingStateImpl(Set encoders, EncodingState previousEncodingState) { this.encoders = encoders; @@ -75,28 +75,34 @@ public int hashCode() { */ @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; - EncodingStateImpl other = (EncodingStateImpl)obj; + } + EncodingStateImpl other = (EncodingStateImpl) obj; if (encoders == null) { - if (other.encoders != null && other.encoders.size() > 0) + if (other.encoders != null && other.encoders.size() > 0) { return false; - } - else if (!encoders.equals(other.encoders)) + } + } else if (!encoders.equals(other.encoders)) { return false; + } return true; } public EncodingState appendEncoder(Encoder encoder) { - if(encoder==null) return this; + if (encoder == null) { + return this; + } Set newEncoders; - if (encoders == null || encoders.size()==0) { + if (encoders == null || encoders.size() == 0) { newEncoders = Collections.singleton(encoder); - } else if (encoders.size()==1 && encoders.contains(encoder)) { + } else if (encoders.size() == 1 && encoders.contains(encoder)) { return this; } else { newEncoders = new LinkedHashSet(); @@ -108,16 +114,16 @@ public EncodingState appendEncoder(Encoder encoder) { @Override public String toString() { - StringBuilder sb=new StringBuilder(); + StringBuilder sb = new StringBuilder(); sb.append("EncodingStateImpl"); - if(encoders != null && encoders.size() > 0) { + if (encoders != null && encoders.size() > 0) { sb.append(" [encoders="); - boolean first=true; - for(Encoder encoder : encoders) { - if(!first) { + boolean first = true; + for (Encoder encoder : encoders) { + if (!first) { sb.append(", "); } else { - first=false; + first = false; } sb.append("[@"); sb.append(System.identityHashCode(encoder)); diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/EncodingStateRegistry.java b/grails-encoder/src/main/groovy/org/grails/encoder/EncodingStateRegistry.java index c6515dfc300..2edd29a50ad 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/EncodingStateRegistry.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/EncodingStateRegistry.java @@ -33,8 +33,7 @@ public interface EncodingStateRegistry { /** * Gets the current encoding state for a CharSequence. * - * @param string - * a CharSequence + * @param string a CharSequence * @return the encoding state for the CharSequence */ EncodingState getEncodingStateFor(CharSequence string); @@ -42,10 +41,8 @@ public interface EncodingStateRegistry { /** * Checks if a encoder should be applied to a CharSequence * - * @param encoderToApply - * the encoder to apply - * @param string - * a CharSequence + * @param encoderToApply the encoder to apply + * @param string a CharSequence * @return true, if it should be applied */ boolean shouldEncodeWith(Encoder encoderToApply, CharSequence string); @@ -53,10 +50,8 @@ public interface EncodingStateRegistry { /** * Checks if the CharSequence is encoded with encoder. * - * @param encoder - * the encoder - * @param string - * a CharSequence + * @param encoder the encoder + * @param string a CharSequence * @return true, if it is encoded with encoder */ boolean isEncodedWith(Encoder encoder, CharSequence string); @@ -64,10 +59,8 @@ public interface EncodingStateRegistry { /** * Registers that the CharSequence has been encoded with encoder * - * @param encoder - * the encoder - * @param escaped - * the CharSequence + * @param encoder the encoder + * @param escaped the CharSequence */ void registerEncodedWith(Encoder encoder, CharSequence escaped); } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/EncodingStateRegistryLookupHolder.java b/grails-encoder/src/main/groovy/org/grails/encoder/EncodingStateRegistryLookupHolder.java index d35e50637d9..198f0abd575 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/EncodingStateRegistryLookupHolder.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/EncodingStateRegistryLookupHolder.java @@ -20,7 +20,8 @@ import grails.util.Holder; -public class EncodingStateRegistryLookupHolder { +public final class EncodingStateRegistryLookupHolder { + private static Holder holder = new Holder("encodingStateRegistryLookup"); private EncodingStateRegistryLookupHolder() { @@ -33,7 +34,7 @@ public static void setEncodingStateRegistryLookup(EncodingStateRegistryLookup lo public static EncodingStateRegistryLookup getEncodingStateRegistryLookup() { return holder.get(); } - + public static void clear() { holder.set(null); } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/StreamEncodeable.java b/grails-encoder/src/main/groovy/org/grails/encoder/StreamEncodeable.java index 942234d7c26..036ad62fc46 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/StreamEncodeable.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/StreamEncodeable.java @@ -35,12 +35,9 @@ public interface StreamEncodeable { * implementation checks if Encoder is a {@link StreamingEncoder} instance * and takes use of that interface. * - * @param appender - * the EncodedAppender instance - * @param encoder - * the encoder - * @throws IOException - * Signals that an I/O exception has occurred. + * @param appender the EncodedAppender instance + * @param encoder the encoder + * @throws IOException Signals that an I/O exception has occurred. */ void encodeTo(EncodedAppender appender, Encoder encoder) throws IOException; } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoder.java b/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoder.java index 615fd05f04f..26e33a19206 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoder.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoder.java @@ -30,22 +30,17 @@ * @since 2.3 */ public interface StreamingEncoder extends Encoder { + /** * Encode and append portion of source CharSequence to the appender. * - * @param source - * The source CharSequence - * @param offset - * Offset from which to start encoding characters - * @param len - * Number of characters to encode - * @param appender - * the appender to write to - * @param encodingState - * the current encoding state - * @throws IOException - * Signals that an I/O exception has occurred. + * @param source The source CharSequence + * @param offset Offset from which to start encoding characters + * @param len Number of characters to encode + * @param appender the appender to write to + * @param encodingState the current encoding state + * @throws IOException Signals that an I/O exception has occurred. */ void encodeToStream(Encoder thisInstance, CharSequence source, int offset, int len, EncodedAppender appender, - EncodingState encodingState) throws IOException; + EncodingState encodingState) throws IOException; } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoderEncodedAppender.java b/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoderEncodedAppender.java index 05cb5fa374d..6367644a1f7 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoderEncodedAppender.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoderEncodedAppender.java @@ -27,9 +27,10 @@ * */ public class StreamingEncoderEncodedAppender extends AbstractEncodedAppender { + private final StreamingEncoder encoder; private final EncodedAppender target; - + public StreamingEncoderEncodedAppender(StreamingEncoder encoder, EncodedAppender target) { this.encoder = encoder; this.target = target; @@ -39,7 +40,7 @@ public StreamingEncoderEncodedAppender(StreamingEncoder encoder, EncodedAppender public void close() throws IOException { target.close(); } - + @Override public void flush() throws IOException { target.flush(); @@ -67,9 +68,9 @@ protected void write(EncodingState encodingState, String str, int off, int len) protected void appendCharSequence(EncodingState encodingState, CharSequence str, int start, int end) throws IOException { if (shouldEncode(encoder, encodingState.getPreviousEncodingState())) { - encoder.encodeToStream(encoder, str, start, end-start, target, encodingState); + encoder.encodeToStream(encoder, str, start, end - start, target, encodingState); } else { - target.appendEncoded(null, encodingState, str, start, end-start); + target.appendEncoded(null, encodingState, str, start, end - start); } } } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoderWritable.java b/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoderWritable.java index c715dd16f66..6de8824afa4 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoderWritable.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoderWritable.java @@ -31,15 +31,12 @@ public interface StreamingEncoderWritable { /** - * Asks the instance to use given writer and EncodesToWriter instance to encode + * Asks the instance to use given writer and EncodesToWriter instance to encode * it's content * - * @param writer - * the target writer instance - * @param encoder - * the encoder - * @throws IOException - * Signals that an I/O exception has occurred. + * @param writer the target writer instance + * @param encoder the encoder + * @throws IOException Signals that an I/O exception has occurred. */ void encodeTo(Writer writer, EncodesToWriter encoder) throws IOException; } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoderWriter.java b/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoderWriter.java index cdae9097f15..c330507cfa7 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoderWriter.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/StreamingEncoderWriter.java @@ -25,17 +25,18 @@ import java.io.Writer; public class StreamingEncoderWriter extends FilterWriter implements EncodedAppenderFactory, EncoderAware { + private EncodesToWriter encodesToWriter; private StreamingEncoder encoder; private EncodingStateRegistry encodingStateRegistry; - + public StreamingEncoderWriter(Writer out, StreamingEncoder encoder, EncodingStateRegistry encodingStateRegistry) { super(out); this.encoder = encoder; - if(encoder instanceof EncodesToWriter) { - this.encodesToWriter = ((EncodesToWriter)encoder); + if (encoder instanceof EncodesToWriter) { + this.encodesToWriter = ((EncodesToWriter) encoder); } else { - this.encodesToWriter = new EncodesToWriterAdapter(encoder, true); + this.encodesToWriter = new EncodesToWriterAdapter(encoder, true); } this.encodingStateRegistry = encodingStateRegistry; } @@ -44,11 +45,11 @@ public StreamingEncoderWriter(Writer out, StreamingEncoder encoder, EncodingStat public void write(char[] cbuf, int off, int len) throws IOException { encodesToWriter.encodeToWriter(cbuf, off, len, out, null); } - + @Override public void write(String str, int off, int len) throws IOException { final EncodingState encodingState = lookupEncodingState(str, off, len); - if(shouldEncodeWith(encoder, encodingState)) { + if (shouldEncodeWith(encoder, encodingState)) { encodesToWriter.encodeToWriter(str, off, len, out, encodingState); } else { out.write(str, off, len); @@ -59,9 +60,9 @@ protected boolean shouldEncodeWith(Encoder encoderToApply, EncodingState encodin return encodingState == null || DefaultEncodingStateRegistry.shouldEncodeWith(encoderToApply, encodingState); } - + protected EncodingState lookupEncodingState(String str, int off, int len) { - if(encodingStateRegistry != null) { + if (encodingStateRegistry != null) { return encodingStateRegistry.getEncodingStateFor(str); } else { return null; diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/WriterEncodedAppender.java b/grails-encoder/src/main/groovy/org/grails/encoder/WriterEncodedAppender.java index 5b49284d124..57767ca11f4 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/WriterEncodedAppender.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/WriterEncodedAppender.java @@ -30,6 +30,7 @@ * @since 2.3 */ public class WriterEncodedAppender extends AbstractEncodedAppender { + private Writer target; /** @@ -79,7 +80,7 @@ protected void appendCharSequence(EncodingState encodingState, CharSequence csq, public void close() throws IOException { target.close(); } - + @Override protected EncodingState createNewEncodingState(Encoder encoder, EncodingState encodingState) { return null; diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/BasicCodecLookup.java b/grails-encoder/src/main/groovy/org/grails/encoder/impl/BasicCodecLookup.java index bcc008843bf..2673ee62cf9 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/BasicCodecLookup.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/BasicCodecLookup.java @@ -19,17 +19,6 @@ package org.grails.encoder.impl; import grails.util.GrailsNameUtils; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - import org.grails.encoder.ChainedDecoder; import org.grails.encoder.ChainedEncoder; import org.grails.encoder.ChainedEncoders; @@ -41,9 +30,20 @@ import org.grails.encoder.StreamingEncoder; import org.springframework.beans.factory.InitializingBean; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + public class BasicCodecLookup implements CodecLookup, InitializingBean { - private static final String NONE_CODEC_NAME = "none"; + public static final StreamingEncoder NONE_ENCODER = new NoneEncoder(); + private static final String NONE_CODEC_NAME = "none"; protected final ConcurrentMap encoders = new ConcurrentHashMap(); protected final ConcurrentMap decoders = new ConcurrentHashMap(); @@ -55,21 +55,21 @@ public BasicCodecLookup() { public Encoder lookupEncoder(String codecName) { return lookupCodec(codecName, encoders, Encoder.class); } - + public Decoder lookupDecoder(String codecName) { return lookupCodec(codecName, decoders, Decoder.class); - } + } @SuppressWarnings("unchecked") protected T lookupCodec(String codecName, ConcurrentMap map, Class returnType) { if (codecName != null && codecName.length() > 0) { if (NONE_CODEC_NAME.equalsIgnoreCase(codecName)) { if (returnType == Encoder.class) { - return (T)NONE_ENCODER; + return (T) NONE_ENCODER; } } else { T resultObject = map.get(codecName); - if(resultObject == null) { + if (resultObject == null) { resultObject = createCodec(codecName, map, returnType); } return resultObject; @@ -77,12 +77,12 @@ protected T lookupCodec(String codecName, Co } return null; } - + @SuppressWarnings("unchecked") protected T createCodec(String codecName, ConcurrentMap map, Class returnType) { - if(codecName.indexOf(',') > -1) { + if (codecName.indexOf(',') > -1) { T createdInstance = createChainedCodecInstance(codecName, map, returnType); - if(createdInstance != null) { + if (createdInstance != null) { createdInstance = putChainedCodecInstance(codecName, map, createdInstance); } return createdInstance; @@ -91,42 +91,42 @@ protected T createCodec(String codecName, Co } protected T putChainedCodecInstance(String codecName, - ConcurrentMap map, T createdInstance) { + ConcurrentMap map, T createdInstance) { T previousInstance = map.putIfAbsent(codecName, createdInstance); - if(previousInstance != null) { + if (previousInstance != null) { return previousInstance; - } else { + } else { return createdInstance; } } protected T createChainedCodecInstance(String codecName, ConcurrentMap map, Class returnType) { - String[] codecs=codecName.split(","); + String[] codecs = codecName.split(","); List codecInstances = new ArrayList(codecs.length); - for(int i=0;i < codecs.length;i++) { + for (int i = 0; i < codecs.length; i++) { T codecInstance = map.get(codecs[i]); - if(codecInstance != null) { + if (codecInstance != null) { codecInstances.add(codecInstance); } } if (returnType == Encoder.class) { - List streamingEncoders = ChainedEncoders.toStreamingEncoders((List)codecInstances); - if(streamingEncoders == null) { + List streamingEncoders = ChainedEncoders.toStreamingEncoders((List) codecInstances); + if (streamingEncoders == null) { throw new RuntimeException("ChainedEncoder only supports StreamingEncoder instances. Couldn't build chained encoder for '" + codecName + "'"); } else { - return (T)ChainedEncoder.createFor(streamingEncoders); + return (T) ChainedEncoder.createFor(streamingEncoders); } } else { Collections.reverse(codecInstances); - return (T)new ChainedDecoder(codecInstances.toArray(new Decoder[codecInstances.size()])); + return (T) new ChainedDecoder(codecInstances.toArray(new Decoder[codecInstances.size()])); } } - + protected synchronized void registerWithNameVaritions(Map destinationMap, T target) { - String name=target.getCodecIdentifier().getCodecName(); + String name = target.getCodecIdentifier().getCodecName(); registerVariationsOfName(destinationMap, target, name); Set aliases = target.getCodecIdentifier().getCodecAliases(); - if (aliases != null) { + if (aliases != null) { for (String alias : aliases) { registerVariationsOfName(destinationMap, target, alias); } @@ -135,11 +135,11 @@ protected synchronized void registerWithName protected void registerVariationsOfName(Map destinationMap, T target, String name) { Collection nameVariations = createNameVariations(name, target); - for(String nameVariation : nameVariations) { + for (String nameVariation : nameVariations) { destinationMap.put(nameVariation, target); } } - + protected Collection createNameVariations(String name, CodecIdentifierProvider target) { Set nameVariations = new LinkedHashSet(); nameVariations.add(name); @@ -150,11 +150,11 @@ protected Collection createNameVariations(String name, CodecIdentifierPr } public void registerCodecFactory(CodecFactory codecFactory) { - Encoder encoder=codecFactory.getEncoder(); + Encoder encoder = codecFactory.getEncoder(); if (encoder != null) { registerEncoder(encoder); } - Decoder decoder=codecFactory.getDecoder(); + Decoder decoder = codecFactory.getDecoder(); if (decoder != null) { registerDecoder(decoder); } @@ -169,13 +169,13 @@ public void registerEncoder(Encoder encoder) { } public void reInitialize() { - encoders.clear(); ; + encoders.clear(); decoders.clear(); registerCodecs(); } - + protected void registerCodecs() { - + } public void afterPropertiesSet() throws Exception { diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/BasicJSONEncoder.java b/grails-encoder/src/main/groovy/org/grails/encoder/impl/BasicJSONEncoder.java index 85298402631..0407357ee92 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/BasicJSONEncoder.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/BasicJSONEncoder.java @@ -18,10 +18,10 @@ */ package org.grails.encoder.impl; +import org.codehaus.groovy.runtime.StringGroovyMethods; import org.grails.encoder.AbstractCharReplacementEncoder; import org.grails.encoder.CodecIdentifier; import org.grails.encoder.DefaultCodecIdentifier; -import org.codehaus.groovy.runtime.StringGroovyMethods; import org.springframework.util.ClassUtils; /** @@ -31,19 +31,20 @@ * @since 2.3.4 */ public class BasicJSONEncoder extends AbstractCharReplacementEncoder { + public static final CodecIdentifier JSON_CODEC_IDENTIFIER = new DefaultCodecIdentifier( "JSON", "Json") { public boolean isEquivalent(CodecIdentifier other) { return super.isEquivalent(other) || JavaScriptEncoder.JAVASCRIPT_CODEC_IDENTIFIER.getCodecName().equals(other.getCodecName()); - }; + } + + ; }; public BasicJSONEncoder() { super(JSON_CODEC_IDENTIFIER); } - - /* (non-Javadoc) * @see AbstractCharReplacementEncoder#escapeCharacter(char, char) */ @@ -64,7 +65,7 @@ protected String escapeCharacter(char ch, char previousChar) { return "\\f"; case '\b': return "\\b"; - case '\u000B': // vertical tab: http://bclary.com/2004/11/07/#a-7.8.4 + case '\u000B': // vertical tab: https://bclary.com/2004/11/07/#a-7.8.4 return "\\u000B"; case '\u2028': return "\\u2028"; // Line separator @@ -74,11 +75,14 @@ protected String escapeCharacter(char ch, char previousChar) { // preserve special handling that exists in JSONObject.quote to improve security if JSON is embedded in HTML document // prevents outputting " * Currently ', ", <, > and & characters are replaced with XML entities. * Additionally backslash (/), non-breaking space, backtick (`) and @ are also replaced for visibility/additional security. * @@ -33,6 +33,9 @@ * @since 2.3 */ public class BasicXMLEncoder extends AbstractCharReplacementEncoder { + + public static final CodecIdentifier XML_CODEC_IDENTIFIER = new DefaultCodecIdentifier("XML"); + private static final String ESCAPED_APOS = xmlEscapeCharacter('\''); // html doesn't have apos, so use numeric entity private static final String ESCAPED_QUOTE = """; private static final String ESCAPED_GT = ">"; @@ -40,7 +43,7 @@ public class BasicXMLEncoder extends AbstractCharReplacementEncoder { private static final String ESCAPED_AMP = "&"; // some extras private static final String ESCAPED_BACKSLASH = xmlEscapeCharacter('\\'); - private static final char NBSP=(char)160; + private static final char NBSP = (char) 160; private static final String ESCAPED_NON_BREAKING_SPACE = xmlEscapeCharacter(NBSP); private static final String ESCAPED_BACKTICK = xmlEscapeCharacter('`'); private static final String ESCAPED_AT = xmlEscapeCharacter('@'); // IE Javascript conditional compilation rules @@ -48,12 +51,6 @@ public class BasicXMLEncoder extends AbstractCharReplacementEncoder { private static final String ESCAPED_LINE_SEPARATOR = xmlEscapeCharacter(LINE_SEPARATOR); private static final char PARAGRAPH_SEPARATOR = '\u2029'; private static final String ESCAPED_PARAGRAPH_SEPARATOR = xmlEscapeCharacter(PARAGRAPH_SEPARATOR); - - protected static final String xmlEscapeCharacter(char ch) { - return "&#" + ((int) ch) + ";"; - } - - public static final CodecIdentifier XML_CODEC_IDENTIFIER=new DefaultCodecIdentifier("XML"); public BasicXMLEncoder() { super(XML_CODEC_IDENTIFIER); @@ -63,47 +60,63 @@ protected BasicXMLEncoder(CodecIdentifier codecIdentifier) { super(codecIdentifier); } + protected static final String xmlEscapeCharacter(char ch) { + return "&#" + ((int) ch) + ";"; + } + /* (non-Javadoc) * @see AbstractCharReplacementEncoder#escapeCharacter(char, char) */ @Override protected String escapeCharacter(char ch, char previousChar) { - if(ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r') { - return ""; - } - switch(ch) { - case '&': return ESCAPED_AMP; - case '<': return ESCAPED_LT; - case '>': return ESCAPED_GT; - case '"': return ESCAPED_QUOTE; - case '\'': return ESCAPED_APOS; - case '\\': return ESCAPED_BACKSLASH; - case '@': return ESCAPED_AT; - case '`': return ESCAPED_BACKTICK; - case NBSP: return ESCAPED_NON_BREAKING_SPACE; - case LINE_SEPARATOR: return ESCAPED_LINE_SEPARATOR; - case PARAGRAPH_SEPARATOR: return ESCAPED_PARAGRAPH_SEPARATOR; - } - return null; + if (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r') { + return ""; + } + switch (ch) { + case '&': + return ESCAPED_AMP; + case '<': + return ESCAPED_LT; + case '>': + return ESCAPED_GT; + case '"': + return ESCAPED_QUOTE; + case '\'': + return ESCAPED_APOS; + case '\\': + return ESCAPED_BACKSLASH; + case '@': + return ESCAPED_AT; + case '`': + return ESCAPED_BACKTICK; + case NBSP: + return ESCAPED_NON_BREAKING_SPACE; + case LINE_SEPARATOR: + return ESCAPED_LINE_SEPARATOR; + case PARAGRAPH_SEPARATOR: + return ESCAPED_PARAGRAPH_SEPARATOR; + default: + return null; + } } - + @Override public final Object encode(Object o) { return doEncode(o); } protected Object doEncode(Object o) { - if(o == null) { + if (o == null) { return null; } - if(o instanceof CharSequence || ClassUtils.isPrimitiveOrWrapper(o.getClass())) { + if (o instanceof CharSequence || ClassUtils.isPrimitiveOrWrapper(o.getClass())) { return doCharReplacementEncoding(o); } else { - return encodeAsXmlObject(o); + return encodeAsXmlObject(o); } } protected Object encodeAsXmlObject(Object o) { return o; - } + } } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTML4Codec.java b/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTML4Codec.java index b36a5229e80..18d06e74040 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTML4Codec.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTML4Codec.java @@ -31,6 +31,7 @@ * @since 2.3 */ public class HTML4Codec implements CodecFactory { + static final String CODEC_NAME = "HTML4"; private static Encoder encoder = new HTML4Encoder(); diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTML4Encoder.java b/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTML4Encoder.java index 6a6019a74ad..d19c5ddf4e1 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTML4Encoder.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTML4Encoder.java @@ -18,11 +18,6 @@ */ package org.grails.encoder.impl; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.grails.encoder.AbstractCharReplacementEncoder; @@ -31,6 +26,11 @@ import org.springframework.util.ReflectionUtils; import org.springframework.web.util.HtmlUtils; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + /** * This encoder is for HTML4 documents. It uses escaping information from * Spring's HtmlUtils so that this is compatible with the previous @@ -40,11 +40,12 @@ * @since 2.3 */ public class HTML4Encoder extends AbstractCharReplacementEncoder { - private static final Log log = LogFactory.getLog(HTML4Encoder.class); + static final String HTML4_CODEC_NAME = "HTML4"; static final CodecIdentifier HTML4_CODEC_IDENTIFIER = new DefaultCodecIdentifier(HTML4_CODEC_NAME); - Map replacements = new ConcurrentHashMap(); + private static final Log LOG = LogFactory.getLog(HTML4Encoder.class); private static final String NULL_MARKER = "NULL_MARKER"; + Map replacements = new ConcurrentHashMap(); public HTML4Encoder() { super(HTML4_CODEC_IDENTIFIER); @@ -71,20 +72,22 @@ protected String escapeCharacter(char ch, char previousChar) { * Calls Spring's HtmlUtils's private method to convert characters to HTML entities. */ private static final class StreamingHTMLEncoderHelper { + private static Object instance; private static Method mapMethod; private static boolean disabled = false; + static { try { Field instanceField = ReflectionUtils.findField(HtmlUtils.class, "characterEntityReferences"); ReflectionUtils.makeAccessible(instanceField); instance = instanceField.get(null); mapMethod = ReflectionUtils.findMethod(instance.getClass(), "convertToReference", char.class); - if (mapMethod != null) + if (mapMethod != null) { ReflectionUtils.makeAccessible(mapMethod); - } - catch (Exception e) { - log.warn("Couldn't use reflection for resolving characterEntityReferences in HtmlUtils class", e); + } + } catch (Exception e) { + LOG.warn("Couldn't use reflection for resolving characterEntityReferences in HtmlUtils class", e); disabled = true; } } @@ -95,9 +98,9 @@ private static final class StreamingHTMLEncoderHelper { * @param c the character to convert * @return the converted entity, returns null if the character doesn't have a replacement */ - public static final String convertToReference(char c) { + public static String convertToReference(char c) { if (!disabled) { - return (String)ReflectionUtils.invokeMethod(mapMethod, instance, c); + return (String) ReflectionUtils.invokeMethod(mapMethod, instance, c); } String charAsString = String.valueOf(c); diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTMLCodecFactory.groovy b/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTMLCodecFactory.groovy index 2fb849bccc6..d3c458dff82 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTMLCodecFactory.groovy +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTMLCodecFactory.groovy @@ -19,18 +19,20 @@ package org.grails.encoder.impl import groovy.transform.CompileStatic -import org.grails.encoder.Encoder import org.grails.encoder.CodecFactory import org.grails.encoder.CodecIdentifier import org.grails.encoder.Decoder +import org.grails.encoder.Encoder @CompileStatic class HTMLCodecFactory implements CodecFactory { + Encoder encoder = new HTMLEncoder() Decoder decoder = decoder = new HTML4Decoder() { + @Override public CodecIdentifier getCodecIdentifier() { return HTMLEncoder.HTML_CODEC_IDENTIFIER; } - } + } } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTMLEncoder.java b/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTMLEncoder.java index 724e45d9f9d..80f70aa8e93 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTMLEncoder.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTMLEncoder.java @@ -25,18 +25,19 @@ * HTMLEncoder implementation currently this doesn't add any extra features to * XMLEncoder This encoder is for XML, XHTML and HTML5 documents. * - * @see HTML4Encoder * @author Lari Hotari + * @see HTML4Encoder * @since 2.3 */ public class HTMLEncoder extends BasicXMLEncoder { + public static final CodecIdentifier HTML_CODEC_IDENTIFIER = new DefaultCodecIdentifier("HTML"); public HTMLEncoder() { super(HTML_CODEC_IDENTIFIER); } - + protected Object doEncode(Object o) { return doCharReplacementEncoding(o); - } + } } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTMLJSCodec.java b/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTMLJSCodec.java index 511b24fb95e..c3a26f06136 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTMLJSCodec.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/HTMLJSCodec.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.encoder.impl; import org.grails.encoder.ChainedDecoder; @@ -27,12 +26,13 @@ import org.grails.encoder.StreamingEncoder; public class HTMLJSCodec implements CodecFactory { + protected final StreamingEncoder[] encoders; protected final Decoder[] decoders; - + public HTMLJSCodec() { - encoders = new StreamingEncoder[]{(StreamingEncoder)new HTMLEncoder(), (StreamingEncoder)JavaScriptCodec.getENCODER()}; - decoders = new Decoder[]{JavaScriptCodec.getDECODER(), new HTML4Decoder()}; + encoders = new StreamingEncoder[]{(StreamingEncoder) new HTMLEncoder(), (StreamingEncoder) JavaScriptCodec.getENCODER()}; + decoders = new Decoder[]{JavaScriptCodec.getDECODER(), new HTML4Decoder()}; } @Override diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/JSONCodecFactory.groovy b/grails-encoder/src/main/groovy/org/grails/encoder/impl/JSONCodecFactory.groovy index 97665199141..cf23e46572c 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/JSONCodecFactory.groovy +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/JSONCodecFactory.groovy @@ -18,20 +18,20 @@ */ package org.grails.encoder.impl -import groovy.transform.CompileStatic - import groovy.json.StringEscapeUtils +import groovy.transform.CompileStatic import org.grails.encoder.CodecFactory import org.grails.encoder.CodecIdentifier -import org.grails.encoder.Encoder import org.grails.encoder.Decoder - +import org.grails.encoder.Encoder @CompileStatic class JSONCodecFactory implements CodecFactory { + Encoder encoder = new BasicJSONEncoder() Decoder decoder = new Decoder() { + def decode(Object obj) { obj != null ? StringEscapeUtils.unescapeJavaScript(obj.toString()) : null } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/JavaScriptCodec.groovy b/grails-encoder/src/main/groovy/org/grails/encoder/impl/JavaScriptCodec.groovy index cee45d259b1..09b28acdc05 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/JavaScriptCodec.groovy +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/JavaScriptCodec.groovy @@ -18,13 +18,12 @@ */ package org.grails.encoder.impl -import groovy.transform.CompileStatic - import groovy.json.StringEscapeUtils -import org.grails.encoder.Encoder +import groovy.transform.CompileStatic import org.grails.encoder.CodecFactory import org.grails.encoder.CodecIdentifier import org.grails.encoder.Decoder +import org.grails.encoder.Encoder /** * A codec that encodes strings to Javascript @@ -38,6 +37,7 @@ class JavaScriptCodec implements CodecFactory { static Encoder ENCODER = new JavaScriptEncoder() static Decoder DECODER = new Decoder() { + def decode(Object obj) { obj != null ? StringEscapeUtils.unescapeJavaScript(obj.toString()) : null } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/JavaScriptEncoder.java b/grails-encoder/src/main/groovy/org/grails/encoder/impl/JavaScriptEncoder.java index 5f3e552fa77..e7241e17fea 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/JavaScriptEncoder.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/JavaScriptEncoder.java @@ -31,11 +31,14 @@ * @since 2.3 */ public class JavaScriptEncoder extends AbstractCharReplacementEncoder { + public static final CodecIdentifier JAVASCRIPT_CODEC_IDENTIFIER = new DefaultCodecIdentifier( "JavaScript", "Js") { public boolean isEquivalent(CodecIdentifier other) { return super.isEquivalent(other) || BasicJSONEncoder.JSON_CODEC_IDENTIFIER.getCodecName().equals(other.getCodecName()); - }; + } + + ; }; public JavaScriptEncoder() { @@ -53,7 +56,7 @@ protected String escapeCharacter(char ch, char previousChar) { case '\'': return "\\u0027"; case '`': // backtick - return "\\u0060"; + return "\\u0060"; case '\\': return "\\u005c"; case '/': @@ -72,7 +75,7 @@ protected String escapeCharacter(char ch, char previousChar) { return "\\f"; case '\b': return "\\b"; - case '\u000B': // vertical tab: http://bclary.com/2004/11/07/#a-7.8.4 + case '\u000B': // vertical tab: https://bclary.com/2004/11/07/#a-7.8.4 return "\\v"; case '&': return "\\u0026"; @@ -102,8 +105,11 @@ protected String escapeCharacter(char ch, char previousChar) { return "\\u2028"; // Line separator case '\u2029': return "\\u2029"; // Paragraph separator + default: + // do nothing + break; } - if(ch < ' ') { + if (ch < ' ') { // remove all other control characters return ""; } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/NoneEncoder.java b/grails-encoder/src/main/groovy/org/grails/encoder/impl/NoneEncoder.java index 3ba7cab4bf6..88fc418bf63 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/NoneEncoder.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/NoneEncoder.java @@ -18,8 +18,6 @@ */ package org.grails.encoder.impl; -import java.io.IOException; - import org.grails.encoder.CodecIdentifier; import org.grails.encoder.DefaultCodecIdentifier; import org.grails.encoder.EncodedAppender; @@ -27,11 +25,14 @@ import org.grails.encoder.EncodingState; import org.grails.encoder.StreamingEncoder; +import java.io.IOException; + /** * @author Lari Hotari * @since 2.3 */ public class NoneEncoder implements StreamingEncoder { + static final CodecIdentifier CODEC_IDENTIFIER = new DefaultCodecIdentifier("None"); public Object encode(Object o) { @@ -55,7 +56,7 @@ public CodecIdentifier getCodecIdentifier() { } public void encodeToStream(Encoder thisInstance, CharSequence source, int offset, int len, EncodedAppender appender, - EncodingState encodingState) throws IOException { + EncodingState encodingState) throws IOException { appender.append(null, encodingState, source, offset, len); } } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/RawCodec.java b/grails-encoder/src/main/groovy/org/grails/encoder/impl/RawCodec.java index 6bf5bbacf13..c990dee0c0d 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/RawCodec.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/RawCodec.java @@ -18,8 +18,6 @@ */ package org.grails.encoder.impl; -import java.io.IOException; - import org.grails.encoder.CodecFactory; import org.grails.encoder.CodecIdentifier; import org.grails.encoder.Decoder; @@ -29,6 +27,8 @@ import org.grails.encoder.EncodingState; import org.grails.encoder.StreamingEncoder; +import java.io.IOException; + /** * Codec that doesn't do any encoding or decoding. This is for marking some text * as "safe" in the buffer. "safe" part of the buffer won't be encoded later if @@ -38,9 +38,14 @@ * @since 2.3 */ public class RawCodec implements Encoder, Decoder, StreamingEncoder, CodecFactory { + static final CodecIdentifier RAW_CODEC_IDENTIFIER = new DefaultCodecIdentifier("Raw") { // using RawCodec will prevent all other codecs from encoding a part encoded with this codec - public boolean isEquivalent(CodecIdentifier other) { return true; }; + public boolean isEquivalent(CodecIdentifier other) { + return true; + } + + ; }; /* (non-Javadoc) @@ -61,10 +66,10 @@ public boolean isSafe() { * @see Encoder#encode(java.lang.Object) */ public Object encode(Object o) { - if(o instanceof String) { + if (o instanceof String) { // create a new copy of the String instance - return new String((String)o); - } else if(o instanceof CharSequence) { + return new String((String) o); + } else if (o instanceof CharSequence) { // convert CharSequence to String so that we have a new instance return String.valueOf(o); } else { @@ -83,7 +88,7 @@ public void markEncoded(CharSequence string) { * @see StreamingEncoder#encodeToStream(Encoder, java.lang.CharSequence, int, int, EncodedAppender, EncodingState) */ public void encodeToStream(Encoder thisInstance, CharSequence source, int offset, int len, EncodedAppender appender, - EncodingState encodingState) throws IOException { + EncodingState encodingState) throws IOException { appender.appendEncoded(thisInstance, encodingState, source, offset, len); } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/StandaloneCodecLookup.groovy b/grails-encoder/src/main/groovy/org/grails/encoder/impl/StandaloneCodecLookup.groovy index 16a7bdbe0b1..22ef2aa8e17 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/StandaloneCodecLookup.groovy +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/StandaloneCodecLookup.groovy @@ -18,23 +18,23 @@ */ package org.grails.encoder.impl -import groovy.transform.CompileStatic - import grails.util.GrailsMetaClassUtils +import groovy.transform.CompileStatic import org.codehaus.groovy.runtime.GStringImpl import org.grails.encoder.CodecFactory import org.grails.encoder.CodecMetaClassSupport @CompileStatic class StandaloneCodecLookup extends BasicCodecLookup { + boolean registerMetaMethods = true boolean cacheLookupsInMetaMethods = true Collection> targetClassesForMetaMethods = [ - String, - GStringImpl, - StringBuffer, - StringBuilder, - Object + String, + GStringImpl, + StringBuffer, + StringBuilder, + Object ] Collection> codecFactoryClasses = [ XMLCodecFactory, @@ -44,12 +44,12 @@ class StandaloneCodecLookup extends BasicCodecLookup { HTMLJSCodec, URLCodecFactory, RawCodec - ] + ] @Override protected void registerCodecs() { codecFactoryClasses.each { Class clazz -> - registerCodecFactory((CodecFactory)clazz.getDeclaredConstructor().newInstance()) + registerCodecFactory((CodecFactory) clazz.getDeclaredConstructor().newInstance()) } } @@ -60,7 +60,7 @@ class StandaloneCodecLookup extends BasicCodecLookup { } protected registerMetaMethods(CodecFactory codecFactory) { - if(registerMetaMethods && targetClassesForMetaMethods) { + if (registerMetaMethods && targetClassesForMetaMethods) { new CodecMetaClassSupport().configureCodecMethods(codecFactory, cacheLookupsInMetaMethods, resolveMetaClasses()) } } @@ -68,7 +68,7 @@ class StandaloneCodecLookup extends BasicCodecLookup { protected List resolveMetaClasses() { targetClassesForMetaMethods.collect { Class clazz -> - GrailsMetaClassUtils.getExpandoMetaClass(clazz) + GrailsMetaClassUtils.getExpandoMetaClass(clazz) } } } diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/URLCodecFactory.groovy b/grails-encoder/src/main/groovy/org/grails/encoder/impl/URLCodecFactory.groovy index 7012311b429..6ebbd2b4882 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/URLCodecFactory.groovy +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/URLCodecFactory.groovy @@ -27,7 +27,7 @@ import org.grails.encoder.Encoder /** * Implements the 'www-form-urlencoded' encoding scheme, also misleadingly known as URL encoding. - * + * * @see Chapter 17.13.4 Form content types * of the HTML 4.01 Specification * @@ -35,16 +35,18 @@ import org.grails.encoder.Encoder */ @CompileStatic public class URLCodecFactory implements CodecFactory { + static final CodecIdentifier URL_CODEC_IDENTIFIER = new DefaultCodecIdentifier("URL"); Encoder encoder = new Encoder() { + @Override public CodecIdentifier getCodecIdentifier() { URL_CODEC_IDENTIFIER; } public Object encode(Object o) { - if(o==null) return o; + if (o == null) return o; URLEncoder.encode(String.valueOf(o), resolveEncoding()); } @@ -57,18 +59,19 @@ public class URLCodecFactory implements CodecFactory { } public void markEncoded(CharSequence string) { - + } }; Decoder decoder = new Decoder() { + public CodecIdentifier getCodecIdentifier() { URL_CODEC_IDENTIFIER; } @Override public Object decode(Object o) { - if(o==null) return o; + if (o == null) return o; URLDecoder.decode(String.valueOf(o), resolveEncoding()); } }; diff --git a/grails-encoder/src/main/groovy/org/grails/encoder/impl/XMLCodecFactory.java b/grails-encoder/src/main/groovy/org/grails/encoder/impl/XMLCodecFactory.java index fcd75552f08..6a5f8e5856f 100644 --- a/grails-encoder/src/main/groovy/org/grails/encoder/impl/XMLCodecFactory.java +++ b/grails-encoder/src/main/groovy/org/grails/encoder/impl/XMLCodecFactory.java @@ -25,6 +25,7 @@ import org.springframework.web.util.HtmlUtils; public class XMLCodecFactory implements CodecFactory { + protected Encoder encoder = new BasicXMLEncoder(); protected Decoder decoder = new Decoder() { public CodecIdentifier getCodecIdentifier() { diff --git a/grails-events/compat/build.gradle b/grails-events/compat/build.gradle index 892c32cd608..be975814056 100644 --- a/grails-events/compat/build.gradle +++ b/grails-events/compat/build.gradle @@ -40,4 +40,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/java-config.gradle') from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-events/compat/src/main/groovy/grails/events/Events.groovy b/grails-events/compat/src/main/groovy/grails/events/Events.groovy index 2291720e005..cc8d98614b2 100644 --- a/grails-events/compat/src/main/groovy/grails/events/Events.groovy +++ b/grails-events/compat/src/main/groovy/grails/events/Events.groovy @@ -51,14 +51,14 @@ trait Events { /** * @see #on(reactor.bus.selector.Selector, reactor.fn.Consumer) */ - def > Registration> on(Selector key, Closure consumer) { + def > Registration> on(Selector key, Closure consumer) { throw new UnsupportedOperationException("Events of type [Selector] are no longer supported. Use string ids") } /** * @see #on(reactor.bus.selector.Selector, reactor.fn.Consumer) */ - def > Registration> on(key, Closure consumer) { + def > Registration> on(key, Closure consumer) { LoggerFactory.getLogger(getClass()).warn("The class [${getClass()}] used the legacy Reactor 2 event bus and needs to be re-compiled") eventBus.on(key.toString(), consumer) as Registration @@ -67,9 +67,9 @@ trait Events { /** * @see #on(reactor.bus.selector.Selector, reactor.fn.Consumer) */ - def > Registration> on(key, Consumer consumer) { + def > Registration> on(key, Consumer consumer) { LoggerFactory.getLogger(getClass()).warn("The class [${getClass()}] used the legacy Reactor 2 event bus and needs to be re-compiled") - if(key instanceof CharSequence) { + if (key instanceof CharSequence) { key = key.toString() } on(key) { @@ -80,7 +80,7 @@ trait Events { /** * @see #on(reactor.bus.selector.Selector, reactor.fn.Consumer) */ - def > Registration> on(Class type, Consumer consumer) { + def > Registration> on(Class type, Consumer consumer) { LoggerFactory.getLogger(getClass()).warn("The class [${getClass()}] used the legacy Reactor 2 event bus and needs to be re-compiled") on(type.name, consumer) } @@ -98,7 +98,7 @@ trait Events { * * @return A {@link Subscription} object that allows the caller to interact with the given mapping */ - def > Registration> on(Selector sel, Consumer consumer) { + def > Registration> on(Selector sel, Consumer consumer) { throw new UnsupportedOperationException("Events of type [Selector] are no longer supported. Use string ids") } @@ -108,13 +108,12 @@ trait Events { @CompileDynamic Bus notify(Object key, Event ev) { LoggerFactory.getLogger(getClass()).warn("The class [${getClass()}] used the legacy Reactor 2 event bus and needs to be re-compiled") - if(eventBus == null) throw new IllegalStateException("EventBus not present. Event notification attempted outside of application context.") - if(ev.replyTo) { - eventBus.sendAndReceive( ev ) { + if (eventBus == null) throw new IllegalStateException("EventBus not present. Event notification attempted outside of application context.") + if (ev.replyTo) { + eventBus.sendAndReceive(ev) { eventBus.notify(ev.replyTo.toString(), it) } - } - else { + } else { eventBus.notify key, ev } return eventBus @@ -130,9 +129,9 @@ trait Events { } def > Bus notify(Object key, Closure supplier) { - if(eventBus == null) throw new IllegalStateException("EventBus not present. Event notification attempted outside of application context.") + if (eventBus == null) throw new IllegalStateException("EventBus not present. Event notification attempted outside of application context.") LoggerFactory.getLogger(getClass()).warn("The class [${getClass()}] used the legacy Reactor 2 event bus and needs to be re-compiled") - eventBus.notify( (CharSequence)key.toString(), supplier.call() ) + eventBus.notify((CharSequence) key.toString(), supplier.call()) return eventBus } @@ -142,14 +141,13 @@ trait Events { return eventBus } - def > Bus sendAndReceive(Object key, Closure reply) { + def > Bus sendAndReceive(Object key, Closure reply) { LoggerFactory.getLogger(getClass()).warn("The class [${getClass()}] used the legacy Reactor 2 event bus and needs to be re-compiled") eventBus.sendAndReceive key.toString(), new grails.events.Event(key.toString(), new Object[0]), reply return eventBus } - /** * Creates an {@link Event} for the given data * @@ -190,7 +188,7 @@ trait Events { */ boolean clearEventConsumers(key) { LoggerFactory.getLogger(getClass()).warn("The class [${getClass()}] used the legacy Reactor 2 event bus and needs to be re-compiled") - if(eventBus) { + if (eventBus) { eventBus.unsubscribeAll(key.toString()) return true } diff --git a/grails-events/compat/src/main/groovy/reactor/bus/Bus.java b/grails-events/compat/src/main/groovy/reactor/bus/Bus.java index c3dc4535c2d..360916c81e3 100644 --- a/grails-events/compat/src/main/groovy/reactor/bus/Bus.java +++ b/grails-events/compat/src/main/groovy/reactor/bus/Bus.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package reactor.bus; import reactor.bus.registry.Subscription; @@ -50,8 +49,8 @@ public interface Bus { * @param consumer The {@literal Consumer} to be triggered * @return A {@link Subscription} object that allows the caller to interact with the given mapping */ - Subscription> on(final Selector selector, - final Consumer consumer); + Subscription> on(Selector selector, + Consumer consumer); /** diff --git a/grails-events/compat/src/main/groovy/reactor/bus/Event.java b/grails-events/compat/src/main/groovy/reactor/bus/Event.java index ff0b2e1fa8e..ec9816cfabf 100644 --- a/grails-events/compat/src/main/groovy/reactor/bus/Event.java +++ b/grails-events/compat/src/main/groovy/reactor/bus/Event.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package reactor.bus; /** @@ -24,7 +23,8 @@ */ @Deprecated public class Event extends grails.events.Event { - private volatile Object replyTo = null; + + private volatile Object replyTo = null; public Event(String id, T data, Object replyTo) { super(id, data); @@ -47,9 +47,7 @@ public Object getReplyTo() { /** * Set the {@code key} that interested parties should send replies to. * - * @param replyTo - * The key to use to notify sender of replies. - * + * @param replyTo The key to use to notify sender of replies. * @return {@literal this} */ public Event setReplyTo(Object replyTo) { diff --git a/grails-events/compat/src/main/groovy/reactor/bus/EventBus.groovy b/grails-events/compat/src/main/groovy/reactor/bus/EventBus.groovy index e00cf6c1433..1d6a00a557c 100644 --- a/grails-events/compat/src/main/groovy/reactor/bus/EventBus.groovy +++ b/grails-events/compat/src/main/groovy/reactor/bus/EventBus.groovy @@ -29,9 +29,10 @@ import reactor.fn.Consumer */ @Deprecated @Slf4j -class EventBus implements Bus { +class EventBus implements Bus { - @Delegate(interfaces = false) grails.events.bus.EventBus eventBus + @Delegate(interfaces = false) + grails.events.bus.EventBus eventBus EventBus(grails.events.bus.EventBus eventBus) { this.eventBus = eventBus diff --git a/grails-events/compat/src/main/groovy/reactor/bus/registry/Registration.groovy b/grails-events/compat/src/main/groovy/reactor/bus/registry/Registration.groovy index 18efa30b7e3..7bfed628249 100644 --- a/grails-events/compat/src/main/groovy/reactor/bus/registry/Registration.groovy +++ b/grails-events/compat/src/main/groovy/reactor/bus/registry/Registration.groovy @@ -23,5 +23,5 @@ package reactor.bus.registry * @deprecated Here for compatibility only. Do not use directly */ @Deprecated -interface Registration extends grails.events.subscriber.Subscription{ +interface Registration extends grails.events.subscriber.Subscription { } \ No newline at end of file diff --git a/grails-events/compat/src/main/groovy/reactor/bus/registry/Subscription.groovy b/grails-events/compat/src/main/groovy/reactor/bus/registry/Subscription.groovy index ab79793252a..2d560678aab 100644 --- a/grails-events/compat/src/main/groovy/reactor/bus/registry/Subscription.groovy +++ b/grails-events/compat/src/main/groovy/reactor/bus/registry/Subscription.groovy @@ -22,4 +22,4 @@ package reactor.bus.registry * @deprecated Here for compatibility only. Do not use directly */ @Deprecated -interface Subscription extends Registration{} \ No newline at end of file +interface Subscription extends Registration {} \ No newline at end of file diff --git a/grails-events/compat/src/main/groovy/reactor/bus/selector/Selector.java b/grails-events/compat/src/main/groovy/reactor/bus/selector/Selector.java index 166b0038259..baddef8f664 100644 --- a/grails-events/compat/src/main/groovy/reactor/bus/selector/Selector.java +++ b/grails-events/compat/src/main/groovy/reactor/bus/selector/Selector.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package reactor.bus.selector; /** @@ -25,8 +24,7 @@ * @deprecated Here for compatibility only. Do not use directly */ @Deprecated -public interface Selector { - +public interface Selector { /** * Get the object being used for comparisons and equals checks. @@ -39,7 +37,6 @@ public interface Selector { * Indicates whether this Selector matches the {@code key}. * * @param key The key to match - * * @return {@code true} if there's a match, otherwise {@code false}. */ boolean matches(T key); diff --git a/grails-events/compat/src/main/groovy/reactor/fn/Consumer.java b/grails-events/compat/src/main/groovy/reactor/fn/Consumer.java index ba2af2fcc66..06ff632dc04 100644 --- a/grails-events/compat/src/main/groovy/reactor/fn/Consumer.java +++ b/grails-events/compat/src/main/groovy/reactor/fn/Consumer.java @@ -13,16 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package reactor.fn; /** * Implementations accept a given value and perform work on the argument. * + * @param the type of values to accept * @author Jon Brisbin * @author Stephane Maldini - * - * @param the type of values to accept * @deprecated Here for compatibility only. Do not use directly */ @Deprecated diff --git a/grails-events/core/build.gradle b/grails-events/core/build.gradle index 38d91983584..96709a91fb7 100644 --- a/grails-events/core/build.gradle +++ b/grails-events/core/build.gradle @@ -47,4 +47,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-events/core/src/main/groovy/grails/events/Event.groovy b/grails-events/core/src/main/groovy/grails/events/Event.groovy index cda2d685555..7b7edf2fde2 100644 --- a/grails-events/core/src/main/groovy/grails/events/Event.groovy +++ b/grails-events/core/src/main/groovy/grails/events/Event.groovy @@ -35,6 +35,7 @@ import groovy.transform.ToString @EqualsAndHashCode @ToString class Event extends EventObject { + /** * The id of the event */ @@ -49,7 +50,7 @@ class Event extends EventObject { final Map parameters Event(String id, T data) { - this(id, Collections.emptyMap() as Map, data) + this(id, Collections.emptyMap() as Map, data) } Event(String id, Map parameters, T data) { diff --git a/grails-events/core/src/main/groovy/grails/events/EventPublisher.groovy b/grails-events/core/src/main/groovy/grails/events/EventPublisher.groovy index 46baf82779f..dc3ec78fc68 100644 --- a/grails-events/core/src/main/groovy/grails/events/EventPublisher.groovy +++ b/grails-events/core/src/main/groovy/grails/events/EventPublisher.groovy @@ -36,7 +36,7 @@ import org.springframework.transaction.event.TransactionPhase trait EventPublisher extends EventBusAware implements EventEmitter { /** - * @see {@link EventEmitter#notify(java.lang.CharSequence, java.lang.Object[])} + * @see {@link EventEmitter#notify(java.lang.CharSequence, java.lang.Object [ ])} */ @Override EventEmitter notify(CharSequence eventId, Object... data) { @@ -68,7 +68,7 @@ trait EventPublisher extends EventBusAware implements EventEmitter { } /** - * @see {@link EventEmitter#notify(java.lang.CharSequence, java.lang.Object[])} )} + * @see {@link EventEmitter#notify(java.lang.CharSequence, java.lang.Object [ ])} )} */ @Override EventEmitter publish(CharSequence eventId, Object... data) { diff --git a/grails-events/core/src/main/groovy/grails/events/bus/EventBusAware.groovy b/grails-events/core/src/main/groovy/grails/events/bus/EventBusAware.groovy index bcae822f34f..d97921754ce 100644 --- a/grails-events/core/src/main/groovy/grails/events/bus/EventBusAware.groovy +++ b/grails-events/core/src/main/groovy/grails/events/bus/EventBusAware.groovy @@ -49,7 +49,7 @@ trait EventBusAware { * @return Retrieves the event bus */ EventBus getEventBus() { - if(this.eventBus == null) { + if (this.eventBus == null) { this.eventBus = new EventBusBuilder().build() } return this.eventBus diff --git a/grails-events/core/src/main/groovy/grails/events/bus/EventBusBuilder.groovy b/grails-events/core/src/main/groovy/grails/events/bus/EventBusBuilder.groovy index 00860a6d54d..02822109db7 100644 --- a/grails-events/core/src/main/groovy/grails/events/bus/EventBusBuilder.groovy +++ b/grails-events/core/src/main/groovy/grails/events/bus/EventBusBuilder.groovy @@ -38,15 +38,13 @@ class EventBusBuilder { */ EventBus build() { List eventBuses = ServiceLoader.load(EventBus).toList() - if(eventBuses.size() == 1) { + if (eventBuses.size() == 1) { EventBus eventBus = eventBuses.get(0) log.debug('Found event bus class to use [{}]', eventBus.getClass().name) return eventBus - } - else if(eventBuses.size() > 1) { + } else if (eventBuses.size() > 1) { throw new IllegalStateException("More than one event bus implementation found on classpath ${eventBuses}. Remove one to continue.") - } - else { + } else { return createDefaultEventBus() } } diff --git a/grails-events/core/src/main/groovy/grails/events/emitter/EventEmitter.groovy b/grails-events/core/src/main/groovy/grails/events/emitter/EventEmitter.groovy index e6e8245da06..945a11d3304 100644 --- a/grails-events/core/src/main/groovy/grails/events/emitter/EventEmitter.groovy +++ b/grails-events/core/src/main/groovy/grails/events/emitter/EventEmitter.groovy @@ -38,7 +38,7 @@ interface EventEmitter { * * @return This emitter */ - EventEmitter notify(CharSequence eventId, Object...data) + EventEmitter notify(CharSequence eventId, Object... data) /** * Notify of an event @@ -62,7 +62,7 @@ interface EventEmitter { /** * Synonym for {@link #notify(Event)} */ - EventEmitter publish(CharSequence eventId, Object...data) + EventEmitter publish(CharSequence eventId, Object... data) /** * Synonym for {@link #notify(Event)} diff --git a/grails-events/core/src/main/groovy/grails/events/subscriber/MethodEventSubscriber.groovy b/grails-events/core/src/main/groovy/grails/events/subscriber/MethodEventSubscriber.groovy index 2a909f33e6d..410b17abe2f 100644 --- a/grails-events/core/src/main/groovy/grails/events/subscriber/MethodEventSubscriber.groovy +++ b/grails-events/core/src/main/groovy/grails/events/subscriber/MethodEventSubscriber.groovy @@ -33,11 +33,11 @@ import java.lang.reflect.Method */ @AutoFinal @CompileStatic -class MethodEventSubscriber extends MethodSubscriber implements EventSubscriber { +class MethodEventSubscriber extends MethodSubscriber implements EventSubscriber { MethodEventSubscriber(Object target, Method method) { super(target, method) - if( !(parameterTypes.length == 1 && parameterTypes[0].isAssignableFrom(Event)) ) { + if (!(parameterTypes.length == 1 && parameterTypes[0].isAssignableFrom(Event))) { throw new IllegalArgumentException('Specified method must accept an Event as an argument') } } diff --git a/grails-events/core/src/main/groovy/grails/events/subscriber/MethodSubscriber.groovy b/grails-events/core/src/main/groovy/grails/events/subscriber/MethodSubscriber.groovy index 31f11847afc..3c1439ff572 100644 --- a/grails-events/core/src/main/groovy/grails/events/subscriber/MethodSubscriber.groovy +++ b/grails-events/core/src/main/groovy/grails/events/subscriber/MethodSubscriber.groovy @@ -19,7 +19,7 @@ package grails.events.subscriber -import grails.events.Event + import groovy.transform.AutoFinal import groovy.transform.CompileStatic import groovy.transform.EqualsAndHashCode @@ -70,44 +70,39 @@ class MethodSubscriber implements Subscriber { return ReflectionUtils.invokeMethod(method, target) as R case 1: Class parameterType = parameterTypes[0] - if(parameterType.isInstance(arg)) { + if (parameterType.isInstance(arg)) { return ReflectionUtils.invokeMethod(method, target, arg) as R - } - else { + } else { def converted = conversionService.canConvert(arg.getClass(), parameterType) ? conversionService.convert(arg, parameterType) : null - if(converted != null) { + if (converted != null) { return ReflectionUtils.invokeMethod(method, target, converted) as R - } - else { + } else { log.debug('Could not convert Event argument [{}] to required type to invoke listener [{}]. Ignoring.', arg, method) break } } default: - if(arg != null && arg.getClass().isArray()) { + if (arg != null && arg.getClass().isArray()) { Object[] array = (Object[]) arg - if(array.length == parameterLength) { + if (array.length == parameterLength) { Object[] converted = new Object[array.length] int i = 0 - for(o in array) { + for (o in array) { Class parameterType = parameterTypes[i] - if(parameterType.isInstance(o)) { + if (parameterType.isInstance(o)) { converted[i] = array[i] - } - else { + } else { converted[i] = conversionService.convert(o, parameterType) } i++ } return ReflectionUtils.invokeMethod(method, target, converted) as R - } - else { + } else { log.debug("Could not convert Event argument [{}] to required type to invoke listener [{}]. Ignoring.", arg, method) break } - } - else { + } else { log.debug("Could not convert Event argument [{}] to required type to invoke listener [{}]. Ignoring.", arg, method) break } diff --git a/grails-events/core/src/main/groovy/org/grails/events/ClosureEventTrigger.groovy b/grails-events/core/src/main/groovy/org/grails/events/ClosureEventTrigger.groovy index d3fbf68e83e..44375197829 100644 --- a/grails-events/core/src/main/groovy/org/grails/events/ClosureEventTrigger.groovy +++ b/grails-events/core/src/main/groovy/org/grails/events/ClosureEventTrigger.groovy @@ -48,7 +48,7 @@ class ClosureEventTrigger implements EventTrigger { this.subscriberClosure = subscriber this.reply = reply this.data = event.data - Closure closure = (Closure)subscriber + Closure closure = (Closure) subscriber Class[] parameterTypes = closure.parameterTypes this.argCount = parameterTypes.length this.eventArg = argCount == 1 && Event.isAssignableFrom(parameterTypes[0]) @@ -61,31 +61,28 @@ class ClosureEventTrigger implements EventTrigger { @Override Object proceed() { - int dataLength = data.getClass().isArray() ? ((Object[])data).length : 1 + int dataLength = data.getClass().isArray() ? ((Object[]) data).length : 1 boolean isSpread = !eventArg && dataLength > 1 && argCount == dataLength try { def result - if(isSpread) { + if (isSpread) { result = callSpread(subscriberClosure, data) - } - else { - if(eventArg) { + } else { + if (eventArg) { result = subscriberClosure.call(event) - } - else { + } else { result = subscriberClosure.call(data) } } - if(reply != null) { + if (reply != null) { return reply.call(result) } return result } catch (Throwable e) { - if(reply != null && reply.parameterTypes && reply.parameterTypes[0].isInstance(e)) { + if (reply != null && reply.parameterTypes && reply.parameterTypes[0].isInstance(e)) { reply.call(e) - } - else { + } else { throw e } } diff --git a/grails-events/core/src/main/groovy/org/grails/events/EventSubscriberTrigger.groovy b/grails-events/core/src/main/groovy/org/grails/events/EventSubscriberTrigger.groovy index 57a8cb9ee1e..cffb63f1d21 100644 --- a/grails-events/core/src/main/groovy/org/grails/events/EventSubscriberTrigger.groovy +++ b/grails-events/core/src/main/groovy/org/grails/events/EventSubscriberTrigger.groovy @@ -49,10 +49,9 @@ class EventSubscriberTrigger implements EventTrigger { @Override Object proceed() { try { - if(subscriber instanceof EventSubscriber) { + if (subscriber instanceof EventSubscriber) { return subscriber.call(event) - } - else { + } else { return subscriber.call(event.data) } } catch (Throwable e) { diff --git a/grails-events/core/src/main/groovy/org/grails/events/bus/AbstractEventBus.groovy b/grails-events/core/src/main/groovy/org/grails/events/bus/AbstractEventBus.groovy index 4ac97fdc198..31f92e4c998 100644 --- a/grails-events/core/src/main/groovy/org/grails/events/bus/AbstractEventBus.groovy +++ b/grails-events/core/src/main/groovy/org/grails/events/bus/AbstractEventBus.groovy @@ -99,8 +99,8 @@ abstract class AbstractEventBus implements EventBus { @Override Subjects unsubscribeAll(CharSequence event) { def subs = subscriptions.get(event.toString()) - for(sub in subs) { - if(!sub.isCancelled()) { + for (sub in subs) { + if (!sub.isCancelled()) { sub.cancel() } } @@ -109,14 +109,13 @@ abstract class AbstractEventBus implements EventBus { } EventEmitter notify(Event event) { - if(TransactionSynchronizationManager.isSynchronizationActive()) { + if (TransactionSynchronizationManager.isSynchronizationActive()) { notify(event, TransactionPhase.AFTER_COMMIT) - } - else { + } else { String eventId = event.id - if(subscriptions.containsKey(eventId)) { + if (subscriptions.containsKey(eventId)) { Collection eventSubscriptions = subscriptions.get(event.id) - if(!eventSubscriptions.isEmpty()) { + if (!eventSubscriptions.isEmpty()) { buildNotificationTrigger(event, eventSubscriptions) .run() } @@ -127,14 +126,14 @@ abstract class AbstractEventBus implements EventBus { @Override EventEmitter sendAndReceive(Event event, Closure reply) { - if(event == null) throw new IllegalArgumentException("Argument [event] cannot be null") - if(event == null) throw new IllegalArgumentException("Argument [reply] cannot be null") + if (event == null) throw new IllegalArgumentException("Argument [event] cannot be null") + if (event == null) throw new IllegalArgumentException("Argument [reply] cannot be null") String eventId = event.id - if(subscriptions.containsKey(eventId)) { + if (subscriptions.containsKey(eventId)) { Collection eventSubscriptions = subscriptions.get(eventId) - if(!eventSubscriptions.isEmpty()) { + if (!eventSubscriptions.isEmpty()) { buildNotificationTrigger(event, eventSubscriptions, reply) - .run() + .run() } } this @@ -142,17 +141,16 @@ abstract class AbstractEventBus implements EventBus { @Override EventEmitter notify(Event event, TransactionPhase transactionPhase) { - if(TransactionSynchronizationManager.isSynchronizationActive()) { + if (TransactionSynchronizationManager.isSynchronizationActive()) { String eventId = event.getId() Collection eventSubscriptions = subscriptions.get(eventId) - if(!eventSubscriptions.isEmpty()) { + if (!eventSubscriptions.isEmpty()) { TransactionSynchronizationManager.registerSynchronization( - new EventTriggerTransactionSynchronization(buildNotificationTrigger(event, eventSubscriptions), transactionPhase) + new EventTriggerTransactionSynchronization(buildNotificationTrigger(event, eventSubscriptions), transactionPhase) ) } return this - } - else { + } else { return notify(event) } } @@ -170,6 +168,7 @@ abstract class AbstractEventBus implements EventBus { final Callable callable = buildNotificationCallable(event, eventSubscriptions, reply) new NotificationTrigger(event, eventSubscriptions, reply) { + @Override void run() { callable.call() @@ -212,24 +211,23 @@ abstract class AbstractEventBus implements EventBus { @Override void beforeCommit(boolean readOnly) { - if(transactionPhase == TransactionPhase.BEFORE_COMMIT && !readOnly) { + if (transactionPhase == TransactionPhase.BEFORE_COMMIT && !readOnly) { notificationTrigger.run() } } @Override void afterCommit() { - if(transactionPhase == TransactionPhase.AFTER_COMMIT) { + if (transactionPhase == TransactionPhase.AFTER_COMMIT) { notificationTrigger.run() } } @Override void afterCompletion(int status) { - if(transactionPhase == TransactionPhase.AFTER_COMPLETION && status == STATUS_COMMITTED) { + if (transactionPhase == TransactionPhase.AFTER_COMPLETION && status == STATUS_COMMITTED) { notificationTrigger.run() - } - else if(transactionPhase == TransactionPhase.AFTER_ROLLBACK && status == STATUS_ROLLED_BACK) { + } else if (transactionPhase == TransactionPhase.AFTER_ROLLBACK && status == STATUS_ROLLED_BACK) { notificationTrigger.run() } } diff --git a/grails-events/core/src/main/groovy/org/grails/events/bus/ExecutorEventBus.groovy b/grails-events/core/src/main/groovy/org/grails/events/bus/ExecutorEventBus.groovy index 4117dba7dab..29bec419ede 100644 --- a/grails-events/core/src/main/groovy/org/grails/events/bus/ExecutorEventBus.groovy +++ b/grails-events/core/src/main/groovy/org/grails/events/bus/ExecutorEventBus.groovy @@ -49,8 +49,8 @@ class ExecutorEventBus extends AbstractEventBus { @Override protected Callable buildNotificationCallable(Event event, Collection eventSubscriptions, Closure reply) { Executor executor = this.executor - if(executor instanceof ExecutorService) { - ExecutorService executorService = (ExecutorService)this.executor + if (executor instanceof ExecutorService) { + ExecutorService executorService = (ExecutorService) this.executor return { executorService.submit { for (Subscription subscription in eventSubscriptions) { @@ -59,8 +59,7 @@ class ExecutorEventBus extends AbstractEventBus { } } } - } - else { + } else { return { executor.execute { for (Subscription subscription in eventSubscriptions) { diff --git a/grails-events/core/src/main/groovy/org/grails/events/bus/SynchronousEventBus.groovy b/grails-events/core/src/main/groovy/org/grails/events/bus/SynchronousEventBus.groovy index 53b323100bc..4eb3eb3b97a 100644 --- a/grails-events/core/src/main/groovy/org/grails/events/bus/SynchronousEventBus.groovy +++ b/grails-events/core/src/main/groovy/org/grails/events/bus/SynchronousEventBus.groovy @@ -39,7 +39,7 @@ class SynchronousEventBus extends AbstractEventBus { @Override protected Callable buildNotificationCallable(Event event, Collection eventSubscriptions, Closure reply) { return { - for(Subscription subscription : eventSubscriptions) { + for (Subscription subscription : eventSubscriptions) { subscription.buildTrigger(event, reply) .proceed() } diff --git a/grails-events/core/src/main/groovy/org/grails/events/bus/spring/EventBusFactoryBean.groovy b/grails-events/core/src/main/groovy/org/grails/events/bus/spring/EventBusFactoryBean.groovy index fe9b4e70492..4da1d560063 100644 --- a/grails-events/core/src/main/groovy/org/grails/events/bus/spring/EventBusFactoryBean.groovy +++ b/grails-events/core/src/main/groovy/org/grails/events/bus/spring/EventBusFactoryBean.groovy @@ -66,11 +66,11 @@ class EventBusFactoryBean extends EventBusBuilder implements FactoryBean eventClassToName = new ConcurrentHashMap().withDefault { Class eventClass -> def clsName = eventClass.name def logicalName = GrailsNameUtils.getLogicalPropertyName(clsName, EVENT_SUFFIX) - if(clsName.startsWith(GDM_EVENT_PACKAGE)) { + if (clsName.startsWith(GDM_EVENT_PACKAGE)) { return "gorm:${logicalName}".toString() - } - else if(clsName.startsWith(SPRING_PACKAGE)) { + } else if (clsName.startsWith(SPRING_PACKAGE)) { return "spring:${logicalName}".toString() - } - else { + } else { return "grails:${logicalName}".toString() } } @@ -68,9 +66,9 @@ class SpringEventTranslator implements ApplicationListener, ApplicationContextA void onApplicationEvent(ApplicationEvent event) { def eventName = eventClassToName[event.getClass()] - if(eventBus.isActive()) { + if (eventBus.isActive()) { // don't relay context closed events because Reactor would have been shutdown - if(!(event instanceof ContextClosedEvent)) { + if (!(event instanceof ContextClosedEvent)) { eventBus.notify(eventName, event) } } @@ -78,6 +76,6 @@ class SpringEventTranslator implements ApplicationListener, ApplicationContextA @Override void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - ((GenericApplicationContext)applicationContext).addApplicationListener(this) + ((GenericApplicationContext) applicationContext).addApplicationListener(this) } } diff --git a/grails-events/plugin/src/main/groovy/org/grails/plugins/events/EventBusGrailsPlugin.groovy b/grails-events/plugin/src/main/groovy/org/grails/plugins/events/EventBusGrailsPlugin.groovy index 5cb71ef75d1..c37a6d0d1d0 100644 --- a/grails-events/plugin/src/main/groovy/org/grails/plugins/events/EventBusGrailsPlugin.groovy +++ b/grails-events/plugin/src/main/groovy/org/grails/plugins/events/EventBusGrailsPlugin.groovy @@ -43,7 +43,7 @@ class EventBusGrailsPlugin extends Plugin { @Override Closure doWithSpring() { - {-> + { -> Config config = grailsApplication.config grailsEventBus(EventBusFactoryBean) gormDispatchEventRegistrar(GormDispatcherRegistrar, ref("grailsEventBus")) @@ -53,7 +53,7 @@ class EventBusGrailsPlugin extends Plugin { // make it possible to enable reactor events - if(config.getProperty(TRANSLATE_SPRING_EVENTS, Boolean.class, false)) { + if (config.getProperty(TRANSLATE_SPRING_EVENTS, Boolean.class, false)) { springEventTranslator(SpringEventTranslator, ref('grailsEventBus')) } } diff --git a/grails-events/rxjava/build.gradle b/grails-events/rxjava/build.gradle index ebb69b7437e..6b670ad6e79 100644 --- a/grails-events/rxjava/build.gradle +++ b/grails-events/rxjava/build.gradle @@ -51,4 +51,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-events/rxjava/src/main/groovy/org/grails/events/rxjava/RxEventBus.groovy b/grails-events/rxjava/src/main/groovy/org/grails/events/rxjava/RxEventBus.groovy index 69806a5e645..d6468fd81b2 100644 --- a/grails-events/rxjava/src/main/groovy/org/grails/events/rxjava/RxEventBus.groovy +++ b/grails-events/rxjava/src/main/groovy/org/grails/events/rxjava/RxEventBus.groovy @@ -21,8 +21,8 @@ package org.grails.events.rxjava import grails.events.Event import grails.events.subscriber.Subscriber -import grails.events.trigger.EventTrigger import grails.events.subscriber.Subscription +import grails.events.trigger.EventTrigger import groovy.transform.AutoFinal import groovy.transform.CompileStatic import groovy.util.logging.Slf4j @@ -82,11 +82,10 @@ class RxEventBus extends AbstractEventBus { protected Callable buildNotificationCallable(Event event, Collection eventSubscriptions, Closure reply) { return { PublishSubject sub = subjects.get(event.id) - if(sub.hasObservers() && !sub.hasCompleted()) { - if(reply != null) { + if (sub.hasObservers() && !sub.hasCompleted()) { + if (reply != null) { sub.onNext(new EventWithReply(event, reply)) - } - else { + } else { sub.onNext(event) } } @@ -99,28 +98,27 @@ class RxEventBus extends AbstractEventBus { RxClosureSubscription(CharSequence eventId, Map> subscriptions, Closure subscriber, Subject subject, Scheduler scheduler) { super(eventId, subscriptions, subscriber) - this.subscription = subject.observeOn(scheduler).subscribe( { eventObject -> + this.subscription = subject.observeOn(scheduler).subscribe({ eventObject -> Event event Closure reply = null - if(eventObject instanceof EventWithReply) { + if (eventObject instanceof EventWithReply) { def eventWithReply = (EventWithReply) eventObject event = eventWithReply.event reply = eventWithReply.reply - } - else { + } else { event = (Event) eventObject } EventTrigger trigger = buildTrigger(event as Event, reply) trigger.proceed() - } as Action1, { Throwable t -> + } as Action1, { Throwable t -> log.error("Error occurred triggering event listener for event [$eventId]: ${t.message}", t) } as Action1) } @Override Subscription cancel() { - if(!subscription.unsubscribed) { + if (!subscription.unsubscribed) { subscription.unsubscribe() } super.cancel() @@ -148,7 +146,7 @@ class RxEventBus extends AbstractEventBus { @Override Subscription cancel() { - if(!subscription.unsubscribed) { + if (!subscription.unsubscribed) { subscription.unsubscribe() } super.cancel() diff --git a/grails-events/rxjava2/build.gradle b/grails-events/rxjava2/build.gradle index 0697285af6b..533ca8a7926 100644 --- a/grails-events/rxjava2/build.gradle +++ b/grails-events/rxjava2/build.gradle @@ -47,4 +47,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-events/rxjava2/src/main/groovy/org/grails/events/rxjava2/RxEventBus.groovy b/grails-events/rxjava2/src/main/groovy/org/grails/events/rxjava2/RxEventBus.groovy index a0283fa4085..4f024ca382a 100644 --- a/grails-events/rxjava2/src/main/groovy/org/grails/events/rxjava2/RxEventBus.groovy +++ b/grails-events/rxjava2/src/main/groovy/org/grails/events/rxjava2/RxEventBus.groovy @@ -21,8 +21,8 @@ package org.grails.events.rxjava2 import grails.events.Event import grails.events.subscriber.Subscriber -import grails.events.trigger.EventTrigger import grails.events.subscriber.Subscription +import grails.events.trigger.EventTrigger import groovy.transform.AutoFinal import groovy.transform.CompileStatic import groovy.util.logging.Slf4j @@ -65,11 +65,10 @@ class RxEventBus extends AbstractEventBus { protected Callable buildNotificationCallable(Event event, Collection eventSubscriptions, Closure reply) { return { PublishSubject sub = subjects.get(event.id) - if(sub.hasObservers() && !sub.hasComplete()) { - if(reply != null) { + if (sub.hasObservers() && !sub.hasComplete()) { + if (reply != null) { sub.onNext(new EventWithReply(event, reply)) - } - else { + } else { sub.onNext(event) } } @@ -100,28 +99,27 @@ class RxEventBus extends AbstractEventBus { RxClosureSubscription(CharSequence eventId, Map> subscriptions, Closure subscriber, Subject subject, Scheduler scheduler) { super(eventId, subscriptions, subscriber) - this.subscription = subject.observeOn(scheduler).subscribe( { eventObject -> + this.subscription = subject.observeOn(scheduler).subscribe({ eventObject -> Event event Closure reply = null - if(eventObject instanceof EventWithReply) { + if (eventObject instanceof EventWithReply) { def eventWithReply = (EventWithReply) eventObject event = eventWithReply.event reply = eventWithReply.reply - } - else { + } else { event = (Event) eventObject } EventTrigger trigger = buildTrigger(event as Event, reply) trigger.proceed() - } as Consumer, { Throwable t -> + } as Consumer, { Throwable t -> log.error("Error occurred triggering event listener for event [$eventId]: ${t.message}", t) } as Consumer) } @Override Subscription cancel() { - if(!subscription.disposed) { + if (!subscription.disposed) { subscription.dispose() } return super.cancel() @@ -139,17 +137,17 @@ class RxEventBus extends AbstractEventBus { RxEventSubscriberSubscription(CharSequence eventId, Map> subscriptions, Subscriber subscriber, Subject subject, Scheduler scheduler) { super(eventId, subscriptions, subscriber) - this.subscription = subject.observeOn(scheduler).subscribe( { event -> + this.subscription = subject.observeOn(scheduler).subscribe({ event -> EventTrigger trigger = buildTrigger(event as Event) trigger.proceed() - } as Consumer, { Throwable t -> + } as Consumer, { Throwable t -> log.error("Error occurred triggering event listener for event [$eventId]: ${t.message}", t) } as Consumer) } @Override Subscription cancel() { - if(!subscription.disposed) { + if (!subscription.disposed) { subscription.dispose() } return super.cancel() diff --git a/grails-events/rxjava3/build.gradle b/grails-events/rxjava3/build.gradle index 040c9bb1629..63cedc4b6a1 100644 --- a/grails-events/rxjava3/build.gradle +++ b/grails-events/rxjava3/build.gradle @@ -47,4 +47,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-events/rxjava3/src/main/groovy/org/grails/events/rxjava3/RxEventBus.groovy b/grails-events/rxjava3/src/main/groovy/org/grails/events/rxjava3/RxEventBus.groovy index e3a7d316bc8..2b60941746b 100644 --- a/grails-events/rxjava3/src/main/groovy/org/grails/events/rxjava3/RxEventBus.groovy +++ b/grails-events/rxjava3/src/main/groovy/org/grails/events/rxjava3/RxEventBus.groovy @@ -21,8 +21,8 @@ package org.grails.events.rxjava3 import grails.events.Event import grails.events.subscriber.Subscriber -import grails.events.trigger.EventTrigger import grails.events.subscriber.Subscription +import grails.events.trigger.EventTrigger import groovy.transform.AutoFinal import groovy.transform.CompileStatic import groovy.util.logging.Slf4j @@ -61,11 +61,10 @@ class RxEventBus extends AbstractEventBus { protected Callable buildNotificationCallable(Event event, Collection eventSubscriptions, Closure reply) { return { PublishSubject sub = subjects.get(event.id) - if(sub.hasObservers() && !sub.hasComplete()) { - if(reply != null) { + if (sub.hasObservers() && !sub.hasComplete()) { + if (reply != null) { sub.onNext(new EventWithReply(event, reply)) - } - else { + } else { sub.onNext(event) } } @@ -96,28 +95,27 @@ class RxEventBus extends AbstractEventBus { RxClosureSubscription(CharSequence eventId, Map> subscriptions, Closure subscriber, Subject subject, Scheduler scheduler) { super(eventId, subscriptions, subscriber) - this.subscription = subject.observeOn(scheduler).subscribe( { eventObject -> + this.subscription = subject.observeOn(scheduler).subscribe({ eventObject -> Event event Closure reply = null - if(eventObject instanceof EventWithReply) { + if (eventObject instanceof EventWithReply) { def eventWithReply = (EventWithReply) eventObject event = eventWithReply.event reply = eventWithReply.reply - } - else { + } else { event = (Event) eventObject } EventTrigger trigger = buildTrigger(event as Event, reply) trigger.proceed() - } as Consumer, { Throwable t -> + } as Consumer, { Throwable t -> log.error("Error occurred triggering event listener for event [$eventId]: ${t.message}", t) } as Consumer) } @Override Subscription cancel() { - if(!subscription.disposed) { + if (!subscription.disposed) { subscription.dispose() } return super.cancel() @@ -135,17 +133,17 @@ class RxEventBus extends AbstractEventBus { RxEventSubscriberSubscription(CharSequence eventId, Map> subscriptions, Subscriber subscriber, Subject subject, Scheduler scheduler) { super(eventId, subscriptions, subscriber) - this.subscription = subject.observeOn(scheduler).subscribe( { event -> + this.subscription = subject.observeOn(scheduler).subscribe({ event -> EventTrigger trigger = buildTrigger(event as Event) trigger.proceed() - } as Consumer, { Throwable t -> + } as Consumer, { Throwable t -> log.error("Error occurred triggering event listener for event [$eventId]: ${t.message}", t) } as Consumer) } @Override Subscription cancel() { - if(!subscription.disposed) { + if (!subscription.disposed) { subscription.dispose() } return super.cancel() diff --git a/grails-events/spring/build.gradle b/grails-events/spring/build.gradle index abdba357213..47aa4c94cb3 100644 --- a/grails-events/spring/build.gradle +++ b/grails-events/spring/build.gradle @@ -47,4 +47,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-events/spring/src/main/groovy/org/grails/events/spring/SpringEventBus.groovy b/grails-events/spring/src/main/groovy/org/grails/events/spring/SpringEventBus.groovy index c981b977239..4a0152e40b4 100644 --- a/grails-events/spring/src/main/groovy/org/grails/events/spring/SpringEventBus.groovy +++ b/grails-events/spring/src/main/groovy/org/grails/events/spring/SpringEventBus.groovy @@ -68,9 +68,9 @@ class SpringEventBus extends AbstractEventBus { void onApplicationEvent(SpringEventBusEvent event) { Event e = event.source Closure reply = event.replyTo - for(reg in registrations.get(e.id)) { + for (reg in registrations.get(e.id)) { reg.buildTrigger(e, reply) - .proceed() + .proceed() } } } diff --git a/grails-events/transforms/build.gradle b/grails-events/transforms/build.gradle index 6a43d17adf3..1946ccbfca3 100644 --- a/grails-events/transforms/build.gradle +++ b/grails-events/transforms/build.gradle @@ -64,4 +64,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-events/transforms/src/main/groovy/org/grails/events/EventIdUtils.groovy b/grails-events/transforms/src/main/groovy/org/grails/events/EventIdUtils.groovy index 1e4ba92a5b0..894db93c4a9 100644 --- a/grails-events/transforms/src/main/groovy/org/grails/events/EventIdUtils.groovy +++ b/grails-events/transforms/src/main/groovy/org/grails/events/EventIdUtils.groovy @@ -25,8 +25,9 @@ import groovy.transform.CompileStatic @AutoFinal @CompileStatic class EventIdUtils { + static String eventIdForMethodName(String methodName) { - if(methodName ==~ /on[A-Z]\S*/) { + if (methodName ==~ /on[A-Z]\S*/) { String methodNameWithoutPrefix = methodName.substring(2) return "${methodNameWithoutPrefix[0].toLowerCase(Locale.ENGLISH)}${methodNameWithoutPrefix.substring(1)}" } diff --git a/grails-events/transforms/src/main/groovy/org/grails/events/gorm/GormAnnotatedListener.groovy b/grails-events/transforms/src/main/groovy/org/grails/events/gorm/GormAnnotatedListener.groovy index f0cf3fe2795..94e0be42848 100644 --- a/grails-events/transforms/src/main/groovy/org/grails/events/gorm/GormAnnotatedListener.groovy +++ b/grails-events/transforms/src/main/groovy/org/grails/events/gorm/GormAnnotatedListener.groovy @@ -22,7 +22,6 @@ package org.grails.events.gorm import grails.events.annotation.gorm.Listener import groovy.transform.AutoFinal import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -55,10 +54,10 @@ trait GormAnnotatedListener extends GormAnnotatedSubscriber { */ void dispatch(AbstractPersistenceEvent event) { def entity = event.getEntityObject() - for(Method method : getSubscribedMethods()) { + for (Method method : getSubscribedMethods()) { Class[] types = method.getAnnotation(Listener)?.value() boolean applies = types == null || types.length == 0 || types.any() { Class cls -> cls.isInstance(entity) } - if(applies && method.parameterTypes[0].isInstance(event)) { + if (applies && method.parameterTypes[0].isInstance(event)) { try { log.debug("Invoking method [{}] for event [{}]", method, event) ReflectionUtils.invokeMethod(method, this, event) diff --git a/grails-events/transforms/src/main/groovy/org/grails/events/gorm/GormDispatcherRegistrar.groovy b/grails-events/transforms/src/main/groovy/org/grails/events/gorm/GormDispatcherRegistrar.groovy index 435f2701863..5f7f7bc336c 100644 --- a/grails-events/transforms/src/main/groovy/org/grails/events/gorm/GormDispatcherRegistrar.groovy +++ b/grails-events/transforms/src/main/groovy/org/grails/events/gorm/GormDispatcherRegistrar.groovy @@ -19,7 +19,7 @@ package org.grails.events.gorm -import grails.events.annotation.Subscriber + import grails.events.bus.EventBus import groovy.transform.AutoFinal import groovy.transform.CompileStatic @@ -41,8 +41,10 @@ import org.springframework.context.ApplicationEventPublisher @CompileStatic class GormDispatcherRegistrar implements FactoryBean, InitializingBean { - @Autowired(required = false) Datastore[] datastores - @Autowired(required = false) GormAnnotatedSubscriber[] subscribers + @Autowired(required = false) + Datastore[] datastores + @Autowired(required = false) + GormAnnotatedSubscriber[] subscribers protected final EventBus eventBus @@ -67,23 +69,22 @@ class GormDispatcherRegistrar implements FactoryBean, I @Override void afterPropertiesSet() throws Exception { - if(datastores && subscribers && eventBus != null) { + if (datastores && subscribers && eventBus != null) { Set> subscribedEvents = [] List listeners = [] - for(sub in subscribers) { - if(sub instanceof GormAnnotatedListener) { - listeners.add((GormAnnotatedListener)sub) - } - else { + for (sub in subscribers) { + if (sub instanceof GormAnnotatedListener) { + listeners.add((GormAnnotatedListener) sub) + } else { subscribedEvents.addAll(sub.getSubscribedEvents()) } } - for(Datastore datastore in datastores) { + for (Datastore datastore in datastores) { ApplicationEventPublisher applicationEventPublisher = datastore.getApplicationEventPublisher() - if(applicationEventPublisher instanceof ConfigurableApplicationEventPublisher) { + if (applicationEventPublisher instanceof ConfigurableApplicationEventPublisher) { - GormEventDispatcher eventDispatcher = new GormEventDispatcher(eventBus, datastore, subscribedEvents, listeners ) - ((ConfigurableApplicationEventPublisher)applicationEventPublisher).addApplicationListener( + GormEventDispatcher eventDispatcher = new GormEventDispatcher(eventBus, datastore, subscribedEvents, listeners) + ((ConfigurableApplicationEventPublisher) applicationEventPublisher).addApplicationListener( eventDispatcher ) } diff --git a/grails-events/transforms/src/main/groovy/org/grails/events/gorm/GormEventDispatcher.groovy b/grails-events/transforms/src/main/groovy/org/grails/events/gorm/GormEventDispatcher.groovy index c77dc765814..9622185edc9 100644 --- a/grails-events/transforms/src/main/groovy/org/grails/events/gorm/GormEventDispatcher.groovy +++ b/grails-events/transforms/src/main/groovy/org/grails/events/gorm/GormEventDispatcher.groovy @@ -39,27 +39,27 @@ import java.beans.Introspector @CompileStatic class GormEventDispatcher extends AbstractPersistenceEventListener { - private static final String GORM_NAMESPACE = "gorm:" protected final EventBus eventBus protected final Map, String> subscribedEvents protected final Set> listenedForEvents = [] protected final List listeners protected final boolean hasEventSubscribers protected final boolean hasListeners + private static final String GORM_NAMESPACE = "gorm:" GormEventDispatcher(EventBus eventBus, Datastore datastore, Set> subscribedEvents, List listeners) { super(datastore) this.eventBus = eventBus Map, String> subscribedEventMap = [:] - for(event in subscribedEvents) { + for (event in subscribedEvents) { subscribedEventMap.put(event, GORM_NAMESPACE + (Introspector.decapitalize(event.simpleName) - "Event")) } this.subscribedEvents = Collections.unmodifiableMap(subscribedEventMap) this.listeners = Collections.unmodifiableList(listeners) this.hasListeners = !listeners.isEmpty() this.hasEventSubscribers = !subscribedEvents.isEmpty() || hasListeners - if(hasListeners) { - for(listener in listeners) { + if (hasListeners) { + for (listener in listeners) { listenedForEvents.addAll(listener.subscribedEvents) } } @@ -67,16 +67,16 @@ class GormEventDispatcher extends AbstractPersistenceEventListener { @Override protected void onPersistenceEvent(AbstractPersistenceEvent event) { - if(hasListeners && listenedForEvents.contains(event.getClass())) { - for(listener in listeners) { - if(listener.supports(event)) { + if (hasListeners && listenedForEvents.contains(event.getClass())) { + for (listener in listeners) { + if (listener.supports(event)) { listener.dispatch(event) } } } String eventName = subscribedEvents.get(event.getClass()) - if(eventName != null) { + if (eventName != null) { eventBus.notify(eventName, event) } } @@ -90,6 +90,6 @@ class GormEventDispatcher extends AbstractPersistenceEventListener { boolean supportsEventType(Class aClass) { return hasEventSubscribers && AbstractPersistenceEvent.isAssignableFrom(aClass) && - (subscribedEvents.containsKey(aClass) || listenedForEvents.contains(aClass) ) + (subscribedEvents.containsKey(aClass) || listenedForEvents.contains(aClass)) } } diff --git a/grails-events/transforms/src/main/groovy/org/grails/events/transform/AnnotatedSubscriber.groovy b/grails-events/transforms/src/main/groovy/org/grails/events/transform/AnnotatedSubscriber.groovy index b551ae94398..284e2ed1f22 100644 --- a/grails-events/transforms/src/main/groovy/org/grails/events/transform/AnnotatedSubscriber.groovy +++ b/grails-events/transforms/src/main/groovy/org/grails/events/transform/AnnotatedSubscriber.groovy @@ -21,16 +21,16 @@ package org.grails.events.transform import grails.events.Event import grails.events.annotation.Events +import grails.events.annotation.Subscriber import grails.events.bus.EventBusAware import grails.events.subscriber.MethodEventSubscriber import grails.events.subscriber.MethodSubscriber -import grails.events.annotation.Subscriber import groovy.transform.CompileStatic +import jakarta.annotation.PostConstruct import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent import org.grails.events.EventIdUtils import org.springframework.util.ReflectionUtils -import jakarta.annotation.PostConstruct import java.beans.Introspector import java.lang.reflect.Method @@ -50,30 +50,28 @@ trait AnnotatedSubscriber extends EventBusAware { @PostConstruct void registerMethods() { Events events = getClass().getAnnotation(Events) - for(Method m in subscribedMethods) { + for (Method m in subscribedMethods) { ReflectionUtils.makeAccessible(m) Subscriber sub = m.getAnnotation(Subscriber) - if(sub != null) { + if (sub != null) { String eventId = sub.value() - if(!eventId) { + if (!eventId) { eventId = EventIdUtils.eventIdForMethodName(m.name) } String namespace = events?.namespace() - if(namespace) { + if (namespace) { eventId = namespace + ':' + eventId } Class[] parameterTypes = m.parameterTypes boolean hasArgument = parameterTypes.length == 1 - if(hasArgument && AbstractPersistenceEvent.isAssignableFrom(parameterTypes[0])) { + if (hasArgument && AbstractPersistenceEvent.isAssignableFrom(parameterTypes[0])) { eventId = "gorm:${Introspector.decapitalize(parameterTypes[0].simpleName)}" - "Event" eventBus.subscribe(eventId, new MethodSubscriber(this, m)) - } - else if(hasArgument && parameterTypes[0].isAssignableFrom(Event)) { + } else if (hasArgument && parameterTypes[0].isAssignableFrom(Event)) { eventBus.subscribe(eventId, new MethodEventSubscriber(this, m)) - } - else { + } else { eventBus.subscribe(eventId, new MethodSubscriber(this, m)) } } diff --git a/grails-events/transforms/src/main/groovy/org/grails/events/transform/PublisherTransform.groovy b/grails-events/transforms/src/main/groovy/org/grails/events/transform/PublisherTransform.groovy index 315ae1758b8..c3c57622560 100644 --- a/grails-events/transforms/src/main/groovy/org/grails/events/transform/PublisherTransform.groovy +++ b/grails-events/transforms/src/main/groovy/org/grails/events/transform/PublisherTransform.groovy @@ -50,7 +50,19 @@ import org.grails.datastore.gorm.transform.AbstractMethodDecoratingTransformatio import org.grails.datastore.mapping.reflect.AstUtils import org.springframework.transaction.event.TransactionPhase -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS +import static org.codehaus.groovy.ast.tools.GeneralUtils.block +import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.param +import static org.codehaus.groovy.ast.tools.GeneralUtils.propX +import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt +import static org.codehaus.groovy.ast.tools.GeneralUtils.throwS +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX /** * A transform that transforms a method publishing the result to the given event @@ -79,7 +91,7 @@ class PublisherTransform extends AbstractMethodDecoratingTransformation { @Override protected void enhanceClassNode(SourceUnit sourceUnit, AnnotationNode annotationNode, ClassNode classNode) { - if(!AstUtils.implementsInterface(classNode, EventPublisher.name)) { + if (!AstUtils.implementsInterface(classNode, EventPublisher.name)) { classNode.addInterface(ClassHelper.make(EventPublisher)) if (compilationUnit != null) { TraitComposer.doExtendTraits(classNode, sourceUnit, compilationUnit) @@ -98,7 +110,7 @@ class PublisherTransform extends AbstractMethodDecoratingTransformation { BlockStatement tryBody = new BlockStatement() TryCatchStatement tryCatch = new TryCatchStatement(tryBody, new EmptyStatement()) newMethodBody.addStatement(declS(result, new EmptyExpression())) - if(methodNode.returnType != ClassHelper.VOID_TYPE) { + if (methodNode.returnType != ClassHelper.VOID_TYPE) { tryBody.addStatement(assignS(result, originalMethodCallExpr)) } // otherwise.. @@ -108,51 +120,49 @@ class PublisherTransform extends AbstractMethodDecoratingTransformation { newMethodBody.addStatement(assignS(result, ConstantExpression.NULL)) } newMethodBody.addStatement( - tryCatch + tryCatch ) AnnotationNode eventsAnn = AstUtils.findAnnotation(classNode, Events) Expression eventId = annotationNode.getMember("value") - if(!eventId?.text) { + if (!eventId?.text) { eventId = constX(methodNode.name) } Expression namespace = eventsAnn?.getMember("namespace") boolean hasNamespace = namespace instanceof ConstantExpression - if(hasNamespace) { - eventId = new ConstantExpression(namespace.text + ':' + eventId.text ) + if (hasNamespace) { + eventId = new ConstantExpression(namespace.text + ':' + eventId.text) } Expression errorEventId = annotationNode.getMember("error") - if(errorEventId == null) { + if (errorEventId == null) { errorEventId = eventsAnn?.getMember("error") } - if(!errorEventId?.text) { + if (!errorEventId?.text) { errorEventId = eventId - } - else if(hasNamespace) { - errorEventId = new ConstantExpression(namespace.text + ':' + errorEventId.text ) + } else if (hasNamespace) { + errorEventId = new ConstantExpression(namespace.text + ':' + errorEventId.text) } Expression phase = annotationNode.getMember("phase") - if(phase == null) { + if (phase == null) { phase = eventsAnn?.getMember("phase") } MapExpression params = new MapExpression() - for(param in methodNode.parameters) { + for (param in methodNode.parameters) { params.addMapEntryExpression( - constX(param.name), - varX(param) + constX(param.name), + varX(param) ) } Expression newEvent = ctorX(ClassHelper.make(Event), args(eventId, params, result)) def eventArgs = args(newEvent) - if(phase != null) { + if (phase != null) { eventArgs.addExpression(phase) - } - else { - if( AstUtils.hasAnnotation(methodNode, Transactional) ) { + } else { + if (AstUtils.hasAnnotation(methodNode, Transactional)) { eventArgs.addExpression(propX(classX(TransactionPhase), "AFTER_COMMIT")) } } @@ -160,23 +170,22 @@ class PublisherTransform extends AbstractMethodDecoratingTransformation { Parameter exceptionParam = param(ClassHelper.make(Throwable), '$t') Expression errorEvent = ctorX(ClassHelper.make(Event), args(errorEventId, params, varX(exceptionParam))) def errorArgs = args(errorEvent) - if(phase != null) { + if (phase != null) { errorArgs.addExpression(phase) - } - else { - if( AstUtils.hasAnnotation(methodNode, Transactional) ) { + } else { + if (AstUtils.hasAnnotation(methodNode, Transactional)) { errorArgs.addExpression(propX(classX(TransactionPhase), "AFTER_ROLLBACK")) } } Statement catchBody = block( - stmt(callThisX("publish", errorArgs)), - throwS(varX(exceptionParam)) + stmt(callThisX("publish", errorArgs)), + throwS(varX(exceptionParam)) ) CatchStatement catchStatement = new CatchStatement(exceptionParam, catchBody) tryCatch.addCatch(catchStatement) tryBody.addStatement( - stmt( callThisX("publish", eventArgs) ) + stmt(callThisX("publish", eventArgs)) ) return result } diff --git a/grails-events/transforms/src/main/groovy/org/grails/events/transform/SubscriberTransform.groovy b/grails-events/transforms/src/main/groovy/org/grails/events/transform/SubscriberTransform.groovy index 1d940b71f91..4322f72bf5c 100644 --- a/grails-events/transforms/src/main/groovy/org/grails/events/transform/SubscriberTransform.groovy +++ b/grails-events/transforms/src/main/groovy/org/grails/events/transform/SubscriberTransform.groovy @@ -24,7 +24,12 @@ import grails.events.annotation.gorm.Listener import groovy.transform.AutoFinal import groovy.transform.CompileStatic import org.apache.grails.common.compiler.GroovyTransformOrder -import org.codehaus.groovy.ast.* +import org.codehaus.groovy.ast.AnnotatedNode +import org.codehaus.groovy.ast.AnnotationNode +import org.codehaus.groovy.ast.ClassHelper +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.MethodNode +import org.codehaus.groovy.ast.Parameter import org.codehaus.groovy.ast.expr.ArgumentListExpression import org.codehaus.groovy.ast.expr.ConstantExpression import org.codehaus.groovy.ast.expr.ListExpression @@ -43,7 +48,11 @@ import org.grails.events.gorm.GormAnnotatedSubscriber import java.lang.reflect.Method import java.lang.reflect.Modifier -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX import static org.grails.datastore.mapping.reflect.AstUtils.ZERO_PARAMETERS /** @@ -56,7 +65,6 @@ class SubscriberTransform extends AbstractTraitApplyingGormASTTransformation { public static final Object APPLIED_MARKER = new Object() - @Override protected Class getTraitClass() { return AnnotatedSubscriber @@ -74,99 +82,90 @@ class SubscriberTransform extends AbstractTraitApplyingGormASTTransformation { @Override void visit(SourceUnit source, AnnotationNode annotationNode, AnnotatedNode annotatedNode) { - if(annotatedNode instanceof MethodNode && !Modifier.isAbstract(((MethodNode)annotatedNode).getModifiers())) { - MethodNode methodNode = (MethodNode)annotatedNode + if (annotatedNode instanceof MethodNode && !Modifier.isAbstract(((MethodNode) annotatedNode).getModifiers())) { + MethodNode methodNode = (MethodNode) annotatedNode ClassNode declaringClass = methodNode.getDeclaringClass() - if ( shouldWeave(annotationNode, declaringClass) ) { - if(declaringClass.getField("lazyInit") == null) { + if (shouldWeave(annotationNode, declaringClass)) { + if (declaringClass.getField("lazyInit") == null) { declaringClass.addField("lazyInit", Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL, ClassHelper.Boolean_TYPE, ConstantExpression.FALSE) } Parameter[] parameters = methodNode.parameters boolean isGormEvent = parameters.length == 1 && AstUtils.isSubclassOf(parameters[0].type, AbstractPersistenceEvent.name) boolean isGormListener = annotationNode.classNode.name == Listener.name - if(!isGormEvent && isGormListener) { + if (!isGormEvent && isGormListener) { addError("A GORM @Listener must accept a GORM event as an argument", annotationNode) return } - if(isGormEvent) { + if (isGormEvent) { ClassNode eventType = parameters[0].type - if(isGormListener) { + if (isGormListener) { weaveTrait(declaringClass, source, GormAnnotatedListener) - } - else { + } else { weaveTrait(declaringClass, source, GormAnnotatedSubscriber) } MethodNode getSubscribersMethod = declaringClass.getDeclaredMethod("getSubscribedEvents") ListExpression listExpression - if(getSubscribersMethod.getAnnotations(ClassHelper.make(Traits.TraitBridge))) { + if (getSubscribersMethod.getAnnotations(ClassHelper.make(Traits.TraitBridge))) { def currentCode = getSubscribersMethod.code - if(currentCode instanceof ExpressionStatement) { + if (currentCode instanceof ExpressionStatement) { ExpressionStatement body = (ExpressionStatement) currentCode def expression = body.getExpression() - if(expression instanceof ListExpression) { - listExpression = (ListExpression) expression - } - else { + if (expression instanceof ListExpression) { + listExpression = (ListExpression) expression + } else { listExpression = new ListExpression() body.setExpression(listExpression) } - } - else { + } else { listExpression = new ListExpression() ExpressionStatement body = new ExpressionStatement(listExpression) getSubscribersMethod.setCode(body) } - } - else { + } else { ExpressionStatement body = (ExpressionStatement) getSubscribersMethod.getCode() - listExpression = (ListExpression) body.getExpression() + listExpression = (ListExpression) body.getExpression() } listExpression.addExpression(classX(eventType)) - } - else { + } else { weaveTrait(declaringClass, source, traitClass) } } MethodNode getSubscribersMethod = declaringClass.getDeclaredMethod("getSubscribedMethods") ListExpression listExpression - if(getSubscribersMethod == null) { + if (getSubscribersMethod == null) { def listOfMethodType = GenericsUtils.makeClassSafeWithGenerics(List, ClassHelper.make(Method)) listExpression = new ListExpression() ExpressionStatement body = new ExpressionStatement(listExpression) declaringClass.addMethod("getSubscribedMethods", Modifier.PUBLIC, listOfMethodType, ZERO_PARAMETERS, null, body) - } - else if(getSubscribersMethod.getAnnotations(ClassHelper.make(Traits.TraitBridge))) { + } else if (getSubscribersMethod.getAnnotations(ClassHelper.make(Traits.TraitBridge))) { def currentCode = getSubscribersMethod.code - if(currentCode instanceof ExpressionStatement) { + if (currentCode instanceof ExpressionStatement) { ExpressionStatement body = (ExpressionStatement) currentCode def expression = body.getExpression() - if(expression instanceof ListExpression) { - listExpression = (ListExpression) expression - } - else { + if (expression instanceof ListExpression) { + listExpression = (ListExpression) expression + } else { listExpression = new ListExpression() body.setExpression(listExpression) } - } - else { + } else { listExpression = new ListExpression() ExpressionStatement body = new ExpressionStatement(listExpression) getSubscribersMethod.setCode(body) } - } - else { + } else { ExpressionStatement body = (ExpressionStatement) getSubscribersMethod.getCode() - listExpression = (ListExpression) body.getExpression() + listExpression = (ListExpression) body.getExpression() } ArgumentListExpression methodArgs = args( constX(methodNode.getName()) ) - for(param in methodNode.parameters) { - methodArgs.addExpression( classX(param.type) ) + for (param in methodNode.parameters) { + methodArgs.addExpression(classX(param.type)) } listExpression.addExpression(callX( callThisX("getClass"), "getMethod", methodArgs) diff --git a/grails-fields/build.gradle b/grails-fields/build.gradle index 74b4fd64e52..7bf4facd666 100644 --- a/grails-fields/build.gradle +++ b/grails-fields/build.gradle @@ -64,4 +64,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/grails-extension-gradle-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-fields/grails-app/init/grails/plugin/formfields/Application.groovy b/grails-fields/grails-app/init/grails/plugin/formfields/Application.groovy index e5fa1418dd4..e8353f0421c 100644 --- a/grails-fields/grails-app/init/grails/plugin/formfields/Application.groovy +++ b/grails-fields/grails-app/init/grails/plugin/formfields/Application.groovy @@ -26,7 +26,7 @@ import groovy.transform.CompileStatic @CompileStatic @PluginSource -class Application extends GrailsAutoConfiguration { +class Application extends GrailsAutoConfiguration { static void main(String[] args) { GrailsApp.run(Application, args) diff --git a/grails-fields/grails-app/taglib/grails/plugin/formfields/FormFieldsTagLib.groovy b/grails-fields/grails-app/taglib/grails/plugin/formfields/FormFieldsTagLib.groovy index bafd61130b7..a848ffd09de 100644 --- a/grails-fields/grails-app/taglib/grails/plugin/formfields/FormFieldsTagLib.groovy +++ b/grails-fields/grails-app/taglib/grails/plugin/formfields/FormFieldsTagLib.groovy @@ -23,11 +23,18 @@ import groovy.transform.CompileStatic import groovy.util.logging.Slf4j import groovy.xml.MarkupBuilder import groovy.xml.MarkupBuilderHelper +import jakarta.servlet.http.HttpServletRequest import org.grails.buffer.FastStringWriter import org.grails.datastore.mapping.model.MappingContext import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.model.PersistentProperty -import org.grails.datastore.mapping.model.types.* +import org.grails.datastore.mapping.model.types.Association +import org.grails.datastore.mapping.model.types.Basic +import org.grails.datastore.mapping.model.types.Embedded +import org.grails.datastore.mapping.model.types.ManyToMany +import org.grails.datastore.mapping.model.types.ManyToOne +import org.grails.datastore.mapping.model.types.OneToMany +import org.grails.datastore.mapping.model.types.OneToOne import org.grails.encoder.CodecLookup import org.grails.gsp.GroovyPage import org.grails.scaffolding.model.DomainModelService @@ -41,7 +48,6 @@ import org.springframework.context.MessageSourceResolvable import org.springframework.context.NoSuchMessageException import org.springframework.web.servlet.LocaleResolver -import jakarta.servlet.http.HttpServletRequest import java.sql.Blob import java.text.NumberFormat import java.time.LocalDate @@ -51,940 +57,949 @@ import static FormFieldsTemplateService.toPropertyNameFormat @Slf4j class FormFieldsTagLib { - static final namespace = 'f' - - static final String STACK_PAGE_SCOPE_VARIABLE = 'f:with:stack' - private static final List DECIMAL_TYPES = ['double', 'float', 'bigdecimal'] - - private static final String THEME_ATTR = "theme" - private static final String WIDGET_ATTR = "widget" - private static final String WRAPPER_ATTR = "wrapper" - private static final String TEMPLATES_ATTR = "templates" - private static final String PROPERTY_ATTR = "property" - private static final String BEAN_ATTR = "bean" - public static final String DISPLAY_STYLE = 'displayStyle' - - @Value('${grails.plugin.fields.localizeNumbers:true}') - Boolean localizeNumbers - - @Value('${grails.plugin.fields.exclusions.list:#{T(java.util.Arrays).asList("id", "dateCreated", "lastUpdated")}}') - List exclusionsList - @Value('${grails.plugin.fields.exclusions.input:#{T(java.util.Arrays).asList("version", "dateCreated", "lastUpdated")}}') - List exclusionsInput - @Value('${grails.plugin.fields.exclusions.display:#{T(java.util.Arrays).asList("version", "dateCreated", "lastUpdated")}}') - List exclusionsDisplay - - enum ExclusionType { - List, Display, Input - } - - FormFieldsTemplateService formFieldsTemplateService - BeanPropertyAccessorFactory beanPropertyAccessorFactory - DomainPropertyFactory fieldsDomainPropertyFactory - - @Autowired(required = false) - Collection mappingContexts - - DomainModelService domainModelService - LocaleResolver localeResolver - CodecLookup codecLookup - MessageSource messageSource - - static defaultEncodeAs = [taglib: 'raw'] - - class BeanAndPrefix { - Object bean - String prefix - Map innerAttributes = [:] - } - - class BeanAndPrefixStack extends Stack { - Object getBean() { - empty() ? null : peek().bean - } - - String getPrefix() { - empty() ? null : peek().prefix - } - - Map getInnerAttributes() { - empty() ? [:] : peek().innerAttributes - } - - String toString() { - bean?.toString() ?: '' - } - } - - BeanAndPrefixStack getBeanStack() { - if (!pageScope.hasVariable(STACK_PAGE_SCOPE_VARIABLE)) { - pageScope.setVariable(STACK_PAGE_SCOPE_VARIABLE, new BeanAndPrefixStack()) - } - pageScope.variables[STACK_PAGE_SCOPE_VARIABLE] - } - - /** - * @attr bean REQUIRED Name of the source bean in the GSP model. - * @attr prefix Prefix to add to input element names. - */ - def with = { attrs, body -> - if (!attrs[BEAN_ATTR]) throwTagError("Tag [with] is missing required attribute [$BEAN_ATTR]") - BeanAndPrefix beanPrefix = resolveBeanAndPrefix(attrs[BEAN_ATTR], attrs.prefix, attrs) - try { - beanStack.push(beanPrefix) - out << body() - } finally { - beanStack.pop() - } - } - - /** - * @attr bean REQUIRED Name of the source bean in the GSP model. - * @attr order A comma-separated list of properties to include in provided order - * @attr except A comma-separated list of properties to exclude from the generated list of input fields - * @attr prefix Prefix to add to input element names. - */ - def all = { attrs -> - if (!attrs[BEAN_ATTR]) throwTagError("Tag [all] is missing required attribute [$BEAN_ATTR]") - BeanAndPrefix beanPrefix = resolveBeanAndPrefix(attrs[BEAN_ATTR], attrs.prefix, attrs) - try { - beanStack.push(beanPrefix) - def bean = resolveBean(attrs[BEAN_ATTR]) - def prefix = resolvePrefix(attrs.prefix) - def domainClass = resolveDomainClass(bean) - if (domainClass) { - for (property in resolvePersistentProperties(domainClass, attrs)) { - out << field([bean: bean, property: property.name, prefix: prefix]) - } - } else { - throwTagError('Tag [all] currently only supports domain types') - } - } finally { - beanStack.pop() - } - } - - /** - * @attr bean Name of the source bean in the GSP model. - * @attr property REQUIRED The name of the property to display. This is resolved - * against the specified bean or the bean in the current scope. - * @attr value Specifies the initial value to display in the field. The default is - * the current value of the property. - * @attr default A default initial value to display if the actual property value - * evaluates to {@code false}. - * @attr required Specifies whether the user is required to enter a value for this - * property. By default, this is determined by the constraints of the property. - * @attr invalid Specifies whether this property is invalid or not. By default, this - * is determined by whether there are any errors associated with it. - * @attr label Overrides the default label displayed next to the input field. - * @attr prefix Prefix to add to input element names. - * @attr wrapper Specify the folder inside _fields where to look up for the wrapper template. - * @attr widget Specify the folder inside _fields where to look up for the widget template. - * @attr templates Specify the folder inside _fields where to look up for the wrapper and widget template. - * @attr theme Theme name - * @attr css html css attribute for wrapper (default: field-contain) - * @attr divClass class for optional div that will be added if set and contain the widget (default: no div created) - * @attr invalidClass class added to wrapper that if property is invalid. (default: error) Also available for widget. - * @attr requiredClass class added to wrapper when property is required. (default: required) Also available for widget. - */ - def field = { attrs, body -> - attrs = beanStack.innerAttributes + attrs - if (attrs.containsKey(BEAN_ATTR) && !attrs[BEAN_ATTR]) throwTagError("Tag [field] requires a non-null value for attribute [$BEAN_ATTR]") - if (!attrs[PROPERTY_ATTR]) throwTagError("Tag [field] is missing required attribute [$PROPERTY_ATTR]") - - def bean = resolveBean(attrs.remove(BEAN_ATTR)) - String property = attrs.remove(PROPERTY_ATTR) - String templatesFolder = attrs.remove(TEMPLATES_ATTR) - String fieldFolder = attrs.remove(WRAPPER_ATTR) - String widgetFolder = attrs.remove(WIDGET_ATTR) - String theme = attrs.remove(THEME_ATTR) - - BeanPropertyAccessor propertyAccessor = resolveProperty(bean, property) - if (propertyAccessor.domainProperty instanceof Embedded) { - renderEmbeddedProperties(bean, propertyAccessor, attrs + [templates: templatesFolder, field: fieldFolder, input: widgetFolder, theme: theme]) - } else { - Map model = buildModel(propertyAccessor, attrs) - Map wrapperAttrs = [:] - Map widgetAttrs = [:] - - String prefixAttribute = formFieldsTemplateService.getWidgetPrefix() ?: 'widget-' - attrs.each { k, v -> - if (k?.startsWith(prefixAttribute)) { - widgetAttrs[k.replace(prefixAttribute, '')] = v - } else { - wrapperAttrs[k] = v - } - } - - List widgetClasses = [widgetAttrs['class'] ?: ''] - String cssClass = widgetAttrs.remove('invalidClass') - if (cssClass && model.invalid) { - widgetClasses << cssClass - } - cssClass = widgetAttrs.remove('requiredClass') - if (cssClass && model.required) { - widgetClasses << cssClass - } - widgetAttrs['class'] = widgetClasses.join(' ').trim() - if (widgetAttrs['class'].isEmpty()) { - widgetAttrs.remove('class') - } - if (hasBody(body)) { - model.widget = raw(body(model + [attrs: widgetAttrs] + widgetAttrs)) - } else { - model.widget = renderWidget(propertyAccessor, model, widgetAttrs, widgetFolder ?: templatesFolder, theme) - } - - String templateName = formFieldsTemplateService.getTemplateFor("wrapper") - Map template = formFieldsTemplateService.findTemplate(propertyAccessor, templateName, fieldFolder ?: templatesFolder, theme) - if (template) { - out << render(template: template.path, plugin: template.plugin, model: model + [attrs: wrapperAttrs] + wrapperAttrs) - } else { - out << renderDefaultField(model, wrapperAttrs) - } - } - } - /** - * Renders a collection of beans in a table - * - * @attr collection REQUIRED The collection of beans to render - * @attr domainClass The FQN of the domain class of the elements in the collection. - * Defaults to the class of the first element in the collection. - * @attr properties OPTIONAL The list of properties to be shown (table columns). - * @attr maxProperties OPTIONAL The number of properties displayed when no explicit properties are given, defaults to 7. - * @attr displayStyle OPTIONAL Determines the display template used for the bean's properties. - * Defaults to 'table', meaning that 'display-table' templates will be used when available. - * @attr order A comma-separated list of properties to include in provided order - * @attr except A comma-separated list of properties to exclude - * @attr theme Theme name - * @attr template OPTIONAL The template used when rendering the collection - */ - def table = { attrs, body -> - def collection = resolveBean(attrs.remove('collection')) - PersistentEntity domainClass - if (attrs.containsKey('domainClass')) { - domainClass = resolveDomainClass((String) attrs.remove('domainClass')) - } else { - domainClass = (collection instanceof Collection) && collection ? resolveDomainClass(collection.iterator().next()) : null - } - - if (domainClass) { - List properties = resolveProperties(domainClass, attrs) - - List columnProperties = properties.collect { propertyAccessor -> - buildColumnModel(propertyAccessor, attrs) - } - - String displayStyle = attrs.remove(DISPLAY_STYLE) - String theme = attrs.remove(THEME_ATTR) - String template = attrs.remove('template') ?: 'table' - - out << render( - template: "/templates/_fields/$template", - model: attrs + [domainClass: domainClass, - domainProperties: columnProperties, - columnProperties: columnProperties, - collection: collection, - displayStyle: displayStyle, - theme: theme]) - } - } - - /** - * @deprecated since version 1.5 - Use widget instead - * @attr bean Name of the source bean in the GSP model. - * @attr property REQUIRED The name of the property to display. This is resolved - * against the specified bean or the bean in the current scope. - */ - def input = { attrs -> - out << widget(attrs) - } - - /** - * @attr bean Name of the source bean in the GSP model. - * @attr property REQUIRED The name of the property to display. This is resolved - * against the specified bean or the bean in the current scope. - * @attr theme Theme name - */ - def widget = { attrs -> - def bean = resolveBean(attrs.remove(BEAN_ATTR)) - if (!bean) throwTagError("Tag [input] is missing required attribute [$BEAN_ATTR]") - if (!attrs.property) throwTagError("Tag [input] is missing required attribute [property]") - - attrs = getPrefixedAttributes(beanStack.innerAttributes) + attrs - - String property = attrs.remove(PROPERTY_ATTR) - String widgetFolder = attrs.remove(WIDGET_ATTR) - String theme = attrs.remove(THEME_ATTR) - - BeanPropertyAccessor propertyAccessor = resolveProperty(bean, property) - Map model = buildModel(propertyAccessor, attrs) - - out << renderWidget(propertyAccessor, model, attrs, widgetFolder, theme) - } - - /** - * @attr bean Name of the source bean in the GSP model. - * @attr property REQUIRED The name of the property to display. This is resolved - * against the specified bean or the bean in the current scope. - * @attr theme Theme name - */ - def displayWidget = { attrs -> - def bean = resolveBean(attrs.remove(BEAN_ATTR)) - if (!bean) throwTagError("Tag [displayWidget] is missing required attribute [$BEAN_ATTR]") - if (!attrs[PROPERTY_ATTR]) throwTagError("Tag [displayWidget] is missing required attribute [property]") - - attrs = getPrefixedAttributes(beanStack.innerAttributes) + attrs - - String property = attrs.remove(PROPERTY_ATTR) - String widgetFolder = attrs.remove(WIDGET_ATTR) - String theme = attrs.remove(THEME_ATTR) - - BeanPropertyAccessor propertyAccessor = resolveProperty(bean, property) - Map model = buildModel(propertyAccessor, attrs, 'HTML') - - out << renderDisplayWidget(propertyAccessor, model, attrs, widgetFolder, theme) - } - - /** - * @attr bean Name of the source bean in the GSP model. - * @attr property The name of the property to display. This is resolved against the specified bean or the bean in the current scope. - * @attr order A comma-separated list of properties to include in provided order - * @attr except A comma-separated list of properties to exclude - * @attr theme Theme name - * @attr template OPTIONAL The template used when rendering the domainClass - */ - def display = { attrs, body -> - attrs = beanStack.innerAttributes + attrs - def bean = resolveBean(attrs.remove(BEAN_ATTR)) - if (!bean) throwTagError("Tag [display] is missing required attribute [$BEAN_ATTR]") - - String property = attrs.remove(PROPERTY_ATTR) - String templatesFolder = attrs.remove(TEMPLATES_ATTR) - String theme = attrs.remove(THEME_ATTR) - - if (property == null) { - PersistentEntity domainClass = resolveDomainClass(bean) - if (domainClass) { - String template = attrs.remove('template') ?: 'list' - - List properties = resolvePersistentProperties(domainClass, attrs, ExclusionType.Display) - out << render(template: "/templates/_fields/$template", model: attrs + [domainClass: domainClass, domainProperties: properties]) { prop -> - BeanPropertyAccessor propertyAccessor = resolveProperty(bean, prop.name) - Map model = buildModel(propertyAccessor, attrs, 'HTML') - out << raw(renderDisplayWidget(propertyAccessor, model, attrs, templatesFolder, theme)) - } - } - } else { - String displayFolder = attrs.remove(WRAPPER_ATTR) - String widgetFolder = attrs.remove(WIDGET_ATTR) - - BeanPropertyAccessor propertyAccessor = resolveProperty(bean, property) - Map model = buildModel(propertyAccessor, attrs, 'HTML') - - Map wrapperAttrs = [:] - Map widgetAttrs = [:] - - String prefixAttribute = formFieldsTemplateService.getWidgetPrefix() ?: 'widget-' - attrs.each { k, v -> - if (k?.startsWith(prefixAttribute)) { - widgetAttrs[k.replace(prefixAttribute, '')] = v - } else { - wrapperAttrs[k] = v - } - } - - - String wrapperFolderTouse = displayFolder ?: templatesFolder - String widgetsFolderToUse = widgetFolder ?: templatesFolder - - if (hasBody(body)) { - model.widget = raw(body(model + [attrs: widgetAttrs] + widgetAttrs)) - model.value = body(model) - } else { - model.widget = renderDisplayWidget(propertyAccessor, model, widgetAttrs, widgetsFolderToUse, theme) - } - - - def displayWrapperTemplateName = formFieldsTemplateService.getTemplateFor("displayWrapper") - def template = formFieldsTemplateService.findTemplate(propertyAccessor, displayWrapperTemplateName, wrapperFolderTouse, theme) - if (template) { - out << render(template: template.path, plugin: template.plugin, model: model + [attrs: wrapperAttrs] + wrapperAttrs) - } else { - out << raw(renderDisplayWidget(propertyAccessor, model, attrs, widgetsFolderToUse, theme)) - } - } - - } - - private Map getPrefixedAttributes(attrs) { - Map widgetAttrs = [:] - attrs.each { k, v -> - String prefixAttribute = formFieldsTemplateService.getWidgetPrefix() - if (k?.startsWith(prefixAttribute)) { - widgetAttrs[k.replace(prefixAttribute, '')] = v - } - } - return widgetAttrs - } - - private void renderEmbeddedProperties(bean, BeanPropertyAccessor propertyAccessor, attrs) { - def legend = resolveMessage(propertyAccessor.labelKeys, propertyAccessor.defaultLabel) - out << applyLayout(name: '_fields/embedded', params: [type: toPropertyNameFormat(propertyAccessor.propertyType), legend: legend]) { - Embedded prop = (Embedded) propertyAccessor.domainProperty - for (embeddedProp in resolvePersistentProperties(prop.associatedEntity, attrs)) { - def propertyPath = "${propertyAccessor.pathFromRoot}.${embeddedProp.name}" - out << field(bean: bean, property: propertyPath, prefix: attrs.prefix, default: attrs.default, field: attrs.field, widget: attrs.widget, theme: attrs[THEME_ATTR]) - } - } - } - - private BeanPropertyAccessor resolveProperty(bean, String propertyPath) { - beanPropertyAccessorFactory.accessorFor(bean, propertyPath) - } - - private List resolveProperties(PersistentEntity domainClass, Map attrs) { - // Starting point for the bean property resolver - def bean = domainClass.javaClass.newInstance() - - List propertyAccessorList = resolvePropertyNames(domainClass, attrs).collect { String propertyPath -> - beanPropertyAccessorFactory.accessorFor(bean, propertyPath) - } - - return propertyAccessorList - - } - - private List resolvePropertyNames(PersistentEntity domainClass, Map attrs) { - if (attrs.containsKey('order')) { - return getList(attrs.order) - } else if (attrs.containsKey('properties')) { - return getList(attrs.remove('properties')) - } else { - List properties = resolvePersistentProperties(domainClass, attrs, ExclusionType.List)*.name - int maxProperties = attrs.containsKey('maxProperties') ? attrs.remove('maxProperties').toInteger() : 7 - if (maxProperties && properties.size() > maxProperties) { - properties = properties[0.. - String errorMsg = null - try { - errorMsg = error instanceof MessageSourceResolvable ? messageSource.getMessage(error, locale) : messageSource.getMessage(error.toString(), null, locale) - } catch (NoSuchMessageException ignored) { - // no-op - } - // unresolved message codes fallback to the defaultMessage and this should - // be escaped as it could be an error message with user input - errorMsg && errorMsg == error.defaultMessage ? message(error: error, encodeAs: "HTML") : message(error: error) - }, - required : attrs.containsKey("required") ? Boolean.valueOf(attrs.remove('required')) : propertyAccessor.required, - invalid : attrs.containsKey("invalid") ? Boolean.valueOf(attrs.remove('invalid')) : propertyAccessor.invalid, - prefix : resolvePrefix(attrs.remove('prefix')), - ] - } - - private CharSequence renderWidget(BeanPropertyAccessor propertyAccessor, Map model, Map attrs = [:], String widgetFolder, String theme) { - String widgetTemplateName = formFieldsTemplateService.getTemplateFor("widget") - Map template = formFieldsTemplateService.findTemplate(propertyAccessor, widgetTemplateName, widgetFolder, theme) - if (template) { - render template: template.path, plugin: template.plugin, model: model + [attrs: attrs] + attrs - } else { - renderDefaultInput propertyAccessor, model, attrs - } - } - - private CharSequence renderDisplayWidget(BeanPropertyAccessor propertyAccessor, Map model, Map attrs = [:], String widgetFolder, String theme) { - String displayStyle = attrs.displayStyle - - Map template = null - if (displayStyle && displayStyle != 'default') { - template = formFieldsTemplateService.findTemplate(propertyAccessor, "displayWidget-$attrs.displayStyle", widgetFolder, theme) - } - if (!template) { - def displayWidgetTemplateName = formFieldsTemplateService.getTemplateFor("displayWidget") - template = formFieldsTemplateService.findTemplate(propertyAccessor, displayWidgetTemplateName, widgetFolder, theme) - } - - if (template) { - render template: template.path, plugin: template.plugin, model: model + [attrs: attrs] + attrs - } else if (!(model.value instanceof CharSequence)) { - renderDefaultDisplay(model, attrs, widgetFolder, theme) - } else { - model.value - } - } - - private resolvePageScopeVariable(attributeName) { - // Tomcat throws NPE if you query pageScope for null/empty values - attributeName?.toString() ? pageScope.variables[attributeName] : null - } - - private BeanAndPrefix resolveBeanAndPrefix(beanAttribute, prefixAttribute, attributes) { - def bean = resolvePageScopeVariable(beanAttribute) ?: beanAttribute - def prefix = resolvePageScopeVariable(prefixAttribute) ?: prefixAttribute - def innerAttributes = attributes.clone() - innerAttributes.remove('bean') - innerAttributes.remove('prefix') - //'except' is a reserved word for the 'all' tag: https://github.com/grails-fields-plugin/grails-fields/issues/12 - innerAttributes.remove('except') - new BeanAndPrefix(bean: bean, prefix: prefix, innerAttributes: innerAttributes) - } - - private Object resolveBean(beanAttribute) { - resolvePageScopeVariable(beanAttribute) ?: beanAttribute ?: beanStack.bean - } - - private String resolvePrefix(prefixAttribute) { - def prefix = resolvePageScopeVariable(prefixAttribute) ?: prefixAttribute ?: beanStack.prefix - if (prefix && !prefix.endsWith('.')) { - prefix = prefix + '.' - } - prefix ?: '' - } - - private PersistentEntity resolveDomainClass(bean) { - resolveDomainClass(bean.getClass()) - } - - private PersistentEntity resolveDomainClass(Class beanClass) { - resolveDomainClass(beanClass.name) - } - - private PersistentEntity resolveDomainClass(String beanClassName) { - mappingContexts.findResult { MappingContext mappingContext -> - mappingContext.getPersistentEntity(beanClassName) - } - } - - private List resolvePersistentProperties(PersistentEntity domainClass, Map attrs, ExclusionType exclusionType = ExclusionType.Input) { - List properties - - boolean list = exclusionType == ExclusionType.List - if (attrs.order) { - def orderBy = getList(attrs.order) - if (attrs.except) { - orderBy = orderBy - getList(attrs.except) - } - properties = orderBy.collect { propertyName -> - fieldsDomainPropertyFactory.build(domainClass.getPropertyByName(propertyName)) - } - } else { - properties = list ? domainModelService.getListOutputProperties(domainClass) : domainModelService.getInputProperties(domainClass, - exclusionType == ExclusionType.Input? exclusionsInput : exclusionsDisplay) - // If 'except' is not set, but 'list' is, exclude 'id', 'dateCreated' and 'lastUpdated' by default - List blacklist = attrs.containsKey('except') ? getList(attrs.except) : (list ? exclusionsList : []) - - properties.removeAll { it.name in blacklist } - } - - return properties - } - - private static List getList(def except, List defaultList = []) { - if (!except) { - return defaultList - } else if (except instanceof String) { - except?.tokenize(',')*.trim() - } else if (except instanceof Collection) { - return except as List - } else { - throw new IllegalArgumentException("Must either be null, comma separated string or java.util.Collection") - } - } - - private boolean hasBody(Closure body) { - return body && !body.is(GroovyPage.EMPTY_BODY_CLOSURE) - } - - private CharSequence resolveLabelText(BeanPropertyAccessor propertyAccessor, Map attrs) { - def labelText - def label = attrs.remove('label') - if (label) { - labelText = message(code: label, default: label) - } - if (!labelText && propertyAccessor.labelKeys) { - labelText = resolveMessage(propertyAccessor.labelKeys, propertyAccessor.defaultLabel) - } - if (!labelText) { - labelText = propertyAccessor.defaultLabel - } - return labelText - } - - private CharSequence resolveMessage(List keysInPreferenceOrder, String defaultMessage) { - def message = keysInPreferenceOrder.findResult { key -> - message(code: key, default: null) ?: null - } - if (log.traceEnabled && !message) { - log.trace("i18n missing translation for one of ${keysInPreferenceOrder}") - } - message ?: defaultMessage - } - - protected CharSequence renderDefaultField(Map model, Map attrs = [:]) { - List classes = [attrs['class'] ?: 'fieldcontain'] - if (model.invalid) classes << (attrs.remove('invalidClass') ?: 'error') - if (model.required) classes << (attrs.remove('requiredClass') ?: 'required') - attrs['class'] = classes.join(' ').trim() - Writer writer = new FastStringWriter() - def mb = new MarkupBuilder(writer) - mb.setDoubleQuotes(true) - mb.div(class: attrs['class']) { - label(class: attrs.labelClass, for: (model.prefix ?: '') + model.property, model.label) { - if (model.required) { - span(class: 'required-indicator', '*') - } - } - if (attrs.divClass) { - div(class: attrs.divClass) { - renderWidget(mkp, model) - } - } else { - renderWidget(mkp, model) - } - } - writer.buffer - } - - private void renderWidget(MarkupBuilderHelper mkp, Map model) { - // TODO: encoding information of widget gets lost - don't use MarkupBuilder - def widget = model.widget - if (widget != null) { - mkp.yieldUnescaped widget - } - } - - CharSequence renderDefaultInput(Map model, Map attrs = [:]) { - renderDefaultInput(null, model, attrs) - } - - CharSequence renderDefaultInput(BeanPropertyAccessor propertyAccessor, Map model, Map attrs = [:]) { - Constrained constrained = (Constrained) model.constraints - attrs.name = (model.prefix ?: '') + model.property - attrs.value = model.value - if (model.required) attrs.required = "" // TODO: configurable how this gets output? Some people prefer required="required" - if (model.invalid) attrs.invalid = "" - if (!isEditable(constrained)) attrs.readonly = "" - - boolean oneToOne = false - boolean manyToOne = false - boolean manyToMany = false - boolean oneToMany = false - if (model.containsKey('persistentProperty')) { - if (model.persistentProperty instanceof PersistentProperty) { - PersistentProperty prop = (PersistentProperty) model.persistentProperty - oneToOne = prop instanceof OneToOne - manyToOne = prop instanceof ManyToOne - manyToMany = prop instanceof ManyToMany - oneToMany = prop instanceof OneToMany - } - } - - // TODO: https://github.com/gpc/fields/issues/392 - boolean datePicker = model.type in [Date, Calendar, java.sql.Date, java.sql.Time, LocalDate, LocalDateTime] - if (!datePicker) { - attrs.remove('selectDateClass') - } - boolean checkBox = model.type in [boolean, Boolean] - String checkBoxClass = attrs.remove('checkBoxClass') - if (checkBox && checkBoxClass) { - attrs['class'] = checkBoxClass - } - - if (model.type in [String, null]) { - return renderStringInput(model, attrs) - } else if (checkBox) { - return g.checkBox(attrs) - } else if (model.type.isPrimitive() || model.type in Number) { - return renderNumericInput(propertyAccessor, model, attrs) - } else if (model.type in URL) { - return g.field(attrs + [type: "url"]) - } else if (model.type.isEnum()) { - return renderEnumInput(model, attrs) - } else if (oneToOne || manyToOne || manyToMany) { - return renderAssociationInput(model, attrs) - } else if (oneToMany) { - return renderOneToManyInput(model, attrs) - } else if (datePicker) { - return renderDateTimeInput(model, attrs) - } else if (model.type in [byte[], Byte[], Blob]) { - return g.field(attrs + [type: "file"]) - } else if (model.type in [TimeZone, Currency, Locale]) { - if (!model.required) attrs.noSelection = ["": ""] - return g."${GrailsStringUtils.uncapitalize(model.type.simpleName)}Select"(attrs) - } else { - return null - } - } - - - CharSequence renderDateTimeInput(Map model, Map attrs) { - attrs.precision = model.type in [java.sql.Time, LocalDateTime]? "minute" : "day" - if (!model.required) { - attrs.noSelection = ["": ""] - attrs.default = "none" - } - return g.datePicker(attrs) - } - - CharSequence renderStringInput(Map model, Map attrs) { - Constrained constrained = (Constrained) model.constraints - - if (!attrs.type) { - if (constrained?.inList) { - attrs.from = constrained.inList - if (!model.required) { - attrs.noSelection = ["": ""] - } - return g.select(attrs) - } else if (constrained?.password) { - attrs.type = "password" - attrs.remove('value') - } else if (constrained?.email) { - attrs.type = "email" - } else if (constrained?.url) { - attrs.type = "url" - } else { - attrs.type = "text" - } - } - - if (constrained?.matches) { attrs.pattern = constrained.matches } - if (constrained?.maxSize) { attrs.maxlength = constrained.maxSize } - - if (constrained?.widget == 'textarea') { - attrs.remove('type') - return g.textArea(attrs) - } - return g.field(attrs) - } - - CharSequence renderNumericInput(BeanPropertyAccessor propertyAccessor, Map model, Map attrs) { - Constrained constrained = (Constrained) model.constraints - - if (!attrs.type && constrained?.inList) { - attrs.from = constrained.inList - if (!model.required) attrs.noSelection = ["": ""] - return g.select(attrs) - } else if (constrained?.range) { - attrs.type = attrs.type ?: "range" - attrs.min = constrained.range.from - attrs.max = constrained.range.to - } else { - attrs.type = attrs.type ?: getDefaultNumberType(model) - if (constrained?.scale != null) attrs.step = "0.${'0' * (constrained.scale - 1)}1" - if (constrained?.min != null) attrs.min = constrained.min - if (constrained?.max != null) attrs.max = constrained.max - } - - if (localizeNumbers && propertyAccessor?.value != null) { - attrs.value = numberFormatter.format(propertyAccessor.value) - } - - return g.field(attrs) - } - - @CompileStatic - protected NumberFormat getNumberFormatter() { - NumberFormat.getInstance(getLocale()) - } - - @CompileStatic - protected Locale getLocale() { - def locale - def request = GrailsWebRequest.lookup()?.currentRequest - if (request instanceof HttpServletRequest) { - locale = localeResolver?.resolveLocale(request) - } - if (locale == null) { - locale = Locale.default - } - return locale - } - - @CompileStatic - protected String getDefaultNumberType(Map model) { - Class modelType = (Class) model.type - - def typeName = modelType.simpleName.toLowerCase() - if (typeName in DECIMAL_TYPES) { - return "number decimal" - } else { - return "number" - } - - } - - private CharSequence renderEnumInput(Map model, Map attrs) { - Constrained constrained = (Constrained) model.constraints - - if (attrs.value instanceof Enum) - attrs.value = attrs.value.name() - if (!model.required) attrs.noSelection = ["": ""] - - if (constrained?.inList) { - attrs.keys = constrained.inList*.name() - attrs.from = constrained.inList - } else { - attrs.keys = model.type.values()*.name() - attrs.from = model.type.values() - } - return g.select(attrs) - } - - private CharSequence renderAssociationInput(Map model, Map attrs) { - attrs.id = (model.prefix ?: '') + model.property - def persistentProperty = model.persistentProperty - Class referencedPropertyType - boolean manyToMany = false - if (persistentProperty instanceof Association) { - Association prop = ((Association) persistentProperty) - PersistentEntity entity = prop.getAssociatedEntity() - if (entity != null) { - referencedPropertyType = entity.getJavaClass() - } else if (prop.isBasic()) { - referencedPropertyType = ((Basic) prop).getComponentType() - } - manyToMany = prop instanceof ManyToMany - } - attrs.from = null != attrs.from ? attrs.from : referencedPropertyType.list() - attrs.optionKey = "id" // TODO: handle alternate id names - if (manyToMany) { - attrs.multiple = "" - attrs.value = model.value*.id - attrs.name = "${model.prefix ?: ''}${model.property}" - } else { - if (!model.required) attrs.noSelection = ["null": ""] - attrs.value = model.value?.id - attrs.name = "${model.prefix ?: ''}${model.property}.id" - } - return g.select(attrs) - } - - private CharSequence renderOneToManyInput(Map model, Map attrs) { - Writer buffer = new FastStringWriter() - buffer << '

      ' - def persistentProperty = model.persistentProperty - def controllerName - def shortName - if (persistentProperty instanceof Association) { - Association prop = ((Association) persistentProperty) - controllerName = prop.associatedEntity.decapitalizedName - shortName = prop.associatedEntity.javaClass.simpleName - } - - attrs.value.each { - buffer << '
    • ' - buffer << g.link(controller: controllerName, action: "show", id: it.id, it.toString().encodeAsHTML()) - buffer << '
    • ' - } - buffer << '
    ' - def referencedTypeLabel = message(code: "${controllerName}.label", default: shortName) - def addLabel = g.message(code: 'default.add.label', args: [referencedTypeLabel]) - PersistentEntity beanClass = (PersistentEntity) model.beanClass - buffer << g.link(controller: controllerName, action: "create", params: [("${beanClass.decapitalizedName}.id".toString()): model.bean.id], addLabel) - buffer.buffer - } - - private CharSequence renderDefaultDisplay(Map model, Map attrs = [:], String templatesFolder, String theme) { - def persistentProperty = model.persistentProperty - if (persistentProperty instanceof Association) { - if (persistentProperty.embedded) { - return (attrs.displayStyle == 'table') ? model.value?.toString().encodeAsHTML() : - displayEmbedded(model.value, persistentProperty.associatedEntity, attrs, templatesFolder, theme) - } else if (persistentProperty instanceof OneToMany || persistentProperty instanceof ManyToMany) { - return displayAssociationList(model.value, ((Association) persistentProperty).associatedEntity) - } else { - return displayAssociation(model.value, ((Association) persistentProperty).associatedEntity) - } - } - - switch (model.type) { - case Boolean.TYPE: - case Boolean: - g.formatBoolean(boolean: model.value) - break - case Calendar: - case Date: - case java.sql.Date: - case java.sql.Time: - case LocalDate: - case LocalDateTime: - g.formatDate(date: model.value) - break - default: - g.fieldValue bean: model.bean, field: model.property - } - } - - private CharSequence displayEmbedded(bean, PersistentEntity domainClass, Map attrs, String templatesFolder, String theme) { - Writer buffer = new FastStringWriter() - def properties = domainModelService.getOutputProperties(domainClass) - buffer << render(template: "/templates/_fields/list", model: [domainClass: domainClass, domainProperties: properties]) { prop -> - def propertyAccessor = resolveProperty(bean, prop.name) - def model = buildModel(propertyAccessor, attrs) - out << raw(renderDisplayWidget(propertyAccessor, model, attrs, templatesFolder, theme)) - } - buffer.buffer - } - - private CharSequence displayAssociationList(values, PersistentEntity referencedDomainClass) { - Writer buffer = new FastStringWriter() - buffer << '
      ' - for (value in values) { - buffer << '
    • ' - buffer << displayAssociation(value, referencedDomainClass) - buffer << '
    • ' - } - buffer << '
    ' - buffer.buffer - } - - private CharSequence displayAssociation(value, PersistentEntity referencedDomainClass) { - if (value && referencedDomainClass) { - g.link(controller: referencedDomainClass.decapitalizedName, action: "show", id: value.id, value.toString().encodeAsHTML()) - } else if (value) { - value.toString() - } - } - - private boolean isEditable(Constrained constraints) { - !constraints || constraints.editable + + static final namespace = 'f' + + static final String STACK_PAGE_SCOPE_VARIABLE = 'f:with:stack' + private static final List DECIMAL_TYPES = ['double', 'float', 'bigdecimal'] + + private static final String THEME_ATTR = "theme" + private static final String WIDGET_ATTR = "widget" + private static final String WRAPPER_ATTR = "wrapper" + private static final String TEMPLATES_ATTR = "templates" + private static final String PROPERTY_ATTR = "property" + private static final String BEAN_ATTR = "bean" + public static final String DISPLAY_STYLE = 'displayStyle' + + @Value('${grails.plugin.fields.localizeNumbers:true}') + Boolean localizeNumbers + + @Value('${grails.plugin.fields.exclusions.list:#{T(java.util.Arrays).asList("id", "dateCreated", "lastUpdated")}}') + List exclusionsList + @Value('${grails.plugin.fields.exclusions.input:#{T(java.util.Arrays).asList("version", "dateCreated", "lastUpdated")}}') + List exclusionsInput + @Value('${grails.plugin.fields.exclusions.display:#{T(java.util.Arrays).asList("version", "dateCreated", "lastUpdated")}}') + List exclusionsDisplay + + enum ExclusionType { + + List, Display, Input + } + + FormFieldsTemplateService formFieldsTemplateService + BeanPropertyAccessorFactory beanPropertyAccessorFactory + DomainPropertyFactory fieldsDomainPropertyFactory + + @Autowired(required = false) + Collection mappingContexts + + DomainModelService domainModelService + LocaleResolver localeResolver + CodecLookup codecLookup + MessageSource messageSource + + static defaultEncodeAs = [taglib: 'raw'] + + class BeanAndPrefix { + + Object bean + String prefix + Map innerAttributes = [:] + } + + class BeanAndPrefixStack extends Stack { + + Object getBean() { + empty() ? null : peek().bean + } + + String getPrefix() { + empty() ? null : peek().prefix + } + + Map getInnerAttributes() { + empty() ? [:] : peek().innerAttributes + } + + String toString() { + bean?.toString() ?: '' + } + } + + BeanAndPrefixStack getBeanStack() { + if (!pageScope.hasVariable(STACK_PAGE_SCOPE_VARIABLE)) { + pageScope.setVariable(STACK_PAGE_SCOPE_VARIABLE, new BeanAndPrefixStack()) + } + pageScope.variables[STACK_PAGE_SCOPE_VARIABLE] + } + + /** + * @attr bean REQUIRED Name of the source bean in the GSP model. + * @attr prefix Prefix to add to input element names. + */ + def with = { attrs, body -> + if (!attrs[BEAN_ATTR]) throwTagError("Tag [with] is missing required attribute [$BEAN_ATTR]") + BeanAndPrefix beanPrefix = resolveBeanAndPrefix(attrs[BEAN_ATTR], attrs.prefix, attrs) + try { + beanStack.push(beanPrefix) + out << body() + } finally { + beanStack.pop() + } + } + + /** + * @attr bean REQUIRED Name of the source bean in the GSP model. + * @attr order A comma-separated list of properties to include in provided order + * @attr except A comma-separated list of properties to exclude from the generated list of input fields + * @attr prefix Prefix to add to input element names. + */ + def all = { attrs -> + if (!attrs[BEAN_ATTR]) throwTagError("Tag [all] is missing required attribute [$BEAN_ATTR]") + BeanAndPrefix beanPrefix = resolveBeanAndPrefix(attrs[BEAN_ATTR], attrs.prefix, attrs) + try { + beanStack.push(beanPrefix) + def bean = resolveBean(attrs[BEAN_ATTR]) + def prefix = resolvePrefix(attrs.prefix) + def domainClass = resolveDomainClass(bean) + if (domainClass) { + for (property in resolvePersistentProperties(domainClass, attrs)) { + out << field([bean: bean, property: property.name, prefix: prefix]) + } + } else { + throwTagError('Tag [all] currently only supports domain types') + } + } finally { + beanStack.pop() + } + } + + /** + * @attr bean Name of the source bean in the GSP model. + * @attr property REQUIRED The name of the property to display. This is resolved + * against the specified bean or the bean in the current scope. + * @attr value Specifies the initial value to display in the field. The default is + * the current value of the property. + * @attr default A default initial value to display if the actual property value + * evaluates to {@code false}. + * @attr required Specifies whether the user is required to enter a value for this + * property. By default, this is determined by the constraints of the property. + * @attr invalid Specifies whether this property is invalid or not. By default, this + * is determined by whether there are any errors associated with it. + * @attr label Overrides the default label displayed next to the input field. + * @attr prefix Prefix to add to input element names. + * @attr wrapper Specify the folder inside _fields where to look up for the wrapper template. + * @attr widget Specify the folder inside _fields where to look up for the widget template. + * @attr templates Specify the folder inside _fields where to look up for the wrapper and widget template. + * @attr theme Theme name + * @attr css html css attribute for wrapper (default: field-contain) + * @attr divClass class for optional div that will be added if set and contain the widget (default: no div created) + * @attr invalidClass class added to wrapper that if property is invalid. (default: error) Also available for widget. + * @attr requiredClass class added to wrapper when property is required. (default: required) Also available for widget. + */ + def field = { attrs, body -> + attrs = beanStack.innerAttributes + attrs + if (attrs.containsKey(BEAN_ATTR) && !attrs[BEAN_ATTR]) throwTagError("Tag [field] requires a non-null value for attribute [$BEAN_ATTR]") + if (!attrs[PROPERTY_ATTR]) throwTagError("Tag [field] is missing required attribute [$PROPERTY_ATTR]") + + def bean = resolveBean(attrs.remove(BEAN_ATTR)) + String property = attrs.remove(PROPERTY_ATTR) + String templatesFolder = attrs.remove(TEMPLATES_ATTR) + String fieldFolder = attrs.remove(WRAPPER_ATTR) + String widgetFolder = attrs.remove(WIDGET_ATTR) + String theme = attrs.remove(THEME_ATTR) + + BeanPropertyAccessor propertyAccessor = resolveProperty(bean, property) + if (propertyAccessor.domainProperty instanceof Embedded) { + renderEmbeddedProperties(bean, propertyAccessor, attrs + [templates: templatesFolder, field: fieldFolder, input: widgetFolder, theme: theme]) + } else { + Map model = buildModel(propertyAccessor, attrs) + Map wrapperAttrs = [:] + Map widgetAttrs = [:] + + String prefixAttribute = formFieldsTemplateService.getWidgetPrefix() ?: 'widget-' + attrs.each { k, v -> + if (k?.startsWith(prefixAttribute)) { + widgetAttrs[k.replace(prefixAttribute, '')] = v + } else { + wrapperAttrs[k] = v + } + } + + List widgetClasses = [widgetAttrs['class'] ?: ''] + String cssClass = widgetAttrs.remove('invalidClass') + if (cssClass && model.invalid) { + widgetClasses << cssClass + } + cssClass = widgetAttrs.remove('requiredClass') + if (cssClass && model.required) { + widgetClasses << cssClass + } + widgetAttrs['class'] = widgetClasses.join(' ').trim() + if (widgetAttrs['class'].isEmpty()) { + widgetAttrs.remove('class') + } + if (hasBody(body)) { + model.widget = raw(body(model + [attrs: widgetAttrs] + widgetAttrs)) + } else { + model.widget = renderWidget(propertyAccessor, model, widgetAttrs, widgetFolder ?: templatesFolder, theme) + } + + String templateName = formFieldsTemplateService.getTemplateFor("wrapper") + Map template = formFieldsTemplateService.findTemplate(propertyAccessor, templateName, fieldFolder ?: templatesFolder, theme) + if (template) { + out << render(template: template.path, plugin: template.plugin, model: model + [attrs: wrapperAttrs] + wrapperAttrs) + } else { + out << renderDefaultField(model, wrapperAttrs) + } + } + } + /** + * Renders a collection of beans in a table + * + * @attr collection REQUIRED The collection of beans to render + * @attr domainClass The FQN of the domain class of the elements in the collection. + * Defaults to the class of the first element in the collection. + * @attr properties OPTIONAL The list of properties to be shown (table columns). + * @attr maxProperties OPTIONAL The number of properties displayed when no explicit properties are given, defaults to 7. + * @attr displayStyle OPTIONAL Determines the display template used for the bean's properties. + * Defaults to 'table', meaning that 'display-table' templates will be used when available. + * @attr order A comma-separated list of properties to include in provided order + * @attr except A comma-separated list of properties to exclude + * @attr theme Theme name + * @attr template OPTIONAL The template used when rendering the collection + */ + def table = { attrs, body -> + def collection = resolveBean(attrs.remove('collection')) + PersistentEntity domainClass + if (attrs.containsKey('domainClass')) { + domainClass = resolveDomainClass((String) attrs.remove('domainClass')) + } else { + domainClass = (collection instanceof Collection) && collection ? resolveDomainClass(collection.iterator().next()) : null + } + + if (domainClass) { + List properties = resolveProperties(domainClass, attrs) + + List columnProperties = properties.collect { propertyAccessor -> + buildColumnModel(propertyAccessor, attrs) + } + + String displayStyle = attrs.remove(DISPLAY_STYLE) + String theme = attrs.remove(THEME_ATTR) + String template = attrs.remove('template') ?: 'table' + + out << render( + template: "/templates/_fields/$template", + model: attrs + [domainClass : domainClass, + domainProperties: columnProperties, + columnProperties: columnProperties, + collection : collection, + displayStyle : displayStyle, + theme : theme]) + } + } + + /** + * @deprecated since version 1.5 - Use widget instead + * @attr bean Name of the source bean in the GSP model. + * @attr property REQUIRED The name of the property to display. This is resolved + * against the specified bean or the bean in the current scope. + */ + def input = { attrs -> + out << widget(attrs) + } + + /** + * @attr bean Name of the source bean in the GSP model. + * @attr property REQUIRED The name of the property to display. This is resolved + * against the specified bean or the bean in the current scope. + * @attr theme Theme name + */ + def widget = { attrs -> + def bean = resolveBean(attrs.remove(BEAN_ATTR)) + if (!bean) throwTagError("Tag [input] is missing required attribute [$BEAN_ATTR]") + if (!attrs.property) throwTagError("Tag [input] is missing required attribute [property]") + + attrs = getPrefixedAttributes(beanStack.innerAttributes) + attrs + + String property = attrs.remove(PROPERTY_ATTR) + String widgetFolder = attrs.remove(WIDGET_ATTR) + String theme = attrs.remove(THEME_ATTR) + + BeanPropertyAccessor propertyAccessor = resolveProperty(bean, property) + Map model = buildModel(propertyAccessor, attrs) + + out << renderWidget(propertyAccessor, model, attrs, widgetFolder, theme) + } + + /** + * @attr bean Name of the source bean in the GSP model. + * @attr property REQUIRED The name of the property to display. This is resolved + * against the specified bean or the bean in the current scope. + * @attr theme Theme name + */ + def displayWidget = { attrs -> + def bean = resolveBean(attrs.remove(BEAN_ATTR)) + if (!bean) throwTagError("Tag [displayWidget] is missing required attribute [$BEAN_ATTR]") + if (!attrs[PROPERTY_ATTR]) throwTagError("Tag [displayWidget] is missing required attribute [property]") + + attrs = getPrefixedAttributes(beanStack.innerAttributes) + attrs + + String property = attrs.remove(PROPERTY_ATTR) + String widgetFolder = attrs.remove(WIDGET_ATTR) + String theme = attrs.remove(THEME_ATTR) + + BeanPropertyAccessor propertyAccessor = resolveProperty(bean, property) + Map model = buildModel(propertyAccessor, attrs, 'HTML') + + out << renderDisplayWidget(propertyAccessor, model, attrs, widgetFolder, theme) + } + + /** + * @attr bean Name of the source bean in the GSP model. + * @attr property The name of the property to display. This is resolved against the specified bean or the bean in the current scope. + * @attr order A comma-separated list of properties to include in provided order + * @attr except A comma-separated list of properties to exclude + * @attr theme Theme name + * @attr template OPTIONAL The template used when rendering the domainClass + */ + def display = { attrs, body -> + attrs = beanStack.innerAttributes + attrs + def bean = resolveBean(attrs.remove(BEAN_ATTR)) + if (!bean) throwTagError("Tag [display] is missing required attribute [$BEAN_ATTR]") + + String property = attrs.remove(PROPERTY_ATTR) + String templatesFolder = attrs.remove(TEMPLATES_ATTR) + String theme = attrs.remove(THEME_ATTR) + + if (property == null) { + PersistentEntity domainClass = resolveDomainClass(bean) + if (domainClass) { + String template = attrs.remove('template') ?: 'list' + + List properties = resolvePersistentProperties(domainClass, attrs, ExclusionType.Display) + out << render(template: "/templates/_fields/$template", model: attrs + [domainClass: domainClass, domainProperties: properties]) { prop -> + BeanPropertyAccessor propertyAccessor = resolveProperty(bean, prop.name) + Map model = buildModel(propertyAccessor, attrs, 'HTML') + out << raw(renderDisplayWidget(propertyAccessor, model, attrs, templatesFolder, theme)) + } + } + } else { + String displayFolder = attrs.remove(WRAPPER_ATTR) + String widgetFolder = attrs.remove(WIDGET_ATTR) + + BeanPropertyAccessor propertyAccessor = resolveProperty(bean, property) + Map model = buildModel(propertyAccessor, attrs, 'HTML') + + Map wrapperAttrs = [:] + Map widgetAttrs = [:] + + String prefixAttribute = formFieldsTemplateService.getWidgetPrefix() ?: 'widget-' + attrs.each { k, v -> + if (k?.startsWith(prefixAttribute)) { + widgetAttrs[k.replace(prefixAttribute, '')] = v + } else { + wrapperAttrs[k] = v + } + } + + + String wrapperFolderTouse = displayFolder ?: templatesFolder + String widgetsFolderToUse = widgetFolder ?: templatesFolder + + if (hasBody(body)) { + model.widget = raw(body(model + [attrs: widgetAttrs] + widgetAttrs)) + model.value = body(model) + } else { + model.widget = renderDisplayWidget(propertyAccessor, model, widgetAttrs, widgetsFolderToUse, theme) + } + + + def displayWrapperTemplateName = formFieldsTemplateService.getTemplateFor("displayWrapper") + def template = formFieldsTemplateService.findTemplate(propertyAccessor, displayWrapperTemplateName, wrapperFolderTouse, theme) + if (template) { + out << render(template: template.path, plugin: template.plugin, model: model + [attrs: wrapperAttrs] + wrapperAttrs) + } else { + out << raw(renderDisplayWidget(propertyAccessor, model, attrs, widgetsFolderToUse, theme)) + } + } + + } + + private Map getPrefixedAttributes(attrs) { + Map widgetAttrs = [:] + attrs.each { k, v -> + String prefixAttribute = formFieldsTemplateService.getWidgetPrefix() + if (k?.startsWith(prefixAttribute)) { + widgetAttrs[k.replace(prefixAttribute, '')] = v + } + } + return widgetAttrs + } + + private void renderEmbeddedProperties(bean, BeanPropertyAccessor propertyAccessor, attrs) { + def legend = resolveMessage(propertyAccessor.labelKeys, propertyAccessor.defaultLabel) + out << applyLayout(name: '_fields/embedded', params: [type: toPropertyNameFormat(propertyAccessor.propertyType), legend: legend]) { + Embedded prop = (Embedded) propertyAccessor.domainProperty + for (embeddedProp in resolvePersistentProperties(prop.associatedEntity, attrs)) { + def propertyPath = "${propertyAccessor.pathFromRoot}.${embeddedProp.name}" + out << field(bean: bean, property: propertyPath, prefix: attrs.prefix, default: attrs.default, field: attrs.field, widget: attrs.widget, theme: attrs[THEME_ATTR]) + } + } + } + + private BeanPropertyAccessor resolveProperty(bean, String propertyPath) { + beanPropertyAccessorFactory.accessorFor(bean, propertyPath) + } + + private List resolveProperties(PersistentEntity domainClass, Map attrs) { + // Starting point for the bean property resolver + def bean = domainClass.javaClass.newInstance() + + List propertyAccessorList = resolvePropertyNames(domainClass, attrs).collect { String propertyPath -> + beanPropertyAccessorFactory.accessorFor(bean, propertyPath) + } + + return propertyAccessorList + + } + + private List resolvePropertyNames(PersistentEntity domainClass, Map attrs) { + if (attrs.containsKey('order')) { + return getList(attrs.order) + } else if (attrs.containsKey('properties')) { + return getList(attrs.remove('properties')) + } else { + List properties = resolvePersistentProperties(domainClass, attrs, ExclusionType.List)*.name + int maxProperties = attrs.containsKey('maxProperties') ? attrs.remove('maxProperties').toInteger() : 7 + if (maxProperties && properties.size() > maxProperties) { + properties = properties[0.. + String errorMsg = null + try { + errorMsg = error instanceof MessageSourceResolvable ? messageSource.getMessage(error, locale) : messageSource.getMessage(error.toString(), null, locale) + } catch (NoSuchMessageException ignored) { + // no-op + } + // unresolved message codes fallback to the defaultMessage and this should + // be escaped as it could be an error message with user input + errorMsg && errorMsg == error.defaultMessage ? message(error: error, encodeAs: "HTML") : message(error: error) + }, + required : attrs.containsKey("required") ? Boolean.valueOf(attrs.remove('required')) : propertyAccessor.required, + invalid : attrs.containsKey("invalid") ? Boolean.valueOf(attrs.remove('invalid')) : propertyAccessor.invalid, + prefix : resolvePrefix(attrs.remove('prefix')), + ] + } + + private CharSequence renderWidget(BeanPropertyAccessor propertyAccessor, Map model, Map attrs = [:], String widgetFolder, String theme) { + String widgetTemplateName = formFieldsTemplateService.getTemplateFor("widget") + Map template = formFieldsTemplateService.findTemplate(propertyAccessor, widgetTemplateName, widgetFolder, theme) + if (template) { + render template: template.path, plugin: template.plugin, model: model + [attrs: attrs] + attrs + } else { + renderDefaultInput propertyAccessor, model, attrs + } + } + + private CharSequence renderDisplayWidget(BeanPropertyAccessor propertyAccessor, Map model, Map attrs = [:], String widgetFolder, String theme) { + String displayStyle = attrs.displayStyle + + Map template = null + if (displayStyle && displayStyle != 'default') { + template = formFieldsTemplateService.findTemplate(propertyAccessor, "displayWidget-$attrs.displayStyle", widgetFolder, theme) + } + if (!template) { + def displayWidgetTemplateName = formFieldsTemplateService.getTemplateFor("displayWidget") + template = formFieldsTemplateService.findTemplate(propertyAccessor, displayWidgetTemplateName, widgetFolder, theme) + } + + if (template) { + render template: template.path, plugin: template.plugin, model: model + [attrs: attrs] + attrs + } else if (!(model.value instanceof CharSequence)) { + renderDefaultDisplay(model, attrs, widgetFolder, theme) + } else { + model.value + } + } + + private resolvePageScopeVariable(attributeName) { + // Tomcat throws NPE if you query pageScope for null/empty values + attributeName?.toString() ? pageScope.variables[attributeName] : null + } + + private BeanAndPrefix resolveBeanAndPrefix(beanAttribute, prefixAttribute, attributes) { + def bean = resolvePageScopeVariable(beanAttribute) ?: beanAttribute + def prefix = resolvePageScopeVariable(prefixAttribute) ?: prefixAttribute + def innerAttributes = attributes.clone() + innerAttributes.remove('bean') + innerAttributes.remove('prefix') + //'except' is a reserved word for the 'all' tag: https://github.com/grails-fields-plugin/grails-fields/issues/12 + innerAttributes.remove('except') + new BeanAndPrefix(bean: bean, prefix: prefix, innerAttributes: innerAttributes) + } + + private Object resolveBean(beanAttribute) { + resolvePageScopeVariable(beanAttribute) ?: beanAttribute ?: beanStack.bean + } + + private String resolvePrefix(prefixAttribute) { + def prefix = resolvePageScopeVariable(prefixAttribute) ?: prefixAttribute ?: beanStack.prefix + if (prefix && !prefix.endsWith('.')) { + prefix = prefix + '.' + } + prefix ?: '' + } + + private PersistentEntity resolveDomainClass(bean) { + resolveDomainClass(bean.getClass()) + } + + private PersistentEntity resolveDomainClass(Class beanClass) { + resolveDomainClass(beanClass.name) + } + + private PersistentEntity resolveDomainClass(String beanClassName) { + mappingContexts.findResult { MappingContext mappingContext -> + mappingContext.getPersistentEntity(beanClassName) + } + } + + private List resolvePersistentProperties(PersistentEntity domainClass, Map attrs, ExclusionType exclusionType = ExclusionType.Input) { + List properties + + boolean list = exclusionType == ExclusionType.List + if (attrs.order) { + def orderBy = getList(attrs.order) + if (attrs.except) { + orderBy = orderBy - getList(attrs.except) + } + properties = orderBy.collect { propertyName -> + fieldsDomainPropertyFactory.build(domainClass.getPropertyByName(propertyName)) + } + } else { + properties = list ? domainModelService.getListOutputProperties(domainClass) : domainModelService.getInputProperties(domainClass, + exclusionType == ExclusionType.Input ? exclusionsInput : exclusionsDisplay) + // If 'except' is not set, but 'list' is, exclude 'id', 'dateCreated' and 'lastUpdated' by default + List blacklist = attrs.containsKey('except') ? getList(attrs.except) : (list ? exclusionsList : []) + + properties.removeAll { it.name in blacklist } + } + + return properties + } + + private static List getList(def except, List defaultList = []) { + if (!except) { + return defaultList + } else if (except instanceof String) { + except?.tokenize(',')*.trim() + } else if (except instanceof Collection) { + return except as List + } else { + throw new IllegalArgumentException("Must either be null, comma separated string or java.util.Collection") + } + } + + private boolean hasBody(Closure body) { + return body && !body.is(GroovyPage.EMPTY_BODY_CLOSURE) + } + + private CharSequence resolveLabelText(BeanPropertyAccessor propertyAccessor, Map attrs) { + def labelText + def label = attrs.remove('label') + if (label) { + labelText = message(code: label, default: label) + } + if (!labelText && propertyAccessor.labelKeys) { + labelText = resolveMessage(propertyAccessor.labelKeys, propertyAccessor.defaultLabel) + } + if (!labelText) { + labelText = propertyAccessor.defaultLabel + } + return labelText + } + + private CharSequence resolveMessage(List keysInPreferenceOrder, String defaultMessage) { + def message = keysInPreferenceOrder.findResult { key -> + message(code: key, default: null) ?: null + } + if (log.traceEnabled && !message) { + log.trace("i18n missing translation for one of ${keysInPreferenceOrder}") + } + message ?: defaultMessage + } + + protected CharSequence renderDefaultField(Map model, Map attrs = [:]) { + List classes = [attrs['class'] ?: 'fieldcontain'] + if (model.invalid) classes << (attrs.remove('invalidClass') ?: 'error') + if (model.required) classes << (attrs.remove('requiredClass') ?: 'required') + attrs['class'] = classes.join(' ').trim() + Writer writer = new FastStringWriter() + def mb = new MarkupBuilder(writer) + mb.setDoubleQuotes(true) + mb.div(class: attrs['class']) { + label(class: attrs.labelClass, for: (model.prefix ?: '') + model.property, model.label) { + if (model.required) { + span(class: 'required-indicator', '*') + } + } + if (attrs.divClass) { + div(class: attrs.divClass) { + renderWidget(mkp, model) + } + } else { + renderWidget(mkp, model) + } + } + writer.buffer + } + + private void renderWidget(MarkupBuilderHelper mkp, Map model) { + // TODO: encoding information of widget gets lost - don't use MarkupBuilder + def widget = model.widget + if (widget != null) { + mkp.yieldUnescaped widget + } + } + + CharSequence renderDefaultInput(Map model, Map attrs = [:]) { + renderDefaultInput(null, model, attrs) + } + + CharSequence renderDefaultInput(BeanPropertyAccessor propertyAccessor, Map model, Map attrs = [:]) { + Constrained constrained = (Constrained) model.constraints + attrs.name = (model.prefix ?: '') + model.property + attrs.value = model.value + if (model.required) attrs.required = "" + // TODO: configurable how this gets output? Some people prefer required="required" + if (model.invalid) attrs.invalid = "" + if (!isEditable(constrained)) attrs.readonly = "" + + boolean oneToOne = false + boolean manyToOne = false + boolean manyToMany = false + boolean oneToMany = false + if (model.containsKey('persistentProperty')) { + if (model.persistentProperty instanceof PersistentProperty) { + PersistentProperty prop = (PersistentProperty) model.persistentProperty + oneToOne = prop instanceof OneToOne + manyToOne = prop instanceof ManyToOne + manyToMany = prop instanceof ManyToMany + oneToMany = prop instanceof OneToMany + } + } + + // TODO: https://github.com/gpc/fields/issues/392 + boolean datePicker = model.type in [Date, Calendar, java.sql.Date, java.sql.Time, LocalDate, LocalDateTime] + if (!datePicker) { + attrs.remove('selectDateClass') + } + boolean checkBox = model.type in [boolean, Boolean] + String checkBoxClass = attrs.remove('checkBoxClass') + if (checkBox && checkBoxClass) { + attrs['class'] = checkBoxClass + } + + if (model.type in [String, null]) { + return renderStringInput(model, attrs) + } else if (checkBox) { + return g.checkBox(attrs) + } else if (model.type.isPrimitive() || model.type in Number) { + return renderNumericInput(propertyAccessor, model, attrs) + } else if (model.type in URL) { + return g.field(attrs + [type: "url"]) + } else if (model.type.isEnum()) { + return renderEnumInput(model, attrs) + } else if (oneToOne || manyToOne || manyToMany) { + return renderAssociationInput(model, attrs) + } else if (oneToMany) { + return renderOneToManyInput(model, attrs) + } else if (datePicker) { + return renderDateTimeInput(model, attrs) + } else if (model.type in [byte[], Byte[], Blob]) { + return g.field(attrs + [type: "file"]) + } else if (model.type in [TimeZone, Currency, Locale]) { + if (!model.required) attrs.noSelection = ["": ""] + return g."${GrailsStringUtils.uncapitalize(model.type.simpleName)}Select"(attrs) + } else { + return null + } + } + + + CharSequence renderDateTimeInput(Map model, Map attrs) { + attrs.precision = model.type in [java.sql.Time, LocalDateTime] ? "minute" : "day" + if (!model.required) { + attrs.noSelection = ["": ""] + attrs.default = "none" + } + return g.datePicker(attrs) + } + + CharSequence renderStringInput(Map model, Map attrs) { + Constrained constrained = (Constrained) model.constraints + + if (!attrs.type) { + if (constrained?.inList) { + attrs.from = constrained.inList + if (!model.required) { + attrs.noSelection = ["": ""] + } + return g.select(attrs) + } else if (constrained?.password) { + attrs.type = "password" + attrs.remove('value') + } else if (constrained?.email) { + attrs.type = "email" + } else if (constrained?.url) { + attrs.type = "url" + } else { + attrs.type = "text" + } + } + + if (constrained?.matches) { + attrs.pattern = constrained.matches + } + if (constrained?.maxSize) { + attrs.maxlength = constrained.maxSize + } + + if (constrained?.widget == 'textarea') { + attrs.remove('type') + return g.textArea(attrs) + } + return g.field(attrs) + } + + CharSequence renderNumericInput(BeanPropertyAccessor propertyAccessor, Map model, Map attrs) { + Constrained constrained = (Constrained) model.constraints + + if (!attrs.type && constrained?.inList) { + attrs.from = constrained.inList + if (!model.required) attrs.noSelection = ["": ""] + return g.select(attrs) + } else if (constrained?.range) { + attrs.type = attrs.type ?: "range" + attrs.min = constrained.range.from + attrs.max = constrained.range.to + } else { + attrs.type = attrs.type ?: getDefaultNumberType(model) + if (constrained?.scale != null) attrs.step = "0.${'0' * (constrained.scale - 1)}1" + if (constrained?.min != null) attrs.min = constrained.min + if (constrained?.max != null) attrs.max = constrained.max + } + + if (localizeNumbers && propertyAccessor?.value != null) { + attrs.value = numberFormatter.format(propertyAccessor.value) + } + + return g.field(attrs) + } + + @CompileStatic + protected NumberFormat getNumberFormatter() { + NumberFormat.getInstance(getLocale()) + } + + @CompileStatic + protected Locale getLocale() { + def locale + def request = GrailsWebRequest.lookup()?.currentRequest + if (request instanceof HttpServletRequest) { + locale = localeResolver?.resolveLocale(request) + } + if (locale == null) { + locale = Locale.default + } + return locale + } + + @CompileStatic + protected String getDefaultNumberType(Map model) { + Class modelType = (Class) model.type + + def typeName = modelType.simpleName.toLowerCase() + if (typeName in DECIMAL_TYPES) { + return "number decimal" + } else { + return "number" + } + + } + + private CharSequence renderEnumInput(Map model, Map attrs) { + Constrained constrained = (Constrained) model.constraints + + if (attrs.value instanceof Enum) + attrs.value = attrs.value.name() + if (!model.required) attrs.noSelection = ["": ""] + + if (constrained?.inList) { + attrs.keys = constrained.inList*.name() + attrs.from = constrained.inList + } else { + attrs.keys = model.type.values()*.name() + attrs.from = model.type.values() + } + return g.select(attrs) + } + + private CharSequence renderAssociationInput(Map model, Map attrs) { + attrs.id = (model.prefix ?: '') + model.property + def persistentProperty = model.persistentProperty + Class referencedPropertyType + boolean manyToMany = false + if (persistentProperty instanceof Association) { + Association prop = ((Association) persistentProperty) + PersistentEntity entity = prop.getAssociatedEntity() + if (entity != null) { + referencedPropertyType = entity.getJavaClass() + } else if (prop.isBasic()) { + referencedPropertyType = ((Basic) prop).getComponentType() + } + manyToMany = prop instanceof ManyToMany + } + attrs.from = null != attrs.from ? attrs.from : referencedPropertyType.list() + attrs.optionKey = "id" // TODO: handle alternate id names + if (manyToMany) { + attrs.multiple = "" + attrs.value = model.value*.id + attrs.name = "${model.prefix ?: ''}${model.property}" + } else { + if (!model.required) attrs.noSelection = ["null": ""] + attrs.value = model.value?.id + attrs.name = "${model.prefix ?: ''}${model.property}.id" + } + return g.select(attrs) + } + + private CharSequence renderOneToManyInput(Map model, Map attrs) { + Writer buffer = new FastStringWriter() + buffer << '
      ' + def persistentProperty = model.persistentProperty + def controllerName + def shortName + if (persistentProperty instanceof Association) { + Association prop = ((Association) persistentProperty) + controllerName = prop.associatedEntity.decapitalizedName + shortName = prop.associatedEntity.javaClass.simpleName + } + + attrs.value.each { + buffer << '
    • ' + buffer << g.link(controller: controllerName, action: "show", id: it.id, it.toString().encodeAsHTML()) + buffer << '
    • ' + } + buffer << '
    ' + def referencedTypeLabel = message(code: "${controllerName}.label", default: shortName) + def addLabel = g.message(code: 'default.add.label', args: [referencedTypeLabel]) + PersistentEntity beanClass = (PersistentEntity) model.beanClass + buffer << g.link(controller: controllerName, action: "create", params: [("${beanClass.decapitalizedName}.id".toString()): model.bean.id], addLabel) + buffer.buffer + } + + private CharSequence renderDefaultDisplay(Map model, Map attrs = [:], String templatesFolder, String theme) { + def persistentProperty = model.persistentProperty + if (persistentProperty instanceof Association) { + if (persistentProperty.embedded) { + return (attrs.displayStyle == 'table') ? model.value?.toString().encodeAsHTML() : + displayEmbedded(model.value, persistentProperty.associatedEntity, attrs, templatesFolder, theme) + } else if (persistentProperty instanceof OneToMany || persistentProperty instanceof ManyToMany) { + return displayAssociationList(model.value, ((Association) persistentProperty).associatedEntity) + } else { + return displayAssociation(model.value, ((Association) persistentProperty).associatedEntity) + } + } + + switch (model.type) { + case Boolean.TYPE: + case Boolean: + g.formatBoolean(boolean: model.value) + break + case Calendar: + case Date: + case java.sql.Date: + case java.sql.Time: + case LocalDate: + case LocalDateTime: + g.formatDate(date: model.value) + break + default: + g.fieldValue bean: model.bean, field: model.property + } + } + + private CharSequence displayEmbedded(bean, PersistentEntity domainClass, Map attrs, String templatesFolder, String theme) { + Writer buffer = new FastStringWriter() + def properties = domainModelService.getOutputProperties(domainClass) + buffer << render(template: "/templates/_fields/list", model: [domainClass: domainClass, domainProperties: properties]) { prop -> + def propertyAccessor = resolveProperty(bean, prop.name) + def model = buildModel(propertyAccessor, attrs) + out << raw(renderDisplayWidget(propertyAccessor, model, attrs, templatesFolder, theme)) + } + buffer.buffer + } + + private CharSequence displayAssociationList(values, PersistentEntity referencedDomainClass) { + Writer buffer = new FastStringWriter() + buffer << '
      ' + for (value in values) { + buffer << '
    • ' + buffer << displayAssociation(value, referencedDomainClass) + buffer << '
    • ' + } + buffer << '
    ' + buffer.buffer + } + + private CharSequence displayAssociation(value, PersistentEntity referencedDomainClass) { + if (value && referencedDomainClass) { + g.link(controller: referencedDomainClass.decapitalizedName, action: "show", id: value.id, value.toString().encodeAsHTML()) + } else if (value) { + value.toString() + } + } + + private boolean isEditable(Constrained constraints) { + !constraints || constraints.editable } } diff --git a/grails-fields/src/main/groovy/grails/plugin/formfields/BeanPropertyAccessorFactory.groovy b/grails-fields/src/main/groovy/grails/plugin/formfields/BeanPropertyAccessorFactory.groovy index 72a4df0f399..3ab5dc90a3f 100644 --- a/grails-fields/src/main/groovy/grails/plugin/formfields/BeanPropertyAccessorFactory.groovy +++ b/grails-fields/src/main/groovy/grails/plugin/formfields/BeanPropertyAccessorFactory.groovy @@ -84,10 +84,10 @@ class BeanPropertyAccessorFactory implements GrailsApplicationAware { } private boolean getAddPathFromRoot() { - grailsApplication.config.getProperty('grails.plugin.fields.i18n.addPathFromRoot', Boolean) - } - - private DomainProperty resolvePropertyFromPathComponents(BeanWrapper beanWrapper, List pathElements, Map params) { + grailsApplication.config.getProperty('grails.plugin.fields.i18n.addPathFromRoot', Boolean) + } + + private DomainProperty resolvePropertyFromPathComponents(BeanWrapper beanWrapper, List pathElements, Map params) { String propertyName = pathElements.remove(0) PersistentEntity beanClass = resolveDomainClass(beanWrapper.wrappedClass) Class propertyType = resolvePropertyType(beanWrapper, beanClass, propertyName) @@ -140,7 +140,7 @@ class BeanPropertyAccessorFactory implements GrailsApplicationAware { } private static Class resolveDomainPropertyType(PersistentEntity beanClass, String propertyName) { - if(beanClass) { + if (beanClass) { String propertyNameWithoutIndex = stripIndex(propertyName) PersistentProperty persistentProperty = beanClass.getPropertyByName(propertyNameWithoutIndex) if (!persistentProperty && beanClass.isIdentityName(propertyNameWithoutIndex)) { @@ -165,25 +165,25 @@ class BeanPropertyAccessorFactory implements GrailsApplicationAware { private static Class resolveNonDomainPropertyType(BeanWrapper beanWrapper, String propertyName) { Class type = beanWrapper.getPropertyType(propertyName) - if (type == null) { - String match = getPropertyMatch(propertyName) - if (match) { - Type genericType = beanWrapper.getPropertyDescriptor(match).readMethod.genericReturnType - if (genericType instanceof ParameterizedType) { + if (type == null) { + String match = getPropertyMatch(propertyName) + if (match) { + Type genericType = beanWrapper.getPropertyDescriptor(match).readMethod.genericReturnType + if (genericType instanceof ParameterizedType) { ParameterizedType parameterizedType = genericType as ParameterizedType - switch (parameterizedType.rawType) { - case Collection: - return parameterizedType.actualTypeArguments[0] as Class - case Map: - return parameterizedType.actualTypeArguments[1] as Class - } - } else { - return Object - } - } - } - return type - } + switch (parameterizedType.rawType) { + case Collection: + return parameterizedType.actualTypeArguments[0] as Class + case Map: + return parameterizedType.actualTypeArguments[1] as Class + } + } else { + return Object + } + } + } + return type + } private BeanWrapper beanWrapperFor(Class type, value) { value ? PropertyAccessorFactory.forBeanPropertyAccess(unwrapIfProxy(value)) : new BeanWrapperImpl(type) @@ -205,6 +205,6 @@ class BeanPropertyAccessorFactory implements GrailsApplicationAware { def matcher = propertyName =~ INDEXED_PROPERTY_PATTERN matcher.matches() ? (matcher[0] as String[])[1] : propertyName } - - + + } diff --git a/grails-fields/src/main/groovy/grails/plugin/formfields/BeanPropertyAccessorImpl.groovy b/grails-fields/src/main/groovy/grails/plugin/formfields/BeanPropertyAccessorImpl.groovy index 09f6a8b6238..88cb2c05ee0 100644 --- a/grails-fields/src/main/groovy/grails/plugin/formfields/BeanPropertyAccessorImpl.groovy +++ b/grails-fields/src/main/groovy/grails/plugin/formfields/BeanPropertyAccessorImpl.groovy @@ -85,11 +85,11 @@ class BeanPropertyAccessorImpl implements BeanPropertyAccessor { List getLabelKeys() { List labelKeys = [] - - labelKeys << "${GrailsNameUtils.getPropertyName(rootBeanType.simpleName)}.${pathFromRoot}.label".replaceAll(/\[(.+)\]/, '') - if(addPathFromRoot) { + + labelKeys << "${GrailsNameUtils.getPropertyName(rootBeanType.simpleName)}.${pathFromRoot}.label".replaceAll(/\[(.+)\]/, '') + if (addPathFromRoot) { labelKeys << "${pathFromRoot}.label".replaceAll(/\[(.+)\]/, '') - } + } labelKeys << "${GrailsNameUtils.getPropertyName(beanType.simpleName)}.${propertyName}.label".toString() return labelKeys.unique() as List diff --git a/grails-fields/src/main/groovy/grails/plugin/formfields/PropertyPathAccessor.groovy b/grails-fields/src/main/groovy/grails/plugin/formfields/PropertyPathAccessor.groovy index 706a3860dd4..71246053047 100644 --- a/grails-fields/src/main/groovy/grails/plugin/formfields/PropertyPathAccessor.groovy +++ b/grails-fields/src/main/groovy/grails/plugin/formfields/PropertyPathAccessor.groovy @@ -33,8 +33,8 @@ import org.springframework.context.support.StaticMessageSource import org.springframework.validation.FieldError import static grails.plugin.formfields.BeanPropertyAccessorFactory.stripIndex -import static java.util.Collections.EMPTY_LIST import static grails.util.GrailsStringUtils.substringAfterLast +import static java.util.Collections.EMPTY_LIST @CompileStatic @Canonical diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/ScaffoldingBeanConfiguration.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/ScaffoldingBeanConfiguration.groovy index b6a232ee3a6..7582edb6d80 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/ScaffoldingBeanConfiguration.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/ScaffoldingBeanConfiguration.groovy @@ -19,7 +19,12 @@ package org.grails.scaffolding -import org.grails.scaffolding.markup.* +import org.grails.scaffolding.markup.ContextMarkupRenderer +import org.grails.scaffolding.markup.ContextMarkupRendererImpl +import org.grails.scaffolding.markup.DomainMarkupRenderer +import org.grails.scaffolding.markup.DomainMarkupRendererImpl +import org.grails.scaffolding.markup.PropertyMarkupRenderer +import org.grails.scaffolding.markup.PropertyMarkupRendererImpl import org.grails.scaffolding.model.DomainModelService import org.grails.scaffolding.model.DomainModelServiceImpl import org.grails.scaffolding.model.property.DomainPropertyFactory diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/markup/ContextMarkupRenderer.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/markup/ContextMarkupRenderer.groovy index 908161074b1..4ee7ec96a6b 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/markup/ContextMarkupRenderer.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/markup/ContextMarkupRenderer.groovy @@ -19,8 +19,8 @@ package org.grails.scaffolding.markup -import org.grails.scaffolding.model.property.DomainProperty import org.grails.datastore.mapping.model.PersistentEntity +import org.grails.scaffolding.model.property.DomainProperty /** * Used to output context surrounding any given content. Context is any markup that will be rendered @@ -28,7 +28,7 @@ import org.grails.datastore.mapping.model.PersistentEntity * any HTML input type element (A way to retrieve users input). Output is used in this class to mean * the display of a domain property on the page. * - * An example of what might be returned with {@link #inputContext(DomainProperty,Closure)} + * An example of what might be returned with {@link #inputContext(DomainProperty, Closure)} *
    {@code
      * { ->
      *      div([class: "form-group"]) {
    @@ -36,7 +36,7 @@ import org.grails.datastore.mapping.model.PersistentEntity
      *          content.delegate = delegate
      *          content.call()
      *      }}
    - * }
    + *} * * @author James Kleeh */ diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/markup/ContextMarkupRendererImpl.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/markup/ContextMarkupRendererImpl.groovy index e36143eebcb..0a6a359321c 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/markup/ContextMarkupRendererImpl.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/markup/ContextMarkupRendererImpl.groovy @@ -19,14 +19,13 @@ package org.grails.scaffolding.markup -import org.grails.scaffolding.model.property.DomainProperty import grails.util.GrailsNameUtils import groovy.transform.CompileStatic +import jakarta.annotation.Resource import org.grails.datastore.mapping.model.PersistentEntity +import org.grails.scaffolding.model.property.DomainProperty import org.springframework.context.MessageSource -import jakarta.annotation.Resource - /** * @see {@link ContextMarkupRenderer} * @author James Kleeh @@ -105,17 +104,17 @@ class ContextMarkupRendererImpl implements ContextMarkupRenderer { if (property.required) { classes << 'required' } - { -> - content.delegate = delegate - div(class: classes.join(' ')) { - label([for: property.pathFromRoot], getLabelText(property)) { - if (property.required) { - span(class: 'required-indicator', '*') + { -> + content.delegate = delegate + div(class: classes.join(' ')) { + label([for: property.pathFromRoot], getLabelText(property)) { + if (property.required) { + span(class: 'required-indicator', '*') + } + } + content.call() } } - content.call() - } - } } @Override diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/markup/DomainMarkupRendererImpl.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/markup/DomainMarkupRendererImpl.groovy index a4a653c4506..9a17f818fa1 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/markup/DomainMarkupRendererImpl.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/markup/DomainMarkupRendererImpl.groovy @@ -19,13 +19,12 @@ package org.grails.scaffolding.markup -import org.grails.scaffolding.model.DomainModelService -import org.grails.scaffolding.model.property.DomainProperty -import groovy.transform.CompileStatic import groovy.xml.MarkupBuilder import org.grails.buffer.FastStringWriter import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.model.types.Embedded +import org.grails.scaffolding.model.DomainModelService +import org.grails.scaffolding.model.property.DomainProperty import org.springframework.beans.factory.annotation.Autowired /** @@ -82,7 +81,7 @@ class DomainMarkupRendererImpl implements DomainMarkupRenderer { List domainProperties = domainModelService.getListOutputProperties(domainClass) domainProperties.each { DomainProperty property -> if (property.persistentProperty instanceof Embedded) { - domainModelService.getOutputProperties(((Embedded)property.persistentProperty).associatedEntity).each { DomainProperty embedded -> + domainModelService.getOutputProperties(((Embedded) property.persistentProperty).associatedEntity).each { DomainProperty embedded -> embedded.rootProperty = property tableProperties.add(embedded) } @@ -91,52 +90,52 @@ class DomainMarkupRendererImpl implements DomainMarkupRenderer { } } if (tableProperties.size() > maxListOutputSize) { - tableProperties = tableProperties[0..(maxListOutputSize-1)] + tableProperties = tableProperties[0..(maxListOutputSize - 1)] } - outputMarkupContent ( - contextMarkupRenderer.listOutputContext(domainClass, tableProperties) { DomainProperty domainProperty -> - propertyMarkupRenderer.renderListOutput(domainProperty) - } + outputMarkupContent( + contextMarkupRenderer.listOutputContext(domainClass, tableProperties) { DomainProperty domainProperty -> + propertyMarkupRenderer.renderListOutput(domainProperty) + } ) } String renderInput(PersistentEntity domainClass) { outputMarkupContent( - contextMarkupRenderer.inputContext(domainClass) { -> - def contextDelegate = delegate - domainModelService.getInputProperties(domainClass).each { DomainProperty property -> - if (property.persistentProperty instanceof Embedded) { - callWithDelegate(contextDelegate, contextMarkupRenderer.embeddedInputContext(property) { - domainModelService.getInputProperties(((Embedded)property.persistentProperty).associatedEntity).each { DomainProperty embedded -> - embedded.rootProperty = property - callWithDelegate(contextDelegate, renderInput(embedded)) - } - }) - } else { - callWithDelegate(contextDelegate, renderInput(property)) + contextMarkupRenderer.inputContext(domainClass) { -> + def contextDelegate = delegate + domainModelService.getInputProperties(domainClass).each { DomainProperty property -> + if (property.persistentProperty instanceof Embedded) { + callWithDelegate(contextDelegate, contextMarkupRenderer.embeddedInputContext(property) { + domainModelService.getInputProperties(((Embedded) property.persistentProperty).associatedEntity).each { DomainProperty embedded -> + embedded.rootProperty = property + callWithDelegate(contextDelegate, renderInput(embedded)) + } + }) + } else { + callWithDelegate(contextDelegate, renderInput(property)) + } } } - } ) } String renderOutput(PersistentEntity domainClass) { outputMarkupContent( - contextMarkupRenderer.outputContext(domainClass) { -> - def contextDelegate = delegate - domainModelService.getOutputProperties(domainClass).each { DomainProperty property -> - if (property.persistentProperty instanceof Embedded) { - callWithDelegate(contextDelegate, contextMarkupRenderer.embeddedOutputContext(property) { -> - domainModelService.getOutputProperties(((Embedded)property.persistentProperty).associatedEntity).each { DomainProperty embedded -> - embedded.rootProperty = property - callWithDelegate(contextDelegate, renderOutput(embedded)) - } - }) - } else { - callWithDelegate(contextDelegate, renderOutput(property)) + contextMarkupRenderer.outputContext(domainClass) { -> + def contextDelegate = delegate + domainModelService.getOutputProperties(domainClass).each { DomainProperty property -> + if (property.persistentProperty instanceof Embedded) { + callWithDelegate(contextDelegate, contextMarkupRenderer.embeddedOutputContext(property) { -> + domainModelService.getOutputProperties(((Embedded) property.persistentProperty).associatedEntity).each { DomainProperty embedded -> + embedded.rootProperty = property + callWithDelegate(contextDelegate, renderOutput(embedded)) + } + }) + } else { + callWithDelegate(contextDelegate, renderOutput(property)) + } } } - } ) } } diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/markup/PropertyMarkupRendererImpl.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/markup/PropertyMarkupRendererImpl.groovy index 6055ffbc797..90f8d692d67 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/markup/PropertyMarkupRendererImpl.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/markup/PropertyMarkupRendererImpl.groovy @@ -19,10 +19,10 @@ package org.grails.scaffolding.markup +import groovy.transform.CompileStatic import org.grails.scaffolding.model.property.DomainProperty -import org.grails.scaffolding.registry.DomainOutputRendererRegistry import org.grails.scaffolding.registry.DomainInputRendererRegistry -import groovy.transform.CompileStatic +import org.grails.scaffolding.registry.DomainOutputRendererRegistry import org.springframework.beans.factory.annotation.Autowired /** diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/model/DomainModelService.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/model/DomainModelService.groovy index 87ffeaed26e..03d41b9fbd7 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/model/DomainModelService.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/model/DomainModelService.groovy @@ -19,8 +19,8 @@ package org.grails.scaffolding.model -import org.grails.scaffolding.model.property.DomainProperty import org.grails.datastore.mapping.model.PersistentEntity +import org.grails.scaffolding.model.property.DomainProperty /** * An API to retrieve properties from a {@link PersistentEntity} @@ -35,6 +35,7 @@ interface DomainModelService { * @param domainClass The persistent entity */ List getInputProperties(PersistentEntity domainClass) + List getInputProperties(PersistentEntity domainClass, List blackList) /** diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/model/DomainModelServiceImpl.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/model/DomainModelServiceImpl.groovy index d56c6b077f9..e142abe6d9b 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/model/DomainModelServiceImpl.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/model/DomainModelServiceImpl.groovy @@ -19,15 +19,15 @@ package org.grails.scaffolding.model -import org.grails.datastore.mapping.config.Property -import org.grails.scaffolding.model.property.Constrained -import org.grails.scaffolding.model.property.DomainProperty -import org.grails.scaffolding.model.property.DomainPropertyFactory import grails.util.GrailsClassUtils import groovy.transform.CompileStatic +import org.grails.datastore.mapping.config.Property import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.mapping.model.types.Embedded +import org.grails.scaffolding.model.property.Constrained +import org.grails.scaffolding.model.property.DomainProperty +import org.grails.scaffolding.model.property.DomainPropertyFactory import org.springframework.beans.factory.annotation.Autowired import java.lang.reflect.Method @@ -69,12 +69,12 @@ class DomainModelServiceImpl implements DomainModelService { } Object scaffoldProp = GrailsClassUtils.getStaticPropertyValue(domainClass.javaClass, 'scaffold') if (scaffoldProp instanceof Map) { - Map scaffold = (Map)scaffoldProp + Map scaffold = (Map) scaffoldProp if (scaffold.containsKey('exclude')) { if (scaffold.exclude instanceof Collection) { - blacklist.addAll((Collection)scaffold.exclude) + blacklist.addAll((Collection) scaffold.exclude) } else if (scaffold.exclude instanceof String) { - blacklist.add((String)scaffold.exclude) + blacklist.add((String) scaffold.exclude) } } } @@ -151,7 +151,7 @@ class DomainModelServiceImpl implements DomainModelService { getInputProperties(domainClass).each { DomainProperty domainProperty -> PersistentProperty property = domainProperty.persistentProperty if (property instanceof Embedded) { - getInputProperties(((Embedded)property).associatedEntity).each { DomainProperty embedded -> + getInputProperties(((Embedded) property).associatedEntity).each { DomainProperty embedded -> embedded.rootProperty = domainProperty if (closure.call(embedded)) { properties.add(embedded) diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/model/property/Constrained.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/model/property/Constrained.groovy index 151a38a1227..71a3146320c 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/model/property/Constrained.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/model/property/Constrained.groovy @@ -83,7 +83,7 @@ class Constrained { true } } - + List getInList() { if (this.constrained1 != null) { this.constrained1.inList @@ -229,6 +229,6 @@ class Constrained { } boolean isNull() { - this.constrained1 == null + this.constrained1 == null } } diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/model/property/DomainPropertyImpl.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/model/property/DomainPropertyImpl.groovy index ea5e4605ef3..5fc2c5dee49 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/model/property/DomainPropertyImpl.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/model/property/DomainPropertyImpl.groovy @@ -29,6 +29,7 @@ import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.mapping.model.types.Association import org.grails.datastore.mapping.model.types.Basic import org.springframework.validation.Validator + import static grails.gorm.validation.ConstrainedProperty.BLANK_CONSTRAINT /** @@ -38,7 +39,8 @@ import static grails.gorm.validation.ConstrainedProperty.BLANK_CONSTRAINT @CompileStatic class DomainPropertyImpl implements DomainProperty { - @Delegate PersistentProperty persistentProperty + @Delegate + PersistentProperty persistentProperty PersistentProperty rootProperty PersistentEntity domainClass Constrained constrained @@ -52,7 +54,7 @@ class DomainPropertyImpl implements DomainProperty { this.domainClass = persistentProperty.owner Validator validator = mappingContext.getEntityValidator(domainClass) if (validator instanceof PersistentEntityValidator) { - this.constrained = new Constrained(((PersistentEntityValidator)validator).constrainedProperties.get(name)) + this.constrained = new Constrained(((PersistentEntityValidator) validator).constrainedProperties.get(name)) } if (this.constrained?.isNull()) { this.constrained = null @@ -82,7 +84,7 @@ class DomainPropertyImpl implements DomainProperty { Class getAssociatedType() { if (persistentProperty instanceof Association) { if (persistentProperty instanceof Basic) { - ((Basic)persistentProperty).componentType + ((Basic) persistentProperty).componentType } else { associatedEntity.javaClass } @@ -92,7 +94,7 @@ class DomainPropertyImpl implements DomainProperty { } PersistentEntity getAssociatedEntity() { - ((Association)persistentProperty).associatedEntity + ((Association) persistentProperty).associatedEntity } boolean isRequired() { @@ -133,7 +135,7 @@ class DomainPropertyImpl implements DomainProperty { Constrained cp2 = o2.constrained - if (constrained == null && cp2 == null) { + if (constrained == null && cp2 == null) { return name.compareTo(o2.name) } diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/DomainRendererRegisterer.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/DomainRendererRegisterer.groovy index 1d8118b432d..2709bb19936 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/DomainRendererRegisterer.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/DomainRendererRegisterer.groovy @@ -19,12 +19,27 @@ package org.grails.scaffolding.registry -import org.grails.scaffolding.registry.input.* -import org.grails.scaffolding.registry.output.DefaultOutputRenderer import grails.web.mapping.LinkGenerator import groovy.transform.CompileStatic -import org.springframework.beans.factory.annotation.Autowired import jakarta.annotation.PostConstruct +import org.grails.scaffolding.registry.input.AssociationInputRenderer +import org.grails.scaffolding.registry.input.BidirectionalToManyInputRenderer +import org.grails.scaffolding.registry.input.BooleanInputRenderer +import org.grails.scaffolding.registry.input.CurrencyInputRenderer +import org.grails.scaffolding.registry.input.DateInputRenderer +import org.grails.scaffolding.registry.input.DefaultInputRenderer +import org.grails.scaffolding.registry.input.EnumInputRenderer +import org.grails.scaffolding.registry.input.FileInputRenderer +import org.grails.scaffolding.registry.input.InListInputRenderer +import org.grails.scaffolding.registry.input.LocaleInputRenderer +import org.grails.scaffolding.registry.input.NumberInputRenderer +import org.grails.scaffolding.registry.input.StringInputRenderer +import org.grails.scaffolding.registry.input.TextareaInputRenderer +import org.grails.scaffolding.registry.input.TimeInputRenderer +import org.grails.scaffolding.registry.input.TimeZoneInputRenderer +import org.grails.scaffolding.registry.input.UrlInputRenderer +import org.grails.scaffolding.registry.output.DefaultOutputRenderer +import org.springframework.beans.factory.annotation.Autowired /** * Bean for registering the default domain renderers diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/DomainRendererRegistry.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/DomainRendererRegistry.groovy index f294d55d3e6..59193bab761 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/DomainRendererRegistry.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/DomainRendererRegistry.groovy @@ -19,8 +19,8 @@ package org.grails.scaffolding.registry -import org.grails.scaffolding.model.property.DomainProperty import groovy.transform.CompileStatic +import org.grails.scaffolding.model.property.DomainProperty import java.util.concurrent.atomic.AtomicInteger @@ -54,6 +54,7 @@ abstract class DomainRendererRegistry { } private class Entry implements Comparable { + protected final T renderer private final int priority; private final int seq; diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/AssociationInputRenderer.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/AssociationInputRenderer.groovy index 4ea48d64457..58d4241baa6 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/AssociationInputRenderer.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/AssociationInputRenderer.groovy @@ -19,9 +19,9 @@ package org.grails.scaffolding.registry.input +import org.grails.datastore.mapping.model.types.Association import org.grails.scaffolding.model.property.DomainProperty import org.grails.scaffolding.registry.DomainInputRenderer -import org.grails.datastore.mapping.model.types.Association /** * The default renderer for rendering associations diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/BidirectionalToManyInputRenderer.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/BidirectionalToManyInputRenderer.groovy index 273a5d3ea70..94d289435b3 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/BidirectionalToManyInputRenderer.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/BidirectionalToManyInputRenderer.groovy @@ -19,12 +19,12 @@ package org.grails.scaffolding.registry.input -import org.grails.scaffolding.model.property.DomainProperty -import org.grails.scaffolding.registry.DomainInputRenderer import grails.util.GrailsNameUtils import grails.web.mapping.LinkGenerator import org.grails.datastore.mapping.model.PersistentProperty import org.grails.datastore.mapping.model.types.ToMany +import org.grails.scaffolding.model.property.DomainProperty +import org.grails.scaffolding.registry.DomainInputRenderer /** * The default renderer for rendering bidirectional to many associations diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/CurrencyInputRenderer.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/CurrencyInputRenderer.groovy index 828640fde16..0267002a338 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/CurrencyInputRenderer.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/CurrencyInputRenderer.groovy @@ -19,9 +19,8 @@ package org.grails.scaffolding.registry.input -import org.grails.scaffolding.model.property.DomainProperty -import org.grails.scaffolding.registry.DomainInputRenderer import groovy.transform.CompileStatic +import org.grails.scaffolding.model.property.DomainProperty /** * The default renderer for rendering {@link Currency} properties diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/LocaleInputRenderer.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/LocaleInputRenderer.groovy index 2fa59200f39..af3022a5e8f 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/LocaleInputRenderer.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/LocaleInputRenderer.groovy @@ -19,9 +19,8 @@ package org.grails.scaffolding.registry.input -import org.grails.scaffolding.model.property.DomainProperty -import org.grails.scaffolding.registry.DomainInputRenderer import groovy.transform.CompileStatic +import org.grails.scaffolding.model.property.DomainProperty /** * The default renderer for rendering {@link Locale} properties diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/MapToSelectInputRenderer.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/MapToSelectInputRenderer.groovy index b8248255834..40406390047 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/MapToSelectInputRenderer.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/MapToSelectInputRenderer.groovy @@ -27,7 +27,7 @@ import org.grails.scaffolding.registry.DomainInputRenderer * of options and a default option * * @author James Kleeh - * @param Any type + * @param Any type */ trait MapToSelectInputRenderer implements DomainInputRenderer { @@ -59,7 +59,7 @@ trait MapToSelectInputRenderer implements DomainInputRenderer { */ abstract Map getOptions() - /** @see DomainInputRenderer#renderInput() **/ + /** @see DomainInputRenderer#renderInput() * */ Closure renderInput(Map defaultAttributes, DomainProperty property) { String selected = getOptionKey(defaultOption) diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/NumberInputRenderer.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/NumberInputRenderer.groovy index 33a32e71996..e4da54ed79d 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/NumberInputRenderer.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/NumberInputRenderer.groovy @@ -53,7 +53,7 @@ class NumberInputRenderer implements DomainInputRenderer { attributes.type = "number" - if(typeName in ['double', 'float', 'bigdecimal']) { + if (typeName in ['double', 'float', 'bigdecimal']) { attributes.step = "any" } if (constraints?.scale != null) { diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/StringInputRenderer.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/StringInputRenderer.groovy index 22579823caf..ed0e8961ed0 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/StringInputRenderer.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/StringInputRenderer.groovy @@ -44,7 +44,7 @@ class StringInputRenderer implements DomainInputRenderer { Constrained constraints = domainProperty.constrained if (constraints?.password) { standardAttributes.type = "password" - } else if (constraints?.email) { + } else if (constraints?.email) { standardAttributes.type = "email" } else if (constraints?.url) { standardAttributes.type = "url" diff --git a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/TimeZoneInputRenderer.groovy b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/TimeZoneInputRenderer.groovy index 870864557eb..8ebf146c7fe 100644 --- a/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/TimeZoneInputRenderer.groovy +++ b/grails-fields/src/main/groovy/org/grails/scaffolding/registry/input/TimeZoneInputRenderer.groovy @@ -19,9 +19,8 @@ package org.grails.scaffolding.registry.input -import org.grails.scaffolding.model.property.DomainProperty -import org.grails.scaffolding.registry.DomainInputRenderer import groovy.transform.CompileStatic +import org.grails.scaffolding.model.property.DomainProperty /** * The default renderer for rendering {@link TimeZone} properties diff --git a/grails-fields/src/test/groovy/grails/plugin/formfields/DomainClassPropertyAccessorSpec.groovy b/grails-fields/src/test/groovy/grails/plugin/formfields/DomainClassPropertyAccessorSpec.groovy index 37b61e2131c..0cd18a84810 100644 --- a/grails-fields/src/test/groovy/grails/plugin/formfields/DomainClassPropertyAccessorSpec.groovy +++ b/grails-fields/src/test/groovy/grails/plugin/formfields/DomainClassPropertyAccessorSpec.groovy @@ -301,11 +301,11 @@ class DomainClassPropertyAccessorSpec extends BuildsAccessorFactory { propertyAccessor.invalid } - @Issue("http://jira.grails.org/browse/GRAILS-7713") + @Issue("GRAILS-7713") void "resolves errors for an embedded property"() { given: person.address.country = "Australia" - person.errors.rejectValue('address.country', 'not.inList') // http://jira.grails.org/browse/GRAILS-8480 + person.errors.rejectValue('address.country', 'not.inList') // GRAILS-8480 when: BeanPropertyAccessor propertyAccessor = factory.accessorFor(person, "address.country") @@ -315,11 +315,11 @@ class DomainClassPropertyAccessorSpec extends BuildsAccessorFactory { propertyAccessor.invalid } - @Issue("http://jira.grails.org/browse/GRAILS-7713") + @Issue("GRAILS-7713") void "resolves errors for an indexed property"() { given: author.books[0].title = "" - author.errors.rejectValue('books[0].title', 'blank') // http://jira.grails.org/browse/GRAILS-7713 + author.errors.rejectValue('books[0].title', 'blank') // GRAILS-7713 and: def propertyAccessor = factory.accessorFor(author, "books[0].title") diff --git a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AbstractFormFieldsTagLibSpec.groovy b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AbstractFormFieldsTagLibSpec.groovy index 7d39cf98e24..60bd7906ae7 100644 --- a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AbstractFormFieldsTagLibSpec.groovy +++ b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AbstractFormFieldsTagLibSpec.groovy @@ -22,6 +22,11 @@ package grails.plugin.formfields.taglib import grails.core.support.proxy.DefaultProxyHandler import grails.plugin.formfields.BeanPropertyAccessorFactory import grails.plugin.formfields.FieldsGrailsPlugin +import grails.plugin.formfields.mock.Address +import grails.plugin.formfields.mock.Cyborg +import grails.plugin.formfields.mock.Gender +import grails.plugin.formfields.mock.Person +import grails.plugin.formfields.mock.Product import grails.testing.gorm.DataTest import grails.testing.web.GrailsWebUnitTest import org.grails.datastore.mapping.model.MappingContext @@ -32,7 +37,6 @@ import org.grails.scaffolding.model.property.DomainPropertyFactoryImpl import org.grails.spring.beans.factory.InstanceFactoryBean import org.springframework.context.support.StaticMessageSource import spock.lang.Specification -import grails.plugin.formfields.mock.* abstract class AbstractFormFieldsTagLibSpec extends Specification implements GrailsWebUnitTest, DataTest { diff --git a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AllTagSpec.groovy b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AllTagSpec.groovy index 7de46973742..1c70b335b09 100644 --- a/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AllTagSpec.groovy +++ b/grails-fields/src/test/groovy/grails/plugin/formfields/taglib/AllTagSpec.groovy @@ -19,11 +19,13 @@ package grails.plugin.formfields.taglib +import grails.plugin.formfields.FormFieldsTagLib +import grails.plugin.formfields.FormFieldsTemplateService import grails.plugin.formfields.mock.Cyborg import grails.plugin.formfields.mock.Person -import grails.plugin.formfields.* import grails.testing.web.taglib.TagLibUnitTest -import spock.lang.* +import spock.lang.Issue +import spock.lang.Unroll @Unroll class AllTagSpec extends AbstractFormFieldsTagLibSpec implements TagLibUnitTest { diff --git a/grails-forge/config/checkstyle/suppressions.xml b/grails-forge/etc/config/checkstyle/suppressions.xml similarity index 96% rename from grails-forge/config/checkstyle/suppressions.xml rename to grails-forge/etc/config/checkstyle/suppressions.xml index c36038ae6ba..1fd82e5b329 100644 --- a/grails-forge/config/checkstyle/suppressions.xml +++ b/grails-forge/etc/config/checkstyle/suppressions.xml @@ -22,10 +22,8 @@ - - diff --git a/grails-forge/gradle.properties b/grails-forge/gradle.properties index 80c5036d4a3..6d39f14f153 100644 --- a/grails-forge/gradle.properties +++ b/grails-forge/gradle.properties @@ -43,8 +43,6 @@ micronautBuildVersion=1.1.5 micronautDocsVersion=2.0.0 micronautGradlePlugins=5.4.10 micronautVersion=3.10.4 -nexusPublishVersion=1.3.0 -nohttpGradleVersion=0.0.11 objenesisVersion=3.4 picocliVersion=4.7.5 postgresqlVersion=42.7.5 @@ -55,7 +53,6 @@ shadowVersion=8.3.6 slf4jVersion=2.0.17 snakeyamlVersion=2.4 spockVersion=2.1-groovy-3.0 -spotlessVersion=6.25.0 testRetryVersion=1.6.2 typesafeConfigVersion=1.4.3 diff --git a/grails-forge/gradle/style-enforcement-config.gradle b/grails-forge/gradle/style-enforcement-config.gradle index 374fec9ed83..c70e7bcdf6c 100644 --- a/grails-forge/gradle/style-enforcement-config.gradle +++ b/grails-forge/gradle/style-enforcement-config.gradle @@ -1,3 +1,5 @@ +import com.diffplug.gradle.spotless.SpotlessExtension + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -21,23 +23,32 @@ apply plugin: 'checkstyle' apply plugin: 'com.diffplug.spotless' apply plugin: 'io.spring.nohttp' // enforce https everywhere -spotless { - java { - licenseHeaderFile(rootProject.file("${rootDir}/config/spotless.license.java")) - target('src/main/java/**/*.java') +extensions.configure(SpotlessExtension) { + // Explicit `it` required in extension configuration + it.java { + licenseHeaderFile(rootProject.layout.projectDirectory.file('../etc/config/spotless/license.java')) + target( + 'src/main/java/**/*.java' + ) } - groovy { - licenseHeaderFile(rootProject.file("${rootDir}/config/spotless.license.java")) - target('src/main/groovy/**') + it.groovy { + licenseHeaderFile(rootProject.layout.projectDirectory.file('../etc/config/spotless/license.java')) + target( + 'src/main/groovy/**' + ) } - format 'javaMisc', { - target('src/main/**/package-info.java', 'src/main/**/module-info.java') - licenseHeaderFile(rootProject.file('config/spotless.license.java'), '\\/\\*\\*') + it.format('javaMisc') { + licenseHeaderFile(rootProject.layout.projectDirectory.file('../etc/config/spotless/license.java'), '\\/\\*\\*') + target( + 'src/main/**/module-info.java', + 'src/main/**/package-info.java' + ) } } checkstyle { - configFile = project.rootProject.file('config/checkstyle/checkstyle.xml') + configFile = project.rootProject.layout.projectDirectory.file('../etc/config/checkstyle/checkstyle.xml').asFile + configDirectory = project.rootProject.layout.projectDirectory.dir('etc/config/checkstyle').asFile // Per submodule maxErrors = 1 diff --git a/grails-forge/grails-forge-analytics-postgres/src/main/java/org/grails/forge/analytics/postgres/Application.java b/grails-forge/grails-forge-analytics-postgres/src/main/java/org/grails/forge/analytics/postgres/Application.java index a76606ff4c4..d444ce612e5 100644 --- a/grails-forge/grails-forge-analytics-postgres/src/main/java/org/grails/forge/analytics/postgres/Application.java +++ b/grails-forge/grails-forge-analytics-postgres/src/main/java/org/grails/forge/analytics/postgres/Application.java @@ -21,7 +21,11 @@ import io.micronaut.core.annotation.Creator; import io.micronaut.core.annotation.NonNull; import io.micronaut.core.annotation.Nullable; -import io.micronaut.data.annotation.*; +import io.micronaut.data.annotation.DateCreated; +import io.micronaut.data.annotation.GeneratedValue; +import io.micronaut.data.annotation.Id; +import io.micronaut.data.annotation.MappedEntity; +import io.micronaut.data.annotation.Relation; import org.grails.forge.application.ApplicationType; import org.grails.forge.options.GormImpl; import org.grails.forge.options.JdkVersion; diff --git a/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/ApplicationController.java b/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/ApplicationController.java index 4e20aec27d9..0b21b15be96 100644 --- a/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/ApplicationController.java +++ b/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/ApplicationController.java @@ -27,18 +27,22 @@ import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.http.annotation.Produces; -import org.grails.forge.application.ApplicationType; -import org.grails.forge.application.OperatingSystem; -import org.grails.forge.options.*; -import org.grails.forge.template.RockerWritable; -import org.grails.forge.template.api.grailsForgeApi; -import org.grails.forge.util.VersionInfo; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.annotations.info.License; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponse; +import org.grails.forge.application.ApplicationType; +import org.grails.forge.application.OperatingSystem; +import org.grails.forge.options.FeatureFilter; +import org.grails.forge.options.GormImpl; +import org.grails.forge.options.JdkVersion; +import org.grails.forge.options.Options; +import org.grails.forge.options.ServletImpl; +import org.grails.forge.template.RockerWritable; +import org.grails.forge.template.api.grailsForgeApi; +import org.grails.forge.util.VersionInfo; import java.io.OutputStream; import java.io.Writer; diff --git a/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/SelectOptionsDTO.java b/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/SelectOptionsDTO.java index 5373aac511c..ff502f9ce34 100644 --- a/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/SelectOptionsDTO.java +++ b/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/SelectOptionsDTO.java @@ -22,10 +22,18 @@ import io.micronaut.core.annotation.Creator; import io.micronaut.core.annotation.Introspected; import io.swagger.v3.oas.annotations.media.Schema; -import org.grails.forge.api.options.*; +import org.grails.forge.api.options.ApplicationTypeSelectOptions; +import org.grails.forge.api.options.GormImplSelectOptions; +import org.grails.forge.api.options.JdkVersionSelectOptions; +import org.grails.forge.api.options.LanguageSelectOptions; +import org.grails.forge.api.options.ServletImplSelectOptions; +import org.grails.forge.api.options.TestFrameworkSelectOptions; import org.grails.forge.application.ApplicationType; +import org.grails.forge.options.GormImpl; +import org.grails.forge.options.JdkVersion; +import org.grails.forge.options.Language; +import org.grails.forge.options.ServletImpl; import org.grails.forge.options.TestFramework; -import org.grails.forge.options.*; import java.util.Arrays; import java.util.List; diff --git a/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/create/AbstractCreateController.java b/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/create/AbstractCreateController.java index d91c31b33a5..b1bf8dda3aa 100644 --- a/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/create/AbstractCreateController.java +++ b/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/create/AbstractCreateController.java @@ -33,7 +33,11 @@ import org.grails.forge.application.generator.GeneratorContext; import org.grails.forge.application.generator.ProjectGenerator; import org.grails.forge.io.ConsoleOutput; -import org.grails.forge.options.*; +import org.grails.forge.options.BuildTool; +import org.grails.forge.options.GormImpl; +import org.grails.forge.options.JdkVersion; +import org.grails.forge.options.Options; +import org.grails.forge.options.ServletImpl; import org.grails.forge.util.NameUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/diff/DiffController.java b/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/diff/DiffController.java index 62f9c9c9e4f..cfa671f66d8 100644 --- a/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/diff/DiffController.java +++ b/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/diff/DiffController.java @@ -25,6 +25,9 @@ import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.http.exceptions.HttpStatusException; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.grails.forge.api.RequestInfo; import org.grails.forge.api.UserAgentParser; import org.grails.forge.application.ApplicationType; @@ -33,11 +36,13 @@ import org.grails.forge.application.generator.ProjectGenerator; import org.grails.forge.diff.FeatureDiffer; import org.grails.forge.io.ConsoleOutput; -import org.grails.forge.options.*; +import org.grails.forge.options.BuildTool; +import org.grails.forge.options.GormImpl; +import org.grails.forge.options.JdkVersion; +import org.grails.forge.options.Options; +import org.grails.forge.options.ServletImpl; +import org.grails.forge.options.TestFramework; import org.grails.forge.util.NameUtils; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; diff --git a/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/diff/DiffOperations.java b/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/diff/DiffOperations.java index 6249b23f457..cb5bc690cf7 100644 --- a/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/diff/DiffOperations.java +++ b/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/diff/DiffOperations.java @@ -20,10 +20,14 @@ import io.micronaut.core.annotation.NonNull; import io.micronaut.core.annotation.Nullable; +import io.swagger.v3.oas.annotations.Parameter; import org.grails.forge.api.RequestInfo; import org.grails.forge.application.ApplicationType; -import org.grails.forge.options.*; -import io.swagger.v3.oas.annotations.Parameter; +import org.grails.forge.options.BuildTool; +import org.grails.forge.options.GormImpl; +import org.grails.forge.options.JdkVersion; +import org.grails.forge.options.ServletImpl; +import org.grails.forge.options.TestFramework; import org.reactivestreams.Publisher; import javax.validation.constraints.NotBlank; diff --git a/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/preview/PreviewController.java b/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/preview/PreviewController.java index ae20e133ec4..a50db0ae692 100644 --- a/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/preview/PreviewController.java +++ b/grails-forge/grails-forge-api/src/main/java/org/grails/forge/api/preview/PreviewController.java @@ -25,6 +25,7 @@ import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.http.exceptions.HttpStatusException; +import io.swagger.v3.oas.annotations.Parameter; import org.grails.forge.api.Relationship; import org.grails.forge.api.RequestInfo; import org.grails.forge.api.TestFramework; @@ -34,9 +35,12 @@ import org.grails.forge.application.generator.ProjectGenerator; import org.grails.forge.io.ConsoleOutput; import org.grails.forge.io.MapOutputHandler; -import org.grails.forge.options.*; +import org.grails.forge.options.BuildTool; +import org.grails.forge.options.GormImpl; +import org.grails.forge.options.JdkVersion; +import org.grails.forge.options.Options; +import org.grails.forge.options.ServletImpl; import org.grails.forge.util.NameUtils; -import io.swagger.v3.oas.annotations.Parameter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/grails-forge/grails-forge-cli/src/main/java/org/grails/forge/cli/Application.java b/grails-forge/grails-forge-cli/src/main/java/org/grails/forge/cli/Application.java index f0c23b9a02c..73488707a75 100644 --- a/grails-forge/grails-forge-cli/src/main/java/org/grails/forge/cli/Application.java +++ b/grails-forge/grails-forge-cli/src/main/java/org/grails/forge/cli/Application.java @@ -23,15 +23,25 @@ import io.micronaut.context.annotation.Prototype; import io.micronaut.core.annotation.TypeHint; import io.micronaut.inject.BeanDefinition; -import org.grails.forge.cli.command.*; +import org.grails.forge.cli.command.BaseCommand; +import org.grails.forge.cli.command.CodeGenCommand; +import org.grails.forge.cli.command.CreateAppCommand; +import org.grails.forge.cli.command.CreatePluginCommand; +import org.grails.forge.cli.command.CreateRestApiCommand; +import org.grails.forge.cli.command.CreateWebPluginCommand; +import org.grails.forge.cli.command.CreateWebappCommand; +import org.grails.forge.cli.command.GormImplCandidates; +import org.grails.forge.cli.command.GormImplConverter; +import org.grails.forge.cli.command.ServletImplCandidates; +import org.grails.forge.cli.command.ServletImplConverter; +import org.grails.forge.cli.command.TestFrameworkCandidates; +import org.grails.forge.cli.command.TestFrameworkConverter; import org.grails.forge.io.ConsoleOutput; import picocli.CommandLine; import java.util.concurrent.Callable; import java.util.function.BiFunction; - - @CommandLine.Command(name = "grails-forge-cli", description = { "Grails Forge CLI command line interface for generating projects and services.", "Application generation commands are:", diff --git a/grails-forge/grails-forge-cli/src/main/java/org/grails/forge/cli/CodeGenConfig.java b/grails-forge/grails-forge-cli/src/main/java/org/grails/forge/cli/CodeGenConfig.java index 8ec644449c2..5458ed2e80e 100644 --- a/grails-forge/grails-forge-cli/src/main/java/org/grails/forge/cli/CodeGenConfig.java +++ b/grails-forge/grails-forge-cli/src/main/java/org/grails/forge/cli/CodeGenConfig.java @@ -38,7 +38,11 @@ import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; -import java.util.*; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; @Introspected diff --git a/grails-forge/grails-forge-cli/src/main/java/org/grails/forge/cli/command/CreateCommand.java b/grails-forge/grails-forge-cli/src/main/java/org/grails/forge/cli/command/CreateCommand.java index 5baf21df43c..28934db4252 100644 --- a/grails-forge/grails-forge-cli/src/main/java/org/grails/forge/cli/command/CreateCommand.java +++ b/grails-forge/grails-forge-cli/src/main/java/org/grails/forge/cli/command/CreateCommand.java @@ -28,7 +28,11 @@ import org.grails.forge.feature.AvailableFeatures; import org.grails.forge.io.FileSystemOutputHandler; import org.grails.forge.io.OutputHandler; -import org.grails.forge.options.*; +import org.grails.forge.options.GormImpl; +import org.grails.forge.options.JdkVersion; +import org.grails.forge.options.Options; +import org.grails.forge.options.ServletImpl; +import org.grails.forge.options.TestFramework; import org.grails.forge.util.NameUtils; import picocli.CommandLine; diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/analytics/Generated.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/analytics/Generated.java index 80b8c28d955..0bb89849f31 100644 --- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/analytics/Generated.java +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/analytics/Generated.java @@ -22,7 +22,10 @@ import io.micronaut.core.annotation.Introspected; import io.micronaut.core.annotation.NonNull; import org.grails.forge.application.ApplicationType; -import org.grails.forge.options.*; +import org.grails.forge.options.GormImpl; +import org.grails.forge.options.JdkVersion; +import org.grails.forge.options.ServletImpl; +import org.grails.forge.options.TestFramework; import org.grails.forge.util.VersionInfo; import java.util.ArrayList; diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/application/ContextFactory.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/application/ContextFactory.java index 4b03e0ea268..7ddec5975c9 100644 --- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/application/ContextFactory.java +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/application/ContextFactory.java @@ -28,7 +28,12 @@ import org.grails.forge.feature.FeatureContext; import org.grails.forge.feature.validation.FeatureValidator; import org.grails.forge.io.ConsoleOutput; -import org.grails.forge.options.*; +import org.grails.forge.options.BuildTool; +import org.grails.forge.options.GormImpl; +import org.grails.forge.options.Language; +import org.grails.forge.options.Options; +import org.grails.forge.options.ServletImpl; +import org.grails.forge.options.TestFramework; import java.util.Collections; import java.util.IdentityHashMap; diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/application/generator/GeneratorContext.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/application/generator/GeneratorContext.java index 7771a619443..389edef4851 100644 --- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/application/generator/GeneratorContext.java +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/application/generator/GeneratorContext.java @@ -26,7 +26,12 @@ import org.grails.forge.application.Project; import org.grails.forge.build.BuildPlugin; import org.grails.forge.build.BuildProperties; -import org.grails.forge.build.dependencies.*; +import org.grails.forge.build.dependencies.Coordinate; +import org.grails.forge.build.dependencies.CoordinateResolver; +import org.grails.forge.build.dependencies.Dependency; +import org.grails.forge.build.dependencies.DependencyContext; +import org.grails.forge.build.dependencies.LookupFailedException; +import org.grails.forge.build.dependencies.Scope; import org.grails.forge.build.gradle.GradleRepository; import org.grails.forge.feature.Feature; import org.grails.forge.feature.Features; @@ -35,14 +40,28 @@ import org.grails.forge.feature.config.BootstrapConfiguration; import org.grails.forge.feature.config.Configuration; import org.grails.forge.feature.other.template.markdownLink; -import org.grails.forge.options.*; +import org.grails.forge.options.GormImpl; +import org.grails.forge.options.JdkVersion; +import org.grails.forge.options.Language; +import org.grails.forge.options.Options; +import org.grails.forge.options.ServletImpl; +import org.grails.forge.options.TestFramework; +import org.grails.forge.options.TestRockerModelProvider; import org.grails.forge.template.RockerTemplate; import org.grails.forge.template.RockerWritable; import org.grails.forge.template.Template; import org.grails.forge.template.Writable; import org.grails.forge.util.VersionInfo; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; /** * A context object used when generating projects. diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/build/gradle/GradlePlugin.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/build/gradle/GradlePlugin.java index ad35259bdc1..ec6fb00ed82 100644 --- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/build/gradle/GradlePlugin.java +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/build/gradle/GradlePlugin.java @@ -21,7 +21,10 @@ import io.micronaut.core.annotation.NonNull; import io.micronaut.core.annotation.Nullable; import org.grails.forge.build.BuildPlugin; -import org.grails.forge.build.dependencies.*; +import org.grails.forge.build.dependencies.Coordinate; +import org.grails.forge.build.dependencies.CoordinateResolver; +import org.grails.forge.build.dependencies.LookupFailedException; +import org.grails.forge.build.dependencies.Scope; import org.grails.forge.options.BuildTool; import org.grails.forge.template.Writable; diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/FeatureContext.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/FeatureContext.java index d66a927b79b..d481bd6d799 100644 --- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/FeatureContext.java +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/FeatureContext.java @@ -27,7 +27,12 @@ import org.grails.forge.options.Options; import org.grails.forge.options.TestFramework; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.ListIterator; +import java.util.Set; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toSet; diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/test/GebWithTestcontainers.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/test/GebWithTestcontainers.java index f214f4902bf..470719ee213 100644 --- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/test/GebWithTestcontainers.java +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/test/GebWithTestcontainers.java @@ -29,7 +29,11 @@ import org.grails.forge.feature.FeatureContext; import org.grails.forge.feature.FeaturePhase; import org.grails.forge.feature.test.template.groovyJunit; -import org.grails.forge.options.*; +import org.grails.forge.options.DefaultTestRockerModelProvider; +import org.grails.forge.options.Language; +import org.grails.forge.options.Options; +import org.grails.forge.options.TestFramework; +import org.grails.forge.options.TestRockerModelProvider; import org.grails.forge.template.RockerTemplate; import java.util.Set; diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/test/GebWithWebDriverBinaries.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/test/GebWithWebDriverBinaries.java index 9612f57e7b2..89520b0323a 100644 --- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/test/GebWithWebDriverBinaries.java +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/test/GebWithWebDriverBinaries.java @@ -25,13 +25,17 @@ import org.grails.forge.application.generator.GeneratorContext; import org.grails.forge.build.dependencies.Dependency; import org.grails.forge.build.gradle.GradlePlugin; -import org.grails.forge.feature.*; +import org.grails.forge.feature.Feature; +import org.grails.forge.feature.FeatureContext; +import org.grails.forge.feature.FeaturePhase; +import org.grails.forge.feature.test.template.gebConfig; import org.grails.forge.feature.test.template.groovyJunit; import org.grails.forge.feature.test.template.webdriverBinariesPlugin; -import org.grails.forge.options.*; +import org.grails.forge.options.DefaultTestRockerModelProvider; +import org.grails.forge.options.Language; +import org.grails.forge.options.TestRockerModelProvider; import org.grails.forge.template.RockerTemplate; import org.grails.forge.template.RockerWritable; -import org.grails.forge.feature.test.template.gebConfig; import java.util.stream.Stream; diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/view/json/ViewJson.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/view/json/ViewJson.java index 6bc89715100..be24bd464d7 100644 --- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/view/json/ViewJson.java +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/view/json/ViewJson.java @@ -27,7 +27,11 @@ import org.grails.forge.feature.DefaultFeature; import org.grails.forge.feature.Feature; import org.grails.forge.feature.view.GrailsViews; -import org.grails.forge.feature.view.json.templates.*; +import org.grails.forge.feature.view.json.templates._errors; +import org.grails.forge.feature.view.json.templates._object; +import org.grails.forge.feature.view.json.templates.error; +import org.grails.forge.feature.view.json.templates.index; +import org.grails.forge.feature.view.json.templates.notFound; import org.grails.forge.feature.web.GrailsWeb; import org.grails.forge.options.Options; import org.grails.forge.template.RockerTemplate; diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/view/markup/ViewMarkup.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/view/markup/ViewMarkup.java index 318f5942d70..3761cef92aa 100644 --- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/view/markup/ViewMarkup.java +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/view/markup/ViewMarkup.java @@ -25,7 +25,11 @@ import org.grails.forge.build.gradle.GradlePlugin; import org.grails.forge.feature.Feature; import org.grails.forge.feature.view.GrailsViews; -import org.grails.forge.feature.view.markup.templates.*; +import org.grails.forge.feature.view.markup.templates._errors; +import org.grails.forge.feature.view.markup.templates._object; +import org.grails.forge.feature.view.markup.templates.error; +import org.grails.forge.feature.view.markup.templates.index; +import org.grails.forge.feature.view.markup.templates.notFound; import org.grails.forge.feature.web.GrailsWeb; import org.grails.forge.template.RockerTemplate; diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/options/Options.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/options/Options.java index f510ffd0a59..d14786e0114 100644 --- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/options/Options.java +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/options/Options.java @@ -24,7 +24,11 @@ import org.grails.forge.application.OperatingSystem; import org.grails.forge.util.VersionInfo; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.Set; public class Options implements ConvertibleValues { diff --git a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/util/IOFeatureUtil.java b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/util/IOFeatureUtil.java index 0dc11099a0c..a7a5fbbb441 100644 --- a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/util/IOFeatureUtil.java +++ b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/util/IOFeatureUtil.java @@ -23,7 +23,12 @@ import java.io.IOException; import java.net.URI; -import java.nio.file.*; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.ProviderNotFoundException; import java.util.function.BiFunction; import java.util.stream.Stream; diff --git a/grails-forge/src/main/docs/guide/installation/installSdkman.adoc b/grails-forge/src/main/docs/guide/installation/installSdkman.adoc index ef120295b30..ff48b4e8855 100644 --- a/grails-forge/src/main/docs/guide/installation/installSdkman.adoc +++ b/grails-forge/src/main/docs/guide/installation/installSdkman.adoc @@ -16,7 +16,7 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. //// -The best way to install Grails on Unix systems is with http://sdkman.io/[SDKMAN] which greatly simplifies installing +The best way to install Grails on Unix systems is with https://sdkman.io/[SDKMAN] which greatly simplifies installing and managing multiple Grails versions. Before updating make sure you have latest version of SDKMAN installed. If not, run @@ -40,7 +40,7 @@ You can also specify the version to the `sdk install` command. $ sdk install grails {project-version} ---- -You can find more information about SDKMAN usage on the http://sdkman.io/usage[SDKMAN Docs] +You can find more information about SDKMAN usage on the https://sdkman.io/usage[SDKMAN Docs] You should now be able to run the Grails Forge CLI. diff --git a/grails-geb/README.md b/grails-geb/README.md index a0abbb30b70..6cb1498a8b3 100644 --- a/grails-geb/README.md +++ b/grails-geb/README.md @@ -179,7 +179,7 @@ You also need to add a `GebConfig.groovy` file in the `src/integration-test/reso /* This is the Geb configuration file. - See: http://www.gebish.org/manual/current/#configuration + See: https://www.gebish.org/manual/current/#configuration */ /* ... */ diff --git a/grails-geb/build.gradle b/grails-geb/build.gradle index 51758839afa..32d9dccaeb1 100644 --- a/grails-geb/build.gradle +++ b/grails-geb/build.gradle @@ -69,4 +69,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/grails-extension-gradle-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-geb/src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy b/grails-geb/src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy index 67df92d889f..b27e0ddf4cf 100644 --- a/grails-geb/src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy +++ b/grails-geb/src/main/groovy/grails/plugin/geb/GebGrailsPlugin.groovy @@ -26,6 +26,7 @@ import groovy.transform.CompileStatic @PluginSource @CompileStatic class GebGrailsPlugin extends Plugin { + def grailsVersion = "7.0.0 > *" def pluginExcludes = [] def title = "Grails Geb Plugin" diff --git a/grails-geb/src/main/scripts/CreateFunctionalTest.groovy b/grails-geb/src/main/scripts/CreateFunctionalTest.groovy index f7d1edea47e..cc8b58c0737 100644 --- a/grails-geb/src/main/scripts/CreateFunctionalTest.groovy +++ b/grails-geb/src/main/scripts/CreateFunctionalTest.groovy @@ -19,12 +19,12 @@ description("Creates a Geb Functional Test") { usage "grails create-functional-test [TEST NAME]" - argument name:'Test Name', description:"The name of the test" - completer AllClassCompleter + argument name: 'Test Name', description: "The name of the test" + completer AllClassCompleter } -model = model( args[0] ) -render template:"FunctionalSpec.groovy", - destination: file( "src/integration-test/groovy/$model.packagePath/${model.simpleName}Spec.groovy"), - model: model +model = model(args[0]) +render template: "FunctionalSpec.groovy", + destination: file("src/integration-test/groovy/$model.packagePath/${model.simpleName}Spec.groovy"), + model: model diff --git a/grails-geb/src/main/templates/FunctionalSpec.groovy b/grails-geb/src/main/templates/FunctionalSpec.groovy index 86686c1adcd..b571d8d7c8e 100644 --- a/grails-geb/src/main/templates/FunctionalSpec.groovy +++ b/grails-geb/src/main/templates/FunctionalSpec.groovy @@ -6,7 +6,7 @@ import grails.testing.mixin.integration.Integration import geb.spock.* /** - * See http://www.gebish.org/manual/current/ for more instructions + * See https://www.gebish.org/manual/current/ for more instructions */ @Integration @Rollback diff --git a/grails-gradle/docs-core/src/main/resources/grails/doc/doc.properties b/grails-gradle/docs-core/src/main/resources/grails/doc/doc.properties index 183d37b6013..e8dec26e817 100644 --- a/grails-gradle/docs-core/src/main/resources/grails/doc/doc.properties +++ b/grails-gradle/docs-core/src/main/resources/grails/doc/doc.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/docs-core/src/main/resources/radeox_messages_en.properties b/grails-gradle/docs-core/src/main/resources/radeox_messages_en.properties index e7be7c1c5f9..75074ad32a1 100644 --- a/grails-gradle/docs-core/src/main/resources/radeox_messages_en.properties +++ b/grails-gradle/docs-core/src/main/resources/radeox_messages_en.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/docs-core/src/main/template/log4j.properties b/grails-gradle/docs-core/src/main/template/log4j.properties index 2ad54fae729..3375f3224b9 100644 --- a/grails-gradle/docs-core/src/main/template/log4j.properties +++ b/grails-gradle/docs-core/src/main/template/log4j.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/docs-core/src/test/resources/docs/guide/single.html b/grails-gradle/docs-core/src/test/resources/docs/guide/single.html index 8959896c663..82244ed51d9 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/guide/single.html +++ b/grails-gradle/docs-core/src/test/resources/docs/guide/single.html @@ -747,7 +747,7 @@

    1.1.1 GORM 6 Suite

    -

    There are so many new features and novelties in GORM that we had to write its own independent What’s New Guide!

    +

    There are so many new features and novelties in GORM that we had to write its own independent What’s New Guide!

    @@ -761,7 +761,7 @@

    1.1.2 RxJava Support

    -

    In addition to RxGORM, support for RxJava has been added to the Grails framework via an RxJava plugin.

    +

    In addition to RxGORM, support for RxJava has been added to the Grails framework via an RxJava plugin.

    Reactive controllers with RxJava

    @@ -893,7 +893,7 @@

    1.1.4 JSON Views 1.1

    -

    Version 1.1 of the JSON Views plugin is included with Grails 3.2’s "rest-api" profile and includes a number of new features. Below are some of the highlights:

    +

    Version 1.1 of the JSON Views plugin is included with Grails 3.2’s "rest-api" profile and includes a number of new features. Below are some of the highlights:

    Template Inheritance

    @@ -1251,10 +1251,10 @@

    REST Profile

    JSON and Markup Views

    -

    The REST profile includes the ability to define JSON and Markup views and the build.gradle features the ability to compile these views for production use.

    +

    The REST profile includes the ability to define JSON and Markup views and the build.gradle features the ability to compile these views for production use.

    -

    The REST profile also creates JSON views to render the index action and common commands such as generate-views have been overridden to generate JSON views.

    +

    The REST profile also creates JSON views to render the index action and common commands such as generate-views have been overridden to generate JSON views.

    @@ -1826,7 +1826,7 @@

    2.7 Convention over Configuration

    utils - Grails specific utilities.

  • -

    views - Groovy Server Pages or JSON Views - The V in MVC.

    +

    views - Groovy Server Pages or JSON Views - The V in MVC.

  • @@ -4330,7 +4330,7 @@

    More on dbCreate

    -

    Setting the dbCreate setting to "none" is recommended once your schema is relatively stable and definitely when your application and database are deployed in production. Database changes are then managed through proper migrations, either with SQL scripts or a migration tool like Flyway or Liquibase. The Database Migration plugin uses Liquibase.

    +

    Setting the dbCreate setting to "none" is recommended once your schema is relatively stable and definitely when your application and database are deployed in production. Database changes are then managed through proper migrations, either with SQL scripts or a migration tool like Flyway or Liquibase. The Database Migration plugin uses Liquibase.

    @@ -4741,7 +4741,7 @@

    Hibernate Mapped Domain Classes

    <?xml version='1.0' encoding='UTF-8'?>
     <!DOCTYPE hibernate-configuration PUBLIC
               '-//Hibernate/Hibernate Configuration DTD 3.0//EN'
    -          'http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd'>
    +          'https://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd'>
     <hibernate-configuration>
        <session-factory>
           <mapping class='org.example.Book'/>
    @@ -4757,7 +4757,7 @@ 

    Hibernate Mapped Domain Classes

    <?xml version='1.0' encoding='UTF-8'?>
     <!DOCTYPE hibernate-configuration PUBLIC
               '-//Hibernate/Hibernate Configuration DTD 3.0//EN'
    -          'http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd'>
    +          'https://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd'>
     <hibernate-configuration>
        <session-factory>
           <mapping class='org.example.Library'/>
    @@ -5351,7 +5351,7 @@ 

    5.5 Building with Gradle

    The build is defined by the build.gradle file which specifies the version of your project, the dependencies of the project and the repositories where to find those dependencies (amongst other things).

    -

    When you invoke the grails command the version of Gradle that ships with Grails 3.1 (currently 2.9) is invoked by the grails process via the Gradle Tooling API:

    +

    When you invoke the grails command the version of Gradle that ships with Grails 3.1 (currently 2.9) is invoked by the grails process via the Gradle Tooling API:

    @@ -5379,7 +5379,7 @@

    5.5.1 Defining Dependencies with Gradle

    -

    Dependencies for your project are defined in the dependencies block. In general you can follow the Gradle documentation on dependency management to understand how to configure additional dependencies.

    +

    Dependencies for your project are defined in the dependencies block. In general you can follow the Gradle documentation on dependency management to understand how to configure additional dependencies.

    The default dependencies for the "web" profile can be seen below:

    @@ -5543,7 +5543,7 @@

    5.5.3 Grails plugins for Gradle

    • -

      war - The WAR plugin changes the packaging so that Gradle creates as WAR file from your application. You can comment out this plugin if you wish to create only a runnable JAR file for standalone deployment.

      +

      war - The WAR plugin changes the packaging so that Gradle creates as WAR file from your application. You can comment out this plugin if you wish to create only a runnable JAR file for standalone deployment.

    • asset-pipeline - The asset pipeline] plugin enables the compilation of static assets (JavaScript, CSS etc.)

      @@ -6582,7 +6582,7 @@

      7.2 Further Reading on GORM

      -

      For more information on using GORM see the dedicated documentation for the GORM project.

      +

      For more information on using GORM see the dedicated documentation for the GORM project.

      @@ -15056,7 +15056,7 @@

      10.1.9.5 JSON Views by Convention

      If a validation error occurs in the above example the grails-app/views/book/_errors.gson template will be rendered.

    -

    For more information on JSON views (and Markup views), see the JSON Views user guide.

    +

    For more information on JSON views (and Markup views), see the JSON Views user guide.

    @@ -16529,7 +16529,7 @@

    11.2.2 RxGORM

    -

    RxGORM is new implementation of GORM that has the following goals:

    +

    RxGORM is new implementation of GORM that has the following goals:

      @@ -16573,7 +16573,7 @@

      11.2.2 RxGORM

    -

    For more information on how to use RxGORM, see the RxGORM user guide.

    +

    For more information on how to use RxGORM, see the RxGORM user guide.

    @@ -16766,7 +16766,7 @@

    11.3.4 Events from GORM

    -These events are triggered asynchronously, and so cannot cancel or manipulate the persistence operations. If you want to do that see the section on Events & Auto Timestamping in the GORM docs +These events are triggered asynchronously, and so cannot cancel or manipulate the persistence operations. If you want to do that see the section on Events & Auto Timestamping in the GORM docs @@ -21298,7 +21298,7 @@

    15.3 Functional Testing

    Functional tests involve making HTTP requests against the running application and verifying the resultant behaviour. This is useful for end-to-end testing scenarios, such as making REST calls against a JSON API.

    -

    Grails by default ships with support for writing functional tests using the Geb framework. To create a functional test you can use the create-functional-test command which will create a new functional test:

    +

    Grails by default ships with support for writing functional tests using the Geb framework. To create a functional test you can use the create-functional-test command which will create a new functional test:

    @@ -22765,7 +22765,7 @@

    Distribut -If you have created a Grails plugin and want it to be hosted in the central repository, you’ll find instructions for getting an account on the plugin portal website. +If you have created a Grails plugin and want it to be hosted in the central repository, you’ll find instructions for getting an account on the plugin portal website. @@ -24904,7 +24904,7 @@

    20.1 Using Hibernate XML Mapping Files<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" - "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> + "https://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Example mapping file inclusion --> @@ -25004,7 +25004,7 @@

    20.2 Mapping with Hibernate Annotations
    <!DOCTYPE hibernate-configuration SYSTEM
    -  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    +  "https://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
     <hibernate-configuration>
         <session-factory>
             <mapping package="com.books" />
    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/inList.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/inList.html
    index 2cafea6458c..fe516e41226 100644
    --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/inList.html
    +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/inList.html
    @@ -153,7 +153,7 @@ 

    Description

    Constrains a value so that it must be contained within the given list.

    -

    This constraint influences schema generation.

    +

    This constraint influences schema generation.

    Error Code: className.propertyName.not.inList

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/max.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/max.html index cebca2d286c..f8ce6020c81 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/max.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/max.html @@ -170,7 +170,7 @@

    Description

    -

    This constraint influences schema generation.

    +

    This constraint influences schema generation.

    Error Code: className.propertyName.max.exceeded

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/maxSize.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/maxSize.html index a944b25da02..9a6ae293f67 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/maxSize.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/maxSize.html @@ -150,7 +150,7 @@

    Examples

    Description

    -

    This constraint influences schema generation.

    +

    This constraint influences schema generation.

    Error Code: className.propertyName.maxSize.exceeded

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/min.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/min.html index b2ba0d456e8..5a3d0af536b 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/min.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/min.html @@ -170,7 +170,7 @@

    Description

    -

    This constraint influences schema generation.

    +

    This constraint influences schema generation.

    Error Code: className.propertyName.min.notmet

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/minSize.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/minSize.html index fbb7c426733..e77c3770a3f 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/minSize.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/minSize.html @@ -153,7 +153,7 @@

    Description

    Sets the minimum size of a collection or number property.

    -

    This constraint influences schema generation.

    +

    This constraint influences schema generation.

    Error Code: className.propertyName.minSize.notmet

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/nullable.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/nullable.html index 027df94c1e4..19b274fd268 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/nullable.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/nullable.html @@ -153,7 +153,7 @@

    Description

    Set to true if the property allows null values.

    -

    This constraint influences schema generation.

    +

    This constraint influences schema generation.

    Error Code: className.propertyName.nullable

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/range.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/range.html index 8203d320374..44f17105198 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/range.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/range.html @@ -153,7 +153,7 @@

    Description

    Set to a Groovy range which can contain numbers in the form of an IntRange, dates or any object that implements Comparable and provides next and previous methods for navigation.

    -

    This constraint influences schema generation.

    +

    This constraint influences schema generation.

    Error Code: className.propertyName.range.toosmall or className.propertyName.range.toobig

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/scale.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/scale.html index 8bab9eecb85..ecdf42a4bbe 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/scale.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/scale.html @@ -153,7 +153,7 @@

    Description

    Set to the desired scale for floating point numbers (i.e., the number of digits to the right of the decimal point). This constraint is applicable for properties of the following types: java.lang.Float, java.lang.Double, and java.math.BigDecimal (and its subclasses). When validation is invoked, this constraint determines if the number includes more nonzero decimal places than the scale permits. If so, it rounds the number to the maximum number of decimal places allowed by the scale. This constraint does not generate validation error messages.

    -

    This constraint influences schema generation.

    +

    This constraint influences schema generation.

    Error Code: N/A

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/size.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/size.html index 4545ead49d6..4097c309c4e 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/size.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/size.html @@ -165,7 +165,7 @@

    Description

    -

    This constraint influences schema generation.

    +

    This constraint influences schema generation.

    Error Code: className.propertyName.size.toosmall or className.propertyName.size.toobig

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/unique.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/unique.html index 136d2d89c79..0d87b304899 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/unique.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Constraints/unique.html @@ -190,7 +190,7 @@

    Description

    In this example username must be unique in group and department. There might be same logins in different groups or different departments.

    -

    This constraint influences schema generation.

    +

    This constraint influences schema generation.

    Error Code: className.propertyName.unique

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/Usage.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/Usage.html index 16f21a58fb4..85138051180 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/Usage.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/Usage.html @@ -160,7 +160,7 @@

    Database Mapping Usage

    -

    Refer to the user guide section on ORM Mapping for more information.

    +

    Refer to the user guide section on ORM Mapping for more information.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/cache.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/cache.html index 9a3720d3aeb..c038c7696e3 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/cache.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/cache.html @@ -216,7 +216,7 @@

    Description

    -

    For more information see the section on Caching in the user guide.

    +

    For more information see the section on Caching in the user guide.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/fetch.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/fetch.html index d63a4cb845b..639424781e9 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/fetch.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/fetch.html @@ -194,7 +194,7 @@

    Description

    -

    Note that excessive use of joins can be a performance bottleneck. See the section on Eager vs Lazing Fetching in the user guide.

    +

    Note that excessive use of joins can be a performance bottleneck. See the section on Eager vs Lazing Fetching in the user guide.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/id.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/id.html index 2c09b9207d9..e160e22c1e5 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/id.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/id.html @@ -237,7 +237,7 @@

    Description

    -

    See the section on Custom Database Identity in the user guide for more information.

    +

    See the section on Custom Database Identity in the user guide for more information.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/lazy.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/lazy.html index fba84210c34..d9e018acfb8 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/lazy.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/lazy.html @@ -173,7 +173,7 @@

    Description

    -

    See the section on Eager vs Lazing Fetching in the user guide.

    +

    See the section on Eager vs Lazing Fetching in the user guide.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/version.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/version.html index dd0c7c36401..04112e8610b 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/version.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Database Mapping/version.html @@ -158,7 +158,7 @@

    Description

    Usage: version(string/boolean)

    -

    By default GORM is configured with optimistic locking enabled. You can disable this by calling the version method with an argument of false:

    +

    By default GORM is configured with optimistic locking enabled. You can disable this by calling the version method with an argument of false:

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/Usage.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/Usage.html index 8473b75dcd8..8663a84162b 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/Usage.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/Usage.html @@ -158,7 +158,7 @@

    Domain Class Usage

    The class name, by default, is mapped to the table name in lower case and separated by underscores instead of camel case so a domain class named BookStore by default would map to a table named book_store. Each property maps to individual columns.

    -

    One limitation of the default table naming scheme is that it is problematic to have 2 domain classes with the same name, even if they are defined to be in separate packages. For example, com.bookstore.BookStore and com.publishing.utility.BookStore would each map to a table named book_store. If the 2 classes are defined in the application this problem can be managed by giving the classes different names or by providing a specific table name for one or both of the classes that deviates from the default (see the ORM DSL section of the user guide for more details). If one or both of the domain classes is provided by a plugin the application author may not have access to those options. To help manage a situation like that, GORM may be configured to prefix table names with plugin names by default. For example, if the com.publishing.utility.BookStore domain class is provided by a plugin named PublishingUtilities, the default table name could be publishing_utilities_book_store. To enable that behavior the grails.gorm.table.prefix.enabled config property must be set to true. Example:

    +

    One limitation of the default table naming scheme is that it is problematic to have 2 domain classes with the same name, even if they are defined to be in separate packages. For example, com.bookstore.BookStore and com.publishing.utility.BookStore would each map to a table named book_store. If the 2 classes are defined in the application this problem can be managed by giving the classes different names or by providing a specific table name for one or both of the classes that deviates from the default (see the ORM DSL section of the user guide for more details). If one or both of the domain classes is provided by a plugin the application author may not have access to those options. To help manage a situation like that, GORM may be configured to prefix table names with plugin names by default. For example, if the com.publishing.utility.BookStore domain class is provided by a plugin named PublishingUtilities, the default table name could be publishing_utilities_book_store. To enable that behavior the grails.gorm.table.prefix.enabled config property must be set to true. Example:

    grails-app/conf/application.groovy
    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/belongsTo.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/belongsTo.html index 9aaf31c1a28..b73f360c344 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/belongsTo.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/belongsTo.html @@ -215,7 +215,7 @@

    Description

    In these examples, both techniques create an Author property named author. Also, the Map property can specify multiple properties and types if the class belongs to more than one owner.

    -

    The belongsTo property is simple and means you don’t have to worry about the Hibernate cascading strategies, but if you need more control over cascading you can use the ORM DSL. This allows fine grained control of cascading updates and deletes.

    +

    The belongsTo property is simple and means you don’t have to worry about the Hibernate cascading strategies, but if you need more control over cascading you can use the ORM DSL. This allows fine grained control of cascading updates and deletes.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/countBy.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/countBy.html index 2609aea87d8..f7dbe52b34e 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/countBy.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/countBy.html @@ -172,7 +172,7 @@

    Examples

    Description

    -

    GORM supports the notion of Dynamic Finders. The countBy* method counts the number of records for the given expression

    +

    GORM supports the notion of Dynamic Finders. The countBy* method counts the number of records for the given expression

    The following operator names can be used within the respective dynamic methods:

    @@ -224,7 +224,7 @@

    Description

    -

    These names can be considered keywords, and you will have problems when querying domain classes that have one of these names as a property name. For more information on dynamic finders refer to the user guide.

    +

    These names can be considered keywords, and you will have problems when querying domain classes that have one of these names as a property name. For more information on dynamic finders refer to the user guide.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/createCriteria.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/createCriteria.html index 4a3420ab7c8..671f51f2cab 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/createCriteria.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/createCriteria.html @@ -198,7 +198,7 @@

    Examples

    Description

    -

    Criteria queries are a type-safe, advanced way to query that uses a Groovy builder to construct potentially complex queries. It is a much better alternative to using a StringBuilder to dynamically construct an HQL query. Refer to the user guide section on Criteria for usage instructions.

    +

    Criteria queries are a type-safe, advanced way to query that uses a Groovy builder to construct potentially complex queries. It is a much better alternative to using a StringBuilder to dynamically construct an HQL query. Refer to the user guide section on Criteria for usage instructions.

    Method reference:

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/embedded.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/embedded.html index 4c24192f961..2feb8a9074a 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/embedded.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/embedded.html @@ -136,7 +136,7 @@

    embedded

    Purpose

    -

    Supports embedding domain components into domain classes - otherwise known as composition.

    +

    Supports embedding domain components into domain classes - otherwise known as composition.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/executeQuery.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/executeQuery.html index 492396f496e..7bb213cfdc9 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/executeQuery.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/executeQuery.html @@ -136,7 +136,7 @@

    executeQuery

    Purpose

    -

    Executes HQL queries

    +

    Executes HQL queries

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/find.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/find.html index 401f7647e49..e9606535bf4 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/find.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/find.html @@ -170,7 +170,7 @@

    Examples

    Description

    -

    The find method allows querying with Hibernate’s query language HQL and querying by example. The basic syntax is:

    +

    The find method allows querying with Hibernate’s query language HQL and querying by example. The basic syntax is:

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findAll.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findAll.html index 88c36ca9f86..9e1daecc659 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findAll.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findAll.html @@ -191,7 +191,7 @@

    Examples

    Description

    -

    The findAll method allows querying with Hibernate’s query language HQL and querying by example, returning all matching instances. Pagination can be controlled using the max and offset parameters:

    +

    The findAll method allows querying with Hibernate’s query language HQL and querying by example, returning all matching instances. Pagination can be controlled using the max and offset parameters:

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findAllBy.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findAllBy.html index 6c51f6f578d..1a2e7516a45 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findAllBy.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findAllBy.html @@ -189,7 +189,7 @@

    Examples

    Description

    -

    GORM supports the notion of Dynamic Finders. The findAllBy* method finds all the results for the given method expression.

    +

    GORM supports the notion of Dynamic Finders. The findAllBy* method finds all the results for the given method expression.

    Parameters:

    @@ -263,7 +263,7 @@

    Description

    -

    These operator names can be considered keywords, and you will run into problems when querying domain classes that have one of these names as property names. For more information on dynamic finders refer to the user guide.

    +

    These operator names can be considered keywords, and you will run into problems when querying domain classes that have one of these names as property names. For more information on dynamic finders refer to the user guide.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findBy.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findBy.html index 89f566c8af7..46455cad3f2 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findBy.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findBy.html @@ -178,7 +178,7 @@

    Examples

    Description

    -

    GORM supports the notion of Dynamic Finders. The findBy* method finds the first result for the given method expression.

    +

    GORM supports the notion of Dynamic Finders. The findBy* method finds the first result for the given method expression.

    The following operator names can be used within the respective dynamic methods:

    @@ -230,7 +230,7 @@

    Description

    -

    The above operator names can be considered keywords, and you will run into problems when querying domain classes that have one of these names used as property names. For more information on dynamic finders refer to the user guide.

    +

    The above operator names can be considered keywords, and you will run into problems when querying domain classes that have one of these names used as property names. For more information on dynamic finders refer to the user guide.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findOrCreateBy.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findOrCreateBy.html index 4799e2b63fb..0f7166e120b 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findOrCreateBy.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findOrCreateBy.html @@ -182,7 +182,7 @@

    Examples

    Description

    -

    GORM supports the notion of Dynamic Finders. The findOrCreateBy* method finds the first result for the given method expression.

    +

    GORM supports the notion of Dynamic Finders. The findOrCreateBy* method finds the first result for the given method expression.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findOrSaveBy.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findOrSaveBy.html index aec398efaa1..02fd318a8cb 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findOrSaveBy.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/findOrSaveBy.html @@ -181,7 +181,7 @@

    Examples

    Description

    -

    GORM supports the notion of Dynamic Finders. The findOrSaveBy* method finds the first result for the given method expression.

    +

    GORM supports the notion of Dynamic Finders. The findOrSaveBy* method finds the first result for the given method expression.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/lock.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/lock.html index e603d195675..a549abf68d9 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/lock.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/lock.html @@ -157,7 +157,7 @@

    Description

    The lock is automatically released when the transaction commits. In Grails this is typically after an action has finished executing.

    -

    Refer to the section on Optimistic and Pessimistic locking in the user guide for info.

    +

    Refer to the section on Optimistic and Pessimistic locking in the user guide for info.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/mapping.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/mapping.html index 1c62a560338..7f555b2021d 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/mapping.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/mapping.html @@ -136,7 +136,7 @@

    mapping

    Purpose

    -

    The mapping static property configures how GORM maps the domain class to the database. See the section on the ORM DSL in the user guide for more information.

    +

    The mapping static property configures how GORM maps the domain class to the database. See the section on the ORM DSL in the user guide for more information.

    @@ -160,7 +160,7 @@

    Examples

    -

    This example uses the ORM DSL to map the Person class onto a table called people

    +

    This example uses the ORM DSL to map the Person class onto a table called people

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/namedQueries.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/namedQueries.html index 33528527534..25ef030d38c 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/namedQueries.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/namedQueries.html @@ -136,7 +136,7 @@

    namedQueries

    Purpose

    -

    The namedQueries static property defines named queries. Named queries support the criteria builder syntax. See the section on the Criteria Builder in the user guide for more information.

    +

    The namedQueries static property defines named queries. Named queries support the criteria builder syntax. See the section on the Criteria Builder in the user guide for more information.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/save.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/save.html index 279b5d1dc14..aec3d59167f 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/save.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/save.html @@ -179,7 +179,7 @@

    Description

    validate (optional) - Set to false if validation should be skipped

  • -

    flush (optional) - When set to true flushes the persistence context, persisting the object immediately and updating the version column for optimistic locking

    +

    flush (optional) - When set to true flushes the persistence context, persisting the object immediately and updating the version column for optimistic locking

  • insert (optional) - When set to true will force Hibernate to do a SQL INSERT; this is useful in certain situations (for example when using assigned ids) and Hibernate cannot detect whether to do an INSERT or an UPDATE

    @@ -199,7 +199,7 @@

    Description

  • -By default GORM classes are configured for optimistic locking, which is a feature of Hibernate that involves storing an incrementing version in the table. This value is only updated in the database when the Hibernate session is flushed. +By default GORM classes are configured for optimistic locking, which is a feature of Hibernate that involves storing an incrementing version in the table. This value is only updated in the database when the Hibernate session is flushed.
    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/where.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/where.html index 843e918de61..6daa4ec5bfe 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/where.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/where.html @@ -197,7 +197,7 @@

    Examples

    Description

    -

    The where method is a powerful new type-safe querying option introduced in Grails 2.0. For more information on using the where method see the dedicated section on Where Queries and Detached Criteria in the user guide.

    +

    The where method is a powerful new type-safe querying option introduced in Grails 2.0. For more information on using the where method see the dedicated section on Where Queries and Detached Criteria in the user guide.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/whereAny.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/whereAny.html index 4d1511fc5d7..0a01308d8e6 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/whereAny.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/whereAny.html @@ -160,7 +160,7 @@

    Description

    The where method defaults to a conjunction (logical AND) for the created query. The whereAny compliments the where method by allowing the creation of DetachedCriteria using a disjunction (logical OR).

    -

    The where method is a powerful new type-safe querying option introduced in Grails 2.0. For more information on using the where method see the dedicated section on Where Queries and Detached Criteria in the user guide.

    +

    The where method is a powerful new type-safe querying option introduced in Grails 2.0. For more information on using the where method see the dedicated section on Where Queries and Detached Criteria in the user guide.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/withCriteria.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/withCriteria.html index c62365e65e1..83a4f2d0c2a 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/withCriteria.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/withCriteria.html @@ -176,7 +176,7 @@

    Examples

    Description

    -

    The withCriteria method allows the inline definition of Criteria. Arguments to the [http://grails.github.io/grails-data-mapping/latest/api/grails/orm/HibernateCriteriaBuilder.html] can be passed as the first parameter:

    +

    The withCriteria method allows the inline definition of Criteria. Arguments to the [http://grails.github.io/grails-data-mapping/latest/api/grails/orm/HibernateCriteriaBuilder.html] can be passed as the first parameter:

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/withTransaction.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/withTransaction.html index 39e7e8679ad..3723c9e871e 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/withTransaction.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Domain Classes/withTransaction.html @@ -183,7 +183,7 @@

    Description

    The withTransaction method accepts a Closure with a TransactionStatus argument. The TransactionStatus object can be used to programmatically control rollback of the transaction.

    -

    Refer to the user guide section of Programmatic Transactions for more information.

    +

    Refer to the user guide section of Programmatic Transactions for more information.

    diff --git a/grails-gradle/docs-core/src/test/resources/docs/ref/Plug-ins/domainClasses.html b/grails-gradle/docs-core/src/test/resources/docs/ref/Plug-ins/domainClasses.html index b504b805945..2db54a50f48 100644 --- a/grails-gradle/docs-core/src/test/resources/docs/ref/Plug-ins/domainClasses.html +++ b/grails-gradle/docs-core/src/test/resources/docs/ref/Plug-ins/domainClasses.html @@ -157,7 +157,7 @@

    Examples

    Description

    -

    Refer to the section on GORM in the Grails user guide which details how to create Grails domain classes.

    +

    Refer to the section on GORM in the Grails user guide which details how to create Grails domain classes.

    Configured Spring Beans given a domain class of Book:

    diff --git a/grails-gradle/gradle.properties b/grails-gradle/gradle.properties index eb85b460241..b7073aaed82 100644 --- a/grails-gradle/gradle.properties +++ b/grails-gradle/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/child-project-with-unrelated-parent/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/child-project-with-unrelated-parent/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/child-project-with-unrelated-parent/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/child-project-with-unrelated-parent/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/child-project-with-unrelated-parent/otherProject/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/child-project-with-unrelated-parent/otherProject/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/child-project-with-unrelated-parent/otherProject/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/child-project-with-unrelated-parent/otherProject/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-no-subproject-build-gradle-publish-all/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-no-subproject-build-gradle-publish-all/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-no-subproject-build-gradle-publish-all/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-no-subproject-build-gradle-publish-all/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-no-subproject-build-gradle-publish-per-project/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-no-subproject-build-gradle-publish-per-project/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-no-subproject-build-gradle-publish-per-project/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-no-subproject-build-gradle-publish-per-project/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-parent-child-setup-per-project-child-published/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-parent-child-setup-per-project-child-published/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-parent-child-setup-per-project-child-published/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-parent-child-setup-per-project-child-published/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-parent-child-setup-per-project-parent-published/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-parent-child-setup-per-project-parent-published/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-parent-child-setup-per-project-parent-published/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-parent-child-setup-per-project-parent-published/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-with-subproject-gradle/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-with-subproject-gradle/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-with-subproject-gradle/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/legacy-apply/multi-project-with-subproject-gradle/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/explicit-jar-creation-without-gradle-assistance/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/explicit-jar-creation-without-gradle-assistance/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/explicit-jar-creation-without-gradle-assistance/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/explicit-jar-creation-without-gradle-assistance/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/groovy-doc-disabled/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/groovy-doc-disabled/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/groovy-doc-disabled/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/groovy-doc-disabled/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/groovy-only-project/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/groovy-only-project/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/groovy-only-project/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/groovy-only-project/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/java-already-configured/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/java-already-configured/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/java-already-configured/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/java-already-configured/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/java-only-project/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/java-only-project/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/java-only-project/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/java-only-project/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/multi-project-plugins-applied-child/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/multi-project-plugins-applied-child/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/multi-project-plugins-applied-child/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/multi-project-plugins-applied-child/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/multi-project-plugins-applied-parent/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/multi-project-plugins-applied-parent/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/multi-project-plugins-applied-parent/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/multi-project-plugins-applied-parent/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/multiple-source-sets/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/multiple-source-sets/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/multiple-source-sets/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/multiple-source-sets/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/non-groovy-java-sources-included/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/non-groovy-java-sources-included/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/non-groovy-java-sources-included/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/non-groovy-java-sources-included/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/simple-project/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/simple-project/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/simple-project/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/other-artifacts/simple-project/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/child-project-with-unrelated-parent/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/child-project-with-unrelated-parent/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/child-project-with-unrelated-parent/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/child-project-with-unrelated-parent/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/child-project-with-unrelated-parent/otherProject/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/child-project-with-unrelated-parent/otherProject/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/child-project-with-unrelated-parent/otherProject/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/child-project-with-unrelated-parent/otherProject/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/multi-project-parent-child-setup-per-project-child-published/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/multi-project-parent-child-setup-per-project-child-published/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/multi-project-parent-child-setup-per-project-child-published/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/multi-project-parent-child-setup-per-project-child-published/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/multi-project-parent-child-setup-per-project-parent-published/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/multi-project-parent-child-setup-per-project-parent-published/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/multi-project-parent-child-setup-per-project-parent-published/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/multi-project-parent-child-setup-per-project-parent-published/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/multi-project-with-subproject-gradle/gradle.properties b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/multi-project-with-subproject-gradle/gradle.properties index 0a8a923d749..7374d1fb295 100644 --- a/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/multi-project-with-subproject-gradle/gradle.properties +++ b/grails-gradle/plugins/src/e2eTest/resources/publish-projects/plugins-block/multi-project-with-subproject-gradle/gradle.properties @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# 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, diff --git a/grails-gsp/core/build.gradle b/grails-gsp/core/build.gradle index 30362e0b1fd..36a7f174174 100644 --- a/grails-gsp/core/build.gradle +++ b/grails-gsp/core/build.gradle @@ -93,4 +93,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/CompileStaticGroovyPage.groovy b/grails-gsp/core/src/main/groovy/org/grails/gsp/CompileStaticGroovyPage.groovy index 4480992556f..74a99731be8 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/CompileStaticGroovyPage.groovy +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/CompileStaticGroovyPage.groovy @@ -31,6 +31,7 @@ import org.grails.taglib.encoder.OutputContext */ @CompileStatic abstract class CompileStaticGroovyPage extends GroovyPage { + TagLibNamespaceMethodDispatcher defaultTagDispatcher @Override diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPage.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPage.java index 9b608c272a7..cd50ba46438 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPage.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPage.java @@ -33,7 +33,12 @@ import org.grails.gsp.jsp.JspTag; import org.grails.gsp.jsp.JspTagLib; import org.grails.gsp.jsp.TagLibraryResolver; -import org.grails.taglib.*; +import org.grails.taglib.AbstractTemplateVariableBinding; +import org.grails.taglib.GrailsTagException; +import org.grails.taglib.GroovyPageAttributes; +import org.grails.taglib.TagBodyClosure; +import org.grails.taglib.TagLibraryLookup; +import org.grails.taglib.TagOutput; import org.grails.taglib.encoder.OutputContext; import org.grails.taglib.encoder.OutputEncodingStack; import org.grails.taglib.encoder.OutputEncodingStackAttributes; @@ -41,7 +46,13 @@ import java.io.Writer; import java.lang.reflect.Field; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; /** *

    NOTE: Based on work done by on the GSP standalone project (https://gsp.dev.java.net/) @@ -54,12 +65,9 @@ * @author Lari Hotari */ public abstract class GroovyPage extends Script { - private static final String APPLY_CODEC_TAG_NAME = "applyCodec"; + public static final String ENCODE_AS_ATTRIBUTE_NAME = "encodeAs"; public static final Closure EMPTY_BODY_CLOSURE = TagOutput.EMPTY_BODY_CLOSURE; - - private static final Log LOG = LogFactory.getLog(GroovyPage.class); - public static final String OUT = "out"; public static final String EXPRESSION_OUT = "expressionOut"; public static final String EXPRESSION_OUT_STATEMENT = EXPRESSION_OUT; // "getCodecOut()"; @@ -79,19 +87,21 @@ public abstract class GroovyPage extends Script { PLUGIN_CONTEXT_PATH, PAGE_SCOPE); + private static final String APPLY_CODEC_TAG_NAME = "applyCodec"; + private static final Log LOG = LogFactory.getLog(GroovyPage.class); private static final String BINDING = "binding"; private static final String BLANK_STRING = ""; + protected TagLibraryLookup gspTagLibraryLookup; + protected OutputContext outputContext; @SuppressWarnings("rawtypes") private Map jspTags = Collections.emptyMap(); private TagLibraryResolver jspTagLibraryResolver; - protected TagLibraryLookup gspTagLibraryLookup; private String[] htmlParts; private Set htmlPartsSet; private GrailsPrintWriter out; private GrailsPrintWriter staticOut; private GrailsPrintWriter expressionOut; private OutputEncodingStack outputStack; - protected OutputContext outputContext; private String pluginContextPath; private Encoder rawEncoder; @@ -154,7 +164,7 @@ public void initRun(Writer target, OutputContext outputContext, GroovyPageMetaIn } private void applyModelFieldsFromBinding(Iterable modelFields) { - for(Field field : modelFields) { + for (Field field : modelFields) { try { Object value = getProperty(field.getName()); if (value != null) { @@ -177,7 +187,7 @@ public Object raw(Object value) { private void setVariableDirectly(String name, Object value) { Binding binding = getBinding(); if (binding instanceof AbstractTemplateVariableBinding) { - ((AbstractTemplateVariableBinding)binding).setVariableDirectly(name, value); + ((AbstractTemplateVariableBinding) binding).setVariableDirectly(name, value); } else { binding.getVariables().put(name, value); } @@ -256,7 +266,7 @@ public Object evaluate(String exprText, int lineNumber, Object outerIt, Closure< return evaluator.call(outerIt); } catch (Exception e) { throw new GroovyPagesException("Error evaluating expression [" + exprText + "] on line [" + - lineNumber + "]: " + e.getMessage(), e, lineNumber, getGroovyPageFileName()); + lineNumber + "]: " + e.getMessage(), e, lineNumber, getGroovyPageFileName()); } } @@ -264,12 +274,18 @@ public Object evaluate(String exprText, int lineNumber, Object outerIt, Closure< @Override public Object getProperty(String property) { - if (OUT.equals(property)) return out; - if (EXPRESSION_OUT.equals(property)) return expressionOut; + if (OUT.equals(property)) { + return out; + } + if (EXPRESSION_OUT.equals(property)) { + return expressionOut; + } // in GSP we assume if a property doesn't exist that // it is null rather than throw an error this works nicely // with the Groovy Truth - if (BINDING.equals(property)) return getBinding(); + if (BINDING.equals(property)) { + return getBinding(); + } return resolveProperty(property); } @@ -364,7 +380,7 @@ public final void invokeTag(String tagName, String tagNamespace, int lineNumber, Object tagLibClosure = tagLib.getProperty(tagName); if (tagLibClosure instanceof Closure) { Map encodeAsForTag = gspTagLibraryLookup.getEncodeAsForTag(tagNamespace, tagName); - invokeTagLibClosure(tagName, tagNamespace, (Closure)tagLibClosure, attrs, body, returnsObject, encodeAsForTag); + invokeTagLibClosure(tagName, tagNamespace, (Closure) tagLibClosure, attrs, body, returnsObject, encodeAsForTag); } else { throw new GrailsTagException("Tag [" + tagName + "] does not exist in tag library [" + tagLib.getClass().getName() + "]", getGroovyPageFileName(), lineNumber); } @@ -389,13 +405,15 @@ public final void invokeTag(String tagName, String tagNamespace, int lineNumber, staticOut.append('\"').append(value).append('\"'); } } - + if (body == null) { staticOut.append("/>"); } else { staticOut.append('>'); Object bodyOutput = body.call(); - if (bodyOutput != null) staticOut.print(bodyOutput); + if (bodyOutput != null) { + staticOut.print(bodyOutput); + } staticOut.append("'); } @@ -421,20 +439,20 @@ public final void invokeTag(String tagName, String tagNamespace, int lineNumber, } private void invokeTagLibClosure(String tagName, String tagNamespace, Closure tagLibClosure, Map attrs, Closure body, - boolean returnsObject, Map defaultEncodeAs) { - Closure tag = (Closure)tagLibClosure.clone(); + boolean returnsObject, Map defaultEncodeAs) { + Closure tag = (Closure) tagLibClosure.clone(); if (!(attrs instanceof GroovyPageAttributes)) { attrs = new GroovyPageAttributes(attrs); } - ((GroovyPageAttributes)attrs).setGspTagSyntaxCall(true); + ((GroovyPageAttributes) attrs).setGspTagSyntaxCall(true); - boolean encodeAsPushedToStack=false; + boolean encodeAsPushedToStack = false; try { Map codecSettings = TagOutput.createCodecSettings(tagNamespace, tagName, attrs, defaultEncodeAs); if (codecSettings != null) { outputStack.push(WithCodecHelper.createOutputStackAttributesBuilder(codecSettings, outputContext.getGrailsApplication()).build()); - encodeAsPushedToStack=true; + encodeAsPushedToStack = true; } Object tagresult = null; switch (tag.getParameterTypes().length) { @@ -449,15 +467,20 @@ private void invokeTagLibClosure(String tagName, String tagNamespace, Closure tagresult = tag.call(new Object[]{attrs, (body != null) ? body : TagOutput.EMPTY_BODY_CLOSURE}); outputTagResult(returnsObject, tagresult); break; + default: + // do nothing + break; } } finally { - if (encodeAsPushedToStack) outputStack.pop(); + if (encodeAsPushedToStack) { + outputStack.pop(); + } } } private void outputTagResult(boolean returnsObject, Object tagresult) { if (returnsObject && tagresult != null && !(tagresult instanceof Writer)) { - if (tagresult instanceof String && isHtmlPart((String)tagresult)) { + if (tagresult instanceof String && isHtmlPart((String) tagresult)) { staticOut.print(tagresult); } else { outputStack.getTaglibWriter().print(tagresult); @@ -486,7 +509,7 @@ private GroovyObject getTagLib(String namespace, String tagName) { * @param name True if it can't * @return A boolean true or false */ - public final static boolean isReservedName(String name) { + public static boolean isReservedName(String name) { return RESERVED_NAMES.contains(name); } @@ -516,7 +539,7 @@ public void setHtmlParts(String[] htmlParts) { this.htmlParts = htmlParts; this.htmlPartsSet = new HashSet(); if (htmlParts != null) { - for(String htmlPart : htmlParts) { + for (String htmlPart : htmlParts) { if (htmlPart != null) { htmlPartsSet.add(System.identityHashCode(htmlPart)); } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageBinding.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageBinding.java index 1140d444005..628f8a7441f 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageBinding.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageBinding.java @@ -32,7 +32,8 @@ * @author Lari Hotari */ public class GroovyPageBinding extends TemplateVariableBinding { - private static final Log log = LogFactory.getLog(GroovyPageBinding.class); + + private static final Log LOG = LogFactory.getLog(GroovyPageBinding.class); public GroovyPageBinding() { super(); @@ -60,7 +61,9 @@ public GroovyPageBinding(String[] args) { public Object getVariable(String name) { Object val = getVariablesMap().get(name); if (val == null && !getVariablesMap().containsKey(name)) { - if (GroovyPage.PAGE_SCOPE.equals(name)) return this; + if (GroovyPage.PAGE_SCOPE.equals(name)) { + return this; + } return super.getVariable(name); } return val; @@ -72,11 +75,11 @@ protected boolean shouldUseChildBinding(TemplateVariableBinding childBinding) { private boolean hasSameOwnerClass(TemplateVariableBinding otherBinding) { // owner class can be same in recursive rendering; in that case, the child binding should be used for setting variable values - return (getOwner() != null && otherBinding.getOwner() != null && getOwner().getClass()==otherBinding.getOwner().getClass()); + return (getOwner() != null && otherBinding.getOwner() != null && getOwner().getClass() == otherBinding.getOwner().getClass()); } public String getPluginContextPath() { - return (String)getVariable(GroovyPage.PLUGIN_CONTEXT_PATH); + return (String) getVariable(GroovyPage.PLUGIN_CONTEXT_PATH); } @SuppressWarnings("unchecked") @@ -90,7 +93,7 @@ public void setPagePlugin(GrailsPlugin plugin) { } public GrailsPlugin getPagePlugin() { - return (GrailsPlugin)getVariable("pagePlugin"); + return (GrailsPlugin) getVariable("pagePlugin"); } protected boolean isReservedName(String name) { diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageMetaInfo.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageMetaInfo.java index f83d0f16ad3..45d9a493b37 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageMetaInfo.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageMetaInfo.java @@ -61,11 +61,22 @@ */ public class GroovyPageMetaInfo implements GrailsApplicationAware { + public static final String HTML_DATA_POSTFIX = "_html.data"; + public static final String LINENUMBERS_DATA_POSTFIX = "_linenumbers.data"; + public static final long LASTMODIFIED_CHECK_INTERVAL = Long.getLong("grails.gsp.reload.interval", 5000); + //CHECKSTYLE:OFF + public static String DEFAULT_PLUGIN_PATH = ""; + //CHECKSTYLE:ON + private static final Log LOG = LogFactory.getLog(GroovyPageMetaInfo.class); + private static final long LASTMODIFIED_CHECK_GRANULARITY = Long.getLong("grails.gsp.reload.granularity", 2000); + + volatile boolean metaClassShouldBeRemoved = false; + private TagLibraryLookup tagLibraryLookup; private TagLibraryResolver jspTagLibraryResolver; - private boolean precompiledMode=false; + private boolean precompiledMode = false; private Class pageClass; private long lastModified; private InputStream groovySource; @@ -87,11 +98,6 @@ public class GroovyPageMetaInfo implements GrailsApplicationAware { private boolean modelFieldsMode; private Set modelFields; - public static final String HTML_DATA_POSTFIX = "_html.data"; - public static final String LINENUMBERS_DATA_POSTFIX = "_linenumbers.data"; - - public static final long LASTMODIFIED_CHECK_INTERVAL = Long.getLong("grails.gsp.reload.interval", 5000).longValue(); - private static final long LASTMODIFIED_CHECK_GRANULARITY = Long.getLong("grails.gsp.reload.granularity", 2000).longValue(); private GrailsApplication grailsApplication; private String pluginPath; @@ -99,9 +105,6 @@ public class GroovyPageMetaInfo implements GrailsApplicationAware { private boolean initialized = false; private CacheEntry shouldReloadCacheEntry = new CacheEntry(); - public static String DEFAULT_PLUGIN_PATH = ""; - - volatile boolean metaClassShouldBeRemoved=false; public GroovyPageMetaInfo() { @@ -110,15 +113,15 @@ public GroovyPageMetaInfo() { @SuppressWarnings("rawtypes") public GroovyPageMetaInfo(Class pageClass) { this(); - precompiledMode=true; + precompiledMode = true; this.pageClass = pageClass; - contentType = (String)ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_CONTENT_TYPE), null); - jspTags = (Map)ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_JSP_TAGS), null); - lastModified = (Long)ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_LAST_MODIFIED), null); - expressionCodecName = (String)ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_EXPRESSION_CODEC), null); - staticCodecName = (String)ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_STATIC_CODEC), null); - outCodecName = (String)ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_OUT_CODEC), null); - taglibCodecName = (String)ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_TAGLIB_CODEC), null); + contentType = (String) ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_CONTENT_TYPE), null); + jspTags = (Map) ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_JSP_TAGS), null); + lastModified = (Long) ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_LAST_MODIFIED), null); + expressionCodecName = (String) ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_EXPRESSION_CODEC), null); + staticCodecName = (String) ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_STATIC_CODEC), null); + outCodecName = (String) ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_OUT_CODEC), null); + taglibCodecName = (String) ReflectionUtils.getField(ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_TAGLIB_CODEC), null); Field compileStaticModeField = ReflectionUtils.findField(pageClass, GroovyPageParser.CONSTANT_NAME_COMPILE_STATIC_MODE); if (compileStaticModeField != null) { compileStaticMode = (Boolean) ReflectionUtils.getField(compileStaticModeField, null); @@ -130,16 +133,11 @@ public GroovyPageMetaInfo(Class pageClass) { try { readHtmlData(); - } - catch (IOException e) { + } catch (IOException e) { throw new RuntimeException("Problem reading html data for page class " + pageClass, e); } } - static interface GroovyPageMetaInfoInitializer { - public void initialize(GroovyPageMetaInfo metaInfo); - } - synchronized void initializeOnDemand(GroovyPageMetaInfoInitializer initializer) { if (!initialized) { initializer.initialize(this); @@ -159,7 +157,7 @@ public void initialize() { } private synchronized void initializeModelFields() { - if(getPageClass() != null) { + if (getPageClass() != null) { Set modelFields = new HashSet<>(); if (modelFieldsMode) { for (Field field : getPageClass().getDeclaredFields()) { @@ -189,7 +187,9 @@ private void initializePluginPath() { GrailsPluginManager pluginManager = applicationContext.getBean(GrailsPluginManager.BEAN_NAME, GrailsPluginManager.class); pluginPath = pluginManager.getPluginPathForClass(pageClass); - if (pluginPath == null) pluginPath=DEFAULT_PLUGIN_PATH ; + if (pluginPath == null) { + pluginPath = DEFAULT_PLUGIN_PATH; + } pagePlugin = pluginManager.getPluginForClass(pageClass); } @@ -214,8 +214,7 @@ private void readHtmlData() throws IOException { htmlParts[i] = input.readUTF(); } } - } - finally { + } finally { IOUtils.closeQuietly(input); } } @@ -236,8 +235,7 @@ private void readLineNumbers() throws IOException { for (int i = 0; i < arrayLen; i++) { lineNumbers[i] = input.readInt(); } - } - finally { + } finally { IOUtils.closeQuietly(input); } } @@ -253,7 +251,7 @@ private String resolveDataResourceName(String postfix) { String dataResourceName = pageClass.getName(); int pos = dataResourceName.lastIndexOf('.'); if (pos > -1) { - dataResourceName = dataResourceName.substring(pos+1); + dataResourceName = dataResourceName.substring(pos + 1); } dataResourceName += postfix; return dataResourceName; @@ -320,8 +318,7 @@ private synchronized int[] getPrecompiledLineNumbers() { if (lineNumbers == null) { try { readLineNumbers(); - } - catch (IOException e) { + } catch (IOException e) { LOG.warn("Problem reading precompiled linenumbers", e); } } @@ -370,10 +367,12 @@ public void applyLastModifiedFromResource(Resource resource) { * @return The last modified date or -1 */ private long establishLastModified(Resource resource) { - if (resource == null) return -1; + if (resource == null) { + return -1; + } if (resource instanceof FileSystemResource) { - return ((FileSystemResource)resource).getFile().lastModified(); + return ((FileSystemResource) resource).getFile().lastModified(); } long last; @@ -382,7 +381,7 @@ private long establishLastModified(Resource resource) { try { URL url = resource.getURL(); if ("file".equals(url.getProtocol())) { - File file=new File(url.getFile()); + File file = new File(url.getFile()); if (file.exists()) { return file.lastModified(); } @@ -391,22 +390,18 @@ private long establishLastModified(Resource resource) { urlc.setDoInput(false); urlc.setDoOutput(false); last = urlc.getLastModified(); - } - catch (FileNotFoundException fnfe) { + } catch (FileNotFoundException fnfe) { last = -1; - } - catch (IOException e) { + } catch (IOException e) { last = -1; - } - finally { + } finally { if (urlc != null) { try { InputStream is = urlc.getInputStream(); if (is != null) { is.close(); } - } - catch (IOException e) { + } catch (IOException e) { // ignore } } @@ -418,7 +413,7 @@ private long establishLastModified(Resource resource) { /** * Checks if this GSP has expired and should be reloaded (there is a newer source gsp available) * PrivilegedAction is used so that locating the Resource is lazily evaluated. - * + *

    * lastModified checking is done only when enough time has expired since the last check. This setting is controlled by the grails.gsp.reload.interval System property, * by default it's value is 5000 (ms). * @@ -426,17 +421,19 @@ private long establishLastModified(Resource resource) { * @return true if the available gsp source file is newer than the loaded one. */ public boolean shouldReload(final PrivilegedAction resourceCallable) { - if (resourceCallable == null) return false; - Resource resource=checkIfReloadableResourceHasChanged(resourceCallable); + if (resourceCallable == null) { + return false; + } + Resource resource = checkIfReloadableResourceHasChanged(resourceCallable); return (resource != null); } public Resource checkIfReloadableResourceHasChanged(final PrivilegedAction resourceCallable) { Callable checkerCallable = new Callable() { public Resource call() { - Resource resource=resourceCallable.run(); + Resource resource = resourceCallable.run(); if (resource != null && resource.exists()) { - long currentLastmodified=establishLastModified(resource); + long currentLastmodified = establishLastModified(resource); // granularity is required since lastmodified information is rounded somewhere in copying & war (zip) file information // usually the lastmodified time is 1000L apart in files and in files extracted from the zip (war) file if (currentLastmodified > 0 && Math.abs(currentLastmodified - lastModified) > LASTMODIFIED_CHECK_GRANULARITY) { @@ -526,14 +523,19 @@ public Set getModelFields() { public void removePageMetaClass() { metaClassShouldBeRemoved = true; - if(pageClass!=null) { + if (pageClass != null) { GroovySystem.getMetaClassRegistry().removeMetaClass(pageClass); } } public void writeToFinished(Writer out) { - if(metaClassShouldBeRemoved) { + if (metaClassShouldBeRemoved) { removePageMetaClass(); } } + + interface GroovyPageMetaInfoInitializer { + + void initialize(GroovyPageMetaInfo metaInfo); + } } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageResourceLoader.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageResourceLoader.java index 7620f9f0ece..51c4b128475 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageResourceLoader.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageResourceLoader.java @@ -29,9 +29,8 @@ * A StaticResourceLoader that loads GSPs from a local grails-app folder instead of from WEB-INF in * development mode. * - * @see org.grails.core.io.StaticResourceLoader - * * @author Graeme Rocher + * @see org.grails.core.io.StaticResourceLoader * @since 0.5 */ public class GroovyPageResourceLoader extends StaticResourceLoader { @@ -65,5 +64,4 @@ public Resource getResource(String location) { return resource; } - } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageSourceDecorator.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageSourceDecorator.java index 2a0a40206ce..a3e760e1512 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageSourceDecorator.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageSourceDecorator.java @@ -19,5 +19,6 @@ package org.grails.gsp; public interface GroovyPageSourceDecorator { - StringBuilder decorate(StringBuilder source); + + StringBuilder decorate(StringBuilder source); } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageTemplate.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageTemplate.java index cb892a1bb22..fb4919b8bd9 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageTemplate.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageTemplate.java @@ -32,6 +32,7 @@ * @since 0.5 */ public class GroovyPageTemplate implements Template, Cloneable { + private final OutputContextLookup outputContextLookup; private GroovyPageMetaInfo metaInfo; private boolean allowSettingContentType = false; @@ -67,7 +68,7 @@ public boolean isAllowSettingContentType() { public void setAllowSettingContentType(boolean allowSettingContentType) { this.allowSettingContentType = allowSettingContentType; } - + @Override public Object clone() { GroovyPageTemplate cloned = new GroovyPageTemplate(metaInfo); diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageWritable.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageWritable.java index a7813d1c735..935c796a306 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageWritable.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPageWritable.java @@ -28,9 +28,12 @@ import org.grails.taglib.encoder.OutputContext; import org.grails.taglib.encoder.OutputContextLookup; -import java.io.*; -import java.text.DateFormat; -import java.util.Date; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.Writer; import java.util.LinkedHashMap; import java.util.Map; @@ -42,8 +45,10 @@ * @since 0.5 */ public class GroovyPageWritable implements Writable { + private static final Log LOG = LogFactory.getLog(GroovyPageWritable.class); - private static final String GSP_NONE_CODEC_NAME = "none"; + private static final String GROOVY_SOURCE_CONTENT_TYPE = "text/plain"; + private GroovyPageMetaInfo metaInfo; private OutputContextLookup outputContextLookup; private boolean allowSettingContentType; @@ -51,15 +56,12 @@ public class GroovyPageWritable implements Writable { private Map additionalBinding = new LinkedHashMap(); private boolean showSource; - private static final String GROOVY_SOURCE_CONTENT_TYPE = "text/plain"; public GroovyPageWritable(GroovyPageMetaInfo metaInfo, OutputContextLookup outputContextLookup, boolean allowSettingContentType) { this.metaInfo = metaInfo; this.outputContextLookup = outputContextLookup; this.allowSettingContentType = allowSettingContentType; } - - /** * This sets any additional variables that need to be placed in the Binding of the GSP page. * @@ -97,10 +99,9 @@ protected Writer doWriteTo(OutputContext outputContext, Writer out) throws IOExc // Set it to TEXT outputContext.setContentType(GROOVY_SOURCE_CONTENT_TYPE); // must come before response.getOutputStream() writeGroovySourceToResponse(metaInfo, out); - } - else { + } else { // Set it to HTML by default - if (metaInfo.getCompilationException()!=null) { + if (metaInfo.getCompilationException() != null) { throw metaInfo.getCompilationException(); } @@ -135,7 +136,7 @@ protected Writer doWriteTo(OutputContext outputContext, Writer out) throws IOExc GroovyPage page = null; try { - page = (GroovyPage)metaInfo.getPageClass().newInstance(); + page = (GroovyPage) metaInfo.getPageClass().newInstance(); } catch (Exception e) { throw new GroovyPagesException("Problem instantiating page class", e); } @@ -146,13 +147,12 @@ protected Writer doWriteTo(OutputContext outputContext, Writer out) throws IOExc try { page.run(); - } - finally { + } finally { page.cleanup(); if (hasRequest) { if (newParentCreated) { outputContext.setBinding(null); - } else { + } else { outputContext.setBinding(parentBinding); } } @@ -170,8 +170,6 @@ private boolean shouldShowGroovySource(OutputContext outputContext) { return isShowSource() && Environment.getCurrent() == Environment.DEVELOPMENT && metaInfo.getGroovySource() != null; } - private static final GspNoneCodec gspNoneCodeInstance = new GspNoneCodec(); - public boolean isShowSource() { return showSource; } @@ -180,13 +178,6 @@ public void setShowSource(boolean showSource) { this.showSource = showSource; } - private static final class GspNoneCodec { - @SuppressWarnings("unused") - public final Object encode(Object object) { - return object; - } - } - private GroovyPageBinding createBinding(Binding parent) { GroovyPageBinding binding = new GroovyPageBinding(); binding.setParent(parent); @@ -197,7 +188,7 @@ private GroovyPageBinding createBinding(Binding parent) { // set plugin context path for top level rendering, this means actual view + layout // view is top level when parent is GroovyPageRequestBinding // pluginContextPath is also resetted when a plugin template is overrided by an application view - if (parent==null || (parent instanceof TemplateVariableBinding && ((TemplateVariableBinding)parent).isRoot()) || "".equals(metaInfo.getPluginPath())) { + if (parent == null || (parent instanceof TemplateVariableBinding && ((TemplateVariableBinding) parent).isRoot()) || "".equals(metaInfo.getPluginPath())) { binding.setPluginContextPath(metaInfo.getPluginPath()); } binding.setPagePlugin(metaInfo.getPagePlugin()); @@ -206,7 +197,8 @@ private GroovyPageBinding createBinding(Binding parent) { /** * Copy all of input to output. - * @param in The input stream to writeInputStreamToResponse from + * + * @param in The input stream to writeInputStreamToResponse from * @param out The output to write to * @throws IOException When an error occurs writing to the response Writer */ @@ -216,13 +208,14 @@ protected void writeInputStreamToResponse(InputStream in, Writer out) throws IOE Reader reader = new InputStreamReader(in, "UTF-8"); char[] buf = new char[8192]; - for (;;) { + for (; ; ) { int read = reader.read(buf); - if (read <= 0) break; + if (read <= 0) { + break; + } out.write(buf, 0, read); } - } - finally { + } finally { out.close(); in.close(); } @@ -233,20 +226,22 @@ protected void writeInputStreamToResponse(InputStream in, Writer out) throws IOE * to the response, prefixing each line with its line number. The * line numbers make it easier to match line numbers in exceptions * to the generated source. + * * @param info The meta info for the GSP page that we want to write - * the generated source for. - * @param out The writer to send the source to. + * the generated source for. + * @param out The writer to send the source to. * @throws IOException If there is either a problem with the input - * stream for the Groovy source, or the writer. + * stream for the Groovy source, or the writer. */ protected void writeGroovySourceToResponse(GroovyPageMetaInfo info, Writer out) throws IOException { InputStream in = info.getGroovySource(); - if (in == null) return; + if (in == null) { + return; + } try { try { in.reset(); - } - catch (IOException e) { + } catch (IOException e) { // ignore } BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8")); @@ -284,8 +279,7 @@ protected void writeGroovySourceToResponse(GroovyPageMetaInfo info, Writer out) out.write(line); out.write('\n'); } - } - finally { + } finally { out.close(); in.close(); } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesException.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesException.java index f1e971bec92..a741e3e23ab 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesException.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesException.java @@ -34,7 +34,7 @@ public class GroovyPagesException extends GrailsException implements SourceCodeA private String fileName; public GroovyPagesException(String message, Throwable e) { - super(message,e); + super(message, e); } public GroovyPagesException(String message, Throwable exception, int lineNumber, String fileName) { @@ -49,14 +49,14 @@ public GroovyPagesException(String message) { public String getFileName() { if (fileName == null && getCause() instanceof SourceCodeAware) { - return ((SourceCodeAware)getCause()).getFileName(); + return ((SourceCodeAware) getCause()).getFileName(); } return fileName; } public int getLineNumber() { if (lineNumber == -1 && getCause() instanceof SourceCodeAware) { - return ((SourceCodeAware)getCause()).getLineNumber(); + return ((SourceCodeAware) getCause()).getLineNumber(); } return lineNumber; } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesMetaUtils.groovy b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesMetaUtils.groovy index c81dbbe442b..0b808b16400 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesMetaUtils.groovy +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesMetaUtils.groovy @@ -17,6 +17,7 @@ * under the License. */ package org.grails.gsp + import grails.util.Environment import grails.util.GrailsMetaClassUtils import groovy.transform.CompileStatic @@ -31,11 +32,11 @@ class GroovyPagesMetaUtils { } static void registerMethodMissingForGSP(final MetaClass emc, final TagLibraryLookup gspTagLibraryLookup) { - if(gspTagLibraryLookup==null) return + if (gspTagLibraryLookup == null) return final boolean addMethodsToMetaClass = !Environment.isDevelopmentMode() - GroovyObject mc = (GroovyObject)emc - synchronized(emc) { + GroovyObject mc = (GroovyObject) emc + synchronized (emc) { mc.setProperty("methodMissing", { String name, Object args -> TagLibraryMetaUtils.methodMissingForTagLib(emc, emc.getTheClass(), gspTagLibraryLookup, GroovyPage.DEFAULT_NAMESPACE, name, args, addMethodsToMetaClass) }) diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesTemplateEngine.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesTemplateEngine.java index 774e56fc9fc..7a042f162c0 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesTemplateEngine.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/GroovyPagesTemplateEngine.java @@ -37,7 +37,11 @@ import org.grails.core.exceptions.DefaultErrorsPrinter; import org.grails.exceptions.ExceptionUtils; import org.grails.gsp.compiler.GroovyPageParser; -import org.grails.gsp.io.*; +import org.grails.gsp.io.DefaultGroovyPageLocator; +import org.grails.gsp.io.GroovyPageCompiledScriptSource; +import org.grails.gsp.io.GroovyPageLocator; +import org.grails.gsp.io.GroovyPageResourceScriptSource; +import org.grails.gsp.io.GroovyPageScriptSource; import org.grails.gsp.jsp.TagLibraryResolver; import org.grails.taglib.TagLibraryLookup; import org.springframework.beans.BeansException; @@ -46,7 +50,11 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ResourceLoaderAware; -import org.springframework.core.io.*; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.io.UrlResource; import org.springframework.scripting.ScriptSource; import org.springframework.scripting.support.ResourceScriptSource; import org.springframework.util.Assert; @@ -57,7 +65,11 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.security.PrivilegedAction; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -68,15 +80,14 @@ * within Groovy. It allows GSP pages to be re-used in different context using code like the below: * * - * Template t = new GroovyPagesTemplateEngine() - * .createTemplate(context,request,response); - * t.make() - * .writeTo(out); + * Template t = new GroovyPagesTemplateEngine() + * .createTemplate(context,request,response); + * t.make() + * .writeTo(out); * * * @author Graeme Rocher * @author Lari Hotari - * * @since 0.1 */ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine implements ResourceLoaderAware, ApplicationContextAware, InitializingBean, BeanClassLoaderAware { @@ -91,7 +102,7 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple private ConcurrentMap> pageCache = new ConcurrentHashMap>(); private ClassLoader classLoader; - private AtomicInteger scriptNameCount=new AtomicInteger(0); + private AtomicInteger scriptNameCount = new AtomicInteger(0); private GroovyPageLocator groovyPageLocator = new DefaultGroovyPageLocator(); @@ -116,56 +127,16 @@ public class GroovyPagesTemplateEngine extends ResourceAwareTemplateEngine imple } } - private class GroovyPagesTemplateEngineCacheEntry extends CacheEntry{ - private final String pageName; - - public GroovyPagesTemplateEngineCacheEntry(String pageName){ - this.pageName = pageName; - } - - @Override - protected boolean hasExpired(long timeout, Object cacheRequestObject) { - GroovyPageMetaInfo meta = getValue(); - Resource resource = (Resource)cacheRequestObject; - return meta == null || isGroovyPageReloadable(resource, meta); - } - - @Override - protected GroovyPageMetaInfo updateValue(GroovyPageMetaInfo oldValue, Callable updater, Object cacheRequestObject) - throws Exception { - if(oldValue != null) { - oldValue.removePageMetaClass(); - } - Resource resource = (Resource)cacheRequestObject; - return buildPageMetaInfo(resource, pageName); - } - } - - private static class GroovyPagesTemplateEngineCallable implements Callable> { - - private final CacheEntry cacheEntry; - - public GroovyPagesTemplateEngineCallable(CacheEntry cacheEntry){ - this.cacheEntry = cacheEntry; - } - - @Override - public CacheEntry call() throws Exception { - return cacheEntry; - } - - } - public GroovyPagesTemplateEngine() { // default } - public void setGroovyPageSourceDecorators(List groovyPageSourceDecorators){ - this.groovyPageSourceDecorators = groovyPageSourceDecorators; + public void setGroovyPageSourceDecorators(List groovyPageSourceDecorators) { + this.groovyPageSourceDecorators = groovyPageSourceDecorators; } - public List getGroovyPageSourceDecorators(){ - return groovyPageSourceDecorators; + public List getGroovyPageSourceDecorators() { + return groovyPageSourceDecorators; } public void setGroovyPageLocator(GroovyPageLocator groovyPageLocator) { @@ -183,7 +154,7 @@ public void setResourceLoader(ResourceLoader resourceLoader) { public void afterPropertiesSet() { if (classLoader == null) { classLoader = initGroovyClassLoader(Thread.currentThread().getContextClassLoader()); - }else if (!classLoader.getClass().equals(GroovyPageClassLoader.class)) { + } else if (!classLoader.getClass().equals(GroovyPageClassLoader.class)) { classLoader = initGroovyClassLoader(classLoader); } if (!Environment.isDevelopmentMode()) { @@ -207,6 +178,7 @@ public void setJspTagLibraryResolver(TagLibraryResolver jspTagLibraryResolver) { /** * Sets the ClassLoader that the TemplateEngine should use to + * * @param classLoader The ClassLoader to use when compilation of Groovy Pages occurs */ public void setClassLoader(ClassLoader classLoader) { @@ -225,10 +197,9 @@ public int[] calculateLineNumbersForPage(String url) { try { Template t = createTemplate(url); if (t instanceof GroovyPageTemplate) { - return ((GroovyPageTemplate)t).getMetaInfo().getLineNumbers(); + return ((GroovyPageTemplate) t).getMetaInfo().getLineNumbers(); } - } - catch (Exception e) { + } catch (Exception e) { // ignore, non critical method used for retrieving debug info LOG.warn("Exception retrieving line numbers from GSP: " + url + ", message: " + e.getMessage()); LOG.debug("Full stack trace of error", e); @@ -258,7 +229,7 @@ public Template createTemplate(Resource resource) { /** * Creates a Template for the given Spring Resource instance * - * @param resource The Resource to create the Template for + * @param resource The Resource to create the Template for * @param cacheable The resource can be cached or not * @return The Template instance */ @@ -274,15 +245,14 @@ public Template createTemplate(Resource resource, final boolean cacheable) { final String pageName = establishPageName(resource, cacheable); try { return createTemplate(resource, pageName, cacheable); - } - catch (IOException e) { + } catch (IOException e) { throw new GroovyPagesException("Error loading template", e); } } protected Template createTemplate(Resource resource, final String pageName, final boolean cacheable) throws IOException { GroovyPageMetaInfo meta; - if(cacheable) { + if (cacheable) { meta = CacheEntry.getValue(pageCache, pageName, -1, null, new GroovyPagesTemplateEngineCallable(new GroovyPagesTemplateEngineCacheEntry(pageName)) , true, resource); @@ -343,7 +313,7 @@ public Template createTemplateForUri(String uri) { return createTemplateForUri(new String[]{uri}); } - public Template createTemplateForUri(String[] uris) { + public Template createTemplateForUri(String[] uris) { GroovyPageScriptSource scriptSource = findScriptSource(uris); if (scriptSource != null) { @@ -361,7 +331,9 @@ public GroovyPageScriptSource findScriptSource(String[] uris) { for (String uri : uris) { scriptSource = groovyPageLocator.findPage(uri); - if (scriptSource != null) break; + if (scriptSource != null) { + break; + } } return scriptSource; } @@ -389,12 +361,11 @@ public Template createTemplate(ScriptSource scriptSource) { * Creates a Template using the given text for the Template and the given name. The name * of the template is required * - * @param txt The URI of the page to create the template for + * @param txt The URI of the page to create the template for * @param pageName The name of the page being parsed - * * @return The Template instance * @throws CompilationFailedException - * @throws IOException Thrown if an IO exception occurs creating the Template + * @throws IOException Thrown if an IO exception occurs creating the Template */ public Template createTemplate(String txt, String pageName) throws IOException { Assert.hasLength(txt, "Argument [txt] cannot be null or blank"); @@ -408,10 +379,9 @@ public Template createTemplate(String txt, String pageName) throws IOException { * * @param file The File to use to construct the template with * @return A Groovy Template instance - * * @throws CompilationFailedException When an error occured compiling the Template - * @throws ClassNotFoundException When a Class cannot be found within the given Template - * @throws IOException When a I/O Exception occurs reading the Template + * @throws ClassNotFoundException When a Class cannot be found within the given Template + * @throws IOException When a I/O Exception occurs reading the Template */ @Override public Template createTemplate(File file) throws CompilationFailedException, ClassNotFoundException, IOException { @@ -423,10 +393,9 @@ public Template createTemplate(File file) throws CompilationFailedException, Cla * * @param url The URL to use to construct the template with * @return A Groovy Template instance - * * @throws CompilationFailedException When an error occured compiling the Template - * @throws ClassNotFoundException When a Class cannot be found within the given Template - * @throws IOException When a I/O Exception occurs reading the Template + * @throws ClassNotFoundException When a Class cannot be found within the given Template + * @throws IOException When a I/O Exception occurs reading the Template */ @Override public Template createTemplate(URL url) throws CompilationFailedException, ClassNotFoundException, IOException { @@ -435,6 +404,7 @@ public Template createTemplate(URL url) throws CompilationFailedException, Class /** * Create a Template for the given InputStream + * * @param inputStream The InputStream to create the Template for * @return The Template instance */ @@ -448,24 +418,23 @@ protected GroovyPageMetaInfo buildPageMetaInfo(Resource resource, String pageNam InputStream inputStream = resource.getInputStream(); try { return buildPageMetaInfo(inputStream, resource, pageName); - } - finally { + } finally { inputStream.close(); } } private StringBuilder decorateGroovyPageSource(StringBuilder source) throws IOException { - for(GroovyPageSourceDecorator groovyPageSourceDecorator : groovyPageSourceDecorators){ - source = groovyPageSourceDecorator.decorate(source); - } - return source; + for (GroovyPageSourceDecorator groovyPageSourceDecorator : groovyPageSourceDecorators) { + source = groovyPageSourceDecorator.decorate(source); + } + return source; } /** * Establishes whether a Groovy page is reloadable. A GSP is only reloadable in the development environment. * * @param resource The Resource to check. - * @param meta The current GroovyPageMetaInfo instance + * @param meta The current GroovyPageMetaInfo instance * @return true if it is reloadable */ private boolean isGroovyPageReloadable(final Resource resource, GroovyPageMetaInfo meta) { @@ -503,7 +472,7 @@ public void setReloadEnabled(boolean b) { public Resource getResourceForUri(String uri) { GroovyPageScriptSource scriptSource = getResourceWithinContext(uri); if (scriptSource != null && (scriptSource instanceof GroovyPageResourceScriptSource)) { - return ((GroovyPageResourceScriptSource)scriptSource).getResource(); + return ((GroovyPageResourceScriptSource) scriptSource).getResource(); } return null; } @@ -521,8 +490,8 @@ private GroovyPageScriptSource getResourceWithinContext(String uri) { * Constructs a GroovyPageMetaInfo instance which holds the script class, modified date and so on * * @param inputStream The InputStream to construct the GroovyPageMetaInfo instance from - * @param res The Spring Resource to construct the MetaInfo from - * @param pageName The name of the page (can be null, in which case method responsible for calculating appropriate alternative) + * @param res The Spring Resource to construct the MetaInfo from + * @param pageName The name of the page (can be null, in which case method responsible for calculating appropriate alternative) * @return The GroovyPageMetaInfo instance */ protected GroovyPageMetaInfo buildPageMetaInfo(InputStream inputStream, Resource res, String pageName) { @@ -531,12 +500,11 @@ protected GroovyPageMetaInfo buildPageMetaInfo(InputStream inputStream, Resource GroovyPageParser parser; String path = getPathForResource(res); try { - String gspSource = IOUtils.toString(inputStream, getGspEncoding()); + String gspSource = IOUtils.toString(inputStream, getGspEncoding()); parser = new GroovyPageParser(name, path, path, decorateGroovyPageSource(new StringBuilder(gspSource)).toString(), - grailsApplication != null? grailsApplication.getConfig() : null); - } - catch (IOException e) { - throw new GroovyPagesException("I/O parsing Groovy page ["+(res != null ? res.getDescription() : name)+"]: " + e.getMessage(),e); + grailsApplication != null ? grailsApplication.getConfig() : null); + } catch (IOException e) { + throw new GroovyPagesException("I/O parsing Groovy page [" + (res != null ? res.getDescription() : name) + "]: " + e.getMessage(), e); } InputStream in = parser.parse(); @@ -547,8 +515,7 @@ protected GroovyPageMetaInfo buildPageMetaInfo(InputStream inputStream, Resource try { metaInfo.setPageClass(compileGroovyPage(in, name, path, metaInfo)); metaInfo.setHtmlParts(parser.getHtmlPartsArray()); - } - catch (GroovyPagesException e) { + } catch (GroovyPagesException e) { metaInfo.setCompilationException(e); } @@ -556,7 +523,9 @@ protected GroovyPageMetaInfo buildPageMetaInfo(InputStream inputStream, Resource } private String getPathForResource(Resource res) { - if (res == null) return ""; + if (res == null) { + return ""; + } String path = null; try { @@ -564,8 +533,7 @@ private String getPathForResource(Resource res) { if (file != null) { path = file.getAbsolutePath(); } - } - catch (IOException e) { + } catch (IOException e) { // ignore } if (path != null) { @@ -579,8 +547,9 @@ private String getPathForResource(Resource res) { /** * Attempts to compile the given InputStream into a Groovy script using the given name - * @param in The InputStream to read the Groovy code from - * @param name The name of the class to use + * + * @param in The InputStream to read the Groovy code from + * @param name The name of the class to use * @param pageName The page name * @param metaInfo * @return The compiled java.lang.Class, which is an instance of groovy.lang.Script @@ -594,22 +563,20 @@ private Class compileGroovyPage(InputStream in, String name, String pageName, String groovySource = IOGroovyMethods.getText(in, GroovyPageParser.GROOVY_SOURCE_CHAR_ENCODING); //System.out.println(groovySource); scriptClass = groovyClassLoader.parseClass(groovySource, name); - } - catch (CompilationFailedException e) { - LOG.error("Compilation error compiling GSP ["+name+"]:" + e.getMessage(), e); + } catch (CompilationFailedException e) { + LOG.error("Compilation error compiling GSP [" + name + "]:" + e.getMessage(), e); int lineNumber = ExceptionUtils.extractLineNumber(e); final int[] lineMappings = metaInfo.getLineNumbers(); - if (lineNumber>0 && lineNumber < lineMappings.length) { - lineNumber = lineMappings[lineNumber-1]; + if (lineNumber > 0 && lineNumber < lineMappings.length) { + lineNumber = lineMappings[lineNumber - 1]; } String relativePageName = DefaultErrorsPrinter.makeRelativeIfPossible(pageName); - throw new GroovyPagesException("Could not parse script [" + relativePageName + "]: " + e.getMessage(),e, lineNumber, pageName); - } - catch (IOException e) { + throw new GroovyPagesException("Could not parse script [" + relativePageName + "]: " + e.getMessage(), e, lineNumber, pageName); + } catch (IOException e) { String relativePageName = DefaultErrorsPrinter.makeRelativeIfPossible(pageName); - throw new GroovyPagesException("IO exception parsing script ["+ relativePageName + "]: " + e.getMessage(), e); + throw new GroovyPagesException("IO exception parsing script [" + relativePageName + "]: " + e.getMessage(), e); } GroovyPagesMetaUtils.registerMethodMissingForGSP(scriptClass, tagLibraryLookup); @@ -620,7 +587,7 @@ private synchronized GroovyClassLoader findOrInitGroovyClassLoader() { if (!(classLoader instanceof GroovyPageClassLoader)) { classLoader = initGroovyClassLoader(classLoader); } - return (GroovyClassLoader)classLoader; + return (GroovyClassLoader) classLoader; } /** @@ -628,7 +595,7 @@ private synchronized GroovyClassLoader findOrInitGroovyClassLoader() { * last modifed date and InputStream * * @param parse The Parse object - * @param in The InputStream instance + * @param in The InputStream instance * @return A GroovyPageMetaInfo instance */ private GroovyPageMetaInfo createPageMetaInfo(GroovyPageParser parse, InputStream in) { @@ -658,8 +625,7 @@ private GroovyPageMetaInfo createPageMetaInfo(GroovyPageParser parse, InputStrea File file = new File(dumpLineNumbersTo, fileName); try { parse.writeLineNumbers(file); - } - catch (IOException ignored) { + } catch (IOException ignored) { if (file.exists()) { file.delete(); } @@ -672,10 +638,9 @@ private GroovyPageMetaInfo createPageMetaInfo(GroovyPageParser parse, InputStrea /** * Establishes the name to use for the given resource * - * @param res The Resource to calculate the name for + * @param res The Resource to calculate the name for * @param pageName The name of the page, can be null, in which case method responsible for calculation - * - * @return The name as a String + * @return The name as a String */ protected String establishPageName(Resource res, String pageName) { if (res == null) { @@ -686,13 +651,13 @@ protected String establishPageName(Resource res, String pageName) { String name = pageName != null ? pageName : res.getURL().getPath(); // As the name take the first / off and then replace all characters that aren't // a word character or a digit with an underscore - if (name.startsWith("/")) name = name.substring(1); + if (name.startsWith("/")) { + name = name.substring(1); + } return name.replaceAll("[^\\w\\d]", "_"); - } - catch (IllegalStateException e) { + } catch (IllegalStateException e) { return generateTemplateName(); - } - catch (IOException ioex) { + } catch (IOException ioex) { return generateTemplateName(); } } @@ -733,10 +698,9 @@ protected String getUriWithinGrailsViews(String relativeUri) { relativeUri = relativeUri.substring(1); } - if (relativeUri.indexOf('/')>-1) { + if (relativeUri.indexOf('/') > -1) { tokens = relativeUri.split("/"); - } - else { + } else { tokens = new String[]{relativeUri}; } @@ -754,10 +718,10 @@ protected String getUriWithinGrailsViews(String relativeUri) { * Clears the page cache. Views will be re-compiled. */ public void clearPageCache() { - for(Iterator>> it = pageCache.entrySet().iterator(); it.hasNext(); ) { + for (Iterator>> it = pageCache.entrySet().iterator(); it.hasNext(); ) { Map.Entry> entry = it.next(); GroovyPageMetaInfo metaInfo = entry.getValue().getValue(); - if(metaInfo != null) { + if (metaInfo != null) { metaInfo.removePageMetaClass(); } it.remove(); @@ -782,7 +746,7 @@ public Map> getDomainClassMap() { /** * The domainClassMap is used in GSP binding to "auto-import" domain classes in packages without package prefix. * real imports aren't used, instead each class is added to the binding - * + *

    * This feature has existed earlier, the code has just been refactored and moved to GroovyPagesTemplateEngine * to prevent using the static cache that was used previously. */ @@ -802,7 +766,7 @@ private Map> createDomainClassMap() { public void setBeanClassLoader(ClassLoader beanClassLoader) { // support passing BeanClassLoader as parent classloader for templates // don't set the classLoader field if it already has an explicit value - if(beanClassLoader != null && this.classLoader == null) { + if (beanClassLoader != null && this.classLoader == null) { this.classLoader = beanClassLoader; } } @@ -810,4 +774,45 @@ public void setBeanClassLoader(ClassLoader beanClassLoader) { public String getGspEncoding() { return this.gspEncoding; } + + private class GroovyPagesTemplateEngineCacheEntry extends CacheEntry { + + private final String pageName; + + public GroovyPagesTemplateEngineCacheEntry(String pageName) { + this.pageName = pageName; + } + + @Override + protected boolean hasExpired(long timeout, Object cacheRequestObject) { + GroovyPageMetaInfo meta = getValue(); + Resource resource = (Resource) cacheRequestObject; + return meta == null || isGroovyPageReloadable(resource, meta); + } + + @Override + protected GroovyPageMetaInfo updateValue(GroovyPageMetaInfo oldValue, Callable updater, Object cacheRequestObject) + throws Exception { + if (oldValue != null) { + oldValue.removePageMetaClass(); + } + Resource resource = (Resource) cacheRequestObject; + return buildPageMetaInfo(resource, pageName); + } + } + + private static class GroovyPagesTemplateEngineCallable implements Callable> { + + private final CacheEntry cacheEntry; + + public GroovyPagesTemplateEngineCallable(CacheEntry cacheEntry) { + this.cacheEntry = cacheEntry; + } + + @Override + public CacheEntry call() throws Exception { + return cacheEntry; + } + + } } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/ModelRecordingGroovyPage.groovy b/grails-gsp/core/src/main/groovy/org/grails/gsp/ModelRecordingGroovyPage.groovy index 2194a9c4c26..05b3fce58af 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/ModelRecordingGroovyPage.groovy +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/ModelRecordingGroovyPage.groovy @@ -41,6 +41,7 @@ import java.util.concurrent.ConcurrentHashMap */ @CompileStatic abstract class ModelRecordingGroovyPage extends GroovyPage { + public static final String CONFIG_SYSTEM_PROPERTY_NAME public static final boolean ENABLED static { @@ -100,6 +101,7 @@ abstract class ModelRecordingGroovyPage extends GroovyPage { @CompileStatic class ModelRecordingCache { + private Map models = new ConcurrentHashMap<>() private boolean initialized @@ -183,7 +185,7 @@ class ModelEntry { model.each { String fieldName, String fieldType -> String cleanedFieldType = fieldType - ~/^java\.(util|lang)\./ String defaultType = DEFAULT_TYPES.get(fieldName) - if(defaultType) { + if (defaultType) { try { // use default field type for if field type is instance of the class // for example instance of 'org.apache.catalina.core.ApplicationHttpRequest', use 'jakarta.servlet.http.HttpServletRequest' diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/ResourceAwareTemplateEngine.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/ResourceAwareTemplateEngine.java index c2e694e368d..0d0e9cfd338 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/ResourceAwareTemplateEngine.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/ResourceAwareTemplateEngine.java @@ -26,7 +26,14 @@ import org.grails.buffer.StreamByteBuffer; import org.springframework.core.io.Resource; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; import java.net.URL; /** @@ -37,6 +44,7 @@ * @since 0.4 */ public abstract class ResourceAwareTemplateEngine extends TemplateEngine { + public static final String BEAN_ID = "groovyPagesTemplateEngine"; private static final String GROOVY_SOURCE_CHAR_ENCODING = "UTF-8"; @@ -45,7 +53,7 @@ public abstract class ResourceAwareTemplateEngine extends TemplateEngine { * * @param resource The Spring Resource to create the template for * @return A Template instance - * @throws IOException Thrown when there was an error reading the Template + * @throws IOException Thrown when there was an error reading the Template * @throws ClassNotFoundException Thrown when there was a problem loading the Template into a class */ public Template createTemplate(Resource resource) throws IOException, ClassNotFoundException { @@ -55,7 +63,7 @@ public Template createTemplate(Resource resource) throws IOException, ClassNotFo /** * Creates the specified Template using the given Spring Resource * - * @param resource The Spring Resource to create the template for + * @param resource The Spring Resource to create the template for * @param cacheable Whether the resource can be cached * @return A Template instance * @@ -64,7 +72,7 @@ public Template createTemplate(Resource resource) throws IOException, ClassNotFo @Override public final Template createTemplate(Reader reader) throws IOException { - StreamByteBuffer buf=new StreamByteBuffer(); + StreamByteBuffer buf = new StreamByteBuffer(); IOUtils.copy(reader, new OutputStreamWriter(buf.getOutputStream(), GROOVY_SOURCE_CHAR_ENCODING)); return createTemplate(buf.getInputStream()); } @@ -101,8 +109,8 @@ private Template createTemplateAndCloseInput(InputStream input) throws FileNotFo DefaultGroovyMethodsSupport.closeWithWarning(input); } } - - abstract public Template createTemplateForUri(String[] uris); - - abstract public int mapStackLineNumber(String url, int lineNumber); + + public abstract Template createTemplateForUri(String[] uris); + + public abstract int mapStackLineNumber(String url, int lineNumber); } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GSPWriter.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GSPWriter.java index 817e2dae3fc..f7c30b0a1e1 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GSPWriter.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GSPWriter.java @@ -45,7 +45,7 @@ public GSPWriter(Writer out, GroovyPageParser parse) { } @Override - public void write(char buf[], int off, int len) { + public void write(char[] buf, int off, int len) { super.write(buf, off, len); } @@ -67,8 +67,10 @@ public void printlnToResponse(String outVarName, String s) { } public void printlnToBuffer(String s, int index) { - if (s == null) s = "''"; - super.print("buf"+index+" << "); + if (s == null) { + s = "''"; + } + super.print("buf" + index + " << "); super.print(s); println(); } @@ -81,21 +83,20 @@ public void println() { private void addLineNumber() { if (lineNumber >= lineNumbers.length) { - lineNumbers = (int[])resizeArray(lineNumbers, lineNumbers.length * 2); - } - else { + lineNumbers = (int[]) resizeArray(lineNumbers, lineNumbers.length * 2); + } else { lineNumbers[lineNumber - 1] = parse.getCurrentOutputLineNumber(); lineNumber++; } } - private Object resizeArray (Object oldArray, int newSize) { + private Object resizeArray(Object oldArray, int newSize) { int oldSize = java.lang.reflect.Array.getLength(oldArray); Class elementType = oldArray.getClass().getComponentType(); - Object newArray = Array.newInstance(elementType,newSize); - int preserveLength = Math.min(oldSize,newSize); + Object newArray = Array.newInstance(elementType, newSize); + int preserveLength = Math.min(oldSize, newSize); if (preserveLength > 0) { - System.arraycopy (oldArray,0,newArray,0,preserveLength); + System.arraycopy(oldArray, 0, newArray, 0, preserveLength); } return newArray; } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GrailsLayoutPreprocessor.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GrailsLayoutPreprocessor.java index 0592aa1ec4c..02b80ad5414 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GrailsLayoutPreprocessor.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GrailsLayoutPreprocessor.java @@ -32,13 +32,13 @@ */ public class GrailsLayoutPreprocessor { + public static final String XML_CLOSING_FOR_EMPTY_TAG_ATTRIBUTE_NAME = "gsp_sm_xmlClosingForEmptyTag"; Pattern parameterPattern = Pattern.compile("]+?)(/*?)>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); Pattern metaPattern = Pattern.compile("]+?)(/*?)>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); Pattern titlePattern = Pattern.compile("]*)?>(.*?)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); Pattern headPattern = Pattern.compile("]*)?>(.*?)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); Pattern bodyPattern = Pattern.compile("]*)?>(.*?)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); Pattern contentPattern = Pattern.compile("]+)>(.*?)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); - public static final String XML_CLOSING_FOR_EMPTY_TAG_ATTRIBUTE_NAME = "gsp_sm_xmlClosingForEmptyTag"; public String addGspGrailsLayoutCapturing(String gspSource) { StringBuffer sb = addHeadCapturing(gspSource); diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageCompiler.groovy b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageCompiler.groovy index dbc947bb125..31ad0552a32 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageCompiler.groovy +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageCompiler.groovy @@ -19,8 +19,9 @@ package org.grails.gsp.compiler import grails.config.ConfigMap -import org.apache.commons.logging.LogFactory +import groovy.transform.CompileStatic import org.apache.commons.logging.Log +import org.apache.commons.logging.LogFactory import org.apache.grails.common.properties.PropertyFileUtils import org.codehaus.groovy.control.CompilationUnit import org.codehaus.groovy.control.CompilerConfiguration @@ -29,14 +30,14 @@ import org.grails.config.CodeGenConfig import org.grails.gsp.GroovyPageMetaInfo import org.grails.gsp.compiler.transform.GroovyPageInjectionOperation import org.grails.taglib.encoder.OutputEncodingSettings -import groovy.transform.CompileStatic + import java.util.concurrent.Callable -import java.util.concurrent.Executors -import java.util.concurrent.ExecutorService -import java.util.concurrent.TimeUnit -import java.util.concurrent.ExecutorCompletionService import java.util.concurrent.CompletionService +import java.util.concurrent.ExecutorCompletionService +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors import java.util.concurrent.Future +import java.util.concurrent.TimeUnit /** * Used to compile GSP files into a specified target directory. @@ -78,25 +79,24 @@ class GroovyPageCompiler { } /** - * Compiles the given GSP pages and returns a Map of URI to classname mappings - */ + * Compiles the given GSP pages and returns a Map of URI to classname mappings + */ Map compile() { if (srcFiles && targetDir && viewsDir) { if (!generatedGroovyPagesDirectory) { - generatedGroovyPagesDirectory = new File(System.getProperty("java.io.tmpdir"),"gspcompile") + generatedGroovyPagesDirectory = new File(System.getProperty("java.io.tmpdir"), "gspcompile") generatedGroovyPagesDirectory.mkdirs() } - if(configs) { + if (configs) { CodeGenConfig codeGenConfig = new CodeGenConfig() codeGenConfig.classLoader = classLoader configMap = codeGenConfig - for(path in configs) { + for (path in configs) { def f = new File(path) - if(f.exists()) { - if(f.name.endsWith('.yml')) { + if (f.exists()) { + if (f.name.endsWith('.yml')) { codeGenConfig.loadYml(f) - } - else if(f.name.endsWith('.groovy')) { + } else if (f.name.endsWith('.groovy')) { codeGenConfig.loadGroovy(f) } } @@ -104,35 +104,35 @@ class GroovyPageCompiler { } compilerConfig.setTargetDirectory(targetDir) compilerConfig.setSourceEncoding(encoding) - ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*2) + ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2) CompletionService completionService = new ExecutorCompletionService(threadPool); List> futures = [] try { - Integer collationLevel = Runtime.getRuntime().availableProcessors()*2 - if(srcFiles.size() < collationLevel) { + Integer collationLevel = Runtime.getRuntime().availableProcessors() * 2 + if (srcFiles.size() < collationLevel) { collationLevel = 1 } def collatedSrcFiles = srcFiles.collate(collationLevel) - for(int index = 0; index < collatedSrcFiles.size(); index++) { + for (int index = 0; index < collatedSrcFiles.size(); index++) { def gspFiles = collatedSrcFiles[index] - + futures.add(completionService.submit({ -> def results = [:] - for(int gspIndex = 0; gspIndex < gspFiles.size(); gspIndex++) { + for (int gspIndex = 0; gspIndex < gspFiles.size(); gspIndex++) { File gsp = gspFiles[gspIndex] try { - compileGSP(viewsDir, gsp, viewPrefix, packagePrefix, results) - } catch(Exception ex) { + compileGSP(viewsDir, gsp, viewPrefix, packagePrefix, results) + } catch (Exception ex) { LOG.error("Error Compiling GSP File: ${gsp.name} - ${ex.message}") throw ex } } - return results + return results } as Callable) as Future) } int pending = futures.size() - + while (pending > 0) { // Wait for up to 100ms to see if anything has completed. // The completed future is returned if one is found; otherwise null. @@ -190,18 +190,17 @@ class GroovyPageCompiler { } packageDir += generateJavaName(relPackagePath) } - String className = generateJavaName(packageDir.replace('/','_')) + String className = generateJavaName(packageDir.replace('/', '_')) className += generateJavaName(gspfile.name) // using default package because of GRAILS-5022 packageDir = '' File classFile = new File(new File(targetDir, packageDir), "${className}.class") - String packageName = packageDir.replace('/','.') + String packageName = packageDir.replace('/', '.') String fullClassName if (packageName) { fullClassName = packageName + '.' + className - } - else { + } else { fullClassName = className } @@ -219,11 +218,11 @@ class GroovyPageCompiler { gpp.generateGsp(gsptarget) gsptarget.flush() // write static html parts to data file (read from classpath at runtime) - File htmlDataFile = new File(new File(targetDir, packageDir), className + GroovyPageMetaInfo.HTML_DATA_POSTFIX) + File htmlDataFile = new File(new File(targetDir, packageDir), className + GroovyPageMetaInfo.HTML_DATA_POSTFIX) htmlDataFile.parentFile.mkdirs() gpp.writeHtmlParts(htmlDataFile) // write linenumber mapping info to data file - File lineNumbersDataFile = new File(new File(targetDir, packageDir), className + GroovyPageMetaInfo.LINENUMBERS_DATA_POSTFIX) + File lineNumbersDataFile = new File(new File(targetDir, packageDir), className + GroovyPageMetaInfo.LINENUMBERS_DATA_POSTFIX) gpp.writeLineNumbers(lineNumbersDataFile) // register viewuri -> classname mapping @@ -231,17 +230,16 @@ class GroovyPageCompiler { CompilationUnit unit = new CompilationUnit(compilerConfig, null, classLoader) unit.addPhaseOperation(operation, Phases.CANONICALIZATION) - unit.addSource(gspgroovyfile.name,gsptarget.toString()) + unit.addSource(gspgroovyfile.name, gsptarget.toString()) // unit.addSource(gspgroovyfile) unit.compile() } - } - else { - compileGSPResults[viewuri] = fullClassName + } else { + compileGSPResults[viewuri] = fullClassName } return compileGSPResults - + } // find out the relative path from relbase to file @@ -262,11 +260,10 @@ class GroovyPageCompiler { char ch while (i < str.length()) { ch = str.charAt(i++) - if (ch=='/') { + if (ch == '/') { nextMustBeStartChar = true sb.append(ch) - } - else { + } else { // package or class name cannot start with a number if (nextMustBeStartChar && !Character.isJavaIdentifierStart(ch)) { sb.append('_') diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageExpressionParser.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageExpressionParser.java index dfbb353caf3..ca00249b134 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageExpressionParser.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageExpressionParser.java @@ -22,26 +22,28 @@ /** * Parses an expression in a GSP. - * + *

    * Used by GroovyPageScanner and GroovyPageParser to search for the end of an expression. * * @author Lari Hotari */ class GroovyPageExpressionParser { + private static enum ParsingState { NORMAL, EXPRESSION, QUOTEDVALUE_SINGLE, QUOTEDVALUE_DOUBLE, TRIPLEQUOTED_SINGLE, TRIPLEQUOTED_DOUBLE; } + String scriptTokens; int startPos; char terminationChar; char nextTerminationChar; Stack parsingStateStack = new Stack(); - boolean containsGstrings=false; + boolean containsGstrings = false; int terminationCharPos = -1; - int relativeCharIndex=0; + int relativeCharIndex = 0; public GroovyPageExpressionParser(String scriptTokens, int startPos, char terminationChar, - char nextTerminationChar, boolean startInExpression) { + char nextTerminationChar, boolean startInExpression) { this.scriptTokens = scriptTokens; this.startPos = startPos; this.terminationChar = terminationChar; @@ -63,58 +65,60 @@ int parse() { char previousChar = 0; char previousPreviousChar = 0; - while(currentPos < scriptTokens.length() && terminationCharPos==-1) { + while (currentPos < scriptTokens.length() && terminationCharPos == -1) { ParsingState parsingState = parsingStateStack.peek(); char ch = scriptTokens.charAt(currentPos++); char nextChar = (currentPos < scriptTokens.length()) ? scriptTokens.charAt(currentPos) : 0; - if (parsingStateStack.size()==1 && ch==terminationChar && (nextTerminationChar==0 || nextTerminationChar==nextChar)) { - terminationCharPos = currentPos-1; - } else if (parsingState==ParsingState.EXPRESSION || parsingState==ParsingState.NORMAL) { - switch(ch) { + if (parsingStateStack.size() == 1 && ch == terminationChar && (nextTerminationChar == 0 || nextTerminationChar == nextChar)) { + terminationCharPos = currentPos - 1; + } else if (parsingState == ParsingState.EXPRESSION || parsingState == ParsingState.NORMAL) { + switch (ch) { case '{': - if (previousChar=='$' && parsingState==ParsingState.EXPRESSION) { + if (previousChar == '$' && parsingState == ParsingState.EXPRESSION) { // invalid expression, starting new ${} expression inside expression return -1; } - if (previousChar=='$' || parsingState==ParsingState.EXPRESSION) { + if (previousChar == '$' || parsingState == ParsingState.EXPRESSION) { changeState(ParsingState.EXPRESSION); } break; case '[': - if (relativeCharIndex==0 || parsingState==ParsingState.EXPRESSION) { + if (relativeCharIndex == 0 || parsingState == ParsingState.EXPRESSION) { changeState(ParsingState.EXPRESSION); } break; case '}': case ']': - if (parsingState==ParsingState.EXPRESSION) { + if (parsingState == ParsingState.EXPRESSION) { parsingStateStack.pop(); } break; case '\'': case '"': - if (parsingState==ParsingState.EXPRESSION) { + if (parsingState == ParsingState.EXPRESSION) { if (nextChar != ch && previousChar != ch) { - changeState(ch=='"' ? ParsingState.QUOTEDVALUE_DOUBLE : ParsingState.QUOTEDVALUE_SINGLE); - } else if (previousChar==ch && previousPreviousChar==ch) { - changeState(ch=='"' ? ParsingState.TRIPLEQUOTED_DOUBLE : ParsingState.TRIPLEQUOTED_SINGLE); + changeState(ch == '"' ? ParsingState.QUOTEDVALUE_DOUBLE : ParsingState.QUOTEDVALUE_SINGLE); + } else if (previousChar == ch && previousPreviousChar == ch) { + changeState(ch == '"' ? ParsingState.TRIPLEQUOTED_DOUBLE : ParsingState.TRIPLEQUOTED_SINGLE); } } break; + default: + // do nothing + break; } - } else if (ch=='"' || ch=='\'') { - if (nextChar != ch && (previousChar != ch || previousPreviousChar=='\\') && (previousChar != '\\' || (previousChar=='\\' && previousPreviousChar=='\\')) + } else if (ch == '"' || ch == '\'') { + if (nextChar != ch && (previousChar != ch || previousPreviousChar == '\\') && (previousChar != '\\' || (previousChar == '\\' && previousPreviousChar == '\\')) && ((parsingState == ParsingState.QUOTEDVALUE_DOUBLE && ch == '"') || (parsingState == ParsingState.QUOTEDVALUE_SINGLE && ch == '\''))) { parsingStateStack.pop(); - } - else if ((previousChar == ch && previousPreviousChar == ch) + } else if ((previousChar == ch && previousPreviousChar == ch) && ((parsingState == ParsingState.TRIPLEQUOTED_DOUBLE && ch == '"') || (parsingState == ParsingState.TRIPLEQUOTED_SINGLE && ch == '\''))) { parsingStateStack.pop(); } } previousPreviousChar = previousChar; - previousChar=ch; + previousChar = ch; relativeCharIndex++; } return terminationCharPos; @@ -123,8 +127,8 @@ else if ((previousChar == ch && previousPreviousChar == ch) private void changeState(ParsingState newState) { ParsingState currentState = parsingStateStack.peek(); // check if expression contains GStrings - if (relativeCharIndex > 1 && newState==ParsingState.EXPRESSION && (currentState==ParsingState.QUOTEDVALUE_DOUBLE || currentState==ParsingState.TRIPLEQUOTED_DOUBLE || currentState==ParsingState.NORMAL)) { - containsGstrings=true; + if (relativeCharIndex > 1 && newState == ParsingState.EXPRESSION && (currentState == ParsingState.QUOTEDVALUE_DOUBLE || currentState == ParsingState.TRIPLEQUOTED_DOUBLE || currentState == ParsingState.NORMAL)) { + containsGstrings = true; } parsingStateStack.push(newState); } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageParser.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageParser.java index 20c29cdb51f..bc0b1067d49 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageParser.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageParser.java @@ -22,8 +22,6 @@ import grails.io.IOUtils; import grails.util.Environment; import grails.util.GrailsStringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.grails.buffer.FastStringWriter; import org.grails.buffer.StreamByteBuffer; @@ -36,9 +34,30 @@ import org.grails.io.support.SpringIOUtils; import org.grails.taglib.GrailsTagException; import org.grails.taglib.encoder.OutputEncodingSettings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.io.*; -import java.util.*; +import java.io.BufferedOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Stack; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -53,6 +72,39 @@ */ public class GroovyPageParser implements Tokens { + public static final String CONSTANT_NAME_JSP_TAGS = "JSP_TAGS"; + public static final String CONSTANT_NAME_CONTENT_TYPE = "CONTENT_TYPE"; + public static final String CONSTANT_NAME_LAST_MODIFIED = "LAST_MODIFIED"; + public static final String CONSTANT_NAME_EXPRESSION_CODEC = "EXPRESSION_CODEC"; + public static final String CONSTANT_NAME_STATIC_CODEC = "STATIC_CODEC"; + public static final String CONSTANT_NAME_OUT_CODEC = "OUT_CODEC"; + public static final String CONSTANT_NAME_TAGLIB_CODEC = "TAGLIB_CODEC"; + public static final String CONSTANT_NAME_COMPILE_STATIC_MODE = "COMPILE_STATIC_MODE"; + public static final String CONSTANT_NAME_MODEL_FIELDS_MODE = "MODEL_FIELDS_MODE"; + public static final String DEFAULT_ENCODING = "UTF-8"; + public static final String MODEL_DIRECTIVE = "model"; + public static final String COMPILE_STATIC_DIRECTIVE = "compileStatic"; + public static final String TAGLIBS_DIRECTIVE = "taglibs"; + public static final List DEFAULT_TAGLIB_NAMESPACES = Collections.unmodifiableList(Arrays.asList(new String[]{"g", "tmpl", "f", "asset", "plugin"})); + public static final String[] DEFAULT_IMPORTS = { + "grails.plugins.metadata.GrailsPlugin", + "org.grails.gsp.compiler.transform.LineNumber", + "org.grails.gsp.GroovyPage", + "org.grails.web.taglib.*", + "org.grails.taglib.GrailsTagException", + "org.springframework.web.util.*", + "grails.util.GrailsUtil" + }; + public static final String CONFIG_PROPERTY_DEFAULT_CODEC = "grails.views.default.codec"; + public static final String CONFIG_PROPERTY_GSP_ENCODING = "grails.views.gsp.encoding"; + public static final String CONFIG_PROPERTY_GSP_KEEPGENERATED_DIR = "grails.views.gsp.keepgenerateddir"; + public static final String CONFIG_PROPERTY_GSP_GRAILS_LAYOUT_PREPROCESS = "grails.views.gsp.layout.preprocess"; + public static final String CONFIG_PROPERTY_GSP_COMPILESTATIC = "grails.views.gsp.compileStatic"; + public static final String CONFIG_PROPERTY_GSP_ALLOWED_TAGLIB_NAMESPACES = "grails.views.gsp.compileStaticConfig.taglibs"; + public static final String CONFIG_PROPERTY_GSP_CODECS = "grails.views.gsp.codecs"; + public static final String CODEC_DIRECTIVE_POSTFIX = "Codec"; + public static final String GROOVY_SOURCE_CHAR_ENCODING = "UTF-8"; + private static final Logger LOG = LoggerFactory.getLogger(GroovyPageParser.class); private static final Pattern PARA_BREAK = Pattern.compile( @@ -72,23 +124,22 @@ public class GroovyPageParser implements Tokens { private static final Pattern NON_WHITESPACE_PATTERN = Pattern.compile("\\S"); private static final Pattern IMPORT_SEMICOLON_PATTERN = Pattern.compile(";"); - public static final String CONSTANT_NAME_JSP_TAGS = "JSP_TAGS"; - public static final String CONSTANT_NAME_CONTENT_TYPE = "CONTENT_TYPE"; - public static final String CONSTANT_NAME_LAST_MODIFIED = "LAST_MODIFIED"; - public static final String CONSTANT_NAME_EXPRESSION_CODEC = "EXPRESSION_CODEC"; - public static final String CONSTANT_NAME_STATIC_CODEC = "STATIC_CODEC"; - public static final String CONSTANT_NAME_OUT_CODEC = "OUT_CODEC"; - public static final String CONSTANT_NAME_TAGLIB_CODEC = "TAGLIB_CODEC"; - public static final String CONSTANT_NAME_COMPILE_STATIC_MODE = "COMPILE_STATIC_MODE"; - public static final String CONSTANT_NAME_MODEL_FIELDS_MODE = "MODEL_FIELDS_MODE"; - public static final String DEFAULT_ENCODING = "UTF-8"; - private static final String MULTILINE_GROOVY_STRING_DOUBLEQUOTES = "\"\"\""; private static final String MULTILINE_GROOVY_STRING_SINGLEQUOTES = "'''"; - public static final String MODEL_DIRECTIVE = "model"; - public static final String COMPILE_STATIC_DIRECTIVE = "compileStatic"; - public static final String TAGLIBS_DIRECTIVE = "taglibs"; - public static final List DEFAULT_TAGLIB_NAMESPACES = Collections.unmodifiableList(Arrays.asList(new String[]{"g", "tmpl", "f", "asset", "plugin"})); + private static final String DEFAULT_CONTENT_TYPE = "text/html;charset=UTF-8"; + private static final String IMPORT_DIRECTIVE = "import"; + private static final String CONTENT_TYPE_DIRECTIVE = "contentType"; + private static final String EXPRESSION_CODEC_DIRECTIVE = OutputEncodingSettings.EXPRESSION_CODEC_NAME + CODEC_DIRECTIVE_POSTFIX; + private static final String EXPRESSION_CODEC_DIRECTIVE_ALIAS = "default" + CODEC_DIRECTIVE_POSTFIX; + private static final String STATIC_CODEC_DIRECTIVE = OutputEncodingSettings.STATIC_CODEC_NAME + CODEC_DIRECTIVE_POSTFIX; + private static final String OUT_CODEC_DIRECTIVE = OutputEncodingSettings.OUT_CODEC_NAME + CODEC_DIRECTIVE_POSTFIX; + private static final String TAGLIB_CODEC_DIRECTIVE = OutputEncodingSettings.TAGLIB_CODEC_NAME + CODEC_DIRECTIVE_POSTFIX; + private static final String GRAILS_LAYOUT_PREPROCESS_DIRECTIVE = "grailsLayoutPreprocess"; + private static GrailsLayoutPreprocessor grailsLayoutPreprocessor = new GrailsLayoutPreprocessor(); + + Set bodyVarsDefined = new HashSet(); + Map attrsVarsMapDefinition = new HashMap(); + int closureLevel = 0; private GroovyPageScanner scan; private GSPWriter out; @@ -102,12 +153,6 @@ public class GroovyPageParser implements Tokens { private GrailsTagRegistry tagRegistry = GrailsTagRegistry.getInstance(); private Environment environment; private List htmlParts = new ArrayList(); - private static GrailsLayoutPreprocessor grailsLayoutPreprocessor = new GrailsLayoutPreprocessor(); - - Set bodyVarsDefined = new HashSet(); - Map attrsVarsMapDefinition = new HashMap(); - - int closureLevel = 0; /* * Set to true when whitespace is currently being saved for later output if @@ -122,44 +167,14 @@ public class GroovyPageParser implements Tokens { private boolean previousContentWasNonWhitespace; private StringBuffer whitespaceBuffer = new StringBuffer(); - private String contentType = DEFAULT_CONTENT_TYPE; private boolean doNextScan = true; private int state; - private static final String DEFAULT_CONTENT_TYPE = "text/html;charset=UTF-8"; private int constantCount = 0; private Map constantsToNumbers = new HashMap(); - private final String pageName; - public static final String[] DEFAULT_IMPORTS = { - "grails.plugins.metadata.GrailsPlugin", - "org.grails.gsp.compiler.transform.LineNumber", - "org.grails.gsp.GroovyPage", - "org.grails.web.taglib.*", - "org.grails.taglib.GrailsTagException", - "org.springframework.web.util.*", - "grails.util.GrailsUtil" - }; - public static final String CONFIG_PROPERTY_DEFAULT_CODEC = "grails.views.default.codec"; - public static final String CONFIG_PROPERTY_GSP_ENCODING = "grails.views.gsp.encoding"; - public static final String CONFIG_PROPERTY_GSP_KEEPGENERATED_DIR = "grails.views.gsp.keepgenerateddir"; - public static final String CONFIG_PROPERTY_GSP_GRAILS_LAYOUT_PREPROCESS = "grails.views.gsp.layout.preprocess"; - public static final String CONFIG_PROPERTY_GSP_COMPILESTATIC = "grails.views.gsp.compileStatic"; - public static final String CONFIG_PROPERTY_GSP_ALLOWED_TAGLIB_NAMESPACES = "grails.views.gsp.compileStaticConfig.taglibs"; - public static final String CONFIG_PROPERTY_GSP_CODECS = "grails.views.gsp.codecs"; - - private static final String IMPORT_DIRECTIVE = "import"; - private static final String CONTENT_TYPE_DIRECTIVE = "contentType"; - public static final String CODEC_DIRECTIVE_POSTFIX = "Codec"; - private static final String EXPRESSION_CODEC_DIRECTIVE = OutputEncodingSettings.EXPRESSION_CODEC_NAME + CODEC_DIRECTIVE_POSTFIX; - private static final String EXPRESSION_CODEC_DIRECTIVE_ALIAS = "default" + CODEC_DIRECTIVE_POSTFIX; - private static final String STATIC_CODEC_DIRECTIVE = OutputEncodingSettings.STATIC_CODEC_NAME + CODEC_DIRECTIVE_POSTFIX; - private static final String OUT_CODEC_DIRECTIVE = OutputEncodingSettings.OUT_CODEC_NAME + CODEC_DIRECTIVE_POSTFIX; - private static final String TAGLIB_CODEC_DIRECTIVE = OutputEncodingSettings.TAGLIB_CODEC_NAME + CODEC_DIRECTIVE_POSTFIX; - private static final String GRAILS_LAYOUT_PREPROCESS_DIRECTIVE = "grailsLayoutPreprocess"; private String pluginAnnotation; - public static final String GROOVY_SOURCE_CHAR_ENCODING = "UTF-8"; private Map jspTags = new HashMap(); private long lastModified; private boolean precompileMode; @@ -176,44 +191,6 @@ public class GroovyPageParser implements Tokens { private File keepGeneratedDirectory; private Set allowedTaglibNamespaces = new LinkedHashSet<>(DEFAULT_TAGLIB_NAMESPACES); - public String getContentType() { - return contentType; - } - - public int getCurrentOutputLineNumber() { - return scan.getLineNumberForToken(); - } - - public Map getJspTags() { - return jspTags; - } - - public void setKeepGeneratedDirectory(File keepGeneratedDirectory) { - this.keepGeneratedDirectory = keepGeneratedDirectory; - } - - public void setEnableGrailsLayoutProcessing(boolean enableGrailsLayoutProcessing) { - this.enableGrailsLayoutProcessing = enableGrailsLayoutProcessing; - } - - class TagMeta { - String name; - String namespace; - Object instance; - boolean isDynamic; - boolean hasAttributes; - int lineNumber; - boolean emptyTag; - int tagIndex; - boolean bufferMode = false; - int bufferPartNumber = -1; - - @Override - public String toString() { - return "<" + namespace + ":" + name + ">"; - } - } - public GroovyPageParser(String name, String uri, String filename, InputStream in, String encoding, String expressionCodecName, ConfigMap configMap) throws IOException { this(name, uri, filename, readStream(in, encoding), expressionCodecName, configMap); } @@ -249,6 +226,26 @@ public GroovyPageParser(String name, String uri, String filename, String gspSour makeSourceName(filename); } + public String getContentType() { + return contentType; + } + + public int getCurrentOutputLineNumber() { + return scan.getLineNumberForToken(); + } + + public Map getJspTags() { + return jspTags; + } + + public void setKeepGeneratedDirectory(File keepGeneratedDirectory) { + this.keepGeneratedDirectory = keepGeneratedDirectory; + } + + public void setEnableGrailsLayoutProcessing(boolean enableGrailsLayoutProcessing) { + this.enableGrailsLayoutProcessing = enableGrailsLayoutProcessing; + } + /** * Configures the parser for the given Config map * @@ -547,7 +544,9 @@ private void scriptletExpr() { } private void expr() { - if (!finalPass) return; + if (!finalPass) { + return; + } String text = scan.getToken().trim(); text = getExpressionText(text); @@ -568,23 +567,23 @@ public String getExpressionText(String text) { return getExpressionText(text, true); } - public String getExpressionText(String text, boolean _safeDereference) { - boolean safeDereference = false; + public String getExpressionText(String text, boolean safeDereference) { + boolean determinedSafeDereference = false; if (text.endsWith("?")) { text = text.substring(0, text.length() - 1); - safeDereference = _safeDereference; + determinedSafeDereference = safeDereference; } if (!precompileMode && !isCompileStaticMode() && (environment == Environment.DEVELOPMENT || environment == Environment.TEST)) { String escaped = escapeGroovy(text); text = "evaluate('" + escaped + "', " + getCurrentOutputLineNumber() + ", it) { return " + text + - " }" + (safeDereference ? "?" : ""); + " }" + (determinedSafeDereference ? "?" : ""); } else { // add extra parenthesis, see http://jira.codehaus.org/browse/GRAILS-4351 // or GroovyPagesTemplateEngineTests.testForEachInProductionMode - text = "(" + text + ")" + (safeDereference ? "?" : ""); + text = "(" + text + ")" + (determinedSafeDereference ? "?" : ""); } return text; } @@ -641,9 +640,10 @@ public void flushTagBuffering() { } } - private void html() { - if (!finalPass) return; + if (!finalPass) { + return; + } String text = scan.getToken(); if (text.length() == 0) { @@ -849,6 +849,9 @@ private void page() { case GEND_TAG: endTag(); break; + default: + // do nothing + break; } } @@ -985,15 +988,18 @@ private int[] filterTrailing0s(int[] lineNumbers) { } private void endTag() { - if (!finalPass) return; + if (!finalPass) { + return; + } String tagName = scan.getToken().trim(); String ns = scan.getNamespace(); - if (tagMetaStack.isEmpty()) + if (tagMetaStack.isEmpty()) { throw new GrailsTagException( "Found closing Grails tag with no opening [" + tagName + "]", pageName, getCurrentOutputLineNumber()); + } TagMeta tm = tagMetaStack.pop(); String lastInStack = tm.name; @@ -1067,7 +1073,9 @@ private void endTag() { @SuppressWarnings({"unchecked", "rawtypes"}) private void startTag() { - if (!finalPass) return; + if (!finalPass) { + return; + } tagIndex++; @@ -1288,7 +1296,9 @@ public static String getGspEncoding() { private void script(boolean gsp) { flushTagBuffering(); - if (!finalPass) return; + if (!finalPass) { + return; + } out.println(); write(scan.getToken().trim(), gsp); @@ -1335,8 +1345,9 @@ private void write(CharSequence text, boolean gsp) { ix += 3; } else { int end = match(PARA_BREAK, text, ix); - if (end <= 0) + if (end <= 0) { end = match(ROW_BREAK, text, ix); + } if (end > 0) { rep = "\n"; //incrementLineNumber(); @@ -1415,4 +1426,23 @@ public boolean isCompileStaticMode() { public boolean isModelFieldsMode() { return modelFieldsMode; } + + static class TagMeta { + + String name; + String namespace; + Object instance; + boolean isDynamic; + boolean hasAttributes; + int lineNumber; + boolean emptyTag; + int tagIndex; + boolean bufferMode = false; + int bufferPartNumber = -1; + + @Override + public String toString() { + return "<" + namespace + ":" + name + ">"; + } + } } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageScanner.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageScanner.java index 2eddf936b34..ae90d34afe8 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageScanner.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageScanner.java @@ -26,15 +26,16 @@ /** * NOTE: Based on work done by on the GSP standalone project (https://gsp.dev.java.net/) - * + *

    * Lexer for GroovyPagesServlet. * * @author Troy Heninger * @author Graeme Rocher - * + *

    * Date: Jan 10, 2004 */ class GroovyPageScanner implements Tokens { + private static final int DEFAULT_MAX_HTML_LENGTH = 64000; private String text; private int end1; @@ -79,7 +80,8 @@ private void resolveLineNumberPositions() { private int found(int newState, int skip) { begin2 = begin1; end2 = --end1; - begin1 = end1 += skip; + end1 += skip; + begin1 = end1; int lastState = state; state = newState; return lastState; @@ -88,7 +90,8 @@ private int found(int newState, int skip) { private int foundStartOrEndTag(int newState, int skip, String namespace) { begin2 = begin1; end2 = --end1; - begin1 = end1 += skip; + end1 += skip; + begin1 = end1; int lastState = state; state = newState; lastNamespace = namespace; @@ -115,7 +118,7 @@ String getNamespace() { } int nextToken() { - for (;;) { + for (; ; ) { int left = len - end1; if (left == 0) { end1++; // in order to include the last letter @@ -140,8 +143,9 @@ int nextToken() { return found(JDECLAR, 3); } if (isStartComment(c1, c2, left)) { - if (skipJComment()) + if (skipJComment()) { continue; + } } return found(JSCRIPT, 2); } @@ -156,15 +160,15 @@ int nextToken() { return foundStartOrEndTag(GEND_TAG, tagNameSpace.length() + 3, tagNameSpace); } - } - else if (isStartOfGExpression(c, c1)) { + } else if (isStartOfGExpression(c, c1)) { return found(GEXPR, 2); } if (c == '%' && c1 == '{') { if (c2 == '-' && left > 3 && text.charAt(end1 + 2) == '-') { - if (skipGComment()) + if (skipGComment()) { continue; + } } return found(GSCRIPT, 2); } @@ -176,7 +180,7 @@ else if (isStartOfGExpression(c, c1)) { if (c == '@' && c1 == '{') { return found(GDIRECT, 2); } - + if (tokenLength > maxHtmlLength) { return found(HTML, 0); } @@ -196,8 +200,7 @@ else if (isStartOfGExpression(c, c1)) { } if (c == '>') { return found(HTML, 1); - } - else if (isClosingTag(c) && c1 == '>') { + } else if (isClosingTag(c) && c1 == '>') { return found(GEND_EMPTY_TAG, 1); } break; @@ -225,6 +228,9 @@ else if (isClosingTag(c) && c1 == '>') { return found(HTML, 2); } break; + default: + // do nothing + break; } } } @@ -233,15 +239,15 @@ protected int parseExpression() { char terminationChar = '}'; char nextTerminationChar = 0; boolean startInExpression = true; - GroovyPageExpressionParser expressionParser = new GroovyPageExpressionParser(text, end1-1, terminationChar, nextTerminationChar, startInExpression); - int endpos= expressionParser.parse(); + GroovyPageExpressionParser expressionParser = new GroovyPageExpressionParser(text, end1 - 1, terminationChar, nextTerminationChar, startInExpression); + int endpos = expressionParser.parse(); if (endpos != -1) { end1 = endpos + 1; int expressionEndState = HTML; if (state == GTAG_EXPR) { expressionEndState = GSTART_TAG; } - return found(expressionEndState,nextTerminationChar==0?1:2); + return found(expressionEndState, nextTerminationChar == 0 ? 1 : 2); } throw new GrailsTagException("Unclosed GSP expression", pageName, getLineNumberForToken()); @@ -279,7 +285,9 @@ private boolean isStartOfGExpression(char c, char c1) { private boolean skipComment(char c3, char c4) { int ix = end1 + 3; for (int ixz = len - 4; ; ix++) { - if (ix > ixz) return false; + if (ix > ixz) { + return false; + } if (text.charAt(ix) == '-' && text.charAt(ix + 1) == '-' && text.charAt(ix + 2) == c3 && text.charAt(ix + 3) == c4) { break; @@ -299,7 +307,10 @@ private boolean skipJComment() { } void reset() { - end1 = begin1 = end2 = begin2 = 0; + end1 = 0; + begin1 = 0; + end2 = 0; + begin2 = 0; state = HTML; lastNamespace = null; lastLineNumberIndex = -1; diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageTypeCheckingConfig.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageTypeCheckingConfig.java index 92893e29b90..413f3a5af63 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageTypeCheckingConfig.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageTypeCheckingConfig.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.gsp.compiler; import java.lang.annotation.ElementType; @@ -27,5 +26,6 @@ @Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) public @interface GroovyPageTypeCheckingConfig { + String[] taglibs() default {}; } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageTypeCheckingExtension.groovy b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageTypeCheckingExtension.groovy index abaeeea9fd9..cd74ee61066 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageTypeCheckingExtension.groovy +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/GroovyPageTypeCheckingExtension.groovy @@ -35,6 +35,7 @@ import org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport * */ class GroovyPageTypeCheckingExtension extends GroovyTypeCheckingExtensionSupport.TypeCheckingDSL { + @Override Object run() { ClassNode configAnnotationClassNode = ClassHelper.make(GroovyPageTypeCheckingConfig) @@ -44,7 +45,7 @@ class GroovyPageTypeCheckingExtension extends GroovyTypeCheckingExtensionSupport allowedTagLibs = [] as Set dynamicProperties = [] as Set } - AnnotationNode configAnnotation = classNode.getAnnotations(configAnnotationClassNode)?.find{it} + AnnotationNode configAnnotation = classNode.getAnnotations(configAnnotationClassNode)?.find { it } if (configAnnotation) { Expression taglibsExpression = configAnnotation.getMember('taglibs') if (taglibsExpression instanceof ListExpression) { diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/Reverse.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/Reverse.java index c4ab5a0cffc..c4d1162402a 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/Reverse.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/Reverse.java @@ -20,12 +20,13 @@ /** * NOTE: Based on work done by on the GSP standalone project (https://gsp.dev.java.net/) - * + *

    * Utility class to reverse a char sequence. * * @author Troy Heninger */ class Reverse implements CharSequence { + private CharSequence text; private int start, end, anchor; diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/Strip.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/Strip.java index 5f31f043d6b..4469d494f79 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/Strip.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/Strip.java @@ -23,13 +23,14 @@ /** * NOTE: Based on work done by on the GSP standalone project (https://gsp.dev.java.net/) - * + *

    * Utility class to strip HTML from around tags that specify it. * * @author Troy Heninger * Date: Jan 10, 2004 */ class Strip { + private static Pattern stripTag = Pattern.compile("\\^([a-zA-Z]+)%\\{([^}]|\\}[^%])*\\}%"); private static Pattern anyTag = Pattern.compile("((\\^[a-zA-Z])?%\\{([^}]|\\}[^%])*\\}%|[$@]\\{[^}]*\\})"); @@ -52,10 +53,14 @@ void strip(int index) { if (matchAfter.find(end)) { int end2 = matchAfter.end(); Matcher matchAny = anyTag.matcher(text.subSequence(0, end2)); - if (matchAny.find(end)) end2 = matchAny.start(); + if (matchAny.find(end)) { + end2 = matchAny.start(); + } Pattern nextTagPat = Pattern.compile("<" + tag + "(\\s|>)", Pattern.CASE_INSENSITIVE); Matcher matchNext = nextTagPat.matcher(text.subSequence(0, end2)); - if (matchNext.find(end)) end2 = matchNext.start(); + if (matchNext.find(end)) { + end2 = matchNext.start(); + } // System.out.println("Stripping " + text.subSequence(end, end2)); text.delete(end, end2); } @@ -65,7 +70,9 @@ void strip(int index) { if (matchBefore.find()) { int start2 = start - matchBefore.end(); Matcher matchAny = anyTag.matcher(text.subSequence(0, start)); - if (matchAny.find(start2)) start2 = matchAny.end(); + if (matchAny.find(start2)) { + start2 = matchAny.end(); + } // System.out.println("Stripping " + text.subSequence(start2, start)); text.delete(start2, start); } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/Tokens.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/Tokens.java index 02499f8ae5d..0f3cc76d73a 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/Tokens.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/Tokens.java @@ -20,15 +20,16 @@ /** * NOTE: Based on work done by on the GSP standalone project (https://gsp.dev.java.net/) - * + *

    * Interface defining an enumeration of tokens for the different scriptlet types * * @author Troy Heninger * @author Graeme Rocher - * + *

    * Date: Jan 10, 2004 */ interface Tokens { + int EOF = -1; int HTML = 0; int JEXPR = 1; // <%= ... %> diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GrailsTag.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GrailsTag.java index 8772f0014e8..b0e64879c27 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GrailsTag.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GrailsTag.java @@ -34,12 +34,14 @@ public interface GrailsTag { /** * Sets the writer that processes the tag + * * @param w */ void setWriter(Writer w); /** * Sets the attributes of the tag + * * @param attributes */ @SuppressWarnings("rawtypes") @@ -47,6 +49,7 @@ public interface GrailsTag { /** * Sets an attribute of the tag + * * @param name * @param value */ diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GrailsTagRegistry.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GrailsTagRegistry.java index 0b9b70997b2..44e0e4c1537 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GrailsTagRegistry.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GrailsTagRegistry.java @@ -28,23 +28,23 @@ * * @author Graeme Rocher */ -public class GrailsTagRegistry { +public final class GrailsTagRegistry { private static GrailsTagRegistry instance = new GrailsTagRegistry(); private static Map> tagRegistry = new ConcurrentHashMap>(); static { - instance.registerTag(GroovyEachTag.TAG_NAME, GroovyEachTag.class); - instance.registerTag(GroovyIfTag.TAG_NAME, GroovyIfTag.class); - instance.registerTag(GroovyUnlessTag.TAG_NAME, GroovyUnlessTag.class); - instance.registerTag(GroovyElseTag.TAG_NAME, GroovyElseTag.class); - instance.registerTag(GroovyElseIfTag.TAG_NAME, GroovyElseIfTag.class); + instance.registerTag(GroovyEachTag.TAG_NAME, GroovyEachTag.class); + instance.registerTag(GroovyIfTag.TAG_NAME, GroovyIfTag.class); + instance.registerTag(GroovyUnlessTag.TAG_NAME, GroovyUnlessTag.class); + instance.registerTag(GroovyElseTag.TAG_NAME, GroovyElseTag.class); + instance.registerTag(GroovyElseIfTag.TAG_NAME, GroovyElseIfTag.class); instance.registerTag(GroovyFindAllTag.TAG_NAME, GroovyFindAllTag.class); instance.registerTag(GroovyCollectTag.TAG_NAME, GroovyCollectTag.class); - instance.registerTag(GroovyGrepTag.TAG_NAME, GroovyGrepTag.class); - instance.registerTag(GroovyWhileTag.TAG_NAME, GroovyWhileTag.class); - instance.registerTag(GroovyDefTag.TAG_NAME, GroovyDefTag.class); + instance.registerTag(GroovyGrepTag.TAG_NAME, GroovyGrepTag.class); + instance.registerTag(GroovyWhileTag.TAG_NAME, GroovyWhileTag.class); + instance.registerTag(GroovyDefTag.TAG_NAME, GroovyDefTag.class); } private GrailsTagRegistry() { @@ -78,13 +78,11 @@ public GrailsTag newTag(String tagName) { Class tagClass = tagRegistry.get(tagName); try { - return (GrailsTag)tagClass.newInstance(); - } - catch (InstantiationException e) { - throw new GrailsTagException("Instantiation error loading tag ["+tagName+"]: " + e.getMessage(), e); - } - catch (IllegalAccessException e) { - throw new GrailsTagException("Illegal access error loading tag ["+tagName+"]: " + e.getMessage(), e); + return (GrailsTag) tagClass.newInstance(); + } catch (InstantiationException e) { + throw new GrailsTagException("Instantiation error loading tag [" + tagName + "]: " + e.getMessage(), e); + } catch (IllegalAccessException e) { + throw new GrailsTagException("Illegal access error loading tag [" + tagName + "]: " + e.getMessage(), e); } } } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyCollectTag.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyCollectTag.java index 2e1945696ce..59050f589c6 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyCollectTag.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyCollectTag.java @@ -21,6 +21,7 @@ import grails.util.GrailsStringUtils; import org.grails.taglib.GrailsTagException; +//CHECKSTYLE:OFF /** * Example: *

    @@ -34,6 +35,7 @@
      * @author Graeme Rocher
      * @since 19-Jan-2006
      */
    +//CHECKSTYLE:ON
     public class GroovyCollectTag extends GroovySyntaxTag {
     
         public static final String TAG_NAME = "collect";
    diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyFindAllTag.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyFindAllTag.java
    index 86546c5af6c..ab12ef2533d 100644
    --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyFindAllTag.java
    +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyFindAllTag.java
    @@ -21,11 +21,12 @@
     import grails.util.GrailsStringUtils;
     import org.grails.taglib.GrailsTagException;
     
    +//CHECKSTYLE:OFF
     /**
      * Example:
      *
      * 
    - * {@code 
    + * {@code
      *  
      *        

    ${it}

    *
    @@ -35,6 +36,7 @@ * @author Graeme Rocher * @since 19-Jan-2006 */ +//CHECKSTYLE:ON public class GroovyFindAllTag extends GroovySyntaxTag { public static final String TAG_NAME = "findAll"; @@ -51,10 +53,10 @@ public boolean isAllowPrecedingContent() { } public void doStartTag() { - String in = attributes.get(ATTRIBUTE_IN); - if (GrailsStringUtils.isBlank(in)) { - throw new GrailsTagException("Tag [" + TAG_NAME + "] missing required attribute [" + ATTRIBUTE_IN + "]", parser.getPageName(), parser.getCurrentOutputLineNumber()); - } + String in = attributes.get(ATTRIBUTE_IN); + if (GrailsStringUtils.isBlank(in)) { + throw new GrailsTagException("Tag [" + TAG_NAME + "] missing required attribute [" + ATTRIBUTE_IN + "]", parser.getPageName(), parser.getCurrentOutputLineNumber()); + } String expr = attributes.get(ATTRIBUTE_EXPR); if (GrailsStringUtils.isBlank(expr)) { diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyGrepTag.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyGrepTag.java index ba61314b7f1..cfbae3175ad 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyGrepTag.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyGrepTag.java @@ -21,12 +21,13 @@ import grails.util.GrailsStringUtils; import org.grails.taglib.GrailsTagException; +//CHECKSTYLE:OFF /** * * Example: * *
    - * {@code 
    + * {@code
      *  
      *        

    ${it}

    *
    @@ -35,6 +36,7 @@ * * @author Graeme Rocher */ +//CHECKSTYLE:ON public class GroovyGrepTag extends GroovySyntaxTag { public static final String TAG_NAME = "grep"; diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyIfTag.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyIfTag.java index ae67ba35117..67da0cfa559 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyIfTag.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyIfTag.java @@ -19,6 +19,7 @@ package org.grails.gsp.compiler.tags; public class GroovyIfTag extends GroovyConditionalTag { + public static final String TAG_NAME = "if"; @Override diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovySyntaxTag.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovySyntaxTag.java index 4dacf72e778..2362e157a2a 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovySyntaxTag.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovySyntaxTag.java @@ -41,11 +41,11 @@ */ public abstract class GroovySyntaxTag implements GrailsTag { - private static final String ERROR_NO_VAR_WITH_STATUS = "When using with a [status] attribute, you must also define a [var]. eg. "; - private static final String ERROR_NO_VAR_WITH_COMPILE_STATIC = "When using in CompileStatic mode, you must also define a [var]. eg. "; protected static final String ATTRIBUTE_IN = "in"; protected static final String ATTRIBUTE_VAR = "var"; protected static final String ATTRIBUTES_STATUS = "status"; + private static final String ERROR_NO_VAR_WITH_STATUS = "When using with a [status] attribute, you must also define a [var]. eg. "; + private static final String ERROR_NO_VAR_WITH_COMPILE_STATIC = "When using in CompileStatic mode, you must also define a [var]. eg. "; @SuppressWarnings("rawtypes") protected Map tagContext; protected PrintWriter out; @@ -60,7 +60,7 @@ public void init(Map context) { parser = (GroovyPageParser) context.get(GroovyPageParser.class); Object outObj = context.get(GroovyPage.OUT); if (outObj instanceof PrintWriter) { - out = (PrintWriter)context.get(GroovyPage.OUT); + out = (PrintWriter) context.get(GroovyPage.OUT); } } @@ -70,27 +70,28 @@ protected boolean isCompileStaticMode() { public void setWriter(Writer w) { Assert.isInstanceOf(PrintWriter.class, w, "A GroovySynax tag requires a java.io.PrintWriter instance"); - out = (PrintWriter)w; + out = (PrintWriter) w; } @SuppressWarnings("rawtypes") public void setAttributes(Map attributes) { - for (Iterator i = attributes.keySet().iterator(); i.hasNext();) { + for (Iterator i = attributes.keySet().iterator(); i.hasNext(); ) { String attrName = (String) i.next(); - setAttribute(attrName,attributes.get(attrName)); + setAttribute(attrName, attributes.get(attrName)); } } public void setAttribute(String name, Object value) { Assert.isInstanceOf(String.class, value, "A GroovySyntax tag requires only string valued attributes"); - attributes.put(name.substring(1,name.length()-1), (String)value); + attributes.put(name.substring(1, name.length() - 1), (String) value); } /** *

    Tags must return the correct value to indicate whether or not whitespace before this tag should be kept in the output.

    *

    This is for tags that must follow other tags, such as g:else or g:elseif that do not allow content between them and the * previous tag, and need to swallow the whitespace between them.

    + * * @return true if any whitespace immediately before the tag should be kept in the output - false if it is to be discarded */ public abstract boolean isKeepPrecedingWhiteSpace(); @@ -100,6 +101,7 @@ public void setAttribute(String name, Object value) { *

    This is for tags that must follow other tags, such as g:else or g:elseif that do not allow content between them and the * previous tag. It is simply used as a safety mechanism to trap incorrect usage of tags.

    * TODO rework this and combine with isKeepPrecedingWhiteSpace as really they are used in the same situations + * * @return true if any content is allowed immediately before the tag - false if it is an error to have such content before it */ public abstract boolean isAllowPrecedingContent(); @@ -110,11 +112,11 @@ protected String calculateExpression(String expr) { expr = expr.trim(); if ((expr.startsWith("\"") && expr.endsWith("\"")) || (expr.startsWith("\'") && expr.endsWith("\'"))) { - expr = expr.substring(1,expr.length()-1); + expr = expr.substring(1, expr.length() - 1); expr = expr.trim(); } if (expr.startsWith("${") && expr.endsWith("}")) { - expr = expr.substring(2,expr.length()-1); + expr = expr.substring(2, expr.length() - 1); expr = expr.trim(); } return expr; @@ -142,13 +144,13 @@ protected void doEachMethod(String in) { if (hasStatus) { out.println("loop:{"); - out.println("int "+ status +" = 0"); + out.println("int " + status + " = 0"); } if (!hasVar) { if (isCompileStaticMode()) { throw new GrailsTagException(ERROR_NO_VAR_WITH_COMPILE_STATIC, parser.getPageName(), parser.getCurrentOutputLineNumber()); } - var = "_it"+ Math.abs(System.identityHashCode(this)); + var = "_it" + Math.abs(System.identityHashCode(this)); foreachRenamedIt = var; } @@ -165,7 +167,7 @@ protected void doEachMethod(String in) { out.print(" {"); // start closure out.println(); if (!hasVar) { - out.println("changeItVariable(" + foreachRenamedIt +")" ); + out.println("changeItVariable(" + foreachRenamedIt + ")"); } else if (entryVars != null) { out.println("def " + entryVars[0].trim() + "=" + var + ".getKey()"); out.println("def " + entryVars[1].trim() + "=" + var + ".getValue()"); @@ -178,7 +180,7 @@ protected void endEachMethod() { boolean hasStatus = !GrailsStringUtils.isBlank(status); if (hasStatus) { - out.println(status +"++"); + out.println(status + "++"); out.println("}"); } out.println("}"); @@ -189,10 +191,10 @@ protected String extractAttributeValue(String attr) { return ""; } if (((attr.startsWith("\"") && attr.endsWith("\"")) || (attr.startsWith("'") && attr.endsWith("'"))) && attr.length() > 1) { - attr = attr.substring(1,attr.length()-1); + attr = attr.substring(1, attr.length() - 1); } if (attr.endsWith("?") && attr.length() > 1) { - attr = attr.substring(0,attr.length()-1); + attr = attr.substring(0, attr.length() - 1); } return attr; } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyUnlessTag.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyUnlessTag.java index 05b4dc8453b..c3c3f2060f2 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyUnlessTag.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/tags/GroovyUnlessTag.java @@ -19,6 +19,7 @@ package org.grails.gsp.compiler.tags; public class GroovyUnlessTag extends GroovyConditionalTag { + public static final String TAG_NAME = "unless"; @Override diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/GroovyPageBytecodeOptimizer.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/GroovyPageBytecodeOptimizer.java index 674be66eb15..6101a5e51a1 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/GroovyPageBytecodeOptimizer.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/GroovyPageBytecodeOptimizer.java @@ -32,7 +32,7 @@ @AstTransformer public class GroovyPageBytecodeOptimizer implements GroovyPageInjector { - private final static String RUN_METHOD = "run"; + private static final String RUN_METHOD = "run"; public void performInjection(SourceUnit source, GeneratorContext context, ClassNode classNode) { diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/GroovyPageInjectionOperation.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/GroovyPageInjectionOperation.java index a1f94e50213..f570859b132 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/GroovyPageInjectionOperation.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/GroovyPageInjectionOperation.java @@ -54,14 +54,14 @@ public void call(SourceUnit source, GeneratorContext context, ClassNode classNod } private GroovyPageInjector[] getGroovyPageInjectors() { - if (groovyPageInjectors == null) { - List injectors = new ArrayList(); - for (ClassInjector ci : getClassInjectors()) { - if (ci instanceof GroovyPageInjector) { - injectors.add((GroovyPageInjector)ci); - } - } - groovyPageInjectors = injectors.toArray(new GroovyPageInjector[injectors.size()]); + if (groovyPageInjectors == null) { + List injectors = new ArrayList(); + for (ClassInjector ci : getClassInjectors()) { + if (ci instanceof GroovyPageInjector) { + injectors.add((GroovyPageInjector) ci); + } + } + groovyPageInjectors = injectors.toArray(new GroovyPageInjector[injectors.size()]); } return groovyPageInjectors; } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/GroovyPageOptimizerVisitor.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/GroovyPageOptimizerVisitor.java index 8e1a7c2ff7a..3e00703d84b 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/GroovyPageOptimizerVisitor.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/GroovyPageOptimizerVisitor.java @@ -23,7 +23,11 @@ import org.codehaus.groovy.ast.CodeVisitorSupport; import org.codehaus.groovy.ast.MethodNode; import org.codehaus.groovy.ast.Parameter; -import org.codehaus.groovy.ast.expr.*; +import org.codehaus.groovy.ast.expr.ArgumentListExpression; +import org.codehaus.groovy.ast.expr.ClosureExpression; +import org.codehaus.groovy.ast.expr.DeclarationExpression; +import org.codehaus.groovy.ast.expr.MethodCallExpression; +import org.codehaus.groovy.ast.expr.VariableExpression; import org.codehaus.groovy.ast.stmt.BlockStatement; import org.codehaus.groovy.ast.stmt.ExpressionStatement; import org.codehaus.groovy.ast.stmt.Statement; @@ -43,8 +47,8 @@ */ class GroovyPageOptimizerVisitor extends CodeVisitorSupport { - private static final ClassNode groovyPageClassNode = new ClassNode(GroovyPage.class); - private static final MethodNode writerMethodNode = new ClassNode(GrailsPrintWriter.class).getMethod("print", + private static final ClassNode GROOVY_PAGE_CLASS_NODE = new ClassNode(GroovyPage.class); + private static final MethodNode WRITER_METHOD_NODE = new ClassNode(GrailsPrintWriter.class).getMethod("print", new Parameter[]{new Parameter(new ClassNode(Object.class), "obj")}); private static final String THIS_RECEIVER = "this"; @@ -68,12 +72,12 @@ public GroovyPageOptimizerVisitor(ClassNode targetGroovyPage) { thisObjectVariable = new VariableExpression(THISOBJECT, targetGroovyPageNode); thisObjectDeclaration = new DeclarationExpression( - thisObjectVariable - ,Token.newSymbol(Types.EQUALS, 0, 0) - ,thisObjectMethodCall); + thisObjectVariable + , Token.newSymbol(Types.EQUALS, 0, 0) + , thisObjectMethodCall); } -// TODO: Research why http://jira.grails.org/browse/GRAILS-8679 happens with this enabled. See ElvisAndClosureGroovyPageTests +// TODO: Research why GRAILS-8679 happens with this enabled. See ElvisAndClosureGroovyPageTests // @Override // public void visitClosureExpression(ClosureExpression expression) { // innerClosures.push(expression); @@ -85,7 +89,7 @@ public GroovyPageOptimizerVisitor(ClassNode targetGroovyPage) { @SuppressWarnings("unused") private void introduceThisObjectVariable(ClosureExpression closureExpression) { if (closureExpression.getCode() instanceof BlockStatement) { - List oldBlock = ((BlockStatement)closureExpression.getCode()).getStatements(); + List oldBlock = ((BlockStatement) closureExpression.getCode()).getStatements(); BlockStatement newBlock = new BlockStatement(); newBlock.addStatement(new ExpressionStatement(thisObjectDeclaration)); @@ -99,7 +103,7 @@ private void introduceThisObjectVariable(ClosureExpression closureExpression) { public void visitMethodCallExpression(MethodCallExpression call) { if (isCallFromGroovyPageClass(call)) { - // TODO: Research why http://jira.grails.org/browse/GRAILS-8679 happens with this enabled. See ElvisAndClosureGroovyPageTests + // TODO: Research why GRAILS-8679 happens with this enabled. See ElvisAndClosureGroovyPageTests //proceedCallFromGroovyPageClass(call); } else if (isCallFromOutOrCodecOut(call)) { proceedCallFromOutOrCodecOut(call); @@ -109,7 +113,7 @@ public void visitMethodCallExpression(MethodCallExpression call) { } private void proceedCallFromOutOrCodecOut(MethodCallExpression call) { - call.setMethodTarget(writerMethodNode); + call.setMethodTarget(WRITER_METHOD_NODE); } private boolean isCallFromOutOrCodecOut(MethodCallExpression expression) { @@ -120,7 +124,7 @@ private boolean isCallFromOutOrCodecOut(MethodCallExpression expression) { @SuppressWarnings("unused") private void proceedCallFromGroovyPageClass(MethodCallExpression call) { - List methodNodeList = groovyPageClassNode.getMethods(call.getMethodAsString()); + List methodNodeList = GROOVY_PAGE_CLASS_NODE.getMethods(call.getMethodAsString()); if (methodNodeList.size() == 1) { call.setMethodTarget(methodNodeList.get(0)); @@ -148,6 +152,6 @@ private void changeThisObjectExpressionIfInnerClosure(MethodCallExpression call) private boolean isCallFromGroovyPageClass(MethodCallExpression expression) { return expression.getObjectExpression().getText().equals(THIS_RECEIVER) - && !groovyPageClassNode.getMethods(expression.getMethodAsString()).isEmpty(); + && !GROOVY_PAGE_CLASS_NODE.getMethods(expression.getMethodAsString()).isEmpty(); } } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/LineNumber.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/LineNumber.java index 864a15ba7b6..b1606cec6e4 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/LineNumber.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/LineNumber.java @@ -29,9 +29,11 @@ * @author Andrew Eisenberg */ @Retention(RetentionPolicy.SOURCE) -@Target({ ElementType.TYPE }) +@Target({ElementType.TYPE}) @GroovyASTTransformationClass({"org.grails.gsp.compiler.transform.LineNumberTransform"}) public @interface LineNumber { + int[] lines(); + String sourceName(); } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/LineNumberTransform.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/LineNumberTransform.java index 3246b632c14..866a6aabdd4 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/LineNumberTransform.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/compiler/transform/LineNumberTransform.java @@ -23,7 +23,40 @@ import org.codehaus.groovy.ast.AnnotationNode; import org.codehaus.groovy.ast.ClassCodeVisitorSupport; import org.codehaus.groovy.ast.ClassNode; -import org.codehaus.groovy.ast.expr.*; +import org.codehaus.groovy.ast.expr.ArgumentListExpression; +import org.codehaus.groovy.ast.expr.ArrayExpression; +import org.codehaus.groovy.ast.expr.AttributeExpression; +import org.codehaus.groovy.ast.expr.BinaryExpression; +import org.codehaus.groovy.ast.expr.BitwiseNegationExpression; +import org.codehaus.groovy.ast.expr.BooleanExpression; +import org.codehaus.groovy.ast.expr.CastExpression; +import org.codehaus.groovy.ast.expr.ClassExpression; +import org.codehaus.groovy.ast.expr.ClosureExpression; +import org.codehaus.groovy.ast.expr.ClosureListExpression; +import org.codehaus.groovy.ast.expr.ConstantExpression; +import org.codehaus.groovy.ast.expr.ConstructorCallExpression; +import org.codehaus.groovy.ast.expr.DeclarationExpression; +import org.codehaus.groovy.ast.expr.ElvisOperatorExpression; +import org.codehaus.groovy.ast.expr.Expression; +import org.codehaus.groovy.ast.expr.FieldExpression; +import org.codehaus.groovy.ast.expr.GStringExpression; +import org.codehaus.groovy.ast.expr.ListExpression; +import org.codehaus.groovy.ast.expr.MapEntryExpression; +import org.codehaus.groovy.ast.expr.MapExpression; +import org.codehaus.groovy.ast.expr.MethodCallExpression; +import org.codehaus.groovy.ast.expr.MethodPointerExpression; +import org.codehaus.groovy.ast.expr.NotExpression; +import org.codehaus.groovy.ast.expr.PostfixExpression; +import org.codehaus.groovy.ast.expr.PrefixExpression; +import org.codehaus.groovy.ast.expr.PropertyExpression; +import org.codehaus.groovy.ast.expr.RangeExpression; +import org.codehaus.groovy.ast.expr.SpreadExpression; +import org.codehaus.groovy.ast.expr.SpreadMapExpression; +import org.codehaus.groovy.ast.expr.StaticMethodCallExpression; +import org.codehaus.groovy.ast.expr.TernaryExpression; +import org.codehaus.groovy.ast.expr.TupleExpression; +import org.codehaus.groovy.ast.expr.UnaryMinusExpression; +import org.codehaus.groovy.ast.expr.UnaryPlusExpression; import org.codehaus.groovy.ast.stmt.Statement; import org.codehaus.groovy.classgen.BytecodeExpression; import org.codehaus.groovy.control.CompilePhase; @@ -43,7 +76,7 @@ * * @author Andrew Eisenberg */ -@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS) +@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS) public class LineNumberTransform implements ASTTransformation, TransformWithPriority { // LOG statements commented out because they were causing @@ -84,8 +117,8 @@ public void visit(ASTNode[] nodes, SourceUnit source) { } String extractSourceName(AnnotationNode node) { - ConstantExpression newName = (ConstantExpression)node.getMember("sourceName"); - return (String)newName.getValue(); + ConstantExpression newName = (ConstantExpression) node.getMember("sourceName"); + return (String) newName.getValue(); } AnnotationNode findAnnotation(ClassNode clazz) { @@ -101,14 +134,13 @@ AnnotationNode findAnnotation(ClassNode clazz) { } int[] extractLineNumberArray(AnnotationNode node) { - ListExpression lineNumberArray = (ListExpression)node.getMember("lines"); + ListExpression lineNumberArray = (ListExpression) node.getMember("lines"); // make assumption that this is a simple array of constants List numbers = new ArrayList(); for (Expression e : lineNumberArray.getExpressions()) { if (e instanceof ConstantExpression) { - numbers.add((Integer)((ConstantExpression)e).getValue()); - } - else { + numbers.add((Integer) ((ConstantExpression) e).getValue()); + } else { numbers.add(-1); } } @@ -129,6 +161,7 @@ public int priority() { } class LineNumberVisitor extends ClassCodeVisitorSupport { + int[] lineNumbers; LineNumberVisitor(int[] lineNumbers) { @@ -172,9 +205,10 @@ public void visitMethodCallExpression(MethodCallExpression expression) { } super.visitMethodCallExpression(expression); } + @Override public void visitStaticMethodCallExpression(StaticMethodCallExpression expression) { - // LOG.debug "Transforming expression '${expression}':" + // LOG.debug "Transforming expression '${expression}':" if (expression.getLineNumber() >= 0 && expression.getLineNumber() < lineNumbers.length) { // LOG.debug " start from ${expression.lineNumber} to ${lineNumbers[expression.lineNumber - 1]}" @@ -187,6 +221,7 @@ public void visitStaticMethodCallExpression(StaticMethodCallExpression expressio } super.visitStaticMethodCallExpression(expression); } + @Override public void visitConstructorCallExpression(ConstructorCallExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -202,6 +237,7 @@ public void visitConstructorCallExpression(ConstructorCallExpression expression) } super.visitConstructorCallExpression(expression); } + @Override public void visitBinaryExpression(BinaryExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -217,6 +253,7 @@ public void visitBinaryExpression(BinaryExpression expression) { } super.visitBinaryExpression(expression); } + @Override public void visitTernaryExpression(TernaryExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -232,6 +269,7 @@ public void visitTernaryExpression(TernaryExpression expression) { } super.visitTernaryExpression(expression); } + @Override public void visitShortTernaryExpression(ElvisOperatorExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -247,6 +285,7 @@ public void visitShortTernaryExpression(ElvisOperatorExpression expression) { } super.visitShortTernaryExpression(expression); } + @Override public void visitPostfixExpression(PostfixExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -262,6 +301,7 @@ public void visitPostfixExpression(PostfixExpression expression) { } super.visitPostfixExpression(expression); } + @Override public void visitPrefixExpression(PrefixExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -277,6 +317,7 @@ public void visitPrefixExpression(PrefixExpression expression) { } super.visitPrefixExpression(expression); } + @Override public void visitBooleanExpression(BooleanExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -292,6 +333,7 @@ public void visitBooleanExpression(BooleanExpression expression) { } super.visitBooleanExpression(expression); } + @Override public void visitNotExpression(NotExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -307,6 +349,7 @@ public void visitNotExpression(NotExpression expression) { } super.visitNotExpression(expression); } + @Override public void visitClosureExpression(ClosureExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -322,6 +365,7 @@ public void visitClosureExpression(ClosureExpression expression) { } super.visitClosureExpression(expression); } + @Override public void visitTupleExpression(TupleExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -337,6 +381,7 @@ public void visitTupleExpression(TupleExpression expression) { } super.visitTupleExpression(expression); } + @Override public void visitListExpression(ListExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -352,6 +397,7 @@ public void visitListExpression(ListExpression expression) { } super.visitListExpression(expression); } + @Override public void visitArrayExpression(ArrayExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -367,6 +413,7 @@ public void visitArrayExpression(ArrayExpression expression) { } super.visitArrayExpression(expression); } + @Override public void visitMapExpression(MapExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -382,6 +429,7 @@ public void visitMapExpression(MapExpression expression) { } super.visitMapExpression(expression); } + @Override public void visitMapEntryExpression(MapEntryExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -397,6 +445,7 @@ public void visitMapEntryExpression(MapEntryExpression expression) { } super.visitMapEntryExpression(expression); } + @Override public void visitRangeExpression(RangeExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -412,6 +461,7 @@ public void visitRangeExpression(RangeExpression expression) { } super.visitRangeExpression(expression); } + @Override public void visitSpreadExpression(SpreadExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -427,6 +477,7 @@ public void visitSpreadExpression(SpreadExpression expression) { } super.visitSpreadExpression(expression); } + @Override public void visitSpreadMapExpression(SpreadMapExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -442,6 +493,7 @@ public void visitSpreadMapExpression(SpreadMapExpression expression) { } super.visitSpreadMapExpression(expression); } + @Override public void visitMethodPointerExpression( MethodPointerExpression expression) { @@ -458,6 +510,7 @@ public void visitMethodPointerExpression( } super.visitMethodPointerExpression(expression); } + @Override public void visitUnaryMinusExpression(UnaryMinusExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -473,6 +526,7 @@ public void visitUnaryMinusExpression(UnaryMinusExpression expression) { } super.visitUnaryMinusExpression(expression); } + @Override public void visitUnaryPlusExpression(UnaryPlusExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -488,6 +542,7 @@ public void visitUnaryPlusExpression(UnaryPlusExpression expression) { } super.visitUnaryPlusExpression(expression); } + @Override public void visitBitwiseNegationExpression(BitwiseNegationExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -503,6 +558,7 @@ public void visitBitwiseNegationExpression(BitwiseNegationExpression expression) } super.visitBitwiseNegationExpression(expression); } + @Override public void visitCastExpression(CastExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -518,6 +574,7 @@ public void visitCastExpression(CastExpression expression) { } super.visitCastExpression(expression); } + @Override public void visitConstantExpression(ConstantExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -533,6 +590,7 @@ public void visitConstantExpression(ConstantExpression expression) { } super.visitConstantExpression(expression); } + @Override public void visitClassExpression(ClassExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -548,6 +606,7 @@ public void visitClassExpression(ClassExpression expression) { } super.visitClassExpression(expression); } + @Override public void visitDeclarationExpression(DeclarationExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -563,6 +622,7 @@ public void visitDeclarationExpression(DeclarationExpression expression) { } super.visitDeclarationExpression(expression); } + @Override public void visitPropertyExpression(PropertyExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -578,6 +638,7 @@ public void visitPropertyExpression(PropertyExpression expression) { } super.visitPropertyExpression(expression); } + @Override public void visitAttributeExpression(AttributeExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -593,6 +654,7 @@ public void visitAttributeExpression(AttributeExpression expression) { } super.visitAttributeExpression(expression); } + @Override public void visitFieldExpression(FieldExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -608,6 +670,7 @@ public void visitFieldExpression(FieldExpression expression) { } super.visitFieldExpression(expression); } + @Override public void visitGStringExpression(GStringExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -623,6 +686,7 @@ public void visitGStringExpression(GStringExpression expression) { } super.visitGStringExpression(expression); } + @Override public void visitArgumentlistExpression(ArgumentListExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -638,6 +702,7 @@ public void visitArgumentlistExpression(ArgumentListExpression expression) { } super.visitArgumentlistExpression(expression); } + @Override public void visitClosureListExpression(ClosureListExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -653,6 +718,7 @@ public void visitClosureListExpression(ClosureListExpression expression) { } super.visitClosureListExpression(expression); } + @Override public void visitBytecodeExpression(BytecodeExpression expression) { // LOG.debug "Transforming expression '${expression}':" @@ -668,6 +734,7 @@ public void visitBytecodeExpression(BytecodeExpression expression) { } super.visitBytecodeExpression(expression); } + @Override protected SourceUnit getSourceUnit() { return null; diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/io/CachingGroovyPageStaticResourceLocator.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/io/CachingGroovyPageStaticResourceLocator.java index 6a9eec7c822..9252eb40c47 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/io/CachingGroovyPageStaticResourceLocator.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/io/CachingGroovyPageStaticResourceLocator.java @@ -32,7 +32,8 @@ * @author Graeme Rocher * @since 2.0 */ -public class CachingGroovyPageStaticResourceLocator extends GroovyPageStaticResourceLocator{ +public class CachingGroovyPageStaticResourceLocator extends GroovyPageStaticResourceLocator { + private ConcurrentMap> uriResolveCache = new ConcurrentHashMap>(); private long cacheTimeout = -1; diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/io/DefaultGroovyPageLocator.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/io/DefaultGroovyPageLocator.java index 9e1a2611b0a..18169515cb0 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/io/DefaultGroovyPageLocator.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/io/DefaultGroovyPageLocator.java @@ -40,7 +40,12 @@ import java.io.File; import java.security.PrivilegedAction; -import java.util.*; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentMap; @@ -55,16 +60,16 @@ */ public class DefaultGroovyPageLocator implements GroovyPageLocator, ResourceLoaderAware, ApplicationContextAware, PluginManagerAware { - private static final Log LOG = LogFactory.getLog(DefaultGroovyPageLocator.class); public static final String PATH_TO_WEB_INF_VIEWS = "/WEB-INF/grails-app/views"; + private static final Log LOG = LogFactory.getLog(DefaultGroovyPageLocator.class); private static final String SLASHED_VIEWS_DIR_PATH = "/" + GrailsResourceUtils.VIEWS_DIR_PATH; private static final String PLUGINS_PATH = "/plugins/"; private static final String BLANK = ""; protected Collection resourceLoaders = new ConcurrentLinkedQueue(); protected GrailsPluginManager pluginManager; - private ConcurrentMap precompiledGspMap; protected boolean warDeployed = Environment.isWarDeployed(); protected boolean reloadEnabled = !warDeployed; + private ConcurrentMap precompiledGspMap; private Set reloadedPrecompiledGspClassNames = new CopyOnWriteArraySet(); public void setResourceLoader(ResourceLoader resourceLoader) { @@ -110,24 +115,23 @@ public GroovyPageScriptSource findPageInBinding(String pluginName, String uri, T String contextPath = resolveContextPath(pluginName, uri, binding); String fullURI = GrailsResourceUtils.appendPiecesForUri(contextPath, uri); - if(pluginManager != null) { + if (pluginManager != null) { GrailsPlugin grailsPlugin = pluginManager.getGrailsPlugin(pluginName); - if(grailsPlugin instanceof BinaryGrailsPlugin) { + if (grailsPlugin instanceof BinaryGrailsPlugin) { BinaryGrailsPlugin binaryGrailsPlugin = (BinaryGrailsPlugin) grailsPlugin; File projectDirectory = binaryGrailsPlugin.getProjectDirectory(); - if(projectDirectory != null) { + if (projectDirectory != null) { File f = new File(projectDirectory, GrailsResourceUtils.VIEWS_DIR_PATH + uri); - if(f.exists()) { + if (f.exists()) { scriptSource = new GroovyPageResourceScriptSource(uri, new FileSystemResource(f)); } - } - else { + } else { scriptSource = resolveViewInBinaryPlugin(binaryGrailsPlugin, uri); } } } - if(scriptSource == null) { + if (scriptSource == null) { scriptSource = findPageInBinding(fullURI, binding); } @@ -241,10 +245,9 @@ protected GroovyPageScriptSource findBinaryScriptSource(String uri) { LOG.debug(String.format("Found GSP view [%s] in plugin [%s]", uri, plugin.getName())); } return scriptSource; - } - else if(binaryPlugin.getProjectDirectory() != null) { + } else if (binaryPlugin.getProjectDirectory() != null) { scriptSource = resolveViewInPluginProjectDirectory(binaryPlugin, uri); - if(scriptSource != null) { + if (scriptSource != null) { return scriptSource; } } @@ -256,7 +259,7 @@ else if(binaryPlugin.getProjectDirectory() != null) { private GroovyPageScriptSource resolveViewInPluginProjectDirectory(BinaryGrailsPlugin binaryPlugin, String uri) { File projectDirectory = binaryPlugin.getProjectDirectory(); File f = new File(projectDirectory, "grails-app/views" + uri); - if(f.exists()) { + if (f.exists()) { return new GroovyPageResourceScriptSource(uri, new FileSystemResource(f)); } return null; @@ -344,9 +347,9 @@ protected List resolveSearchPaths(String uri) { } } else { searchPaths = CollectionUtils.newList( - GrailsResourceUtils.appendPiecesForUri(SLASHED_VIEWS_DIR_PATH, uri), - GrailsResourceUtils.appendPiecesForUri(PATH_TO_WEB_INF_VIEWS, uri), - uri); + GrailsResourceUtils.appendPiecesForUri(SLASHED_VIEWS_DIR_PATH, uri), + GrailsResourceUtils.appendPiecesForUri(PATH_TO_WEB_INF_VIEWS, uri), + uri); } return searchPaths; } @@ -399,7 +402,9 @@ protected Resource findResource(List searchPaths) { break; } } - if (foundResource != null) break; + if (foundResource != null) { + break; + } } return foundResource; } @@ -420,10 +425,21 @@ public static PluginViewPathInfo getPluginViewPathInfo(String uri) { return new PluginViewPathInfo(uri); } + public boolean isReloadEnabled() { + return reloadEnabled; + } + + public void setReloadEnabled(boolean reloadEnabled) { + this.reloadEnabled = reloadEnabled; + } + public static class PluginViewPathInfo { + + //CHECKSTYLE:OFF public String basePath; public String pluginName; public String path; + //CHECKSTYLE:ON public PluginViewPathInfo(String uri) { basePath = uri.substring(PLUGINS_PATH.length(), uri.length()); @@ -434,12 +450,4 @@ public PluginViewPathInfo(String uri) { } } } - - public boolean isReloadEnabled() { - return reloadEnabled; - } - - public void setReloadEnabled(boolean reloadEnabled) { - this.reloadEnabled = reloadEnabled; - } } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageCompiledScriptSource.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageCompiledScriptSource.java index 8d387546339..d67924c58f7 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageCompiledScriptSource.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageCompiledScriptSource.java @@ -31,6 +31,7 @@ * @since 2.0 */ public class GroovyPageCompiledScriptSource implements GroovyPageScriptSource { + private String uri; private Class compiledClass; private GroovyPageMetaInfo groovyPageMetaInfo; @@ -76,7 +77,9 @@ public boolean isModified() { } public GroovyPageResourceScriptSource getReloadableScriptSource() { - if (resourceCallable == null) return null; + if (resourceCallable == null) { + return null; + } Resource resource = groovyPageMetaInfo.checkIfReloadableResourceHasChanged(resourceCallable); return resource == null ? null : new GroovyPageResourceScriptSource(uri, resource); } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageLocator.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageLocator.java index b44ed927166..952329831c0 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageLocator.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageLocator.java @@ -48,8 +48,8 @@ public interface GroovyPageLocator { * Finds a page for the given URI * * @param pluginName The plugin name - * @param uri The URI - * @param binding The biding to use + * @param uri The URI + * @param binding The biding to use * @return A script source */ GroovyPageScriptSource findPageInBinding(String pluginName, String uri, TemplateVariableBinding binding); @@ -57,7 +57,7 @@ public interface GroovyPageLocator { /** * Finds a page for the URI and binding * - * @param uri The URI + * @param uri The URI * @param binding The binding * @return The page source */ diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageResourceScriptSource.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageResourceScriptSource.java index 30ad071a7c0..3fe002c8662 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageResourceScriptSource.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageResourceScriptSource.java @@ -33,7 +33,7 @@ public class GroovyPageResourceScriptSource extends ResourceScriptSource impleme /** * Create a new ResourceScriptSource for the given resource. * - * @param uri The URI of the resource + * @param uri The URI of the resource * @param resource the Resource to load the script from */ public GroovyPageResourceScriptSource(String uri, Resource resource) { @@ -43,8 +43,7 @@ public GroovyPageResourceScriptSource(String uri, Resource resource) { URL u = getResource().getURL(); if (u == null) { isPublic = isPublicPath(uri); - } - else { + } else { isPublic = isPublicPath(u.getPath()); } } catch (IOException e) { diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageStaticResourceLocator.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageStaticResourceLocator.java index 869c10db2fd..9c0a3e0e45c 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageStaticResourceLocator.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/io/GroovyPageStaticResourceLocator.java @@ -29,7 +29,7 @@ /** *

    - * Extends the {@link DefaultResourceLocator} class with extra methods to evaluate static resources relative to the currently executing GSP page. + * Extends the {@link DefaultResourceLocator} class with extra methods to evaluate static resources relative to the currently executing GSP page. *

    * *

    This class is used to resolve references to static resources like CSS, Javascript and images files

    @@ -45,16 +45,17 @@ public Resource findResourceForURI(String uri) { if (resource == null || !resource.exists()) { AbstractTemplateVariableBinding binding = findBindingInOutputContext(); if (binding instanceof GroovyPageBinding) { - GrailsPlugin pagePlugin = ((GroovyPageBinding)binding).getPagePlugin(); + GrailsPlugin pagePlugin = ((GroovyPageBinding) binding).getPagePlugin(); if (pagePlugin != null && pluginManager != null) { resource = findResourceForPlugin(pagePlugin, uri); } - } - else if (pluginManager != null) { + } else if (pluginManager != null) { // attempt brute force search of all plugins for (GrailsPlugin plugin : pluginManager.getAllPlugins()) { resource = findResourceForPlugin(plugin, uri); - if (resource != null) break; + if (resource != null) { + break; + } } } } diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/jsp/JspTag.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/jsp/JspTag.java index de474b09d16..406a1c5fd0d 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/jsp/JspTag.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/jsp/JspTag.java @@ -32,17 +32,18 @@ public interface JspTag { * Main method to invoke a tag library and output to the target write * * @param targetWriter The writer the tag should write to - * @param attributes The tag attributes + * @param attributes The tag attributes */ - void doTag(Writer targetWriter, Map attributes); + void doTag(Writer targetWriter, Map attributes); /** * Invokes a tag with a closure representing the body of the tag + * * @param targetWriter The target writer to write to - * @param attributes The tag attributes - * @param body The body of the tag + * @param attributes The tag attributes + * @param body The body of the tag */ - void doTag(Writer targetWriter, Map attributes, Closure body); + void doTag(Writer targetWriter, Map attributes, Closure body); /** * @return Return true if the tag class implements the TryCatchFinally interface diff --git a/grails-gsp/core/src/main/groovy/org/grails/gsp/jsp/TagLibraryResolver.java b/grails-gsp/core/src/main/groovy/org/grails/gsp/jsp/TagLibraryResolver.java index f4c923fc99b..c9c519b81b8 100644 --- a/grails-gsp/core/src/main/groovy/org/grails/gsp/jsp/TagLibraryResolver.java +++ b/grails-gsp/core/src/main/groovy/org/grails/gsp/jsp/TagLibraryResolver.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.gsp.jsp; public interface TagLibraryResolver { diff --git a/grails-gsp/grails-layout/build.gradle b/grails-gsp/grails-layout/build.gradle index df50bddb78e..abe5ef871e2 100644 --- a/grails-gsp/grails-layout/build.gradle +++ b/grails-gsp/grails-layout/build.gradle @@ -65,4 +65,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/grails-extension-gradle-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/EmbeddedGrailsLayoutView.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/EmbeddedGrailsLayoutView.java index a03ebcfa372..25119ea6b62 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/EmbeddedGrailsLayoutView.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/EmbeddedGrailsLayoutView.java @@ -18,14 +18,11 @@ */ package org.apache.grails.web.layout; +import com.opensymphony.module.sitemesh.RequestConstants; +import com.opensymphony.sitemesh.Content; import groovy.text.Template; - -import java.io.PrintWriter; -import java.util.Map; - import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; - import org.grails.web.servlet.WrappedResponseHolder; import org.grails.web.servlet.mvc.GrailsWebRequest; import org.grails.web.servlet.mvc.OutputAwareHttpServletResponse; @@ -35,17 +32,15 @@ import org.springframework.http.MediaType; import org.springframework.web.servlet.View; -import com.opensymphony.module.sitemesh.RequestConstants; -import com.opensymphony.sitemesh.Content; +import java.io.PrintWriter; +import java.util.Map; public class EmbeddedGrailsLayoutView extends AbstractGrailsView { + public static final String GSP_GRAILS_LAYOUT_PAGE = EmbeddedGrailsLayoutView.class.getName() + ".GSP_GRAILS_LAYOUT_PAGE"; private static final Logger LOG = LoggerFactory.getLogger(EmbeddedGrailsLayoutView.class); - GroovyPageLayoutFinder groovyPageLayoutFinder; - protected View innerView; - - public static final String GSP_GRAILS_LAYOUT_PAGE = EmbeddedGrailsLayoutView.class.getName() + ".GSP_GRAILS_LAYOUT_PAGE"; + GroovyPageLayoutFinder groovyPageLayoutFinder; public EmbeddedGrailsLayoutView(GroovyPageLayoutFinder groovyPageLayoutFinder, View innerView) { this.groovyPageLayoutFinder = groovyPageLayoutFinder; @@ -88,6 +83,9 @@ protected void renderTemplate(Map model, GrailsWebRequest webReq return; } break; + default: + // do nothing + break; } PrintWriter writer = response.getWriter(); if (LOG.isDebugEnabled()) { @@ -100,7 +98,6 @@ protected void renderTemplate(Map model, GrailsWebRequest webReq } } - } protected void beforeDecorating(Content content, Map model, GrailsWebRequest webRequest, @@ -169,4 +166,4 @@ public Template getTemplate() { public View getInnerView() { return innerView; } -} \ No newline at end of file +} diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/EmbeddedGrailsLayoutViewResolver.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/EmbeddedGrailsLayoutViewResolver.java index 72fda268a0e..0545553677b 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/EmbeddedGrailsLayoutViewResolver.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/EmbeddedGrailsLayoutViewResolver.java @@ -18,10 +18,7 @@ */ package org.apache.grails.web.layout; -import java.util.Locale; - import jakarta.servlet.ServletContext; - import org.grails.web.servlet.view.LayoutViewResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,14 +31,16 @@ import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; +import java.util.Locale; + public class EmbeddedGrailsLayoutViewResolver implements LayoutViewResolver, Ordered, ServletContextAware, ApplicationContextAware { private static final Logger LOG = LoggerFactory.getLogger(EmbeddedGrailsLayoutViewResolver.class); protected ViewResolver innerViewResolver; protected GroovyPageLayoutFinder groovyPageLayoutFinder; - private int order = Ordered.LOWEST_PRECEDENCE - 30; protected ServletContext servletContext; + private int order = Ordered.LOWEST_PRECEDENCE - 30; public EmbeddedGrailsLayoutViewResolver(ViewResolver innerViewResolver, GroovyPageLayoutFinder groovyPageLayoutFinder) { this.innerViewResolver = innerViewResolver; diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/FactoryHolder.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/FactoryHolder.java index eaf52001d7a..0f8fa15b835 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/FactoryHolder.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/FactoryHolder.java @@ -19,9 +19,8 @@ package org.apache.grails.web.layout; -import grails.util.Holder; - import com.opensymphony.module.sitemesh.Factory; +import grails.util.Holder; /** * Holds a reference to the Grails Layout Factory object. @@ -29,7 +28,7 @@ * @author Graeme Rocher * @since 0.6 */ -public class FactoryHolder { +public final class FactoryHolder { private static Holder holder = new Holder("factory"); @@ -49,4 +48,4 @@ public static Factory getGrailsLayoutFactory() { public static synchronized void setFactory(Factory factory) { holder.set(factory); } -} \ No newline at end of file +} diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GSPGrailsLayoutPage.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GSPGrailsLayoutPage.java index 8c954f6b803..915f6dac8fd 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GSPGrailsLayoutPage.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GSPGrailsLayoutPage.java @@ -234,4 +234,4 @@ public boolean isTitleCaptured() { public void setTitleCaptured(boolean titleCaptured) { this.titleCaptured = titleCaptured; } -} \ No newline at end of file +} diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsContentBufferingResponse.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsContentBufferingResponse.java index 8e7404088ef..4b95010dc60 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsContentBufferingResponse.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsContentBufferingResponse.java @@ -18,21 +18,19 @@ */ package org.apache.grails.web.layout; -import java.io.IOException; - +import com.opensymphony.module.sitemesh.PageParser; +import com.opensymphony.module.sitemesh.PageParserSelector; +import com.opensymphony.sitemesh.Content; +import com.opensymphony.sitemesh.ContentProcessor; +import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; import grails.web.mvc.GrailsResponseMutator; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponseWrapper; - import org.grails.buffer.StreamCharBuffer; import org.grails.web.servlet.mvc.GrailsWebRequest; import org.grails.web.util.WebUtils; -import com.opensymphony.module.sitemesh.PageParser; -import com.opensymphony.module.sitemesh.PageParserSelector; -import com.opensymphony.sitemesh.Content; -import com.opensymphony.sitemesh.ContentProcessor; -import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; +import java.io.IOException; public class GrailsContentBufferingResponse extends HttpServletResponseWrapper implements GrailsResponseMutator, StreamCharBuffer.LazyInitializingWriter { diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsHTMLPageParser.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsHTMLPageParser.java index 254ea686d9e..1e25c193665 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsHTMLPageParser.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsHTMLPageParser.java @@ -18,8 +18,6 @@ */ package org.apache.grails.web.layout; -import java.io.IOException; - import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.html.HTMLProcessor; import com.opensymphony.module.sitemesh.html.State; @@ -39,6 +37,8 @@ import com.opensymphony.module.sitemesh.parser.TokenizedHTMLPage; import com.opensymphony.sitemesh.Content; +import java.io.IOException; + public class GrailsHTMLPageParser extends HTMLPageParser { @Override diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsLayoutDecoratorMapper.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsLayoutDecoratorMapper.java index 8536f33a762..fea14378e10 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsLayoutDecoratorMapper.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsLayoutDecoratorMapper.java @@ -18,20 +18,18 @@ */ package org.apache.grails.web.layout; -import java.util.Properties; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.http.HttpServletRequest; - -import grails.core.GrailsApplication; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.context.support.WebApplicationContextUtils; - import com.opensymphony.module.sitemesh.Config; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.module.sitemesh.DecoratorMapper; import com.opensymphony.module.sitemesh.Page; import com.opensymphony.module.sitemesh.mapper.AbstractDecoratorMapper; +import grails.core.GrailsApplication; +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import java.util.Properties; /** * Implements the SiteMesh decorator mapper interface and allows grails views to map to grails layouts. diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsLayoutView.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsLayoutView.java index e515280cb40..1f0be57768c 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsLayoutView.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsLayoutView.java @@ -19,16 +19,14 @@ package org.apache.grails.web.layout; -import java.util.Map; - +import com.opensymphony.sitemesh.ContentProcessor; +import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; - import org.grails.web.servlet.mvc.GrailsWebRequest; import org.springframework.web.servlet.View; -import com.opensymphony.sitemesh.ContentProcessor; -import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; +import java.util.Map; public class GrailsLayoutView extends EmbeddedGrailsLayoutView { @@ -44,4 +42,4 @@ protected GrailsContentBufferingResponse createContentBufferingResponse(Map { private static final String FACTORY_SERVLET_CONTEXT_ATTRIBUTE = "grails.layout.factory"; - private ContentProcessor contentProcessor; protected GrailsApplication grailsApplication; + private ContentProcessor contentProcessor; private boolean grailsLayoutConfigLoaded = false; private int order = Ordered.LOWEST_PRECEDENCE - 50; @@ -61,7 +59,9 @@ protected View createLayoutView(View innerView) { } public void init() { - if (servletContext == null) return; + if (servletContext == null) { + return; + } Factory grailsLayoutFactory = (Factory) servletContext.getAttribute(FACTORY_SERVLET_CONTEXT_ATTRIBUTE); if (grailsLayoutFactory == null) { @@ -119,7 +119,9 @@ public void destroy() throws Exception { } protected void clearGrailsLayoutConfig() { - if (servletContext == null) return; + if (servletContext == null) { + return; + } if (grailsLayoutConfigLoaded) { FactoryHolder.setFactory(null); if (servletContext != null) { diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsNoDecorator.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsNoDecorator.java index b775cddcfbd..92cf7143cd7 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsNoDecorator.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsNoDecorator.java @@ -19,10 +19,11 @@ package org.apache.grails.web.layout; -import java.util.Iterator; import com.opensymphony.module.sitemesh.Decorator; import com.opensymphony.sitemesh.webapp.decorator.NoDecorator; +import java.util.Iterator; + /** * Grails version of Sitemesh's NoDecorator * @@ -54,4 +55,4 @@ public String getInitParameter(String paramName) { public Iterator getInitParameterNames() { return null; } -} \ No newline at end of file +} diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsPageResponseWrapper.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsPageResponseWrapper.java index a9449838aad..c4a7a19b2f2 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsPageResponseWrapper.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsPageResponseWrapper.java @@ -18,29 +18,27 @@ */ package org.apache.grails.web.layout; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; - +import com.opensymphony.module.sitemesh.Page; +import com.opensymphony.module.sitemesh.PageParser; +import com.opensymphony.module.sitemesh.PageParserSelector; +import com.opensymphony.module.sitemesh.filter.HttpContentType; +import com.opensymphony.module.sitemesh.filter.RoutableServletOutputStream; +import com.opensymphony.module.sitemesh.filter.TextEncoder; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.WriteListener; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponseWrapper; - -import org.grails.buffer.GrailsRoutablePrintWriter; -import org.grails.web.servlet.mvc.GrailsWebRequest; import org.grails.buffer.GrailsPrintWriterAdapter; +import org.grails.buffer.GrailsRoutablePrintWriter; import org.grails.buffer.StreamByteBuffer; import org.grails.buffer.StreamCharBuffer; +import org.grails.web.servlet.mvc.GrailsWebRequest; import org.grails.web.util.WebUtils; -import com.opensymphony.module.sitemesh.Page; -import com.opensymphony.module.sitemesh.PageParser; -import com.opensymphony.module.sitemesh.PageParserSelector; -import com.opensymphony.module.sitemesh.filter.HttpContentType; -import com.opensymphony.module.sitemesh.filter.RoutableServletOutputStream; -import com.opensymphony.module.sitemesh.filter.TextEncoder; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; /** * @author Graeme Rocher @@ -174,7 +172,9 @@ public ServletOutputStream create() throws IOException { */ @Override public void setContentLength(int contentLength) { - if (!parseablePage) super.setContentLength(contentLength); + if (!parseablePage) { + super.setContentLength(contentLength); + } } /** @@ -182,7 +182,9 @@ public void setContentLength(int contentLength) { */ @Override public void flushBuffer() throws IOException { - if (!parseablePage) super.flushBuffer(); + if (!parseablePage) { + super.flushBuffer(); + } } /** @@ -283,10 +285,10 @@ private boolean isGrailsLayoutNotActive() { } private static class GrailsBuffer { + private static final TextEncoder TEXT_ENCODER = new TextEncoder(); private final PageParserSelector parserSelector; private final String contentType; private final String encoding; - private final static TextEncoder TEXT_ENCODER = new TextEncoder(); private StreamCharBuffer charBuffer; private GrailsPrintWriterAdapter exposedWriter; @@ -389,4 +391,4 @@ public boolean isUsingStream() { return byteBuffer != null; } } -} \ No newline at end of file +} diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsViewBufferingResponse.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsViewBufferingResponse.java index ec90d842821..3bd7ccd0a8e 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsViewBufferingResponse.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GrailsViewBufferingResponse.java @@ -18,25 +18,30 @@ */ package org.apache.grails.web.layout; -import java.io.IOException; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - import com.opensymphony.sitemesh.Content; import com.opensymphony.sitemesh.ContentProcessor; import com.opensymphony.sitemesh.SiteMeshContext; import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; public class GrailsViewBufferingResponse extends GrailsContentBufferingResponse { + public GrailsViewBufferingResponse(HttpServletRequest request, HttpServletResponse response) { + super(response, new SimpleHtmlOnlyContentProcessor(), new SimpleWebAppContext(request, response)); + } + private static class SimpleWebAppContext extends SiteMeshWebAppContext { + public SimpleWebAppContext(HttpServletRequest request, HttpServletResponse response) { super(request, response, request.getServletContext()); } } private static class SimpleHtmlOnlyContentProcessor implements ContentProcessor { + @Override public Content build(final char[] data, SiteMeshContext context) throws IOException { return new GrailsHTMLPageParser().parseContent(data); @@ -52,8 +57,4 @@ public boolean handles(String contentType) { return contentType != null && contentType.contains("html"); } } - - public GrailsViewBufferingResponse(HttpServletRequest request, HttpServletResponse response) { - super(response, new SimpleHtmlOnlyContentProcessor(), new SimpleWebAppContext(request, response)); - } -} \ No newline at end of file +} diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GroovyPageLayoutFinder.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GroovyPageLayoutFinder.java index 8c806eafa97..ff21b1d9142 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GroovyPageLayoutFinder.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/GroovyPageLayoutFinder.java @@ -18,25 +18,23 @@ */ package org.apache.grails.web.layout; +import com.opensymphony.module.sitemesh.Decorator; +import com.opensymphony.module.sitemesh.Page; +import com.opensymphony.sitemesh.Content; import grails.util.Environment; +import grails.util.GrailsClassUtils; import grails.util.GrailsNameUtils; +import grails.util.GrailsStringUtils; import grails.web.pages.GroovyPagesUriService; import groovy.lang.GroovyObject; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - import jakarta.servlet.http.HttpServletRequest; - -import grails.util.GrailsClassUtils; -import grails.util.GrailsStringUtils; import org.grails.core.artefact.ControllerArtefactHandler; import org.grails.io.support.GrailsResourceUtils; import org.grails.web.servlet.mvc.GrailsWebRequest; -import org.grails.web.servlet.view.GrailsViewResolver; -import org.grails.web.util.GrailsApplicationAttributes; import org.grails.web.servlet.view.AbstractGrailsView; +import org.grails.web.servlet.view.GrailsViewResolver; import org.grails.web.servlet.view.LayoutViewResolver; +import org.grails.web.util.GrailsApplicationAttributes; import org.grails.web.util.WebUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,9 +44,8 @@ import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; -import com.opensymphony.module.sitemesh.Decorator; -import com.opensymphony.module.sitemesh.Page; -import com.opensymphony.sitemesh.Content; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Provides the logic for GrailsLayoutDecoratorMapper without so many ties to @@ -253,7 +250,15 @@ private Decorator createDecorator(String decoratorName, View view) { return new SpringMVCViewDecorator(decoratorName, view); } + @Override + public void onApplicationEvent(ContextRefreshedEvent event) { + if (!(viewResolver instanceof GrailsViewResolver)) { + setViewResolver(event.getApplicationContext().getBean(GrailsViewResolver.class)); + } + } + private static class LayoutCacheKey { + private String controllerName; private String actionUri; @@ -264,13 +269,21 @@ public LayoutCacheKey(String controllerName, String actionUri) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } LayoutCacheKey that = (LayoutCacheKey) o; - if (!actionUri.equals(that.actionUri)) return false; - if (!controllerName.equals(that.controllerName)) return false; + if (!actionUri.equals(that.actionUri)) { + return false; + } + if (!controllerName.equals(that.controllerName)) { + return false; + } return true; } @@ -284,6 +297,7 @@ public int hashCode() { } private static class DecoratorCacheValue { + Decorator decorator; long createTimestamp = System.currentTimeMillis(); @@ -299,11 +313,4 @@ public boolean isExpired() { return System.currentTimeMillis() - createTimestamp > LAYOUT_CACHE_EXPIRATION_MILLIS; } } - - @Override - public void onApplicationEvent(ContextRefreshedEvent event) { - if (!(viewResolver instanceof GrailsViewResolver)) { - setViewResolver(event.getApplicationContext().getBean(GrailsViewResolver.class)); - } - } -} \ No newline at end of file +} diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/LayoutGrailsPlugin.groovy b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/LayoutGrailsPlugin.groovy index e73b2bb6c3c..ad14e9ffae3 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/LayoutGrailsPlugin.groovy +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/LayoutGrailsPlugin.groovy @@ -21,13 +21,12 @@ package org.apache.grails.web.layout import grails.config.Config import grails.config.Settings +import grails.plugins.Plugin import grails.util.Environment +import grails.util.GrailsUtil import grails.util.Metadata -import org.grails.plugins.web.taglib.RenderGrailsLayoutTagLib import org.grails.plugins.web.taglib.GrailsLayoutTagLib - -import grails.plugins.Plugin -import grails.util.GrailsUtil +import org.grails.plugins.web.taglib.RenderGrailsLayoutTagLib /** * Plugin responsible for Grails Layout specific configuration. diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/LayoutSelector.groovy b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/LayoutSelector.groovy index 0be3240ae60..770b991bc80 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/LayoutSelector.groovy +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/LayoutSelector.groovy @@ -23,7 +23,7 @@ import grails.web.pages.GrailsLayoutSelector import org.grails.web.util.WebUtils class LayoutSelector implements GrailsLayoutSelector { - + @Override String selectLayout(String explicitLayoutArg, boolean renderView) { explicitLayoutArg != null ? explicitLayoutArg : (renderView ? null : WebUtils.NONE_LAYOUT) diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/SpringMVCViewDecorator.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/SpringMVCViewDecorator.java index 32d0c7cd319..1459178b97b 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/SpringMVCViewDecorator.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/SpringMVCViewDecorator.java @@ -16,30 +16,26 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.grails.web.layout; +import com.opensymphony.module.sitemesh.HTMLPage; +import com.opensymphony.module.sitemesh.RequestConstants; +import com.opensymphony.module.sitemesh.mapper.DefaultDecorator; +import com.opensymphony.sitemesh.Content; +import com.opensymphony.sitemesh.SiteMeshContext; +import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; import groovy.text.Template; - -import java.util.Collections; -import java.util.Map; - import jakarta.servlet.ServletContext; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; - -import org.grails.web.util.GrailsApplicationAttributes; import org.grails.web.servlet.view.AbstractGrailsView; +import org.grails.web.util.GrailsApplicationAttributes; import org.grails.web.util.WebUtils; import org.springframework.web.servlet.View; import org.springframework.web.servlet.view.AbstractUrlBasedView; -import com.opensymphony.module.sitemesh.HTMLPage; -import com.opensymphony.module.sitemesh.RequestConstants; -import com.opensymphony.module.sitemesh.mapper.DefaultDecorator; -import com.opensymphony.sitemesh.Content; -import com.opensymphony.sitemesh.SiteMeshContext; -import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext; +import java.util.Collections; +import java.util.Map; /** * Encapsulates the logic for rendering a layout. @@ -48,10 +44,11 @@ * @since 2.0 */ public class SpringMVCViewDecorator extends DefaultDecorator implements com.opensymphony.sitemesh.Decorator { + private View view; public SpringMVCViewDecorator(String name, View view) { - super(name, (view instanceof AbstractUrlBasedView) ? ((AbstractUrlBasedView)view).getUrl() : view.toString(), Collections.emptyMap()); + super(name, (view instanceof AbstractUrlBasedView) ? ((AbstractUrlBasedView) view).getUrl() : view.toString(), Collections.emptyMap()); this.view = view; } @@ -79,8 +76,8 @@ public void render(Content content, Map model, HttpServletRequest req } catch (Exception e) { cleanRequestAttributes(request); String message = "Error applying layout : " + getName(); - if(view instanceof AbstractGrailsView) { - ((AbstractGrailsView)view).rethrowRenderException(e, message); + if (view instanceof AbstractGrailsView) { + ((AbstractGrailsView) view).rethrowRenderException(e, message); } else { throw new RuntimeException(message, e); } @@ -106,8 +103,8 @@ public View getView() { } public Template getTemplate() { - if(view instanceof AbstractGrailsView) { - return ((AbstractGrailsView)view).getTemplate(); + if (view instanceof AbstractGrailsView) { + return ((AbstractGrailsView) view).getTemplate(); } return null; } diff --git a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/TokenizedHTMLPage2Content.java b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/TokenizedHTMLPage2Content.java index 2350ca34c04..e81182a9735 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/TokenizedHTMLPage2Content.java +++ b/grails-gsp/grails-layout/src/main/groovy/org/apache/grails/web/layout/TokenizedHTMLPage2Content.java @@ -18,12 +18,12 @@ */ package org.apache.grails.web.layout; +import com.opensymphony.module.sitemesh.parser.TokenizedHTMLPage; +import com.opensymphony.sitemesh.Content; + import java.io.IOException; import java.io.Writer; -import com.opensymphony.sitemesh.Content; -import com.opensymphony.module.sitemesh.parser.TokenizedHTMLPage; - final class TokenizedHTMLPage2Content implements Content { private final TokenizedHTMLPage page; @@ -75,4 +75,4 @@ public void addProperty(String name, String value) { public TokenizedHTMLPage getPage() { return page; } -} \ No newline at end of file +} diff --git a/grails-gsp/grails-layout/src/main/groovy/org/grails/plugins/web/taglib/GrailsLayoutTagLib.groovy b/grails-gsp/grails-layout/src/main/groovy/org/grails/plugins/web/taglib/GrailsLayoutTagLib.groovy index 206cb3de994..c24f9334d22 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/grails/plugins/web/taglib/GrailsLayoutTagLib.groovy +++ b/grails-gsp/grails-layout/src/main/groovy/org/grails/plugins/web/taglib/GrailsLayoutTagLib.groovy @@ -24,13 +24,13 @@ import grails.artefact.TagLibrary import grails.gsp.TagLib import groovy.transform.CompileStatic import jakarta.servlet.http.HttpServletRequest +import org.apache.grails.web.layout.GSPGrailsLayoutPage import org.grails.buffer.FastStringWriter import org.grails.buffer.GrailsPrintWriter import org.grails.buffer.StreamCharBuffer import org.grails.encoder.CodecLookup import org.grails.encoder.Encoder import org.grails.gsp.compiler.GrailsLayoutPreprocessor -import org.apache.grails.web.layout.GSPGrailsLayoutPage /** * Internal Grails Layout pre-processor tags. diff --git a/grails-gsp/grails-layout/src/main/groovy/org/grails/plugins/web/taglib/RenderGrailsLayoutTagLib.groovy b/grails-gsp/grails-layout/src/main/groovy/org/grails/plugins/web/taglib/RenderGrailsLayoutTagLib.groovy index 95f8d668249..499a51dc036 100644 --- a/grails-gsp/grails-layout/src/main/groovy/org/grails/plugins/web/taglib/RenderGrailsLayoutTagLib.groovy +++ b/grails-gsp/grails-layout/src/main/groovy/org/grails/plugins/web/taglib/RenderGrailsLayoutTagLib.groovy @@ -19,12 +19,11 @@ package org.grails.plugins.web.taglib import com.opensymphony.module.sitemesh.Decorator +import com.opensymphony.module.sitemesh.Factory import com.opensymphony.module.sitemesh.HTMLPage import com.opensymphony.module.sitemesh.Page import com.opensymphony.module.sitemesh.PageParser import com.opensymphony.module.sitemesh.RequestConstants -import com.opensymphony.module.sitemesh.Factory - import grails.artefact.TagLibrary import grails.core.GrailsApplication import grails.core.support.GrailsApplicationAware @@ -32,10 +31,11 @@ import grails.gsp.TagLib import grails.util.TypeConvertingMap import groovy.text.Template import groovy.transform.CompileStatic +import jakarta.servlet.http.HttpServletRequest +import org.apache.grails.web.layout.EmbeddedGrailsLayoutView import org.apache.grails.web.layout.FactoryHolder import org.apache.grails.web.layout.GSPGrailsLayoutPage import org.apache.grails.web.layout.GrailsHTMLPageParser -import org.apache.grails.web.layout.EmbeddedGrailsLayoutView import org.apache.grails.web.layout.GroovyPageLayoutFinder import org.apache.grails.web.layout.SpringMVCViewDecorator import org.grails.buffer.FastStringWriter @@ -46,7 +46,6 @@ import org.grails.gsp.compiler.GroovyPageParser import org.grails.taglib.TagLibraryLookup import org.grails.taglib.TagOutput import org.grails.taglib.encoder.OutputContextLookupHelper -import jakarta.servlet.http.HttpServletRequest import java.nio.charset.StandardCharsets @@ -76,7 +75,6 @@ class RenderGrailsLayoutTagLib implements RequestConstants, TagLibrary, GrailsAp grailsLayoutPreprocessMode } - /** * Apply a layout to a particular block of text or to the given view or template.
    * diff --git a/grails-gsp/grails-sitemesh3/build.gradle b/grails-gsp/grails-sitemesh3/build.gradle index b78dc048c1a..4b52256fd05 100644 --- a/grails-gsp/grails-sitemesh3/build.gradle +++ b/grails-gsp/grails-sitemesh3/build.gradle @@ -86,4 +86,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') from rootProject.layout.projectDirectory.file('gradle/grails-extension-gradle-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } \ No newline at end of file diff --git a/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/sitemesh3/GrailsLayoutHandlerMapping.java b/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/sitemesh3/GrailsLayoutHandlerMapping.java index df0a86d2a6b..153693961d8 100644 --- a/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/sitemesh3/GrailsLayoutHandlerMapping.java +++ b/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/sitemesh3/GrailsLayoutHandlerMapping.java @@ -16,9 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.plugins.sitemesh3; +import jakarta.servlet.http.HttpServletRequest; import org.grails.web.gsp.io.GrailsConventionGroovyPageLocator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; @@ -26,14 +26,13 @@ import org.springframework.web.servlet.handler.AbstractHandlerMapping; import org.springframework.web.servlet.mvc.ParameterizableViewController; -import jakarta.servlet.http.HttpServletRequest; - import java.util.HashMap; import java.util.Map; import static org.springframework.http.HttpStatus.NOT_FOUND; public class GrailsLayoutHandlerMapping extends AbstractHandlerMapping { + @Autowired GrailsConventionGroovyPageLocator groovyPageLocator; @@ -53,7 +52,7 @@ protected Object getHandlerInternal(HttpServletRequest request) { ParameterizableViewController pvc = layoutCache.get(servletPath); if (pvc == null) { if (groovyPageLocator.findViewByPath(servletPath) == null) { - throw new ResponseStatusException(NOT_FOUND, "Unable to find resource "+servletPath); + throw new ResponseStatusException(NOT_FOUND, "Unable to find resource " + servletPath); } pvc = new ParameterizableViewController(); pvc.setSupportedMethods(HttpMethod.GET.name(), HttpMethod.HEAD.name(), HttpMethod.POST.name()); @@ -64,4 +63,4 @@ protected Object getHandlerInternal(HttpServletRequest request) { } return null; } -} \ No newline at end of file +} diff --git a/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/sitemesh3/Sitemesh3GrailsPlugin.groovy b/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/sitemesh3/Sitemesh3GrailsPlugin.groovy index 8798f1ffb79..ddd1c483847 100644 --- a/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/sitemesh3/Sitemesh3GrailsPlugin.groovy +++ b/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/sitemesh3/Sitemesh3GrailsPlugin.groovy @@ -46,19 +46,19 @@ class Sitemesh3GrailsPlugin extends Plugin { def loadBefore = ['groovyPages'] def providedArtefacts = [ - RenderSitemeshTagLib, - SitemeshTagLib, + RenderSitemeshTagLib, + SitemeshTagLib, ] static PropertySource getDefaultPropertySource(ConfigurableEnvironment configurableEnvironment, String defaultLayout) { Map props = [ 'grails.gsp.view.layoutViewResolver': 'false', - 'sitemesh.decorator.metaTag': 'layout', - 'sitemesh.decorator.attribute': WebUtils.LAYOUT_ATTRIBUTE, - 'sitemesh.decorator.prefix': '/layouts/', - 'sitemesh.filter.order': GrailsFilters.SITEMESH_FILTER.order, - 'sitemesh.decorator.tagRuleBundles': ['org.sitemesh.content.tagrules.html.Sm2TagRuleBundle'] + 'sitemesh.decorator.metaTag' : 'layout', + 'sitemesh.decorator.attribute' : WebUtils.LAYOUT_ATTRIBUTE, + 'sitemesh.decorator.prefix' : '/layouts/', + 'sitemesh.filter.order' : GrailsFilters.SITEMESH_FILTER.order, + 'sitemesh.decorator.tagRuleBundles' : ['org.sitemesh.content.tagrules.html.Sm2TagRuleBundle'] ] if (defaultLayout) { props['sitemesh.decorator.default'] = defaultLayout diff --git a/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/web/taglib/RenderSitemeshTagLib.groovy b/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/web/taglib/RenderSitemeshTagLib.groovy index c9d35acfba1..9c782382f48 100644 --- a/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/web/taglib/RenderSitemeshTagLib.groovy +++ b/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/web/taglib/RenderSitemeshTagLib.groovy @@ -19,6 +19,8 @@ package org.grails.plugins.web.taglib +import grails.artefact.TagLibrary +import grails.gsp.TagLib import org.grails.web.util.WebUtils import org.sitemesh.content.Content import org.sitemesh.content.ContentProperty @@ -28,8 +30,6 @@ import org.sitemesh.webapp.contentfilter.ResponseMetaData import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Qualifier import org.springframework.boot.web.servlet.FilterRegistrationBean -import grails.artefact.TagLibrary -import grails.gsp.TagLib import java.nio.CharBuffer @@ -46,7 +46,7 @@ class RenderSitemeshTagLib implements TagLibrary { Closure applyLayout = { Map attrs, body -> String savedAttribute = request.getAttribute(WebUtils.LAYOUT_ATTRIBUTE) WebAppContext context = new WebAppContext("text/html", request, response, - servletContext, siteMeshFilter.contentProcessor, new ResponseMetaData(), false); + servletContext, siteMeshFilter.contentProcessor, new ResponseMetaData(), false); Content content = siteMeshFilter.contentProcessor.build(CharBuffer.wrap(body()), context); if (attrs.name) { request.setAttribute(WebUtils.LAYOUT_ATTRIBUTE, attrs.name) @@ -88,7 +88,7 @@ class RenderSitemeshTagLib implements TagLibrary { } String propertyName = attrs.name as String ContentProperty contentProperty = getContentProperty(propertyName) - def propertyValue = contentProperty?.hasValue()? contentProperty.getValue() : attrs.'default' ?: null + def propertyValue = contentProperty?.hasValue() ? contentProperty.getValue() : attrs.'default' ?: null if (propertyValue) { if (attrs.writeEntireProperty) { @@ -119,7 +119,7 @@ class RenderSitemeshTagLib implements TagLibrary { if (!attrs.name) { return } - List names = ((attrs.name instanceof List) ? (List)attrs.name : [attrs.name]) + List names = ((attrs.name instanceof List) ? (List) attrs.name : [attrs.name]) def invokeBody = true for (i in 0.. - out << """${attrs.default?:''}""".toString() + out << """${attrs.default ?: ''}""".toString() } Closure layoutHead = { attrs, body -> diff --git a/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/web/taglib/SitemeshTagLib.groovy b/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/web/taglib/SitemeshTagLib.groovy index f52cce344c8..589f92d086b 100644 --- a/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/web/taglib/SitemeshTagLib.groovy +++ b/grails-gsp/grails-sitemesh3/src/main/groovy/org/grails/plugins/web/taglib/SitemeshTagLib.groovy @@ -19,15 +19,16 @@ package org.grails.plugins.web.taglib +import grails.artefact.TagLibrary +import grails.gsp.TagLib import org.grails.buffer.GrailsPrintWriter import org.grails.buffer.StreamCharBuffer import org.grails.encoder.CodecLookup import org.grails.encoder.Encoder -import grails.artefact.TagLibrary -import grails.gsp.TagLib @TagLib class SitemeshTagLib implements TagLibrary { + static String namespace = 'sitemesh' CodecLookup codecLookup // from org.grails.gsp.compiler.SitemeshPreprocessor @@ -37,13 +38,12 @@ class SitemeshTagLib implements TagLibrary { this.codecLookup = codecLookup } - def captureTagContent(GrailsPrintWriter writer, String tagname, Map attrs, Object body, boolean noEndTagForEmpty=false, boolean useNamespace = false) { + def captureTagContent(GrailsPrintWriter writer, String tagname, Map attrs, Object body, boolean noEndTagForEmpty = false, boolean useNamespace = false) { def content = null if (body != null) { if (body instanceof Closure) { content = body() - } - else { + } else { content = body } } @@ -51,12 +51,12 @@ class SitemeshTagLib implements TagLibrary { if (content instanceof StreamCharBuffer) { content.setPreferSubChunkWhenWritingToOtherBuffer(true) } - writer << '<'+(useNamespace? SitemeshTagLib.namespace + ':' : '') + writer << '<' + (useNamespace ? SitemeshTagLib.namespace + ':' : '') writer << tagname def useXmlClosingForEmptyTag = false if (attrs) { def xmlClosingString = attrs.remove(XML_CLOSING_FOR_EMPTY_TAG_ATTRIBUTE_NAME) - if (xmlClosingString=='/') { + if (xmlClosingString == '/') { useXmlClosingForEmptyTag = true } Encoder htmlEncoder = codecLookup?.lookupEncoder('HTML') @@ -73,23 +73,21 @@ class SitemeshTagLib implements TagLibrary { writer << '>' // the following row must be written separately (append StreamCharBuffer gets appended as subchunk) writer << content - writer << '' - } - else { + } else { if (!useXmlClosingForEmptyTag) { writer << '>' // in valid HTML , closing of an empty tag depends on the element name // for empty title, the tag must be closed properly // for empty meta tag shouldn't be closed at all, see GRAILS-5696 if (!noEndTagForEmpty) { - writer << '' } - } - else { + } else { // XML / XHTML empty tag writer << '/>' } diff --git a/grails-gsp/grails-taglib/build.gradle b/grails-gsp/grails-taglib/build.gradle index fdb81e6d1cf..7b5c48f8cc9 100644 --- a/grails-gsp/grails-taglib/build.gradle +++ b/grails-gsp/grails-taglib/build.gradle @@ -84,4 +84,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-gsp/grails-taglib/src/main/groovy/grails/core/gsp/GrailsTagLibClass.java b/grails-gsp/grails-taglib/src/main/groovy/grails/core/gsp/GrailsTagLibClass.java index 46163d7fe05..b094fe22597 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/grails/core/gsp/GrailsTagLibClass.java +++ b/grails-gsp/grails-taglib/src/main/groovy/grails/core/gsp/GrailsTagLibClass.java @@ -56,5 +56,6 @@ public interface GrailsTagLibClass extends InjectableGrailsClass { String getNamespace(); Object getEncodeAsForTag(String tagName); + Object getDefaultEncodeAs(); } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/core/artefact/gsp/TagLibArtefactHandler.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/core/artefact/gsp/TagLibArtefactHandler.java index 06f44ad4290..9bb0e170855 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/core/artefact/gsp/TagLibArtefactHandler.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/core/artefact/gsp/TagLibArtefactHandler.java @@ -18,9 +18,6 @@ */ package org.grails.core.artefact.gsp; -import java.util.HashMap; -import java.util.Map; - import grails.core.ArtefactHandlerAdapter; import grails.core.ArtefactInfo; import grails.core.GrailsClass; @@ -28,13 +25,15 @@ import org.apache.commons.logging.LogFactory; import org.grails.core.gsp.DefaultGrailsTagLibClass; +import java.util.HashMap; +import java.util.Map; + /** * Configures tag libraries within namespaces in Grails. * * @author Marc Palmer (marc@anyware.co.uk) * @author Graeme Rocher * @author a.shneyderman - * * @since 3.3 */ public class TagLibArtefactHandler extends ArtefactHandlerAdapter { @@ -68,8 +67,7 @@ public void initialize(ArtefactInfo artefacts) { String tagName = namespace + ":" + o; if (!tag2libMap.containsKey(tagName)) { tag2libMap.put(tagName, taglibClass); - } - else { + } else { GrailsTagLibClass current = tag2libMap.get(tagName); if (!taglibClass.equals(current)) { LogFactory.getLog(TagLibArtefactHandler.class).info("There are conflicting tags: " + taglibClass.getFullName() + "." + @@ -92,7 +90,7 @@ public void initialize(ArtefactInfo artefacts) { @Override public GrailsClass getArtefactForFeature(Object feature) { final Object tagLib = tag2libMap.get(feature); - if (tagLib!= null) { + if (tagLib != null) { return (GrailsClass) tagLib; } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/core/gsp/DefaultGrailsTagLibClass.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/core/gsp/DefaultGrailsTagLibClass.java index d86dd0447cf..7cf17f16781 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/core/gsp/DefaultGrailsTagLibClass.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/core/gsp/DefaultGrailsTagLibClass.java @@ -26,7 +26,12 @@ import org.grails.core.artefact.gsp.TagLibArtefactHandler; import java.lang.reflect.Modifier; -import java.util.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * Default implementation of a tag lib class. @@ -47,7 +52,7 @@ public class DefaultGrailsTagLibClass extends AbstractInjectableGrailsClass impl /** * Default constructor. * - * @param clazz the tag library class + * @param clazz the tag library class */ @SuppressWarnings("rawtypes") public DefaultGrailsTagLibClass(Class clazz) { @@ -81,7 +86,7 @@ public DefaultGrailsTagLibClass(Class clazz) { Map encodeAsForTagsMap = getStaticPropertyValue(ENCODE_AS_FOR_TAGS_FIELD_NAME, Map.class); if (encodeAsForTagsMap != null) { for (@SuppressWarnings("unchecked") - Iterator it = encodeAsForTagsMap.entrySet().iterator(); it.hasNext();) { + Iterator it = encodeAsForTagsMap.entrySet().iterator(); it.hasNext(); ) { Map.Entry entry = it.next(); encodeAsForTags.put(entry.getKey().toString(), entry.getValue()); } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/AbstractTemplateVariableBinding.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/AbstractTemplateVariableBinding.java index 0a5bf32c478..5326dec102a 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/AbstractTemplateVariableBinding.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/AbstractTemplateVariableBinding.java @@ -20,7 +20,13 @@ import groovy.lang.Binding; -import java.util.*; +import java.util.AbstractSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; /** * Abstract super class for GroovyPage bindings @@ -30,6 +36,7 @@ */ @SuppressWarnings("rawtypes") public abstract class AbstractTemplateVariableBinding extends Binding { + public AbstractTemplateVariableBinding() { super(); } @@ -83,10 +90,11 @@ public boolean isVariableCachingAllowed(String name) { } protected static final class TemplateVariableBindingMap implements Map { + AbstractTemplateVariableBinding binding; public TemplateVariableBindingMap(AbstractTemplateVariableBinding binding) { - this.binding=binding; + this.binding = binding; } public int size() { @@ -121,7 +129,7 @@ public Object remove(Object key) { public void putAll(Map m) { for (Object entryObj : m.entrySet()) { - Map.Entry entry=(Map.Entry)entryObj; + Map.Entry entry = (Map.Entry) entryObj; binding.setVariable(String.valueOf(entry.getKey()), entry.getValue()); } } @@ -164,11 +172,13 @@ private Iterator entryIterator() { public boolean hasNext() { return iter.hasNext(); } + public Object next() { Object key = iter.next(); Object value = get(key); return new BindingMapEntry(binding, key, value); } + public void remove() { throw new UnsupportedOperationException("remove() not supported"); } @@ -177,10 +187,12 @@ public void remove() { } protected static class BindingMapEntry implements Map.Entry { + private AbstractTemplateVariableBinding binding; private Object key; private Object value; + protected BindingMapEntry(AbstractTemplateVariableBinding binding, Object key, Object value) { this.binding = binding; this.key = key; diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/GrailsTagException.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/GrailsTagException.java index e5c4d09cb2f..0598cfc94ab 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/GrailsTagException.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/GrailsTagException.java @@ -66,10 +66,9 @@ public int getLineNumber() { public String getMessage() { String fn = getFileName(); int ln = getLineNumber(); - if(fn != null && ln > 0) { - return "[" + fn + ":" + ln + "] " + super.getMessage(); - } - else { + if (fn != null && ln > 0) { + return "[" + fn + ":" + ln + "] " + super.getMessage(); + } else { return super.getMessage(); } } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/GroovyPageAttributes.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/GroovyPageAttributes.java index 03f1c797a16..9612cfb587b 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/GroovyPageAttributes.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/GroovyPageAttributes.java @@ -30,8 +30,9 @@ * @author Lari Hotari * @since 1.2 */ -@SuppressWarnings({ "unchecked", "rawtypes" }) +@SuppressWarnings({"unchecked", "rawtypes"}) public class GroovyPageAttributes extends TypeConvertingMap implements Cloneable { + boolean gspTagSyntaxCall = true; public GroovyPageAttributes() { @@ -44,7 +45,7 @@ public GroovyPageAttributes(Map map) { public GroovyPageAttributes(Map map, boolean gspTagSyntaxCall) { super(map); - this.gspTagSyntaxCall=gspTagSyntaxCall; + this.gspTagSyntaxCall = gspTagSyntaxCall; } public boolean isGspTagSyntaxCall() { @@ -52,7 +53,7 @@ public boolean isGspTagSyntaxCall() { } public void setGspTagSyntaxCall(boolean gspTagSyntaxCall) { - this.gspTagSyntaxCall=gspTagSyntaxCall; + this.gspTagSyntaxCall = gspTagSyntaxCall; } @Override diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/NamespacedTagDispatcher.groovy b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/NamespacedTagDispatcher.groovy index 0af455ef9ab..cbc8d6d2e47 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/NamespacedTagDispatcher.groovy +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/NamespacedTagDispatcher.groovy @@ -31,6 +31,7 @@ import groovy.transform.CompileStatic */ @CompileStatic class NamespacedTagDispatcher extends GroovyObjectSupport { + protected String namespace protected GrailsApplication application protected Class type diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagBodyClosure.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagBodyClosure.java index 05a73f9b7aa..4f5e95abc37 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagBodyClosure.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagBodyClosure.java @@ -38,6 +38,7 @@ */ @SuppressWarnings("rawtypes") public class TagBodyClosure extends Closure { + private static final long serialVersionUID = 4396762064131558457L; private static final Class[] PARAMETER_TYPES = new Class[]{Map.class}; private Closure bodyClosure; @@ -66,7 +67,7 @@ public TagBodyClosure(Object owner, OutputContext outputContext, private Object captureClosureOutput(Object args, boolean hasArgument) { final GroovyPageTagWriter capturedOut = new GroovyPageTagWriter(); Binding currentBinding = outputContext.getBinding(); - Map savedVariablesMap = null; + Map savedVariablesMap = null; Object originalIt = null; try { pushCapturedOut(capturedOut); @@ -78,7 +79,7 @@ private Object captureClosureOutput(Object args, boolean hasArgument) { originalIt = saveItVariable(currentBinding, args); } - if (args instanceof Map && ((Map)args).size() > 0) { + if (args instanceof Map && ((Map) args).size() > 0) { // The body can be passed a set of variables as a map that // are then made available in the binding. This allows the // contents of the body to reference any of these variables @@ -99,7 +100,7 @@ private Object captureClosureOutput(Object args, boolean hasArgument) { // Binding is only changed currently when body gets a map // argument - savedVariablesMap = addAndSaveVariables(currentBinding, (Map)args); + savedVariablesMap = addAndSaveVariables(currentBinding, (Map) args); } } bodyResult = executeClosure(args); @@ -108,8 +109,7 @@ private Object captureClosureOutput(Object args, boolean hasArgument) { return bodyResult; } return capturedOut.getBuffer(); - } - finally { + } finally { if (currentBinding != null) { restoreVariables(currentBinding, savedVariablesMap); if (hasArgument) { @@ -122,14 +122,14 @@ private Object captureClosureOutput(Object args, boolean hasArgument) { /** * Sets "it" variable to binding and returns the previous value. - * + *

    * changing "it" variable is required to support refering to body argument with "it"; that was supported pre Grails 2.0 * "it" is in binding because g:each loops are converted to ordinary for loops in Grails 2.0 with a generated variable name (if no variable name is specified) */ @SuppressWarnings("unchecked") private Object saveItVariable(Binding currentBinding, Object args) { Object originalIt; - Map variablesMap = (currentBinding instanceof AbstractTemplateVariableBinding) ? ((AbstractTemplateVariableBinding)currentBinding) + Map variablesMap = (currentBinding instanceof AbstractTemplateVariableBinding) ? ((AbstractTemplateVariableBinding) currentBinding) .getVariablesMap() : currentBinding.getVariables(); originalIt = variablesMap.get("it"); variablesMap.put("it", args); @@ -141,7 +141,7 @@ private Object saveItVariable(Binding currentBinding, Object args) { */ @SuppressWarnings("unchecked") private void restoreItVariable(Binding currentBinding, Object originalIt) { - Map variablesMap = (currentBinding instanceof AbstractTemplateVariableBinding) ? ((AbstractTemplateVariableBinding)currentBinding) + Map variablesMap = (currentBinding instanceof AbstractTemplateVariableBinding) ? ((AbstractTemplateVariableBinding) currentBinding) .getVariablesMap() : currentBinding.getVariables(); variablesMap.put("it", originalIt); } @@ -150,14 +150,14 @@ private void restoreItVariable(Binding currentBinding, Object originalIt) { * Adds variables to binding and returns a map with previous values. */ @SuppressWarnings("unchecked") - private Map addAndSaveVariables(Binding binding, Map args) { - Map savedVariablesMap = new LinkedHashMap(); + private Map addAndSaveVariables(Binding binding, Map args) { + Map savedVariablesMap = new LinkedHashMap(); for (Iterator i = args.keySet().iterator(); i.hasNext(); ) { String varname = String.valueOf(i.next()); savedVariablesMap.put(varname, binding.getVariable(varname)); } if (binding instanceof AbstractTemplateVariableBinding) { - ((AbstractTemplateVariableBinding)binding).addMap(args); + ((AbstractTemplateVariableBinding) binding).addMap(args); } else { for (Iterator i = args.entrySet().iterator(); i.hasNext(); ) { Map.Entry entry = i.next(); @@ -181,8 +181,7 @@ private void restoreVariables(Binding binding, Map savedVariable private void popCapturedOut() { if (outputContext != null) { OutputEncodingStack.currentStack(outputContext).pop(); - } - else { + } else { OutputEncodingStack.currentStack().pop(); } } @@ -190,8 +189,7 @@ private void popCapturedOut() { private void pushCapturedOut(GroovyPageTagWriter capturedOut) { if (outputContext != null) { OutputEncodingStack.currentStack(outputContext).push(capturedOut); - } - else { + } else { OutputEncodingStack.currentStack().push(capturedOut); } } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagLibNamespaceMethodDispatcher.groovy b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagLibNamespaceMethodDispatcher.groovy index e4fd9566490..a7aa5df9da0 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagLibNamespaceMethodDispatcher.groovy +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagLibNamespaceMethodDispatcher.groovy @@ -26,6 +26,7 @@ import org.grails.taglib.encoder.OutputContext */ @CompileStatic class TagLibNamespaceMethodDispatcher { + private final String namespace private final TagLibraryLookup lookup private final OutputContext outputContext diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagLibraryLookup.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagLibraryLookup.java index 2b8d67a1e58..e6053d791ec 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagLibraryLookup.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagLibraryLookup.java @@ -31,7 +31,12 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; -import java.util.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; /** * Looks up tag library instances. @@ -40,6 +45,7 @@ * @since 1.1 */ public class TagLibraryLookup implements ApplicationContextAware, GrailsApplicationAware, InitializingBean { + protected ApplicationContext applicationContext; protected GrailsApplication grailsApplication; protected Map> tagNamespaces = new LinkedHashMap<>(); @@ -63,7 +69,7 @@ public void afterPropertiesSet() throws Exception { } private void registerNamespaceDispatchers() { - for( String namespace : tagNamespaces.keySet()) { + for (String namespace : tagNamespaces.keySet()) { registerNamespaceDispatcher(namespace); } } @@ -73,9 +79,9 @@ protected void registerNamespaceDispatcher(String namespace) { } protected void registerTagLibraries() { - GrailsClass[] taglibs = grailsApplication.getArtefacts(TagLibArtefactHandler.TYPE); + GrailsClass[] taglibs = grailsApplication.getArtefacts(TagLibArtefactHandler.TYPE); for (GrailsClass grailsClass : taglibs) { - registerTagLib((GrailsTagLibClass)grailsClass, true); + registerTagLib((GrailsTagLibClass) grailsClass, true); } } @@ -89,6 +95,7 @@ protected void registerTemplateNamespace() { * taglib has already been registered, this method will override * the existing information and update the tags to use the new * version. + * * @param taglib The taglib descriptor class. */ public void registerTagLib(GrailsTagLibClass taglib) { @@ -98,10 +105,10 @@ public void registerTagLib(GrailsTagLibClass taglib) { private void registerTagLib(GrailsTagLibClass taglib, boolean isInitialization) { String namespace = taglib.getNamespace(); - if(!isInitialization) { + if (!isInitialization) { registerNamespaceDispatcher(namespace); } - Set tagsThatReturnObject=tagsThatReturnObjectForNamespace.get(namespace); + Set tagsThatReturnObject = tagsThatReturnObjectForNamespace.get(namespace); if (tagsThatReturnObject == null) { tagsThatReturnObject = new HashSet(); tagsThatReturnObjectForNamespace.put(namespace, tagsThatReturnObject); @@ -120,8 +127,8 @@ private void registerTagLib(GrailsTagLibClass taglib, boolean isInitialization) tagsThatReturnObject.add(tagName); } - Map> encodeAsForTagNamespace = encodeAsForTagNamespaces.get(namespace); - if (encodeAsForTagNamespace==null) { + Map> encodeAsForTagNamespace = encodeAsForTagNamespaces.get(namespace); + if (encodeAsForTagNamespace == null) { encodeAsForTagNamespace = new HashMap<>(); encodeAsForTagNamespaces.put(namespace, encodeAsForTagNamespace); } @@ -148,15 +155,15 @@ protected void putTagLib(Map tags, String name, GrailsTagLibClas * Looks up a tag library for the given namespace and tag name. * * @param namespace The tag library namespace - * @param tagName The tag name + * @param tagName The tag name * @return The tag library or null if it wasn't found */ public GroovyObject lookupTagLibrary(String namespace, String tagName) { - Maptags = tagNamespaces.get(namespace); + Map tags = tagNamespaces.get(namespace); if (tags == null) { return null; } - return (GroovyObject)tags.get(tagName); + return (GroovyObject) tags.get(tagName); } public boolean doesTagReturnObject(String namespace, String tagName) { @@ -165,12 +172,13 @@ public boolean doesTagReturnObject(String namespace, String tagName) { } public Map getEncodeAsForTag(String namespace, String tagName) { - Map> encodeAsForTagNamespace = encodeAsForTagNamespaces.get(namespace); + Map> encodeAsForTagNamespace = encodeAsForTagNamespaces.get(namespace); return encodeAsForTagNamespace != null ? encodeAsForTagNamespace.get(tagName) : null; } /** * Looks up a namespace dispatcher for the given namespace + * * @param namespace The namespace * @return The NamespacedTagDispatcher */ @@ -180,6 +188,7 @@ public NamespacedTagDispatcher lookupNamespaceDispatcher(String namespace) { /** * Returns whether the given namespace is in use + * * @param namespace The namespace * @return true if it is in use */ @@ -193,13 +202,13 @@ public boolean hasNamespace(String namespace) { public Set getAvailableNamespaces() { return namespaceDispatchers.keySet(); } - + public Set getAvailableTags(String namespace) { - Maptags = tagNamespaces.get(namespace); + Map tags = tagNamespaces.get(namespace); if (tags == null) { return Collections.emptySet(); } - return tags.keySet(); + return tags.keySet(); } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagLibraryMetaUtils.groovy b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagLibraryMetaUtils.groovy index c3e41d8cd5d..ae224897cd0 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagLibraryMetaUtils.groovy +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagLibraryMetaUtils.groovy @@ -29,6 +29,7 @@ import org.grails.taglib.encoder.OutputContextLookupHelper import org.springframework.context.ApplicationContext class TagLibraryMetaUtils { + // used for testing (GroovyPageUnitTestMixin.mockTagLib) and "nonEnhancedTagLibClasses" in GroovyPagesGrailsPlugin private final static Object[] EMPTY_OBJECT_ARRAY = new Object[0] @@ -47,45 +48,45 @@ class TagLibraryMetaUtils { @CompileStatic static void registerNamespaceMetaProperties(MetaClass mc, TagLibraryLookup gspTagLibraryLookup) { - for(String ns : gspTagLibraryLookup.getAvailableNamespaces()) { + for (String ns : gspTagLibraryLookup.getAvailableNamespaces()) { registerNamespaceMetaProperty(mc, gspTagLibraryLookup, ns) } } - + @CompileStatic static void registerNamespaceMetaProperty(MetaClass metaClass, TagLibraryLookup gspTagLibraryLookup, String namespace) { - if(!metaClass.hasProperty(namespace) && !doesMethodExist(metaClass, GrailsClassUtils.getGetterName(namespace), [] as Class[])) { + if (!metaClass.hasProperty(namespace) && !doesMethodExist(metaClass, GrailsClassUtils.getGetterName(namespace), [] as Class[])) { registerPropertyMissingForTag(metaClass, namespace, gspTagLibraryLookup.lookupNamespaceDispatcher(namespace)) } } @CompileStatic - static registerMethodMissingForTags(MetaClass metaClass, TagLibraryLookup gspTagLibraryLookup, String namespace, String name, boolean addAll=true, boolean overrideMethods=true) { - GroovyObject mc = (GroovyObject)metaClass; - - if(overrideMethods || !doesMethodExist(metaClass, name, [Map, Closure] as Class[])) { - mc.setProperty(name) {Map attrs, Closure body -> + static registerMethodMissingForTags(MetaClass metaClass, TagLibraryLookup gspTagLibraryLookup, String namespace, String name, boolean addAll = true, boolean overrideMethods = true) { + GroovyObject mc = (GroovyObject) metaClass; + + if (overrideMethods || !doesMethodExist(metaClass, name, [Map, Closure] as Class[])) { + mc.setProperty(name) { Map attrs, Closure body -> TagOutput.captureTagOutput(gspTagLibraryLookup, namespace, name, attrs, body, OutputContextLookupHelper.lookupOutputContext()) } } - if(overrideMethods || !doesMethodExist(metaClass, name, [Map, CharSequence] as Class[])) { - mc.setProperty(name) {Map attrs, CharSequence body -> + if (overrideMethods || !doesMethodExist(metaClass, name, [Map, CharSequence] as Class[])) { + mc.setProperty(name) { Map attrs, CharSequence body -> TagOutput.captureTagOutput(gspTagLibraryLookup, namespace, name, attrs, new TagOutput.ConstantClosure(body), OutputContextLookupHelper.lookupOutputContext()) } } - if(overrideMethods || !doesMethodExist(metaClass, name, [Map] as Class[])) { - mc.setProperty(name) {Map attrs -> + if (overrideMethods || !doesMethodExist(metaClass, name, [Map] as Class[])) { + mc.setProperty(name) { Map attrs -> TagOutput.captureTagOutput(gspTagLibraryLookup, namespace, name, attrs, null, OutputContextLookupHelper.lookupOutputContext()) } } if (addAll) { - if(overrideMethods || !doesMethodExist(metaClass, name, [Closure] as Class[])) { - mc.setProperty(name) {Closure body -> + if (overrideMethods || !doesMethodExist(metaClass, name, [Closure] as Class[])) { + mc.setProperty(name) { Closure body -> TagOutput.captureTagOutput(gspTagLibraryLookup, namespace, name, [:], body, OutputContextLookupHelper.lookupOutputContext()) } } - if(overrideMethods || !doesMethodExist(metaClass, name, [] as Class[])) { - mc.setProperty(name) {-> + if (overrideMethods || !doesMethodExist(metaClass, name, [] as Class[])) { + mc.setProperty(name) { -> TagOutput.captureTagOutput(gspTagLibraryLookup, namespace, name, [:], null, OutputContextLookupHelper.lookupOutputContext()) } } @@ -101,13 +102,13 @@ class TagLibraryMetaUtils { @CompileStatic static void registerPropertyMissingForTag(MetaClass metaClass, String name, Object result) { - GroovyObject mc = (GroovyObject)metaClass; - mc.setProperty(GrailsClassUtils.getGetterName(name)) {-> result } + GroovyObject mc = (GroovyObject) metaClass; + mc.setProperty(GrailsClassUtils.getGetterName(name)) { -> result } } - + @CompileStatic static void registerTagMetaMethods(MetaClass emc, TagLibraryLookup lookup, String namespace) { - for(String tagName : lookup.getAvailableTags(namespace)) { + for (String tagName : lookup.getAvailableTags(namespace)) { boolean addAll = !(namespace == TagOutput.DEFAULT_NAMESPACE && tagName == 'hasErrors') registerMethodMissingForTags(emc, lookup, namespace, tagName, addAll, false) } @@ -115,39 +116,40 @@ class TagLibraryMetaUtils { registerTagMetaMethods(emc, lookup, TagOutput.DEFAULT_NAMESPACE) } } - + @CompileStatic - protected static boolean doesMethodExist(final MetaClass mc, final String methodName, final Class[] parameterTypes, boolean staticScope=false, boolean onlyReal=false) { + protected static boolean doesMethodExist(final MetaClass mc, final String methodName, final Class[] parameterTypes, boolean staticScope = false, boolean onlyReal = false) { boolean methodExists = false try { MetaMethod existingMethod = mc.pickMethod(methodName, parameterTypes) - if(existingMethod && existingMethod.isStatic()==staticScope && (!onlyReal || isRealMethod(existingMethod)) && parameterTypes.length==existingMethod.parameterTypes.length) { + if (existingMethod && existingMethod.isStatic() == staticScope && (!onlyReal || isRealMethod(existingMethod)) && parameterTypes.length == existingMethod.parameterTypes.length) { methodExists = true } } catch (MethodSelectionException mse) { // the metamethod already exists with multiple signatures, must check if the exact method exists methodExists = mc.methods.contains { MetaMethod existingMethod -> - existingMethod.name == methodName && existingMethod.isStatic()==staticScope && (!onlyReal || isRealMethod(existingMethod)) && ((!parameterTypes && !existingMethod.parameterTypes) || Arrays.equals(parameterTypes, existingMethod.getNativeParameterTypes())) + existingMethod.name == methodName && existingMethod.isStatic() == staticScope && (!onlyReal || isRealMethod(existingMethod)) && ((!parameterTypes && !existingMethod.parameterTypes) || Arrays.equals(parameterTypes, existingMethod.getNativeParameterTypes())) } } } - + @CompileStatic private static boolean isRealMethod(MetaMethod existingMethod) { existingMethod instanceof CachedMethod } private static Object[] makeObjectArray(Object args) { - args instanceof Object[] ? (Object[])args : [args] as Object[] + args instanceof Object[] ? (Object[]) args : [args] as Object[] } - @CompileStatic(TypeCheckingMode.SKIP) // workaround for GROOVY-6147 bug + @CompileStatic(TypeCheckingMode.SKIP) + // workaround for GROOVY-6147 bug static Object methodMissingForTagLib(MetaClass mc, Class type, TagLibraryLookup gspTagLibraryLookup, String namespace, String name, Object argsParam, boolean addMethodsToMetaClass) { Object[] args = makeObjectArray(argsParam) final GroovyObject tagBean = gspTagLibraryLookup.lookupTagLibrary(namespace, name) if (tagBean != null) { MetaClass tagBeanMc = tagBean.getMetaClass() - final MetaMethod method=tagBeanMc.respondsTo(tagBean, name, args).find{ it } + final MetaMethod method = tagBeanMc.respondsTo(tagBean, name, args).find { it } if (method != null) { if (addMethodsToMetaClass) { // add all methods with the same name to metaclass at once to prevent "wrong number of arguments" exception @@ -164,9 +166,9 @@ class TagLibraryMetaUtils { static addTagLibMethodToMetaClass(final GroovyObject tagBean, final MetaMethod method, final MetaClass mc) { Class[] paramTypes = method.nativeParameterTypes Closure methodMissingClosure = null - switch(paramTypes.length) { + switch (paramTypes.length) { case 0: - methodMissingClosure = {-> + methodMissingClosure = { -> method.invoke(tagBean, EMPTY_OBJECT_ARRAY) } break @@ -175,12 +177,12 @@ class TagLibraryMetaUtils { methodMissingClosure = { Closure body -> method.invoke(tagBean, body) } - } else if (paramTypes[0]==Map) { - methodMissingClosure = { Map attrs-> + } else if (paramTypes[0] == Map) { + methodMissingClosure = { Map attrs -> method.invoke(tagBean, attrs) } } else { - methodMissingClosure = { Object attrs-> + methodMissingClosure = { Object attrs -> method.invoke(tagBean, attrs) } } @@ -208,8 +210,8 @@ class TagLibraryMetaUtils { break } if (methodMissingClosure != null) { - synchronized(mc) { - ((GroovyObject)mc).setProperty(method.name, methodMissingClosure) + synchronized (mc) { + ((GroovyObject) mc).setProperty(method.name, methodMissingClosure) } } } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagOutput.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagOutput.java index 60e9ecfe6ad..d5bb70ab445 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagOutput.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TagOutput.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.taglib; import groovy.lang.Closure; @@ -34,7 +33,8 @@ /** * Created by lari on 16/07/14. */ -public class TagOutput { +public final class TagOutput { + public static final String APPLY_CODEC_TAG_NAME = "applyCodec"; public static final String ENCODE_AS_ATTRIBUTE_NAME = "encodeAs"; public static final Closure EMPTY_BODY_CLOSURE = new ConstantClosure(""); @@ -44,8 +44,8 @@ private TagOutput() { } @SuppressWarnings("rawtypes") - public final static Object captureTagOutput(TagLibraryLookup gspTagLibraryLookup, String namespace, - String tagName, Map attrs, Object body, OutputContext outputContext) { + public static Object captureTagOutput(TagLibraryLookup gspTagLibraryLookup, String namespace, + String tagName, Map attrs, Object body, OutputContext outputContext) { GroovyObject tagLib = lookupCachedTagLib(gspTagLibraryLookup, namespace, tagName); @@ -56,7 +56,7 @@ public final static Object captureTagOutput(TagLibraryLookup gspTagLibraryLookup if (!(attrs instanceof GroovyPageAttributes)) { attrs = new GroovyPageAttributes(attrs, false); } - ((GroovyPageAttributes)attrs).setGspTagSyntaxCall(false); + ((GroovyPageAttributes) attrs).setGspTagSyntaxCall(false); Closure actualBody = createOutputCapturingClosure(tagLib, body, outputContext); final GroovyPageTagWriter tagOutput = new GroovyPageTagWriter(); @@ -109,7 +109,7 @@ public final static Object captureTagOutput(TagLibraryLookup gspTagLibraryLookup if (returnsObject && bodyResult != null && !(bodyResult instanceof Writer)) { if (taglibEncoder != null) { - bodyResult=taglibEncoder.encode(bodyResult); + bodyResult = taglibEncoder.encode(bodyResult); } return bodyResult; } @@ -125,18 +125,20 @@ public final static Object captureTagOutput(TagLibraryLookup gspTagLibraryLookup throw new GrailsTagException("Tag [" + tagName + "] does not exist in tag library [" + tagLib.getClass().getName() + "]"); } finally { - if (outputStack != null) outputStack.pop(); + if (outputStack != null) { + outputStack.pop(); + } } } - public final static GroovyObject lookupCachedTagLib(TagLibraryLookup gspTagLibraryLookup, - String namespace, String tagName) { + public static GroovyObject lookupCachedTagLib(TagLibraryLookup gspTagLibraryLookup, + String namespace, String tagName) { return gspTagLibraryLookup != null ? gspTagLibraryLookup.lookupTagLibrary(namespace, tagName) : null; } - public final static Closure createOutputCapturingClosure(Object wrappedInstance, final Object body1, - final OutputContext outputContext) { + public static Closure createOutputCapturingClosure(Object wrappedInstance, final Object body1, + final OutputContext outputContext) { if (body1 == null) { return EMPTY_BODY_CLOSURE; } @@ -166,8 +168,9 @@ public static Map createCodecSettings(String namespace, String t @SuppressWarnings("rawtypes") public static final class ConstantClosure extends Closure { + private static final long serialVersionUID = 1L; - private static final Class[] EMPTY_CLASS_ARR=new Class[0]; + private static final Class[] EMPTY_CLASS_ARR = new Class[0]; final Object retval; public ConstantClosure(Object retval) { diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TemplateNamespacedTagDispatcher.groovy b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TemplateNamespacedTagDispatcher.groovy index 48eacd06af4..456d8dae271 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TemplateNamespacedTagDispatcher.groovy +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TemplateNamespacedTagDispatcher.groovy @@ -17,6 +17,7 @@ * under the License. */ package org.grails.taglib + import grails.core.GrailsApplication import grails.util.Environment import groovy.transform.CompileStatic @@ -24,36 +25,35 @@ import org.grails.taglib.encoder.OutputContextLookupHelper @CompileStatic class TemplateNamespacedTagDispatcher extends NamespacedTagDispatcher { - public static final String TEMPLATE_NAMESPACE = "tmpl" - private boolean developmentMode = Environment.current.isDevelopmentMode() + public static final String TEMPLATE_NAMESPACE = "tmpl" TemplateNamespacedTagDispatcher(Class callingType, GrailsApplication application, TagLibraryLookup lookup) { super(TEMPLATE_NAMESPACE, callingType, application, lookup) } def methodMissing(String name, Object args) { - ((GroovyObject)getMetaClass()).setProperty(name, { Object[] varArgs -> + ((GroovyObject) getMetaClass()).setProperty(name, { Object[] varArgs -> callRender(argsToAttrs(name, varArgs), filterBodyAttr(varArgs)) }) callRender(argsToAttrs(name, args), filterBodyAttr(args)) } - + protected void registerTagMetaMethods(ExpandoMetaClass emc) { - + } protected callRender(Map attrs, Object body) { - TagOutput.captureTagOutput(lookup, TagOutput.DEFAULT_NAMESPACE, 'render', attrs, body, OutputContextLookupHelper.lookupOutputContext() ) + TagOutput.captureTagOutput(lookup, TagOutput.DEFAULT_NAMESPACE, 'render', attrs, body, OutputContextLookupHelper.lookupOutputContext()) } protected Map argsToAttrs(String name, Object args) { Map attr = [:] attr.template = name if (args instanceof Object[]) { - Object[] tagArgs = ((Object[])args) + Object[] tagArgs = ((Object[]) args) if (tagArgs.length > 0 && tagArgs[0] instanceof Map) { - Map modelMap = (Map)tagArgs[0] + Map modelMap = (Map) tagArgs[0] Object encodeAs = modelMap.remove(TagOutput.ENCODE_AS_ATTRIBUTE_NAME) if (encodeAs != null) { attr.put(TagOutput.ENCODE_AS_ATTRIBUTE_NAME, encodeAs) @@ -63,13 +63,13 @@ class TemplateNamespacedTagDispatcher extends NamespacedTagDispatcher { } attr } - + protected Object filterBodyAttr(Object args) { if (args instanceof Object[]) { - Object[] tagArgs = ((Object[])args) + Object[] tagArgs = ((Object[]) args) if (tagArgs.length > 0) { - for(Object arg : tagArgs) { - if(!(arg instanceof Map)) { + for (Object arg : tagArgs) { + if (!(arg instanceof Map)) { return arg } } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TemplateVariableBinding.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TemplateVariableBinding.java index 0e6b4b3cd5b..d1323dd77cc 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TemplateVariableBinding.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/TemplateVariableBinding.java @@ -32,11 +32,12 @@ * @author Lari Hotari */ public class TemplateVariableBinding extends AbstractTemplateVariableBinding { - private static final Log log = LogFactory.getLog(TemplateVariableBinding.class); + + private static final Log LOG = LogFactory.getLog(TemplateVariableBinding.class); private Binding parent; private Object owner; - private Set cachedParentVariableNames=new HashSet(); + private Set cachedParentVariableNames = new HashSet(); private boolean root; public TemplateVariableBinding() { @@ -66,13 +67,17 @@ public Object getProperty(String property) { public Object getVariable(String name) { Object val = getVariablesMap().get(name); if (val == null && !getVariablesMap().containsKey(name)) { - if ("variables".equals(name)) return getVariables(); - if ("metaClass".equals(name)) return getMetaClass(); + if ("variables".equals(name)) { + return getVariables(); + } + if ("metaClass".equals(name)) { + return getMetaClass(); + } Binding variableBinding = findBindingForVariable(name); if (variableBinding != null) { val = variableBinding.getVariable(name); if (val != null) { - if (!(variableBinding instanceof AbstractTemplateVariableBinding) || ((AbstractTemplateVariableBinding)variableBinding).isVariableCachingAllowed(name)) { + if (!(variableBinding instanceof AbstractTemplateVariableBinding) || ((AbstractTemplateVariableBinding) variableBinding).isVariableCachingAllowed(name)) { // cache variable in this context since parent context cannot change during usage of this context getVariablesMap().put(name, val); cachedParentVariableNames.add(name); @@ -97,7 +102,7 @@ public void setProperty(String property, Object newValue) { public Binding findBindingForVariable(String name) { if (cachedParentVariableNames.contains(name)) { if (parent instanceof AbstractTemplateVariableBinding) { - return ((AbstractTemplateVariableBinding)parent).findBindingForVariable(name); + return ((AbstractTemplateVariableBinding) parent).findBindingForVariable(name); } return parent; } @@ -107,7 +112,7 @@ public Binding findBindingForVariable(String name) { } if (parent instanceof AbstractTemplateVariableBinding) { - return ((AbstractTemplateVariableBinding)parent).findBindingForVariable(name); + return ((AbstractTemplateVariableBinding) parent).findBindingForVariable(name); } if (parent != null && parent.getVariables().containsKey(name)) { @@ -127,12 +132,12 @@ private void internalSetVariable(Binding bindingToUse, String name, Object value if (!isReservedName(name)) { if (bindingToUse == null) { bindingToUse = findBindingForVariable(name); - if (bindingToUse == null || (bindingToUse instanceof TemplateVariableBinding && ((TemplateVariableBinding)bindingToUse).shouldUseChildBinding(this))) { + if (bindingToUse == null || (bindingToUse instanceof TemplateVariableBinding && ((TemplateVariableBinding) bindingToUse).shouldUseChildBinding(this))) { bindingToUse = this; } } if (bindingToUse instanceof AbstractTemplateVariableBinding) { - ((AbstractTemplateVariableBinding)bindingToUse).getVariablesMap().put(name, value); + ((AbstractTemplateVariableBinding) bindingToUse).getVariablesMap().put(name, value); } else { bindingToUse.getVariables().put(name, value); } @@ -142,8 +147,8 @@ private void internalSetVariable(Binding bindingToUse, String name, Object value getVariablesMap().put(name, value); } } else { - if (log.isDebugEnabled()) { - log.debug("Cannot override reserved variable '" + name + "'"); + if (LOG.isDebugEnabled()) { + LOG.debug("Cannot override reserved variable '" + name + "'"); } } } @@ -187,10 +192,10 @@ public void setRoot(boolean root) { @SuppressWarnings("unchecked") @Override public Set getVariableNames() { - Set variableNames=new HashSet(); + Set variableNames = new HashSet(); if (parent != null) { if (parent instanceof AbstractTemplateVariableBinding) { - variableNames.addAll(((AbstractTemplateVariableBinding)parent).getVariableNames()); + variableNames.addAll(((AbstractTemplateVariableBinding) parent).getVariableNames()); } else { variableNames.addAll(parent.getVariables().keySet()); } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/DefaultOutputContextLookup.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/DefaultOutputContextLookup.java index e20e900267e..a31edd326f3 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/DefaultOutputContextLookup.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/DefaultOutputContextLookup.java @@ -31,16 +31,21 @@ import java.io.Writer; public class DefaultOutputContextLookup implements OutputContextLookup, EncodingStateRegistryLookup, Ordered { - private ThreadLocal outputContextThreadLocal = new ThreadLocal(){ + + private ThreadLocal outputContextThreadLocal = new ThreadLocal() { @Override protected OutputContext initialValue() { return new DefaultOutputContext(); } }; + public DefaultOutputContextLookup() { + + } + @Override public OutputContext lookupOutputContext() { - if(EncodingStateRegistryLookupHolder.getEncodingStateRegistryLookup()==null) { + if (EncodingStateRegistryLookupHolder.getEncodingStateRegistryLookup() == null) { // TODO: improve EncodingStateRegistry solution so that global state doesn't have to be used EncodingStateRegistryLookupHolder.setEncodingStateRegistryLookup(this); } @@ -57,11 +62,8 @@ public EncodingStateRegistry lookup() { return lookupOutputContext().getEncodingStateRegistry(); } - public DefaultOutputContextLookup() { - - } - public static class DefaultOutputContext implements OutputContext { + private OutputEncodingStack outputEncodingStack; private Writer currentWriter; private AbstractTemplateVariableBinding binding; diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputContext.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputContext.java index 8205956384b..9e633d605e6 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputContext.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputContext.java @@ -28,20 +28,26 @@ * Created by lari on 02/01/15. */ public interface OutputContext { + EncodingStateRegistry getEncodingStateRegistry(); OutputEncodingStack getCurrentOutputEncodingStack(); + void setCurrentOutputEncodingStack(OutputEncodingStack outputEncodingStack); Writer getCurrentWriter(); + void setCurrentWriter(Writer writer); AbstractTemplateVariableBinding createAndRegisterRootBinding(); + AbstractTemplateVariableBinding getBinding(); + void setBinding(AbstractTemplateVariableBinding binding); GrailsApplication getGrailsApplication(); void setContentType(String contentType); + boolean isContentTypeAlreadySet(); } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputContextLookup.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputContextLookup.java index f31fbb0b430..8248f11764d 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputContextLookup.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputContextLookup.java @@ -22,5 +22,6 @@ * Created by lari on 02/01/15. */ public interface OutputContextLookup { + OutputContext lookupOutputContext(); } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputContextLookupHelper.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputContextLookupHelper.java index 59e7300d88c..3098b4f5349 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputContextLookupHelper.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputContextLookupHelper.java @@ -26,27 +26,27 @@ * @author Lari Hotari * @author Graeme Rocher */ -public class OutputContextLookupHelper { - private static final OutputContextLookup outputContextLookup; +public final class OutputContextLookupHelper { + + private static final OutputContextLookup OUTPUT_CONTEXT_LOOKUP; static { OutputContextLookup foundViaFactory = GrailsFactoriesLoader.loadFactory(OutputContextLookup.class, OutputContextLookupHelper.class.getClassLoader()); - if(foundViaFactory != null) { - outputContextLookup = foundViaFactory; - } - else { - outputContextLookup = new DefaultOutputContextLookup(); + if (foundViaFactory != null) { + OUTPUT_CONTEXT_LOOKUP = foundViaFactory; + } else { + OUTPUT_CONTEXT_LOOKUP = new DefaultOutputContextLookup(); } } - private OutputContextLookupHelper() { } public static OutputContext lookupOutputContext() { - return outputContextLookup.lookupOutputContext(); + return OUTPUT_CONTEXT_LOOKUP.lookupOutputContext(); } + public static OutputContextLookup getOutputContextLookup() { - return outputContextLookup; + return OUTPUT_CONTEXT_LOOKUP; } } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputEncodingSettings.groovy b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputEncodingSettings.groovy index 1c5155e1229..5b8f2b7fd3d 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputEncodingSettings.groovy +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputEncodingSettings.groovy @@ -22,34 +22,35 @@ import groovy.transform.CompileStatic @CompileStatic class OutputEncodingSettings { + /** scriptlet codec escapes the static html parts coming from the GSP file scriptlets to output */ - public static final String OUT_CODEC_NAME="scriptlet" + public static final String OUT_CODEC_NAME = "scriptlet" /** expression codec escapes values inside ${} to output */ - public static final String EXPRESSION_CODEC_NAME="expression" + public static final String EXPRESSION_CODEC_NAME = "expression" /** staticparts escapes the static html parts coming from the GSP file to output */ - public static final String STATIC_CODEC_NAME="staticparts" + public static final String STATIC_CODEC_NAME = "staticparts" /** taglib codec escapes taglib output */ - public static final String TAGLIB_CODEC_NAME="taglib" + public static final String TAGLIB_CODEC_NAME = "taglib" /** taglibdefault codec setting name is the fallback for taglib default codec, taglibCodec in gsp directive uses this setting internally */ - public static final String TAGLIB_DEFAULT_CODEC_NAME="taglibdefault" + public static final String TAGLIB_DEFAULT_CODEC_NAME = "taglibdefault" /** allow inheriting codecs from parent levels */ - public static final String INHERIT_SETTING_NAME="inherit" + public static final String INHERIT_SETTING_NAME = "inherit" /** only use for safe codecs for replacement */ - public static final String REPLACE_ONLY_SETTING_NAME="replaceonly" + public static final String REPLACE_ONLY_SETTING_NAME = "replaceonly" public static final String CONFIG_PROPERTY_GSP_CODECS = "grails.views.gsp.codecs" public static final String CONFIG_PROPERTY_DEFAULT_CODEC = "grails.views.default.codec" public static final Set VALID_CODEC_SETTING_NAMES = - ([OUT_CODEC_NAME, EXPRESSION_CODEC_NAME, STATIC_CODEC_NAME, TAGLIB_CODEC_NAME, TAGLIB_DEFAULT_CODEC_NAME] as Set).asImmutable() + ([OUT_CODEC_NAME, EXPRESSION_CODEC_NAME, STATIC_CODEC_NAME, TAGLIB_CODEC_NAME, TAGLIB_DEFAULT_CODEC_NAME] as Set).asImmutable() private static final Map defaultSettings = - [(EXPRESSION_CODEC_NAME): 'html', - (STATIC_CODEC_NAME): 'none', - (OUT_CODEC_NAME): 'none', - (TAGLIB_CODEC_NAME): 'none', - (TAGLIB_DEFAULT_CODEC_NAME): 'none'] + [(EXPRESSION_CODEC_NAME) : 'html', + (STATIC_CODEC_NAME) : 'none', + (OUT_CODEC_NAME) : 'none', + (TAGLIB_CODEC_NAME) : 'none', + (TAGLIB_DEFAULT_CODEC_NAME): 'none'] static String getDefaultValue(String codecName) { diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputEncodingStack.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputEncodingStack.java index 807a051b1b6..1f57907229e 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputEncodingStack.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputEncodingStack.java @@ -24,18 +24,71 @@ import org.grails.buffer.GrailsLazyProxyPrintWriter; import org.grails.buffer.GrailsLazyProxyPrintWriter.DestinationFactory; import org.grails.buffer.GrailsWrappedWriter; -import org.grails.encoder.*; +import org.grails.encoder.EncodedAppender; +import org.grails.encoder.EncodedAppenderFactory; +import org.grails.encoder.EncodedAppenderWriterFactory; +import org.grails.encoder.Encoder; +import org.grails.encoder.EncoderAware; +import org.grails.encoder.EncodingStateRegistry; +import org.grails.encoder.StreamingEncoder; +import org.grails.encoder.StreamingEncoderWriter; import java.io.IOException; import java.io.Writer; import java.util.Stack; public final class OutputEncodingStack { - public static final Log log = LogFactory.getLog(OutputEncodingStack.class); - private static final String ATTRIBUTE_NAME_OUTPUT_STACK="org.grails.taglib.encoder.OUTPUT_ENCODING_STACK"; + public static final Log LOG = LogFactory.getLog(OutputEncodingStack.class); + + private static final String ATTRIBUTE_NAME_OUTPUT_STACK = "org.grails.taglib.encoder.OUTPUT_ENCODING_STACK"; private final OutputContext outputContext; + private Stack stack = new Stack(); + private OutputProxyWriter taglibWriter; + private OutputProxyWriter outWriter; + private OutputProxyWriter staticWriter; + private OutputProxyWriter expressionWriter; + private boolean autoSync; + private EncodingStateRegistry encodingStateRegistry; + private OutputProxyWriterGroup writerGroup = new OutputProxyWriterGroup(); + + private OutputEncodingStack(OutputEncodingStackAttributes attributes) { + outWriter = new OutputProxyWriter(writerGroup, new DestinationFactory() { + public Writer activateDestination() throws IOException { + StackEntry stackEntry = stack.peek(); + return createEncodingWriter(stackEntry.unwrappedTarget, stackEntry.outEncoder, encodingStateRegistry, OutputEncodingSettings.OUT_CODEC_NAME); + } + }); + staticWriter = new OutputProxyWriter(writerGroup, new DestinationFactory() { + public Writer activateDestination() throws IOException { + StackEntry stackEntry = stack.peek(); + if (stackEntry.staticEncoder == null) { + return stackEntry.unwrappedTarget; + } + return createEncodingWriter(stackEntry.unwrappedTarget, stackEntry.staticEncoder, encodingStateRegistry, OutputEncodingSettings.STATIC_CODEC_NAME); + } + }); + expressionWriter = new OutputProxyWriter(writerGroup, new DestinationFactory() { + public Writer activateDestination() throws IOException { + StackEntry stackEntry = stack.peek(); + return createEncodingWriter(stackEntry.unwrappedTarget, stackEntry.expressionEncoder, encodingStateRegistry, OutputEncodingSettings.EXPRESSION_CODEC_NAME); + } + }); + taglibWriter = new OutputProxyWriter(writerGroup, new DestinationFactory() { + public Writer activateDestination() throws IOException { + StackEntry stackEntry = stack.peek(); + return createEncodingWriter(stackEntry.unwrappedTarget, stackEntry.taglibEncoder != null ? stackEntry.taglibEncoder : stackEntry.defaultTaglibEncoder, encodingStateRegistry, OutputEncodingSettings.TAGLIB_CODEC_NAME); + } + }); + this.autoSync = attributes.isAutoSync(); + push(attributes, false); + if (!autoSync) { + applyWriterThreadLocals(outWriter); + } + this.encodingStateRegistry = attributes.getOutputContext().getEncodingStateRegistry(); + this.outputContext = attributes.getOutputContext() != null ? attributes.getOutputContext() : OutputContextLookupHelper.lookupOutputContext(); + } public static OutputEncodingStack currentStack() { return currentStack(true); @@ -81,9 +134,9 @@ public static OutputEncodingStack currentStack(OutputEncodingStackAttributes att return null; } - private static final OutputEncodingStack createNew(OutputEncodingStackAttributes attributes) { + private static OutputEncodingStack createNew(OutputEncodingStackAttributes attributes) { if (attributes.getTopWriter() == null) { - attributes=new OutputEncodingStackAttributes.Builder(attributes).topWriter(lookupCurrentWriter(attributes.getOutputContext())).build(); + attributes = new OutputEncodingStackAttributes.Builder(attributes).topWriter(lookupCurrentWriter(attributes.getOutputContext())).build(); } OutputEncodingStack instance = new OutputEncodingStack(attributes); attributes.getOutputContext().setCurrentOutputEncodingStack(instance); @@ -95,8 +148,8 @@ private static OutputEncodingStack lookupStack(OutputContext outputContext) { return outputStack; } - public static final Writer currentWriter() { - OutputEncodingStack outputStack=currentStack(false); + public static Writer currentWriter() { + OutputEncodingStack outputStack = currentStack(false); if (outputStack != null) { return outputStack.getOutWriter(); } @@ -105,7 +158,7 @@ public static final Writer currentWriter() { } private static Writer lookupCurrentWriter() { - OutputContext outputContext=OutputContextLookupHelper.lookupOutputContext(); + OutputContext outputContext = OutputContextLookupHelper.lookupOutputContext(); return lookupCurrentWriter(outputContext); } @@ -116,142 +169,9 @@ private static Writer lookupCurrentWriter(OutputContext outputContext) { return null; } - private Stack stack = new Stack(); - private OutputProxyWriter taglibWriter; - private OutputProxyWriter outWriter; - private OutputProxyWriter staticWriter; - private OutputProxyWriter expressionWriter; - private boolean autoSync; - private EncodingStateRegistry encodingStateRegistry; - private OutputProxyWriterGroup writerGroup = new OutputProxyWriterGroup(); - - private static class StackEntry implements Cloneable { - Writer originalTarget; - Writer unwrappedTarget; - Encoder staticEncoder; - Encoder taglibEncoder; - Encoder defaultTaglibEncoder; - Encoder outEncoder; - Encoder expressionEncoder; - - StackEntry(Writer originalTarget, Writer unwrappedTarget) { - this.originalTarget = originalTarget; - this.unwrappedTarget = unwrappedTarget; - } - - @Override - public StackEntry clone() { - StackEntry newEntry = new StackEntry(originalTarget, unwrappedTarget); - newEntry.staticEncoder = staticEncoder; - newEntry.outEncoder = outEncoder; - newEntry.taglibEncoder = taglibEncoder; - newEntry.defaultTaglibEncoder = defaultTaglibEncoder; - newEntry.expressionEncoder = expressionEncoder; - return newEntry; - } - } - - static class OutputProxyWriterGroup { - OutputProxyWriter activeWriter; - - void reset() { - activateWriter(null); - } - - void activateWriter(OutputProxyWriter newWriter) { - if (newWriter != activeWriter) { - flushActive(); - activeWriter = newWriter; - } - } - - void flushActive() { - if (activeWriter != null) { - activeWriter.flush(); - } - } - } - - public class OutputProxyWriter extends GrailsLazyProxyPrintWriter implements EncodedAppenderFactory, EncoderAware { - OutputProxyWriterGroup writerGroup; - - OutputProxyWriter(OutputProxyWriterGroup writerGroup, DestinationFactory factory) { - super(factory); - this.writerGroup = writerGroup; - } - - public OutputEncodingStack getOutputStack() { - return OutputEncodingStack.this; - } - - @Override - public Writer getOut() { - writerGroup.activateWriter(this); - return super.getOut(); - } - - @Override - public EncodedAppender getEncodedAppender() { - Writer out = getOut(); - if(out instanceof EncodedAppenderFactory) { - return ((EncodedAppenderFactory)out).getEncodedAppender(); - } else if(out instanceof EncodedAppender) { - return (EncodedAppender)getOut(); - } else { - return null; - } - } - - @Override - public Encoder getEncoder() { - Writer out = getOut(); - if(out instanceof EncoderAware) { - return ((EncoderAware)out).getEncoder(); - } - return null; - } - } - - private OutputEncodingStack(OutputEncodingStackAttributes attributes) { - outWriter = new OutputProxyWriter(writerGroup, new DestinationFactory() { - public Writer activateDestination() throws IOException { - StackEntry stackEntry = stack.peek(); - return createEncodingWriter(stackEntry.unwrappedTarget, stackEntry.outEncoder, encodingStateRegistry, OutputEncodingSettings.OUT_CODEC_NAME); - } - }); - staticWriter = new OutputProxyWriter(writerGroup, new DestinationFactory() { - public Writer activateDestination() throws IOException { - StackEntry stackEntry = stack.peek(); - if (stackEntry.staticEncoder == null) { - return stackEntry.unwrappedTarget; - } - return createEncodingWriter(stackEntry.unwrappedTarget, stackEntry.staticEncoder, encodingStateRegistry, OutputEncodingSettings.STATIC_CODEC_NAME); - } - }); - expressionWriter = new OutputProxyWriter(writerGroup, new DestinationFactory() { - public Writer activateDestination() throws IOException { - StackEntry stackEntry = stack.peek(); - return createEncodingWriter(stackEntry.unwrappedTarget, stackEntry.expressionEncoder, encodingStateRegistry, OutputEncodingSettings.EXPRESSION_CODEC_NAME); - } - }); - taglibWriter = new OutputProxyWriter(writerGroup, new DestinationFactory() { - public Writer activateDestination() throws IOException { - StackEntry stackEntry = stack.peek(); - return createEncodingWriter(stackEntry.unwrappedTarget, stackEntry.taglibEncoder != null ? stackEntry.taglibEncoder : stackEntry.defaultTaglibEncoder, encodingStateRegistry, OutputEncodingSettings.TAGLIB_CODEC_NAME); - } - }); - this.autoSync = attributes.isAutoSync(); - push(attributes, false); - if (!autoSync) { - applyWriterThreadLocals(outWriter); - } - this.encodingStateRegistry = attributes.getOutputContext().getEncodingStateRegistry(); - this.outputContext = attributes.getOutputContext() != null ? attributes.getOutputContext() : OutputContextLookupHelper.lookupOutputContext(); - } - private Writer unwrapTargetWriter(Writer targetWriter) { - if (targetWriter instanceof GrailsWrappedWriter && ((GrailsWrappedWriter)targetWriter).isAllowUnwrappingOut()) { - return ((GrailsWrappedWriter)targetWriter).unwrap(); + if (targetWriter instanceof GrailsWrappedWriter && ((GrailsWrappedWriter) targetWriter).isAllowUnwrappingOut()) { + return ((GrailsWrappedWriter) targetWriter).unwrap(); } return targetWriter; } @@ -261,7 +181,7 @@ public void push(final Writer newWriter) { } public void push(final Writer newWriter, final boolean checkExisting) { - OutputEncodingStackAttributes.Builder attributesBuilder=new OutputEncodingStackAttributes.Builder(); + OutputEncodingStackAttributes.Builder attributesBuilder = new OutputEncodingStackAttributes.Builder(); attributesBuilder.inheritPreviousEncoders(true); attributesBuilder.topWriter(newWriter); push(attributesBuilder.build(), checkExisting); @@ -274,7 +194,9 @@ public void push(final OutputEncodingStackAttributes attributes) { public void push(final OutputEncodingStackAttributes attributes, final boolean checkExisting) { writerGroup.reset(); - if (checkExisting) checkExistingStack(attributes.getTopWriter()); + if (checkExisting) { + checkExistingStack(attributes.getTopWriter()); + } StackEntry previousStackEntry = null; if (stack.size() > 0) { @@ -283,9 +205,9 @@ public void push(final OutputEncodingStackAttributes attributes, final boolean c Writer topWriter = attributes.getTopWriter(); Writer unwrappedWriter = null; - if (topWriter!=null) { + if (topWriter != null) { if (topWriter instanceof OutputProxyWriter) { - topWriter = ((OutputProxyWriter)topWriter).getOut(); + topWriter = ((OutputProxyWriter) topWriter).getOut(); } unwrappedWriter = unwrapTargetWriter(topWriter); } else if (previousStackEntry != null) { @@ -312,7 +234,7 @@ public void push(final OutputEncodingStackAttributes attributes, final boolean c } private Encoder applyEncoder(Encoder newEncoder, Encoder previousEncoder, boolean allowInheriting, boolean replaceOnly) { - if (newEncoder != null && (!replaceOnly || previousEncoder==null || replaceOnly && previousEncoder.isSafe())) { + if (newEncoder != null && (!replaceOnly || previousEncoder == null || replaceOnly && previousEncoder.isSafe())) { return newEncoder; } if (allowInheriting) { @@ -325,7 +247,7 @@ private void checkExistingStack(final Writer topWriter) { if (topWriter != null) { for (StackEntry item : stack) { if (item.originalTarget == topWriter) { - log.warn("Pushed a writer to stack a second time. Writer type " + + LOG.warn("Pushed a writer to stack a second time. Writer type " + topWriter.getClass().getName(), new Exception()); } } @@ -342,11 +264,11 @@ private void resetWriters() { private Writer createEncodingWriter(Writer out, Encoder encoder, EncodingStateRegistry encodingStateRegistry, String codecWriterName) { Writer encodingWriter; if (out instanceof EncodedAppenderWriterFactory) { - encodingWriter=((EncodedAppenderWriterFactory)out).getWriterForEncoder(encoder, encodingStateRegistry); + encodingWriter = ((EncodedAppenderWriterFactory) out).getWriterForEncoder(encoder, encodingStateRegistry); } else if (encoder instanceof StreamingEncoder) { - encodingWriter=new StreamingEncoderWriter(out, (StreamingEncoder)encoder, encodingStateRegistry); + encodingWriter = new StreamingEncoderWriter(out, (StreamingEncoder) encoder, encodingStateRegistry); } else { - encodingWriter=new CodecPrintWriter(out, encoder, encodingStateRegistry); + encodingWriter = new CodecPrintWriter(out, encoder, encodingStateRegistry); } return encodingWriter; } @@ -413,7 +335,7 @@ public void restoreThreadLocalsToOriginals() { } private void applyWriterThreadLocals(Writer writer) { - if(outputContext != null) { + if (outputContext != null) { outputContext.setCurrentWriter(writer); } } @@ -425,4 +347,95 @@ public void flushActiveWriter() { public OutputContext getOutputContext() { return outputContext; } + + + public class OutputProxyWriter extends GrailsLazyProxyPrintWriter implements EncodedAppenderFactory, EncoderAware { + + OutputProxyWriterGroup writerGroup; + + OutputProxyWriter(OutputProxyWriterGroup writerGroup, DestinationFactory factory) { + super(factory); + this.writerGroup = writerGroup; + } + + public OutputEncodingStack getOutputStack() { + return OutputEncodingStack.this; + } + + @Override + public Writer getOut() { + writerGroup.activateWriter(this); + return super.getOut(); + } + + @Override + public EncodedAppender getEncodedAppender() { + Writer out = getOut(); + if (out instanceof EncodedAppenderFactory) { + return ((EncodedAppenderFactory) out).getEncodedAppender(); + } else if (out instanceof EncodedAppender) { + return (EncodedAppender) getOut(); + } else { + return null; + } + } + + @Override + public Encoder getEncoder() { + Writer out = getOut(); + if (out instanceof EncoderAware) { + return ((EncoderAware) out).getEncoder(); + } + return null; + } + } + + private static class StackEntry implements Cloneable { + + Writer originalTarget; + Writer unwrappedTarget; + Encoder staticEncoder; + Encoder taglibEncoder; + Encoder defaultTaglibEncoder; + Encoder outEncoder; + Encoder expressionEncoder; + + StackEntry(Writer originalTarget, Writer unwrappedTarget) { + this.originalTarget = originalTarget; + this.unwrappedTarget = unwrappedTarget; + } + + @Override + public StackEntry clone() { + StackEntry newEntry = new StackEntry(originalTarget, unwrappedTarget); + newEntry.staticEncoder = staticEncoder; + newEntry.outEncoder = outEncoder; + newEntry.taglibEncoder = taglibEncoder; + newEntry.defaultTaglibEncoder = defaultTaglibEncoder; + newEntry.expressionEncoder = expressionEncoder; + return newEntry; + } + } + + static class OutputProxyWriterGroup { + + OutputProxyWriter activeWriter; + + void reset() { + activateWriter(null); + } + + void activateWriter(OutputProxyWriter newWriter) { + if (newWriter != activeWriter) { + flushActive(); + activeWriter = newWriter; + } + } + + void flushActive() { + if (activeWriter != null) { + activeWriter.flush(); + } + } + } } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputEncodingStackAttributes.java b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputEncodingStackAttributes.java index 4cf5d7706bb..c89d15b5f3e 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputEncodingStackAttributes.java +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/OutputEncodingStackAttributes.java @@ -22,7 +22,8 @@ import java.io.Writer; -public class OutputEncodingStackAttributes { +public final class OutputEncodingStackAttributes { + private final Writer topWriter; private final Encoder staticEncoder; private final Encoder outEncoder; @@ -36,10 +37,25 @@ public class OutputEncodingStackAttributes { private final boolean replaceOnly; private final OutputContext outputContext; + private OutputEncodingStackAttributes(Builder builder) { + this.topWriter = builder.topWriter; + this.staticEncoder = builder.staticEncoder; + this.outEncoder = builder.outEncoder; + this.taglibEncoder = builder.taglibEncoder; + this.defaultTaglibEncoder = builder.defaultTaglibEncoder; + this.expressionEncoder = builder.expressionEncoder; + this.allowCreate = builder.allowCreate; + this.pushTop = builder.pushTop; + this.autoSync = builder.autoSync; + this.outputContext = builder.outputContext; + this.inheritPreviousEncoders = builder.inheritPreviousEncoders; + this.replaceOnly = builder.replaceOnly; + } + public boolean isInheritPreviousEncoders() { return inheritPreviousEncoders; } - + public boolean isReplaceOnly() { return replaceOnly; } @@ -85,18 +101,19 @@ public OutputContext getOutputContext() { } public static class Builder { + private Writer topWriter; private Encoder staticEncoder; private Encoder outEncoder; private Encoder expressionEncoder; private Encoder taglibEncoder; private Encoder defaultTaglibEncoder; - private boolean allowCreate=true; - private boolean pushTop=true; - private boolean autoSync=true; + private boolean allowCreate = true; + private boolean pushTop = true; + private boolean autoSync = true; private OutputContext outputContext; - private boolean inheritPreviousEncoders=false; - private boolean replaceOnly=false; + private boolean inheritPreviousEncoders = false; + private boolean replaceOnly = false; public Builder() { } @@ -165,7 +182,7 @@ public Builder inheritPreviousEncoders(boolean inheritPreviousEncoders) { this.inheritPreviousEncoders = inheritPreviousEncoders; return this; } - + public Builder replaceOnly(boolean replaceOnly) { this.replaceOnly = replaceOnly; return this; @@ -180,19 +197,4 @@ public OutputEncodingStackAttributes build() { return new OutputEncodingStackAttributes(this); } } - - private OutputEncodingStackAttributes(Builder builder) { - this.topWriter = builder.topWriter; - this.staticEncoder = builder.staticEncoder; - this.outEncoder = builder.outEncoder; - this.taglibEncoder = builder.taglibEncoder; - this.defaultTaglibEncoder = builder.defaultTaglibEncoder; - this.expressionEncoder = builder.expressionEncoder; - this.allowCreate = builder.allowCreate; - this.pushTop = builder.pushTop; - this.autoSync = builder.autoSync; - this.outputContext = builder.outputContext; - this.inheritPreviousEncoders = builder.inheritPreviousEncoders; - this.replaceOnly = builder.replaceOnly; - } } diff --git a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/WithCodecHelper.groovy b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/WithCodecHelper.groovy index c5376bdcd7c..7e66131a0c0 100644 --- a/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/WithCodecHelper.groovy +++ b/grails-gsp/grails-taglib/src/main/groovy/org/grails/taglib/encoder/WithCodecHelper.groovy @@ -18,8 +18,8 @@ */ package org.grails.taglib.encoder -import groovy.transform.CompileStatic import grails.core.GrailsApplication +import groovy.transform.CompileStatic import groovy.util.logging.Commons import org.grails.encoder.CodecLookupHelper import org.grails.encoder.Encoder @@ -42,7 +42,6 @@ class WithCodecHelper { private static final String ALREADY_CANONICAL_KEY_NAME = "_canonical_" - /** * Executes closure with given codecs. * @@ -72,7 +71,7 @@ class WithCodecHelper { * @return the return value of the closure */ static T withCodec(GrailsApplication grailsApplication, Object codecInfo, Closure closure) { - OutputEncodingStack outputStack=OutputEncodingStack.currentStack() + OutputEncodingStack outputStack = OutputEncodingStack.currentStack() try { outputStack.push(createOutputStackAttributesBuilder(codecInfo, grailsApplication).build(), false) return closure.call() @@ -89,7 +88,7 @@ class WithCodecHelper { * @return the builder instance for building {@link OutputEncodingStackAttributes} instance */ static Builder createOutputStackAttributesBuilder(Object codecInfo, GrailsApplication grailsApplication) { - Builder builder=new Builder() + Builder builder = new Builder() builder.inheritPreviousEncoders(true) if (codecInfo != null) { Map codecInfoMap = makeSettingsCanonical(codecInfo) @@ -100,10 +99,10 @@ class WithCodecHelper { encoders.put(codecNameString, lookupEncoder(grailsApplication, codecNameString)) } } - builder.outEncoder(lookupEncoderFromMap(encoders, (String)codecInfoMap.get(OutputEncodingSettings.OUT_CODEC_NAME))) - builder.taglibEncoder(lookupEncoderFromMap(encoders, (String)codecInfoMap.get(OutputEncodingSettings.TAGLIB_CODEC_NAME))) - builder.expressionEncoder(lookupEncoderFromMap(encoders, (String)codecInfoMap.get(OutputEncodingSettings.EXPRESSION_CODEC_NAME))) - builder.staticEncoder(lookupEncoderFromMap(encoders, (String)codecInfoMap.get(OutputEncodingSettings.STATIC_CODEC_NAME))) + builder.outEncoder(lookupEncoderFromMap(encoders, (String) codecInfoMap.get(OutputEncodingSettings.OUT_CODEC_NAME))) + builder.taglibEncoder(lookupEncoderFromMap(encoders, (String) codecInfoMap.get(OutputEncodingSettings.TAGLIB_CODEC_NAME))) + builder.expressionEncoder(lookupEncoderFromMap(encoders, (String) codecInfoMap.get(OutputEncodingSettings.EXPRESSION_CODEC_NAME))) + builder.staticEncoder(lookupEncoderFromMap(encoders, (String) codecInfoMap.get(OutputEncodingSettings.STATIC_CODEC_NAME))) if (codecInfoMap.containsKey(OutputEncodingSettings.INHERIT_SETTING_NAME)) { builder.inheritPreviousEncoders(codecInfoMap.get(OutputEncodingSettings.INHERIT_SETTING_NAME) as boolean) } @@ -118,10 +117,10 @@ class WithCodecHelper { if (!codecInfo) { return null } - Map codecInfoMap =[:] + Map codecInfoMap = [:] if (codecInfo instanceof Map) { if (codecInfo.get(ALREADY_CANONICAL_KEY_NAME)) { - return (Map)codecInfo + return (Map) codecInfo } String allFallback = null String nameFallback = null @@ -130,7 +129,7 @@ class WithCodecHelper { if (codecWriterName == OutputEncodingSettings.INHERIT_SETTING_NAME || codecWriterName == OutputEncodingSettings.REPLACE_ONLY_SETTING_NAME) { codecInfoMap.put(codecWriterName, convertToBoolean(v)) } else { - String codecName=v?.toString() ?: 'none' + String codecName = v?.toString() ?: 'none' if (OutputEncodingSettings.VALID_CODEC_SETTING_NAMES.contains(codecWriterName)) { codecInfoMap.put(codecWriterName, codecName) } else if (codecWriterName == WithCodecHelper.ALL_CODECS_FALLBACK_KEY_NAME) { @@ -142,8 +141,8 @@ class WithCodecHelper { } if (allFallback || nameFallback) { - for(String codecWriterName : OutputEncodingSettings.VALID_CODEC_SETTING_NAMES) { - String codecName=codecInfoMap.get(codecWriterName)?.toString() + for (String codecWriterName : OutputEncodingSettings.VALID_CODEC_SETTING_NAMES) { + String codecName = codecInfoMap.get(codecWriterName)?.toString() if (!codecName) { if (nameFallback && codecWriterName != OutputEncodingSettings.STATIC_CODEC_NAME) { codecName = nameFallback @@ -156,7 +155,7 @@ class WithCodecHelper { } } else { String codecName = codecInfo.toString() - for(String codecWriterName : OutputEncodingSettings.VALID_CODEC_SETTING_NAMES) { + for (String codecWriterName : OutputEncodingSettings.VALID_CODEC_SETTING_NAMES) { if (codecWriterName != OutputEncodingSettings.STATIC_CODEC_NAME) { codecInfoMap.put(codecWriterName, codecName) } @@ -168,7 +167,7 @@ class WithCodecHelper { private static boolean convertToBoolean(v) { Boolean booleanValue = v as Boolean - if (booleanValue && v instanceof CharSequence && (v.toString()=="false" || v.toString()=="no")) { + if (booleanValue && v instanceof CharSequence && (v.toString() == "false" || v.toString() == "no")) { booleanValue = false } return booleanValue @@ -183,7 +182,7 @@ class WithCodecHelper { } static Map mergeSettingsAndMakeCanonical(Object currentSettings, - Map parentSettings) { + Map parentSettings) { Map codecInfoMap if (currentSettings) { Map canonicalCodecInfo = makeSettingsCanonical(currentSettings) @@ -194,7 +193,7 @@ class WithCodecHelper { } else { codecInfoMap = canonicalCodecInfo } - codecInfoMap = (Map)codecInfoMap.asImmutable() + codecInfoMap = (Map) codecInfoMap.asImmutable() } if (codecInfoMap == null) { codecInfoMap = parentSettings diff --git a/grails-gsp/grails-web-gsp-taglib/build.gradle b/grails-gsp/grails-web-gsp-taglib/build.gradle index 6c2deb3629b..e0b1b4341fe 100644 --- a/grails-gsp/grails-web-gsp-taglib/build.gradle +++ b/grails-gsp/grails-web-gsp-taglib/build.gradle @@ -63,4 +63,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-gsp/grails-web-gsp-taglib/src/main/groovy/org/grails/plugins/web/taglib/RenderTagLib.groovy b/grails-gsp/grails-web-gsp-taglib/src/main/groovy/org/grails/plugins/web/taglib/RenderTagLib.groovy index 46818cd160c..4b1fcc58153 100644 --- a/grails-gsp/grails-web-gsp-taglib/src/main/groovy/org/grails/plugins/web/taglib/RenderTagLib.groovy +++ b/grails-gsp/grails-web-gsp-taglib/src/main/groovy/org/grails/plugins/web/taglib/RenderTagLib.groovy @@ -83,7 +83,7 @@ class RenderTagLib implements TagLibrary { if (!(attrs?.exception instanceof Throwable)) { return } - Throwable exception = (Throwable)attrs.exception + Throwable exception = (Throwable) attrs.exception Encoder htmlEncoder = codecLookup.lookupEncoder('HTML') diff --git a/grails-gsp/grails-web-gsp-taglib/src/main/groovy/org/grails/web/pages/StandaloneTagLibraryLookup.java b/grails-gsp/grails-web-gsp-taglib/src/main/groovy/org/grails/web/pages/StandaloneTagLibraryLookup.java index 92df55b3b96..5e52feafc7f 100644 --- a/grails-gsp/grails-web-gsp-taglib/src/main/groovy/org/grails/web/pages/StandaloneTagLibraryLookup.java +++ b/grails-gsp/grails-web-gsp-taglib/src/main/groovy/org/grails/web/pages/StandaloneTagLibraryLookup.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.grails.web.pages; import grails.core.gsp.GrailsTagLibClass; @@ -26,19 +25,24 @@ import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; -import java.util.*; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; /** - * GSP TagLibraryLookup class that's used for standalone GSP - * + * GSP TagLibraryLookup class that's used for standalone GSP + * * @author Lari Hotari * @since 2.4.0 */ -public class StandaloneTagLibraryLookup extends TagLibraryLookup implements ApplicationListener { +public final class StandaloneTagLibraryLookup extends TagLibraryLookup implements ApplicationListener { + Set tagLibInstancesSet; - + private StandaloneTagLibraryLookup() { - + } public void afterPropertiesSet() { @@ -47,8 +51,8 @@ public void afterPropertiesSet() { } protected void registerTagLibraries() { - if(tagLibInstancesSet != null) { - for(Object tagLibInstance : tagLibInstancesSet) { + if (tagLibInstancesSet != null) { + for (Object tagLibInstance : tagLibInstancesSet) { registerTagLib(new DefaultGrailsTagLibClass(tagLibInstance.getClass())); } } @@ -56,8 +60,8 @@ protected void registerTagLibraries() { @Override protected void putTagLib(Map tags, String name, GrailsTagLibClass taglib) { - for(Object tagLibInstance : tagLibInstancesSet) { - if(tagLibInstance.getClass() == taglib.getClazz()) { + for (Object tagLibInstance : tagLibInstancesSet) { + if (tagLibInstance.getClass() == taglib.getClazz()) { tags.put(name, tagLibInstance); break; } @@ -75,15 +79,15 @@ public void onApplicationEvent(ContextRefreshedEvent event) { } public void detectAndRegisterTabLibBeans() { - if(tagLibInstancesSet==null) { + if (tagLibInstancesSet == null) { tagLibInstancesSet = new LinkedHashSet(); } Collection detectedInstances = applicationContext.getBeansWithAnnotation(TagLib.class).values(); - for(Object instance : detectedInstances) { - if(!tagLibInstancesSet.contains(instance)) { + for (Object instance : detectedInstances) { + if (!tagLibInstancesSet.contains(instance)) { tagLibInstancesSet.add(instance); registerTagLib(new DefaultGrailsTagLibClass(instance.getClass())); } } } -} \ No newline at end of file +} diff --git a/grails-gsp/grails-web-gsp/build.gradle b/grails-gsp/grails-web-gsp/build.gradle index ffc612da768..5be4c4f0a21 100644 --- a/grails-gsp/grails-web-gsp/build.gradle +++ b/grails-gsp/grails-web-gsp/build.gradle @@ -131,4 +131,5 @@ apply { from rootProject.layout.projectDirectory.file('gradle/docs-config.gradle') from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') + from rootProject.layout.projectDirectory.file('gradle/style-enforcement-config.gradle') } diff --git a/grails-gsp/grails-web-gsp/src/main/groovy/grails/gsp/PageRenderer.groovy b/grails-gsp/grails-web-gsp/src/main/groovy/grails/gsp/PageRenderer.groovy index fe587baed7b..4cbe185844b 100644 --- a/grails-gsp/grails-web-gsp/src/main/groovy/grails/gsp/PageRenderer.groovy +++ b/grails-gsp/grails-web-gsp/src/main/groovy/grails/gsp/PageRenderer.groovy @@ -18,20 +18,20 @@ */ package grails.gsp +import jakarta.servlet.ServletContext +import jakarta.servlet.http.Cookie +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse import org.grails.buffer.FastStringWriter import org.grails.gsp.GroovyPagesTemplateEngine -import org.grails.web.gsp.io.GrailsConventionGroovyPageLocator import org.grails.gsp.io.GroovyPageScriptSource +import org.grails.web.gsp.io.GrailsConventionGroovyPageLocator import org.grails.web.servlet.mvc.GrailsWebRequest import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContextAware import org.springframework.web.context.ServletContextAware import org.springframework.web.context.request.RequestContextHolder -import jakarta.servlet.ServletContext -import jakarta.servlet.http.Cookie -import jakarta.servlet.http.HttpServletRequest -import jakarta.servlet.http.HttpServletResponse import java.lang.reflect.InvocationHandler import java.lang.reflect.Method import java.lang.reflect.Proxy @@ -119,8 +119,8 @@ class PageRenderer implements ApplicationContextAware, ServletContextAware { try { def localeToUse = locale ?: (oldRequestAttributes?.locale ?: Locale.default) def webRequest = new GrailsWebRequest(PageRenderRequestCreator.createInstance(source.URI, localeToUse), - PageRenderResponseCreator.createInstance(writer instanceof PrintWriter ? writer : new PrintWriter(writer), localeToUse), - servletContext, applicationContext) + PageRenderResponseCreator.createInstance(writer instanceof PrintWriter ? writer : new PrintWriter(writer), localeToUse), + servletContext, applicationContext) RequestContextHolder.setRequestAttributes(webRequest) def template = templateEngine.createTemplate(source) if (template != null) { @@ -139,6 +139,7 @@ class PageRenderer implements ApplicationContextAware, ServletContextAware { * Creates the request object used during the GSP rendering pipeline for render operations outside a web request. * Created dynamically to avoid issues with different servlet API spec versions. */ + static class PageRenderRequestCreator { static HttpServletRequest createInstance(final String requestURI, Locale localeToUse = Locale.getDefault()) { @@ -149,7 +150,8 @@ class PageRenderer implements ApplicationContextAware, ServletContextAware { String contentType = null String characterEncoding = "UTF-8" - (HttpServletRequest)Proxy.newProxyInstance(HttpServletRequest.classLoader, [HttpServletRequest] as Class[], new InvocationHandler() { + (HttpServletRequest) Proxy.newProxyInstance(HttpServletRequest.classLoader, [HttpServletRequest] as Class[], new InvocationHandler() { + Object invoke(proxy, Method method, Object[] args) { String methodName = method.name @@ -209,8 +211,8 @@ class PageRenderer implements ApplicationContextAware, ServletContextAware { return true } if (methodName in [ - 'isRequestedSessionIdFromCookie', 'isRequestedSessionIdFromURL', 'isRequestedSessionIdFromUrl', - 'authenticate', 'isUserInRole', 'isSecure', 'isAsyncStarted', 'isAsyncSupported']) { + 'isRequestedSessionIdFromCookie', 'isRequestedSessionIdFromURL', 'isRequestedSessionIdFromUrl', + 'authenticate', 'isUserInRole', 'isSecure', 'isAsyncStarted', 'isAsyncSupported']) { return false } @@ -306,9 +308,10 @@ class PageRenderer implements ApplicationContextAware, ServletContextAware { } }) } - + private static Enumeration iteratorAsEnumeration(Iterator iterator) { new Enumeration() { + @Override boolean hasMoreElements() { iterator.hasNext() @@ -330,7 +333,8 @@ class PageRenderer implements ApplicationContextAware, ServletContextAware { String contentType = null int bufferSize = 0 - (HttpServletResponse)Proxy.newProxyInstance(HttpServletResponse.classLoader, [HttpServletResponse] as Class[], new InvocationHandler() { + (HttpServletResponse) Proxy.newProxyInstance(HttpServletResponse.classLoader, [HttpServletResponse] as Class[], new InvocationHandler() { + Object invoke(proxy, Method method, Object[] args) { String methodName = method.name diff --git a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/gsp/GroovyPagesTemplateRenderer.java b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/gsp/GroovyPagesTemplateRenderer.java index b5ac1dd70f7..f12fd803971 100644 --- a/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/gsp/GroovyPagesTemplateRenderer.java +++ b/grails-gsp/grails-web-gsp/src/main/groovy/org/grails/web/gsp/GroovyPagesTemplateRenderer.java @@ -63,19 +63,19 @@ /** * Service that provides the actual implementation to RenderTagLib's render tag. - * + *

    * This is an internal Grails service and should not be used by plugins directly. * The implementation was moved from RenderTagLib, ported to Java and then refactored. * * @author Lari Hotari * @author Graeme Rocher - * * @since 2.0 */ public class GroovyPagesTemplateRenderer implements InitializingBean { + private GrailsConventionGroovyPageLocator groovyPageLocator; private GroovyPagesTemplateEngine groovyPagesTemplateEngine; - private ConcurrentMap> templateCache = new ConcurrentHashMap>(); + private ConcurrentMap> templateCache = new ConcurrentHashMap>(); private Object scaffoldingTemplateGenerator; private Map> scaffoldedActionMap; private Map controllerToScaffoldedDomainClassMap; @@ -86,8 +86,8 @@ public class GroovyPagesTemplateRenderer implements InitializingBean { public void afterPropertiesSet() throws Exception { if (scaffoldingTemplateGenerator != null) { // use reflection to locate method (would cause cyclic dependency otherwise) - generateViewMethod = ReflectionUtils.findMethod(scaffoldingTemplateGenerator.getClass(), "generateView", new Class[] { - GrailsDomainClass.class, String.class, Writer.class}); + generateViewMethod = ReflectionUtils.findMethod(scaffoldingTemplateGenerator.getClass(), "generateView", new Class[]{ + GrailsDomainClass.class, String.class, Writer.class}); } } @@ -129,18 +129,18 @@ public void render(GrailsWebRequest webRequest, TemplateVariableBinding pageScop // required for binary compatibility: GRAILS-11598 private Template findAndCacheTemplate(Object controller, GrailsWebRequest webRequest, GroovyPageBinding pageScope, String templateName, - String contextPath, String pluginName, String uri) throws IOException { + String contextPath, String pluginName, String uri) throws IOException { return findAndCacheTemplate(controller, pageScope, templateName, contextPath, pluginName, uri); } private Template findAndCacheTemplate(Object controller, TemplateVariableBinding pageScope, String templateName, - String contextPath, String pluginName, final String uri) throws IOException { + String contextPath, String pluginName, final String uri) throws IOException { String templatePath = GrailsStringUtils.isNotEmpty(contextPath) ? GrailsResourceUtils.appendPiecesForUri(contextPath, templateName) : templateName; final GroovyPageScriptSource scriptSource; if (pluginName == null) { scriptSource = groovyPageLocator.findTemplateInBinding(controller, templatePath, pageScope); - } else { + } else { scriptSource = groovyPageLocator.findTemplateInBinding(controller, pluginName, templatePath, pageScope); } @@ -148,10 +148,9 @@ private Template findAndCacheTemplate(Object controller, TemplateVariableBinding if (scriptSource == null) { cacheKey = contextPath + pluginName + uri; } else { - if(pluginName != null) { + if (pluginName != null) { cacheKey = contextPath + pluginName + scriptSource.getURI(); - } - else { + } else { cacheKey = scriptSource.getURI(); } } @@ -167,15 +166,15 @@ public CacheEntry