From 433764d2179e649dc869b759551c467c19be543a Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 17 Aug 2016 00:47:50 +0200 Subject: [PATCH] GroovyScriptFactory supports CompilationCustomizer next to GroovyObjectCustomizer Issue: SPR-14585 --- .../scripting/groovy/GroovyScriptFactory.java | 49 ++++++++++++++++--- .../scripting/groovy/MyImportCustomizer.java | 30 ++++++++++++ .../scripting/groovy/groovy-with-xsd.xml | 16 +++--- src/asciidoc/integration.adoc | 13 +++-- 4 files changed, 88 insertions(+), 20 deletions(-) create mode 100644 spring-context/src/test/java/org/springframework/scripting/groovy/MyImportCustomizer.java diff --git a/spring-context/src/main/java/org/springframework/scripting/groovy/GroovyScriptFactory.java b/spring-context/src/main/java/org/springframework/scripting/groovy/GroovyScriptFactory.java index c0b1a5033d..cbade53fbb 100644 --- a/spring-context/src/main/java/org/springframework/scripting/groovy/GroovyScriptFactory.java +++ b/spring-context/src/main/java/org/springframework/scripting/groovy/GroovyScriptFactory.java @@ -24,6 +24,8 @@ import groovy.lang.GroovyObject; import groovy.lang.MetaClass; import groovy.lang.Script; import org.codehaus.groovy.control.CompilationFailedException; +import org.codehaus.groovy.control.CompilerConfiguration; +import org.codehaus.groovy.control.customizers.CompilationCustomizer; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanFactory; @@ -57,7 +59,9 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea private final String scriptSourceLocator; - private final GroovyObjectCustomizer groovyObjectCustomizer; + private GroovyObjectCustomizer groovyObjectCustomizer; + + private CompilerConfiguration compilerConfiguration; private GroovyClassLoader groovyClassLoader; @@ -80,27 +84,46 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea * Interpreted by the post-processor that actually creates the script. */ public GroovyScriptFactory(String scriptSourceLocator) { - this(scriptSourceLocator, null); + Assert.hasText(scriptSourceLocator, "'scriptSourceLocator' must not be empty"); + this.scriptSourceLocator = scriptSourceLocator; } /** * Create a new GroovyScriptFactory for the given script source, * specifying a strategy interface that can create a custom MetaClass * to supply missing methods and otherwise change the behavior of the object. - *

We don't need to specify script interfaces here, since - * a Groovy script defines its Java interfaces itself. * @param scriptSourceLocator a locator that points to the source of the script. * Interpreted by the post-processor that actually creates the script. * @param groovyObjectCustomizer a customizer that can set a custom metaclass * or make other changes to the GroovyObject created by this factory * (may be {@code null}) + * @see GroovyObjectCustomizer#customize */ public GroovyScriptFactory(String scriptSourceLocator, GroovyObjectCustomizer groovyObjectCustomizer) { - Assert.hasText(scriptSourceLocator, "'scriptSourceLocator' must not be empty"); - this.scriptSourceLocator = scriptSourceLocator; + this(scriptSourceLocator); this.groovyObjectCustomizer = groovyObjectCustomizer; } + /** + * Create a new GroovyScriptFactory for the given script source, + * specifying a strategy interface that can customize Groovy's compilation + * process within the underlying GroovyClassLoader. + * @param scriptSourceLocator a locator that points to the source of the script. + * Interpreted by the post-processor that actually creates the script. + * @param compilationCustomizer a customizer to be applied to the GroovyClassLoader + * compiler configuration (may be {@code null}) + * @since 4.3.3 + * @see CompilerConfiguration#addCompilationCustomizers + * @see org.codehaus.groovy.control.customizers.ImportCustomizer + */ + public GroovyScriptFactory(String scriptSourceLocator, CompilationCustomizer compilationCustomizer) { + this(scriptSourceLocator); + if (compilationCustomizer != null) { + this.compilerConfiguration = new CompilerConfiguration(); + this.compilerConfiguration.addCompilationCustomizers(compilationCustomizer); + } + } + @Override public void setBeanFactory(BeanFactory beanFactory) { @@ -111,7 +134,7 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea @Override public void setBeanClassLoader(ClassLoader classLoader) { - this.groovyClassLoader = new GroovyClassLoader(classLoader); + this.groovyClassLoader = buildGroovyClassLoader(classLoader); } /** @@ -120,12 +143,22 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea public GroovyClassLoader getGroovyClassLoader() { synchronized (this.scriptClassMonitor) { if (this.groovyClassLoader == null) { - this.groovyClassLoader = new GroovyClassLoader(ClassUtils.getDefaultClassLoader()); + this.groovyClassLoader = buildGroovyClassLoader(ClassUtils.getDefaultClassLoader()); } return this.groovyClassLoader; } } + /** + * Build a {@link GroovyClassLoader} for the given {@code ClassLoader}. + * @param classLoader the ClassLoader to build a GroovyClassLoader for + * @since 4.3.3 + */ + protected GroovyClassLoader buildGroovyClassLoader(ClassLoader classLoader) { + return (this.compilerConfiguration != null ? + new GroovyClassLoader(classLoader, this.compilerConfiguration) : new GroovyClassLoader(classLoader)); + } + @Override public String getScriptSourceLocator() { diff --git a/spring-context/src/test/java/org/springframework/scripting/groovy/MyImportCustomizer.java b/spring-context/src/test/java/org/springframework/scripting/groovy/MyImportCustomizer.java new file mode 100644 index 0000000000..24160f5083 --- /dev/null +++ b/spring-context/src/test/java/org/springframework/scripting/groovy/MyImportCustomizer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2002-2016 the original author or authors. + * + * 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 + * + * http://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.springframework.scripting.groovy; + +import org.codehaus.groovy.control.customizers.ImportCustomizer; + +/** + * @author Juergen Hoeller + */ +public class MyImportCustomizer extends ImportCustomizer { + + public MyImportCustomizer() { + addStarImports("org.springframework.scripting.groovy"); + } + +} diff --git a/spring-context/src/test/resources/org/springframework/scripting/groovy/groovy-with-xsd.xml b/spring-context/src/test/resources/org/springframework/scripting/groovy/groovy-with-xsd.xml index a573d6a2e0..648464ccec 100644 --- a/spring-context/src/test/resources/org/springframework/scripting/groovy/groovy-with-xsd.xml +++ b/spring-context/src/test/resources/org/springframework/scripting/groovy/groovy-with-xsd.xml @@ -2,7 +2,7 @@ @@ -24,7 +24,7 @@ - + package org.springframework.scripting.groovy; import org.springframework.scripting.Calculator @@ -36,10 +36,8 @@ class GroovyCalculator implements Calculator { - + + + - - - + + + diff --git a/src/asciidoc/integration.adoc b/src/asciidoc/integration.adoc index dfe99bb3f4..a9408103f1 100644 --- a/src/asciidoc/integration.adoc +++ b/src/asciidoc/integration.adoc @@ -7639,7 +7639,6 @@ set some default property values, or specify a custom `MetaClass`. public interface GroovyObjectCustomizer { void customize(GroovyObject goo); - } ---- @@ -7678,12 +7677,12 @@ of a `GroovyObjectCustomizer` is easy if you are using the Spring namespace supp [subs="verbatim,quotes"] ---- - + + customizer-ref="tracingCustomizer"/> ---- If you are not using the Spring namespace support, you can still use the @@ -7696,13 +7695,19 @@ If you are not using the Spring namespace support, you can still use the - + ---- +[NOTE] +==== +As of Spring Framework 4.3.3, you may also specify a Groovy `CompilationCustomizer` type +such as an `ImportCustomizer` in the same place as Spring's `GroovyObjectCustomizer`. +==== + [[dynamic-language-beans-bsh]]