From dfb29f4296cb77e6b09511547ced382f62c0c78f Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sat, 26 Oct 2013 01:17:32 +0200 Subject: [PATCH] Introduced ScriptEvaluator strategy interface Including ScriptEvaluator implementations for JSR-223, Groovy and BeanShell. BeanShell consistently receives the bean ClassLoader now. Also revised ScriptFactory and its implementations for varargs. Issue: SPR-11007 --- .../scripting/ScriptEvaluator.java | 54 +++++++ .../scripting/ScriptFactory.java | 8 +- .../scripting/bsh/BshScriptEvaluator.java | 89 ++++++++++++ .../scripting/bsh/BshScriptFactory.java | 23 +-- .../scripting/bsh/BshScriptUtils.java | 17 ++- .../scripting/bsh/package-info.java | 1 + .../groovy/GroovyScriptEvaluator.java | 76 ++++++++++ .../scripting/groovy/GroovyScriptFactory.java | 16 +-- .../scripting/jruby/JRubyScriptFactory.java | 10 +- .../scripting/jruby/JRubyScriptUtils.java | 17 ++- .../support/ResourceScriptSource.java | 58 ++++---- .../support/StandardScriptEvaluator.java | 135 ++++++++++++++++++ .../bsh/BshScriptEvaluatorTests.java | 60 ++++++++ .../scripting/bsh/BshScriptFactoryTests.java | 7 +- .../springframework/scripting/bsh/simple.bsh | 1 + .../scripting/groovy/GroovyAspectTests.java | 8 +- .../groovy/GroovyScriptEvaluatorTests.java | 87 +++++++++++ .../groovy/GroovyScriptFactoryTests.java | 54 ++++--- .../scripting/groovy/simple.groovy | 1 + .../jruby/JRubyScriptFactoryTests.java | 8 +- .../support/ResourceScriptSourceTests.java | 9 -- 21 files changed, 629 insertions(+), 110 deletions(-) create mode 100644 spring-context/src/main/java/org/springframework/scripting/ScriptEvaluator.java create mode 100644 spring-context/src/main/java/org/springframework/scripting/bsh/BshScriptEvaluator.java create mode 100644 spring-context/src/main/java/org/springframework/scripting/groovy/GroovyScriptEvaluator.java create mode 100644 spring-context/src/main/java/org/springframework/scripting/support/StandardScriptEvaluator.java create mode 100644 spring-context/src/test/java/org/springframework/scripting/bsh/BshScriptEvaluatorTests.java create mode 100644 spring-context/src/test/java/org/springframework/scripting/bsh/simple.bsh create mode 100644 spring-context/src/test/java/org/springframework/scripting/groovy/GroovyScriptEvaluatorTests.java create mode 100644 spring-context/src/test/java/org/springframework/scripting/groovy/simple.groovy diff --git a/spring-context/src/main/java/org/springframework/scripting/ScriptEvaluator.java b/spring-context/src/main/java/org/springframework/scripting/ScriptEvaluator.java new file mode 100644 index 0000000000..eb5e115a22 --- /dev/null +++ b/spring-context/src/main/java/org/springframework/scripting/ScriptEvaluator.java @@ -0,0 +1,54 @@ +/* + * Copyright 2002-2013 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; + +import java.util.Map; + +/** + * Spring's strategy interface for evaluating a script. + * + *

Aside from language-specific implementations, Spring also ships + * a version based on the standard {@code javax.script} package (JSR-223): + * {@link org.springframework.scripting.support.StandardScriptEvaluator}. + * + * @author Juergen Hoeller + * @author Costin Leau + * @since 4.0 + */ +public interface ScriptEvaluator { + + /** + * Evaluate the given script. + * @param script the ScriptSource for the script to evaluate + * @return the return value of the script, if any + * @throws ScriptCompilationException if the evaluator failed to read, + * compile or evaluate the script + */ + Object evaluate(ScriptSource script) throws ScriptCompilationException; + + /** + * Evaluate the given script with the given arguments. + * @param script the ScriptSource for the script to evaluate + * @param arguments the key-value pairs to expose to the script, + * typically as script variables. May be {@code null}. + * @return the return value of the script, if any + * @throws ScriptCompilationException if the evaluator failed to read, + * compile or evaluate the script + */ + Object evaluate(ScriptSource script, Map arguments) throws ScriptCompilationException; + +} diff --git a/spring-context/src/main/java/org/springframework/scripting/ScriptFactory.java b/spring-context/src/main/java/org/springframework/scripting/ScriptFactory.java index 2e2f255ae7..dc835a60ff 100644 --- a/spring-context/src/main/java/org/springframework/scripting/ScriptFactory.java +++ b/spring-context/src/main/java/org/springframework/scripting/ScriptFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -49,7 +49,7 @@ public interface ScriptFactory { * its Java interfaces (such as in the case of Groovy). * @return the interfaces for the script */ - Class[] getScriptInterfaces(); + Class[] getScriptInterfaces(); /** * Return whether the script requires a config interface to be @@ -75,7 +75,7 @@ public interface ScriptFactory { * @throws IOException if script retrieval failed * @throws ScriptCompilationException if script compilation failed */ - Object getScriptedObject(ScriptSource scriptSource, Class[] actualInterfaces) + Object getScriptedObject(ScriptSource scriptSource, Class... actualInterfaces) throws IOException, ScriptCompilationException; /** @@ -91,7 +91,7 @@ public interface ScriptFactory { * @throws ScriptCompilationException if script compilation failed * @since 2.0.3 */ - Class getScriptedObjectType(ScriptSource scriptSource) + Class getScriptedObjectType(ScriptSource scriptSource) throws IOException, ScriptCompilationException; /** diff --git a/spring-context/src/main/java/org/springframework/scripting/bsh/BshScriptEvaluator.java b/spring-context/src/main/java/org/springframework/scripting/bsh/BshScriptEvaluator.java new file mode 100644 index 0000000000..83e3f0fee5 --- /dev/null +++ b/spring-context/src/main/java/org/springframework/scripting/bsh/BshScriptEvaluator.java @@ -0,0 +1,89 @@ +/* + * Copyright 2002-2013 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.bsh; + +import java.io.IOException; +import java.io.StringReader; +import java.util.Map; + +import bsh.EvalError; +import bsh.Interpreter; + +import org.springframework.beans.factory.BeanClassLoaderAware; +import org.springframework.scripting.ScriptCompilationException; +import org.springframework.scripting.ScriptEvaluator; +import org.springframework.scripting.ScriptSource; + +/** + * BeanShell-based implementation of Spring's {@link ScriptEvaluator} strategy interface. + * + * @author Juergen Hoeller + * @since 4.0 + * @see Interpreter#eval(String) + */ +public class BshScriptEvaluator implements ScriptEvaluator, BeanClassLoaderAware { + + private ClassLoader classLoader; + + + /** + * Construct a new BshScriptEvaluator. + */ + public BshScriptEvaluator() { + } + + /** + * Construct a new BshScriptEvaluator. + * @param classLoader the ClassLoader to use for the {@link Interpreter} + */ + public BshScriptEvaluator(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + + @Override + public void setBeanClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + + @Override + public Object evaluate(ScriptSource script) { + return evaluate(script, null); + } + + @Override + public Object evaluate(ScriptSource script, Map arguments) { + try { + Interpreter interpreter = new Interpreter(); + interpreter.setClassLoader(this.classLoader); + if (arguments != null) { + for (Map.Entry entry : arguments.entrySet()) { + interpreter.set(entry.getKey(), entry.getValue()); + } + } + return interpreter.eval(new StringReader(script.getScriptAsString())); + } + catch (IOException ex) { + throw new ScriptCompilationException(script, "Cannot access script", ex); + } + catch (EvalError ex) { + throw new ScriptCompilationException(script, "Evaluation failure", ex); + } + } + +} diff --git a/spring-context/src/main/java/org/springframework/scripting/bsh/BshScriptFactory.java b/spring-context/src/main/java/org/springframework/scripting/bsh/BshScriptFactory.java index f22a9a50a8..278e051298 100644 --- a/spring-context/src/main/java/org/springframework/scripting/bsh/BshScriptFactory.java +++ b/spring-context/src/main/java/org/springframework/scripting/bsh/BshScriptFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -45,11 +45,11 @@ public class BshScriptFactory implements ScriptFactory, BeanClassLoaderAware { private final String scriptSourceLocator; - private final Class[] scriptInterfaces; + private final Class[] scriptInterfaces; private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); - private Class scriptClass; + private Class scriptClass; private final Object scriptClassMonitor = new Object(); @@ -64,7 +64,9 @@ public class BshScriptFactory implements ScriptFactory, BeanClassLoaderAware { * Interpreted by the post-processor that actually creates the script. */ public BshScriptFactory(String scriptSourceLocator) { - this(scriptSourceLocator, null); + Assert.hasText(scriptSourceLocator, "'scriptSourceLocator' must not be empty"); + this.scriptSourceLocator = scriptSourceLocator; + this.scriptInterfaces = null; } /** @@ -78,7 +80,7 @@ public class BshScriptFactory implements ScriptFactory, BeanClassLoaderAware { * @param scriptInterfaces the Java interfaces that the scripted object * is supposed to implement (may be {@code null}) */ - public BshScriptFactory(String scriptSourceLocator, Class[] scriptInterfaces) { + public BshScriptFactory(String scriptSourceLocator, Class... scriptInterfaces) { Assert.hasText(scriptSourceLocator, "'scriptSourceLocator' must not be empty"); this.scriptSourceLocator = scriptSourceLocator; this.scriptInterfaces = scriptInterfaces; @@ -96,7 +98,7 @@ public class BshScriptFactory implements ScriptFactory, BeanClassLoaderAware { } @Override - public Class[] getScriptInterfaces() { + public Class[] getScriptInterfaces() { return this.scriptInterfaces; } @@ -113,11 +115,11 @@ public class BshScriptFactory implements ScriptFactory, BeanClassLoaderAware { * @see BshScriptUtils#createBshObject(String, Class[], ClassLoader) */ @Override - public Object getScriptedObject(ScriptSource scriptSource, Class[] actualInterfaces) + public Object getScriptedObject(ScriptSource scriptSource, Class... actualInterfaces) throws IOException, ScriptCompilationException { try { - Class clazz = null; + Class clazz; synchronized (this.scriptClassMonitor) { boolean requiresScriptEvaluation = (this.wasModifiedForTypeCheck && this.scriptClass == null); @@ -165,7 +167,7 @@ public class BshScriptFactory implements ScriptFactory, BeanClassLoaderAware { } @Override - public Class getScriptedObjectType(ScriptSource scriptSource) + public Class getScriptedObjectType(ScriptSource scriptSource) throws IOException, ScriptCompilationException { try { @@ -173,7 +175,8 @@ public class BshScriptFactory implements ScriptFactory, BeanClassLoaderAware { if (scriptSource.isModified()) { // New script content: Let's check whether it evaluates to a Class. this.wasModifiedForTypeCheck = true; - this.scriptClass = BshScriptUtils.determineBshObjectType(scriptSource.getScriptAsString()); + this.scriptClass = BshScriptUtils.determineBshObjectType( + scriptSource.getScriptAsString(), this.beanClassLoader); } return this.scriptClass; } diff --git a/spring-context/src/main/java/org/springframework/scripting/bsh/BshScriptUtils.java b/spring-context/src/main/java/org/springframework/scripting/bsh/BshScriptUtils.java index 1ad320493c..a7562ee308 100644 --- a/spring-context/src/main/java/org/springframework/scripting/bsh/BshScriptUtils.java +++ b/spring-context/src/main/java/org/springframework/scripting/bsh/BshScriptUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -66,7 +66,7 @@ public abstract class BshScriptUtils { * @throws EvalError in case of BeanShell parsing failure * @see #createBshObject(String, Class[], ClassLoader) */ - public static Object createBshObject(String scriptSource, Class[] scriptInterfaces) throws EvalError { + public static Object createBshObject(String scriptSource, Class... scriptInterfaces) throws EvalError { return createBshObject(scriptSource, scriptInterfaces, ClassUtils.getDefaultClassLoader()); } @@ -80,11 +80,11 @@ public abstract class BshScriptUtils { * @param scriptInterfaces the interfaces that the scripted Java object is * supposed to implement (may be {@code null} or empty if the script itself * declares a full class or returns an actual instance of the scripted object) - * @param classLoader the ClassLoader to create the script proxy with + * @param classLoader the ClassLoader to use for evaluating the script * @return the scripted Java object * @throws EvalError in case of BeanShell parsing failure */ - public static Object createBshObject(String scriptSource, Class[] scriptInterfaces, ClassLoader classLoader) + public static Object createBshObject(String scriptSource, Class[] scriptInterfaces, ClassLoader classLoader) throws EvalError { Object result = evaluateBshScript(scriptSource, scriptInterfaces, classLoader); @@ -110,12 +110,14 @@ public abstract class BshScriptUtils { * the scripted object (in which case the Class of the object will be returned). * In any other case, the returned Class will be {@code null}. * @param scriptSource the script source text + * @param classLoader the ClassLoader to use for evaluating the script * @return the scripted Java class, or {@code null} if none could be determined * @throws EvalError in case of BeanShell parsing failure */ - static Class determineBshObjectType(String scriptSource) throws EvalError { + static Class determineBshObjectType(String scriptSource, ClassLoader classLoader) throws EvalError { Assert.hasText(scriptSource, "Script source must not be empty"); Interpreter interpreter = new Interpreter(); + interpreter.setClassLoader(classLoader); Object result = interpreter.eval(scriptSource); if (result instanceof Class) { return (Class) result; @@ -139,15 +141,16 @@ public abstract class BshScriptUtils { * @param scriptInterfaces the interfaces that the scripted Java object is * supposed to implement (may be {@code null} or empty if the script itself * declares a full class or returns an actual instance of the scripted object) - * @param classLoader the ClassLoader to create the script proxy with + * @param classLoader the ClassLoader to use for evaluating the script * @return the scripted Java class or Java object * @throws EvalError in case of BeanShell parsing failure */ - static Object evaluateBshScript(String scriptSource, Class[] scriptInterfaces, ClassLoader classLoader) + static Object evaluateBshScript(String scriptSource, Class[] scriptInterfaces, ClassLoader classLoader) throws EvalError { Assert.hasText(scriptSource, "Script source must not be empty"); Interpreter interpreter = new Interpreter(); + interpreter.setClassLoader(classLoader); Object result = interpreter.eval(scriptSource); if (result != null) { return result; diff --git a/spring-context/src/main/java/org/springframework/scripting/bsh/package-info.java b/spring-context/src/main/java/org/springframework/scripting/bsh/package-info.java index 74d100a958..2dba974b66 100644 --- a/spring-context/src/main/java/org/springframework/scripting/bsh/package-info.java +++ b/spring-context/src/main/java/org/springframework/scripting/bsh/package-info.java @@ -3,6 +3,7 @@ * * Package providing integration of * BeanShell + * (and BeanShell2) * into Spring's scripting infrastructure. * */ diff --git a/spring-context/src/main/java/org/springframework/scripting/groovy/GroovyScriptEvaluator.java b/spring-context/src/main/java/org/springframework/scripting/groovy/GroovyScriptEvaluator.java new file mode 100644 index 0000000000..fbcd7a0512 --- /dev/null +++ b/spring-context/src/main/java/org/springframework/scripting/groovy/GroovyScriptEvaluator.java @@ -0,0 +1,76 @@ +package org.springframework.scripting.groovy; + +import java.io.IOException; +import java.util.Collections; +import java.util.Map; + +import groovy.lang.Binding; +import groovy.lang.GroovyShell; +import org.codehaus.groovy.control.CompilationFailedException; + +import org.springframework.beans.factory.BeanClassLoaderAware; +import org.springframework.scripting.ScriptCompilationException; +import org.springframework.scripting.ScriptEvaluator; +import org.springframework.scripting.ScriptSource; +import org.springframework.scripting.support.ResourceScriptSource; + +/** + * Groovy-based implementation of Spring's {@link ScriptEvaluator} strategy interface. + * + * @author Juergen Hoeller + * @since 4.0 + * @see GroovyShell#evaluate(String, String) + */ +public class GroovyScriptEvaluator implements ScriptEvaluator, BeanClassLoaderAware { + + private ClassLoader classLoader; + + + /** + * Construct a new GroovyScriptEvaluator. + */ + public GroovyScriptEvaluator() { + } + + /** + * Construct a new GroovyScriptEvaluator. + * @param classLoader the ClassLoader to use as a parent for the {@link GroovyShell} + */ + public GroovyScriptEvaluator(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + + @Override + public void setBeanClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + + @Override + public Object evaluate(ScriptSource script) { + return evaluate(script, null); + } + + @Override + public Object evaluate(ScriptSource script, Map arguments) { + GroovyShell groovyShell = new GroovyShell(this.classLoader, new Binding(arguments)); + try { + String filename = (script instanceof ResourceScriptSource ? + ((ResourceScriptSource) script).getResource().getFilename() : null); + if (filename != null) { + return groovyShell.evaluate(script.getScriptAsString(), filename); + } + else { + return groovyShell.evaluate(script.getScriptAsString()); + } + } + catch (IOException ex) { + throw new ScriptCompilationException(script, "Cannot access script", ex); + } + catch (CompilationFailedException ex) { + throw new ScriptCompilationException(script, "Evaluation failure", ex); + } + } + +} 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 4afac28b07..fdaa876c08 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 @@ -43,7 +43,7 @@ import org.springframework.util.ClassUtils; * {@link org.springframework.scripting.support.ScriptFactoryPostProcessor}; * see the latter's javadoc} for a configuration example. * - *

Note: Spring 4.0 supports Groovy 1.7 and higher. + *

Note: Spring 4.0 supports Groovy 1.8 and higher. * * @author Juergen Hoeller * @author Rob Harrop @@ -60,9 +60,9 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea private GroovyClassLoader groovyClassLoader; - private Class scriptClass; + private Class scriptClass; - private Class scriptResultClass; + private Class scriptResultClass; private CachedResultHolder cachedResult; @@ -137,7 +137,7 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea * @return {@code null} always */ @Override - public Class[] getScriptInterfaces() { + public Class[] getScriptInterfaces() { return null; } @@ -156,11 +156,11 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea * @see groovy.lang.GroovyClassLoader */ @Override - public Object getScriptedObject(ScriptSource scriptSource, Class[] actualInterfaces) + public Object getScriptedObject(ScriptSource scriptSource, Class... actualInterfaces) throws IOException, ScriptCompilationException { try { - Class scriptClassToExecute = null; + Class scriptClassToExecute; synchronized (this.scriptClassMonitor) { this.wasModifiedForTypeCheck = false; @@ -198,7 +198,7 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea } @Override - public Class getScriptedObjectType(ScriptSource scriptSource) + public Class getScriptedObjectType(ScriptSource scriptSource) throws IOException, ScriptCompilationException { try { @@ -243,7 +243,7 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea * or the result of running the script instance) * @throws ScriptCompilationException in case of instantiation failure */ - protected Object executeScript(ScriptSource scriptSource, Class scriptClass) throws ScriptCompilationException { + protected Object executeScript(ScriptSource scriptSource, Class scriptClass) throws ScriptCompilationException { try { GroovyObject goo = (GroovyObject) scriptClass.newInstance(); diff --git a/spring-context/src/main/java/org/springframework/scripting/jruby/JRubyScriptFactory.java b/spring-context/src/main/java/org/springframework/scripting/jruby/JRubyScriptFactory.java index a3d59c6acd..5a7b625f67 100644 --- a/spring-context/src/main/java/org/springframework/scripting/jruby/JRubyScriptFactory.java +++ b/spring-context/src/main/java/org/springframework/scripting/jruby/JRubyScriptFactory.java @@ -49,7 +49,7 @@ public class JRubyScriptFactory implements ScriptFactory, BeanClassLoaderAware { private final String scriptSourceLocator; - private final Class[] scriptInterfaces; + private final Class[] scriptInterfaces; private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); @@ -61,7 +61,7 @@ public class JRubyScriptFactory implements ScriptFactory, BeanClassLoaderAware { * @param scriptInterfaces the Java interfaces that the scripted object * is supposed to implement */ - public JRubyScriptFactory(String scriptSourceLocator, Class[] scriptInterfaces) { + public JRubyScriptFactory(String scriptSourceLocator, Class... scriptInterfaces) { Assert.hasText(scriptSourceLocator, "'scriptSourceLocator' must not be empty"); Assert.notEmpty(scriptInterfaces, "'scriptInterfaces' must not be empty"); this.scriptSourceLocator = scriptSourceLocator; @@ -81,7 +81,7 @@ public class JRubyScriptFactory implements ScriptFactory, BeanClassLoaderAware { } @Override - public Class[] getScriptInterfaces() { + public Class[] getScriptInterfaces() { return this.scriptInterfaces; } @@ -98,7 +98,7 @@ public class JRubyScriptFactory implements ScriptFactory, BeanClassLoaderAware { * @see JRubyScriptUtils#createJRubyObject(String, Class[], ClassLoader) */ @Override - public Object getScriptedObject(ScriptSource scriptSource, Class[] actualInterfaces) + public Object getScriptedObject(ScriptSource scriptSource, Class... actualInterfaces) throws IOException, ScriptCompilationException { try { return JRubyScriptUtils.createJRubyObject( @@ -116,7 +116,7 @@ public class JRubyScriptFactory implements ScriptFactory, BeanClassLoaderAware { } @Override - public Class getScriptedObjectType(ScriptSource scriptSource) + public Class getScriptedObjectType(ScriptSource scriptSource) throws IOException, ScriptCompilationException { return null; diff --git a/spring-context/src/main/java/org/springframework/scripting/jruby/JRubyScriptUtils.java b/spring-context/src/main/java/org/springframework/scripting/jruby/JRubyScriptUtils.java index 6b46af7474..fcee64821e 100644 --- a/spring-context/src/main/java/org/springframework/scripting/jruby/JRubyScriptUtils.java +++ b/spring-context/src/main/java/org/springframework/scripting/jruby/JRubyScriptUtils.java @@ -63,7 +63,7 @@ public abstract class JRubyScriptUtils { * @throws JumpException in case of JRuby parsing failure * @see ClassUtils#getDefaultClassLoader() */ - public static Object createJRubyObject(String scriptSource, Class[] interfaces) throws JumpException { + public static Object createJRubyObject(String scriptSource, Class... interfaces) throws JumpException { return createJRubyObject(scriptSource, interfaces, ClassUtils.getDefaultClassLoader()); } @@ -75,8 +75,7 @@ public abstract class JRubyScriptUtils { * @return the scripted Java object * @throws JumpException in case of JRuby parsing failure */ - @SuppressWarnings("deprecation") - public static Object createJRubyObject(String scriptSource, Class[] interfaces, ClassLoader classLoader) { + public static Object createJRubyObject(String scriptSource, Class[] interfaces, ClassLoader classLoader) { Ruby ruby = initializeRuntime(); Node scriptRootNode = ruby.parseEval(scriptSource, "", null, 0); @@ -131,16 +130,16 @@ public abstract class JRubyScriptUtils { } else if (child instanceof NewlineNode) { NewlineNode nn = (NewlineNode) child; - Node found = findClassNode(nn.getNextNode()); - if (found instanceof ClassNode) { - return (ClassNode) found; + ClassNode found = findClassNode(nn.getNextNode()); + if (found != null) { + return found; } } } for (Node child : children) { - Node found = findClassNode(child); - if (found instanceof ClassNode) { - return (ClassNode) found; + ClassNode found = findClassNode(child); + if (found != null) { + return found; } } return null; diff --git a/spring-context/src/main/java/org/springframework/scripting/support/ResourceScriptSource.java b/spring-context/src/main/java/org/springframework/scripting/support/ResourceScriptSource.java index 5c778d3920..75bc8ccb93 100644 --- a/spring-context/src/main/java/org/springframework/scripting/support/ResourceScriptSource.java +++ b/spring-context/src/main/java/org/springframework/scripting/support/ResourceScriptSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -18,12 +18,13 @@ package org.springframework.scripting.support; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.Reader; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.core.io.Resource; +import org.springframework.core.io.support.EncodedResource; import org.springframework.scripting.ScriptSource; import org.springframework.util.Assert; import org.springframework.util.FileCopyUtils; @@ -49,41 +50,56 @@ public class ResourceScriptSource implements ScriptSource { /** Logger available to subclasses */ protected final Log logger = LogFactory.getLog(getClass()); - private final Resource resource; + private EncodedResource resource; private long lastModified = -1; private final Object lastModifiedMonitor = new Object(); - private String encoding = "UTF-8"; /** * Create a new ResourceScriptSource for the given resource. - * @param resource the Resource to load the script from + * @param resource the EncodedResource to load the script from */ - public ResourceScriptSource(Resource resource) { + public ResourceScriptSource(EncodedResource resource) { Assert.notNull(resource, "Resource must not be null"); this.resource = resource; } + /** + * Create a new ResourceScriptSource for the given resource. + * @param resource the Resource to load the script from (using UTF-8 encoding) + */ + public ResourceScriptSource(Resource resource) { + Assert.notNull(resource, "Resource must not be null"); + this.resource = new EncodedResource(resource, "UTF-8"); + } + + /** * Return the {@link org.springframework.core.io.Resource} to load the * script from. */ public final Resource getResource() { - return this.resource; + return this.resource.getResource(); } + /** + * Set the encoding used for reading the script resource. + *

The default value for regular Resources is "UTF-8". + * A {@code null} value implies the platform default. + */ + public void setEncoding(String encoding) { + this.resource = new EncodedResource(this.resource.getResource(), encoding); + } + + @Override public String getScriptAsString() throws IOException { synchronized (this.lastModifiedMonitor) { this.lastModified = retrieveLastModifiedTime(); } - - InputStream stream = this.resource.getInputStream(); - Reader reader = (StringUtils.hasText(encoding) ? new InputStreamReader(stream, encoding) - : new InputStreamReader(stream)); - + Reader reader = this.resource.getReader(); return FileCopyUtils.copyToString(reader); } @@ -101,10 +117,11 @@ public class ResourceScriptSource implements ScriptSource { protected long retrieveLastModifiedTime() { try { return getResource().lastModified(); - } catch (IOException ex) { + } + catch (IOException ex) { if (logger.isDebugEnabled()) { - logger.debug(getResource() + " could not be resolved in the file system - " - + "current timestamp not available for script modification check", ex); + logger.debug(getResource() + " could not be resolved in the file system - " + + "current timestamp not available for script modification check", ex); } return 0; } @@ -115,18 +132,9 @@ public class ResourceScriptSource implements ScriptSource { return StringUtils.stripFilenameExtension(getResource().getFilename()); } - /** - * Sets the encoding used for reading the script resource. The default value is "UTF-8". - * A null value, implies the platform default. - * - * @param encoding charset encoding used for reading the script. - */ - public void setEncoding(String encoding) { - this.encoding = encoding; - } - @Override public String toString() { return this.resource.toString(); } + } diff --git a/spring-context/src/main/java/org/springframework/scripting/support/StandardScriptEvaluator.java b/spring-context/src/main/java/org/springframework/scripting/support/StandardScriptEvaluator.java new file mode 100644 index 0000000000..6fc2a6ad8d --- /dev/null +++ b/spring-context/src/main/java/org/springframework/scripting/support/StandardScriptEvaluator.java @@ -0,0 +1,135 @@ +/* + * Copyright 2002-2013 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.support; + +import java.io.IOException; +import java.util.Map; +import javax.script.Bindings; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import javax.script.SimpleBindings; + +import org.springframework.beans.factory.BeanClassLoaderAware; +import org.springframework.core.io.Resource; +import org.springframework.scripting.ScriptCompilationException; +import org.springframework.scripting.ScriptEvaluator; +import org.springframework.scripting.ScriptSource; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +/** + * {@code javax.script} (JSR-223) based implementation of + * Spring's {@link ScriptEvaluator} strategy interface. + * + * @author Juergen Hoeller + * @author Costin Leau + * @since 4.0 + * @see ScriptEngine#eval(String) + */ +public class StandardScriptEvaluator implements ScriptEvaluator, BeanClassLoaderAware { + + private volatile ScriptEngineManager scriptEngineManager; + + private String language; + + + /** + * Construct a new StandardScriptEvaluator. + */ + public StandardScriptEvaluator() { + } + + /** + * Construct a new StandardScriptEvaluator. + * @param classLoader the class loader to use for script engine detection + */ + public StandardScriptEvaluator(ClassLoader classLoader) { + this.scriptEngineManager = new ScriptEngineManager(classLoader); + } + + + @Override + public void setBeanClassLoader(ClassLoader classLoader) { + this.scriptEngineManager = new ScriptEngineManager(classLoader); + } + + /** + * Set the name of language meant for evaluation the scripts (e.g. "Groovy"). + */ + public void setLanguage(String language) { + this.language = language; + } + + + @Override + public Object evaluate(ScriptSource script) { + return evaluate(script, null); + } + + @Override + public Object evaluate(ScriptSource script, Map arguments) { + ScriptEngine engine = getScriptEngine(script); + Bindings bindings = (!CollectionUtils.isEmpty(arguments) ? new SimpleBindings(arguments) : null); + try { + return (bindings != null ? engine.eval(script.getScriptAsString(), bindings) : + engine.eval(script.getScriptAsString())); + } + catch (IOException ex) { + throw new ScriptCompilationException(script, "Cannot access script", ex); + } + catch (ScriptException ex) { + throw new ScriptCompilationException(script, "Evaluation failure", ex); + } + } + + /** + * Obtain the JSR-223 ScriptEngine to use for the given script. + * @param script the script to evaluate + * @return the ScriptEngine (never {@code null}) + */ + protected ScriptEngine getScriptEngine(ScriptSource script) { + if (this.scriptEngineManager == null) { + this.scriptEngineManager = new ScriptEngineManager(); + } + if (StringUtils.hasText(this.language)) { + ScriptEngine engine = this.scriptEngineManager.getEngineByName(this.language); + if (engine == null) { + throw new IllegalStateException("No matching engine found for language '" + this.language + "'"); + } + return engine; + } + else if (script instanceof ResourceScriptSource) { + Resource resource = ((ResourceScriptSource) script).getResource(); + String extension = StringUtils.getFilenameExtension(resource.getFilename()); + if (extension == null) { + throw new IllegalStateException( + "No script language defined, and no file extension defined for resource: " + resource); + } + ScriptEngine engine = this.scriptEngineManager.getEngineByExtension(extension); + if (engine == null) { + throw new IllegalStateException("No matching engine found for file extension '" + extension + "'"); + } + return engine; + } + else { + throw new IllegalStateException( + "No script language defined, and no resource associated with script: " + script); + } + } + +} diff --git a/spring-context/src/test/java/org/springframework/scripting/bsh/BshScriptEvaluatorTests.java b/spring-context/src/test/java/org/springframework/scripting/bsh/BshScriptEvaluatorTests.java new file mode 100644 index 0000000000..a325658f31 --- /dev/null +++ b/spring-context/src/test/java/org/springframework/scripting/bsh/BshScriptEvaluatorTests.java @@ -0,0 +1,60 @@ +/* + * Copyright 2002-2013 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.bsh; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.scripting.ScriptEvaluator; +import org.springframework.scripting.support.ResourceScriptSource; +import org.springframework.scripting.support.StaticScriptSource; + +import static org.junit.Assert.*; + +/** + * @author Juergen Hoeller + */ +public class BshScriptEvaluatorTests { + + @Test + public void testBshScriptFromString() { + ScriptEvaluator evaluator = new BshScriptEvaluator(); + Object result = evaluator.evaluate(new StaticScriptSource("return 3 * 2;")); + assertEquals(6, result); + } + + @Test + public void testBshScriptFromFile() { + ScriptEvaluator evaluator = new BshScriptEvaluator(); + Object result = evaluator.evaluate(new ResourceScriptSource(new ClassPathResource("simple.bsh", getClass()))); + assertEquals(6, result); + } + + @Test + public void testGroovyScriptWithArguments() { + ScriptEvaluator evaluator = new BshScriptEvaluator(); + Map arguments = new HashMap(); + arguments.put("a", 3); + arguments.put("b", 2); + Object result = evaluator.evaluate(new StaticScriptSource("return a * b;"), arguments); + assertEquals(6, result); + } + +} diff --git a/spring-context/src/test/java/org/springframework/scripting/bsh/BshScriptFactoryTests.java b/spring-context/src/test/java/org/springframework/scripting/bsh/BshScriptFactoryTests.java index 93b33b48bc..b2469698f1 100644 --- a/spring-context/src/test/java/org/springframework/scripting/bsh/BshScriptFactoryTests.java +++ b/spring-context/src/test/java/org/springframework/scripting/bsh/BshScriptFactoryTests.java @@ -195,10 +195,9 @@ public class BshScriptFactoryTests extends TestCase { given(script.getScriptAsString()).willReturn(badScript); given(script.isModified()).willReturn(true); BshScriptFactory factory = new BshScriptFactory( - ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript, - new Class[] {Messenger.class}); + ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript, Messenger.class); try { - Messenger messenger = (Messenger) factory.getScriptedObject(script, new Class[]{Messenger.class}); + Messenger messenger = (Messenger) factory.getScriptedObject(script, Messenger.class); messenger.getMessage(); fail("Must have thrown a BshScriptUtils.BshExecutionException."); } @@ -208,7 +207,7 @@ public class BshScriptFactoryTests extends TestCase { public void testCtorWithNullScriptSourceLocator() throws Exception { try { - new BshScriptFactory(null, new Class[] {Messenger.class}); + new BshScriptFactory(null, Messenger.class); fail("Must have thrown exception by this point."); } catch (IllegalArgumentException expected) { diff --git a/spring-context/src/test/java/org/springframework/scripting/bsh/simple.bsh b/spring-context/src/test/java/org/springframework/scripting/bsh/simple.bsh new file mode 100644 index 0000000000..9f5e0b6a8a --- /dev/null +++ b/spring-context/src/test/java/org/springframework/scripting/bsh/simple.bsh @@ -0,0 +1 @@ +return 3 * 2; diff --git a/spring-context/src/test/java/org/springframework/scripting/groovy/GroovyAspectTests.java b/spring-context/src/test/java/org/springframework/scripting/groovy/GroovyAspectTests.java index fa15ef7bfd..789cbe7624 100644 --- a/spring-context/src/test/java/org/springframework/scripting/groovy/GroovyAspectTests.java +++ b/spring-context/src/test/java/org/springframework/scripting/groovy/GroovyAspectTests.java @@ -25,7 +25,7 @@ public class GroovyAspectTests { GroovyScriptFactory scriptFactory = new GroovyScriptFactory("GroovyServiceImpl.grv"); TestService target = (TestService) scriptFactory.getScriptedObject(new ResourceScriptSource( - new ClassPathResource("GroovyServiceImpl.grv", getClass())), null); + new ClassPathResource("GroovyServiceImpl.grv", getClass()))); testAdvice(new DefaultPointcutAdvisor(logAdvice), logAdvice, target, "GroovyServiceImpl"); @@ -37,7 +37,7 @@ public class GroovyAspectTests { GroovyScriptFactory scriptFactory = new GroovyScriptFactory("GroovyServiceImpl.grv"); TestService target = (TestService) scriptFactory.getScriptedObject(new ResourceScriptSource( - new ClassPathResource("GroovyServiceImpl.grv", getClass())), null); + new ClassPathResource("GroovyServiceImpl.grv", getClass()))); AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); pointcut.setExpression(String.format("execution(* %s.TestService+.*(..))", ClassUtils.getPackageName(getClass()))); @@ -51,7 +51,7 @@ public class GroovyAspectTests { GroovyScriptFactory scriptFactory = new GroovyScriptFactory("GroovyServiceImpl.grv"); TestService target = (TestService) scriptFactory.getScriptedObject(new ResourceScriptSource( - new ClassPathResource("GroovyServiceImpl.grv", getClass())), null); + new ClassPathResource("GroovyServiceImpl.grv", getClass()))); AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); pointcut.setExpression(String.format("@within(%s.Log)", ClassUtils.getPackageName(getClass()))); @@ -66,7 +66,7 @@ public class GroovyAspectTests { GroovyScriptFactory scriptFactory = new GroovyScriptFactory("GroovyServiceImpl.grv"); TestService target = (TestService) scriptFactory.getScriptedObject(new ResourceScriptSource( - new ClassPathResource("GroovyServiceImpl.grv", getClass())), null); + new ClassPathResource("GroovyServiceImpl.grv", getClass()))); AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); pointcut.setExpression(String.format("@within(%s.Log)", ClassUtils.getPackageName(getClass()))); diff --git a/spring-context/src/test/java/org/springframework/scripting/groovy/GroovyScriptEvaluatorTests.java b/spring-context/src/test/java/org/springframework/scripting/groovy/GroovyScriptEvaluatorTests.java new file mode 100644 index 0000000000..14ab7aa356 --- /dev/null +++ b/spring-context/src/test/java/org/springframework/scripting/groovy/GroovyScriptEvaluatorTests.java @@ -0,0 +1,87 @@ +/* + * Copyright 2002-2013 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 java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.scripting.ScriptEvaluator; +import org.springframework.scripting.support.ResourceScriptSource; +import org.springframework.scripting.support.StandardScriptEvaluator; +import org.springframework.scripting.support.StaticScriptSource; + +import static org.junit.Assert.*; + +/** + * @author Juergen Hoeller + */ +public class GroovyScriptEvaluatorTests { + + @Test + public void testGroovyScriptFromString() { + ScriptEvaluator evaluator = new GroovyScriptEvaluator(); + Object result = evaluator.evaluate(new StaticScriptSource("return 3 * 2")); + assertEquals(6, result); + } + + @Test + public void testGroovyScriptFromFile() { + ScriptEvaluator evaluator = new GroovyScriptEvaluator(); + Object result = evaluator.evaluate(new ResourceScriptSource(new ClassPathResource("simple.groovy", getClass()))); + assertEquals(6, result); + } + + @Test + public void testGroovyScriptWithArguments() { + ScriptEvaluator evaluator = new GroovyScriptEvaluator(); + Map arguments = new HashMap(); + arguments.put("a", 3); + arguments.put("b", 2); + Object result = evaluator.evaluate(new StaticScriptSource("return a * b"), arguments); + assertEquals(6, result); + } + + @Test + public void testGroovyScriptFromStringUsingJsr223() { + StandardScriptEvaluator evaluator = new StandardScriptEvaluator(); + evaluator.setLanguage("Groovy"); + Object result = evaluator.evaluate(new StaticScriptSource("return 3 * 2")); + assertEquals(6, result); + } + + @Test + public void testGroovyScriptFromFileUsingJsr223() { + ScriptEvaluator evaluator = new StandardScriptEvaluator(); + Object result = evaluator.evaluate(new ResourceScriptSource(new ClassPathResource("simple.groovy", getClass()))); + assertEquals(6, result); + } + + @Test + public void testGroovyScriptWithArgumentsUsingJsr223() { + StandardScriptEvaluator evaluator = new StandardScriptEvaluator(); + evaluator.setLanguage("Groovy"); + Map arguments = new HashMap(); + arguments.put("a", 3); + arguments.put("b", 2); + Object result = evaluator.evaluate(new StaticScriptSource("return a * b"), arguments); + assertEquals(6, result); + } + +} diff --git a/spring-context/src/test/java/org/springframework/scripting/groovy/GroovyScriptFactoryTests.java b/spring-context/src/test/java/org/springframework/scripting/groovy/GroovyScriptFactoryTests.java index 7ced7671ce..8c01b785af 100644 --- a/spring-context/src/test/java/org/springframework/scripting/groovy/GroovyScriptFactoryTests.java +++ b/spring-context/src/test/java/org/springframework/scripting/groovy/GroovyScriptFactoryTests.java @@ -16,16 +16,16 @@ package org.springframework.scripting.groovy; -import groovy.lang.DelegatingMetaClass; -import groovy.lang.GroovyObject; - import java.io.FileNotFoundException; import java.util.Arrays; import java.util.Map; +import groovy.lang.DelegatingMetaClass; +import groovy.lang.GroovyObject; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; + import org.springframework.aop.support.AopUtils; import org.springframework.aop.target.dynamic.Refreshable; import org.springframework.beans.factory.BeanCreationException; @@ -191,7 +191,8 @@ public class GroovyScriptFactoryTests { try { new ClassPathXmlApplicationContext("org/springframework/scripting/groovy/groovyBrokenContext.xml"); fail("Should throw exception for broken script file"); - } catch (NestedRuntimeException ex) { + } + catch (NestedRuntimeException ex) { assertTrue("Wrong root cause: " + ex, ex.contains(ScriptCompilationException.class)); } } @@ -205,9 +206,10 @@ public class GroovyScriptFactoryTests { GroovyScriptFactory factory = new GroovyScriptFactory(ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript); try { - factory.getScriptedObject(script, new Class[] {}); + factory.getScriptedObject(script); fail("Must have thrown a ScriptCompilationException (no public no-arg ctor in scripted class)."); - } catch (ScriptCompilationException expected) { + } + catch (ScriptCompilationException expected) { assertTrue(expected.contains(InstantiationException.class)); } } @@ -221,9 +223,10 @@ public class GroovyScriptFactoryTests { GroovyScriptFactory factory = new GroovyScriptFactory(ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript); try { - factory.getScriptedObject(script, new Class[] {}); + factory.getScriptedObject(script); fail("Must have thrown a ScriptCompilationException (no oublic no-arg ctor in scripted class)."); - } catch (ScriptCompilationException expected) { + } + catch (ScriptCompilationException expected) { assertTrue(expected.contains(IllegalAccessException.class)); } } @@ -257,7 +260,8 @@ public class GroovyScriptFactoryTests { try { new GroovyScriptFactory(null); fail("Must have thrown exception by this point."); - } catch (IllegalArgumentException expected) { + } + catch (IllegalArgumentException expected) { } } @@ -266,7 +270,8 @@ public class GroovyScriptFactoryTests { try { new GroovyScriptFactory(""); fail("Must have thrown exception by this point."); - } catch (IllegalArgumentException expected) { + } + catch (IllegalArgumentException expected) { } } @@ -275,7 +280,8 @@ public class GroovyScriptFactoryTests { try { new GroovyScriptFactory("\n "); fail("Must have thrown exception by this point."); - } catch (IllegalArgumentException expected) { + } + catch (IllegalArgumentException expected) { } } @@ -284,7 +290,8 @@ public class GroovyScriptFactoryTests { try { new ClassPathXmlApplicationContext("lwspBadGroovyContext.xml", getClass()); fail("Must have thrown a BeanCreationException ('inline:' prefix was preceded by whitespace"); - } catch (BeanCreationException expected) { + } + catch (BeanCreationException expected) { assertTrue(expected.contains(FileNotFoundException.class)); } } @@ -296,7 +303,7 @@ public class GroovyScriptFactoryTests { given(script.suggestedClassName()).willReturn("someName"); GroovyScriptFactory factory = new GroovyScriptFactory("a script source locator (doesn't matter here)"); - Object scriptedObject = factory.getScriptedObject(script, null); + Object scriptedObject = factory.getScriptedObject(script); assertNotNull(scriptedObject); } @@ -304,9 +311,10 @@ public class GroovyScriptFactoryTests { public void testGetScriptedObjectDoesChokeOnNullScriptSourceBeingPassedIn() throws Exception { GroovyScriptFactory factory = new GroovyScriptFactory("a script source locator (doesn't matter here)"); try { - factory.getScriptedObject(null, null); + factory.getScriptedObject(null); fail("Must have thrown a NullPointerException as per contract ('null' ScriptSource supplied"); - } catch (NullPointerException expected) { + } + catch (NullPointerException expected) { } } @@ -395,8 +403,9 @@ public class GroovyScriptFactoryTests { public void testProxyTargetClassNotAllowedIfNotGroovy() throws Exception { try { new ClassPathXmlApplicationContext("jruby-with-xsd-proxy-target-class.xml", getClass()); - } catch (BeanCreationException e) { - assertTrue(e.getMessage().contains("Cannot use proxyTargetClass=true")); + } + catch (BeanCreationException ex) { + assertTrue(ex.getMessage().contains("Cannot use proxyTargetClass=true")); } } @@ -431,7 +440,8 @@ public class GroovyScriptFactoryTests { try { ctx.getBean("bean3"); fail("Should have thrown BeanCreationException"); - } catch (BeanCreationException ex) { + } + catch (BeanCreationException ex) { // expected assertTrue(ex.contains(UnsatisfiedDependencyException.class)); } @@ -454,7 +464,8 @@ public class GroovyScriptFactoryTests { Calculator calc = (Calculator) ctx.getBean("delegatingCalculator"); calc.add(1, 2); fail("expected IllegalStateException"); - } catch (IllegalStateException ex) { + } + catch (IllegalStateException ex) { assertEquals("Gotcha", ex.getMessage()); } } @@ -486,9 +497,10 @@ public class GroovyScriptFactoryTests { DelegatingMetaClass dmc = new DelegatingMetaClass(goo.getMetaClass()) { @Override public Object invokeMethod(Object arg0, String mName, Object[] arg2) { - if (mName.indexOf("Missing") != -1) { + if (mName.contains("Missing")) { throw new IllegalStateException("Gotcha"); - } else { + } + else { return super.invokeMethod(arg0, mName, arg2); } } diff --git a/spring-context/src/test/java/org/springframework/scripting/groovy/simple.groovy b/spring-context/src/test/java/org/springframework/scripting/groovy/simple.groovy new file mode 100644 index 0000000000..1bb7d85d79 --- /dev/null +++ b/spring-context/src/test/java/org/springframework/scripting/groovy/simple.groovy @@ -0,0 +1 @@ +return 3 * 2 diff --git a/spring-context/src/test/java/org/springframework/scripting/jruby/JRubyScriptFactoryTests.java b/spring-context/src/test/java/org/springframework/scripting/jruby/JRubyScriptFactoryTests.java index 55f3016d81..8d84661dca 100644 --- a/spring-context/src/test/java/org/springframework/scripting/jruby/JRubyScriptFactoryTests.java +++ b/spring-context/src/test/java/org/springframework/scripting/jruby/JRubyScriptFactoryTests.java @@ -106,7 +106,7 @@ public class JRubyScriptFactoryTests { @Test public void testCtorWithNullScriptSourceLocator() throws Exception { try { - new JRubyScriptFactory(null, new Class[]{Messenger.class}); + new JRubyScriptFactory(null, Messenger.class); fail("Must have thrown exception by this point."); } catch (IllegalArgumentException expected) { @@ -116,7 +116,7 @@ public class JRubyScriptFactoryTests { @Test public void testCtorWithEmptyScriptSourceLocator() throws Exception { try { - new JRubyScriptFactory("", new Class[]{Messenger.class}); + new JRubyScriptFactory("", Messenger.class); fail("Must have thrown exception by this point."); } catch (IllegalArgumentException expected) { @@ -126,7 +126,7 @@ public class JRubyScriptFactoryTests { @Test public void testCtorWithWhitespacedScriptSourceLocator() throws Exception { try { - new JRubyScriptFactory("\n ", new Class[]{Messenger.class}); + new JRubyScriptFactory("\n ", Messenger.class); fail("Must have thrown exception by this point."); } catch (IllegalArgumentException expected) { @@ -136,7 +136,7 @@ public class JRubyScriptFactoryTests { @Test public void testCtorWithNullScriptInterfacesArray() throws Exception { try { - new JRubyScriptFactory(RUBY_SCRIPT_SOURCE_LOCATOR, null); + new JRubyScriptFactory(RUBY_SCRIPT_SOURCE_LOCATOR); fail("Must have thrown exception by this point."); } catch (IllegalArgumentException expected) { diff --git a/spring-context/src/test/java/org/springframework/scripting/support/ResourceScriptSourceTests.java b/spring-context/src/test/java/org/springframework/scripting/support/ResourceScriptSourceTests.java index 08c9353bb9..367bbfc48f 100644 --- a/spring-context/src/test/java/org/springframework/scripting/support/ResourceScriptSourceTests.java +++ b/spring-context/src/test/java/org/springframework/scripting/support/ResourceScriptSourceTests.java @@ -32,15 +32,6 @@ import static org.mockito.BDDMockito.*; */ public class ResourceScriptSourceTests extends TestCase { - public void testCtorWithNullResource() throws Exception { - try { - new ResourceScriptSource(null); - fail("Must have thrown exception by this point."); - } - catch (IllegalArgumentException expected) { - } - } - public void testDoesNotPropagateFatalExceptionOnResourceThatCannotBeResolvedToAFile() throws Exception { Resource resource = mock(Resource.class); given(resource.lastModified()).willThrow(new IOException());