Backported generics/varargs signature refinements for scripting package

This commit is contained in:
Juergen Hoeller 2014-01-13 23:30:21 +01:00
parent 0ea4f8ecb7
commit 1e0bf493cc
8 changed files with 117 additions and 84 deletions

View File

@ -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;
/**

View File

@ -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,12 +80,13 @@ 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;
}
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
@ -93,7 +96,7 @@ public class BshScriptFactory implements ScriptFactory, BeanClassLoaderAware {
return this.scriptSourceLocator;
}
public Class[] getScriptInterfaces() {
public Class<?>[] getScriptInterfaces() {
return this.scriptInterfaces;
}
@ -108,11 +111,11 @@ public class BshScriptFactory implements ScriptFactory, BeanClassLoaderAware {
* Load and parse the BeanShell script via {@link BshScriptUtils}.
* @see BshScriptUtils#createBshObject(String, Class[], ClassLoader)
*/
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);
@ -125,7 +128,7 @@ public class BshScriptFactory implements ScriptFactory, BeanClassLoaderAware {
if (result instanceof Class) {
// A Class: We'll cache the Class here and create an instance
// outside of the synchronized block.
this.scriptClass = (Class) result;
this.scriptClass = (Class<?>) result;
}
else {
// Not a Class: OK, we'll simply create BeanShell objects
@ -159,7 +162,7 @@ public class BshScriptFactory implements ScriptFactory, BeanClassLoaderAware {
}
}
public Class getScriptedObjectType(ScriptSource scriptSource)
public Class<?> getScriptedObjectType(ScriptSource scriptSource)
throws IOException, ScriptCompilationException {
try {

View File

@ -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,16 +80,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 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);
if (result instanceof Class) {
Class clazz = (Class) result;
Class<?> clazz = (Class<?>) result;
try {
return clazz.newInstance();
}
@ -113,12 +113,12 @@ public abstract class BshScriptUtils {
* @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) throws EvalError {
Assert.hasText(scriptSource, "Script source must not be empty");
Interpreter interpreter = new Interpreter();
Object result = interpreter.eval(scriptSource);
if (result instanceof Class) {
return (Class) result;
return (Class<?>) result;
}
else if (result != null) {
return result.getClass();
@ -139,11 +139,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 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");

View File

@ -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.
@ -58,9 +58,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;
@ -131,7 +131,7 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea
* hence we don't need to explicitly expose interfaces here.
* @return {@code null} always
*/
public Class[] getScriptInterfaces() {
public Class<?>[] getScriptInterfaces() {
return null;
}
@ -148,11 +148,11 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea
* Loads and parses the Groovy script via the GroovyClassLoader.
* @see groovy.lang.GroovyClassLoader
*/
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;
@ -189,7 +189,7 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea
}
}
public Class getScriptedObjectType(ScriptSource scriptSource)
public Class<?> getScriptedObjectType(ScriptSource scriptSource)
throws IOException, ScriptCompilationException {
try {
@ -233,7 +233,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();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 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.
@ -47,7 +47,7 @@ public class JRubyScriptFactory implements ScriptFactory, BeanClassLoaderAware {
private final String scriptSourceLocator;
private final Class[] scriptInterfaces;
private final Class<?>[] scriptInterfaces;
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
@ -59,7 +59,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;
@ -76,7 +76,7 @@ public class JRubyScriptFactory implements ScriptFactory, BeanClassLoaderAware {
return this.scriptSourceLocator;
}
public Class[] getScriptInterfaces() {
public Class<?>[] getScriptInterfaces() {
return this.scriptInterfaces;
}
@ -91,7 +91,7 @@ public class JRubyScriptFactory implements ScriptFactory, BeanClassLoaderAware {
* Load and parse the JRuby script via JRubyScriptUtils.
* @see JRubyScriptUtils#createJRubyObject(String, Class[], ClassLoader)
*/
public Object getScriptedObject(ScriptSource scriptSource, Class[] actualInterfaces)
public Object getScriptedObject(ScriptSource scriptSource, Class<?>... actualInterfaces)
throws IOException, ScriptCompilationException {
try {
return JRubyScriptUtils.createJRubyObject(
@ -108,7 +108,7 @@ public class JRubyScriptFactory implements ScriptFactory, BeanClassLoaderAware {
}
}
public Class getScriptedObjectType(ScriptSource scriptSource)
public Class<?> getScriptedObjectType(ScriptSource scriptSource)
throws IOException, ScriptCompilationException {
return null;

View File

@ -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.
@ -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());
}
@ -76,7 +76,7 @@ public abstract class JRubyScriptUtils {
* @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);
@ -132,16 +132,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;
@ -207,7 +207,7 @@ public abstract class JRubyScriptUtils {
return rubyArgs;
}
private Object convertFromRuby(IRubyObject rubyResult, Class returnType) {
private Object convertFromRuby(IRubyObject rubyResult, Class<?> returnType) {
Object result = JavaEmbedUtils.rubyToJava(this.ruby, rubyResult, returnType);
if (result instanceof RubyArray && returnType.isArray()) {
result = convertFromRubyArray(((RubyArray) result).toJavaArray(), returnType);
@ -215,8 +215,8 @@ public abstract class JRubyScriptUtils {
return result;
}
private Object convertFromRubyArray(IRubyObject[] rubyArray, Class returnType) {
Class targetType = returnType.getComponentType();
private Object convertFromRubyArray(IRubyObject[] rubyArray, Class<?> returnType) {
Class<?> targetType = returnType.getComponentType();
Object javaArray = Array.newInstance(targetType, rubyArray.length);
for (int i = 0; i < rubyArray.length; i++) {
IRubyObject rubyObject = rubyArray[i];

View File

@ -1,12 +1,28 @@
package org.springframework.scripting.groovy;
/*
* 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.
*/
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
package org.springframework.scripting.groovy;
import org.junit.After;
import org.junit.Test;
import org.springframework.context.support.GenericXmlApplicationContext;
import static org.junit.Assert.*;
/**
* @author Dave Syer
*/
@ -14,18 +30,9 @@ public class GroovyAspectIntegrationTests {
private GenericXmlApplicationContext context;
@After
public void close() {
if (context != null) {
context.close();
}
}
@Test
public void testJavaBean() {
context = new GenericXmlApplicationContext(getClass(), getClass().getSimpleName()+"-java-context.xml");
TestService bean = context.getBean("javaBean", TestService.class);
LogUserAdvice logAdvice = context.getBean(LogUserAdvice.class);
@ -33,8 +40,9 @@ public class GroovyAspectIntegrationTests {
try {
bean.sayHello();
fail("Expected exception");
} catch (RuntimeException e) {
assertEquals("TestServiceImpl", e.getMessage());
}
catch (RuntimeException ex) {
assertEquals("TestServiceImpl", ex.getMessage());
}
assertEquals(1, logAdvice.getCountThrows());
@ -43,7 +51,6 @@ public class GroovyAspectIntegrationTests {
@Test
public void testGroovyBeanInterface() {
context = new GenericXmlApplicationContext(getClass(), getClass().getSimpleName()+"-groovy-interface-context.xml");
TestService bean = context.getBean("groovyBean", TestService.class);
LogUserAdvice logAdvice = context.getBean(LogUserAdvice.class);
@ -51,8 +58,9 @@ public class GroovyAspectIntegrationTests {
try {
bean.sayHello();
fail("Expected exception");
} catch (RuntimeException e) {
assertEquals("GroovyServiceImpl", e.getMessage());
}
catch (RuntimeException ex) {
assertEquals("GroovyServiceImpl", ex.getMessage());
}
assertEquals(1, logAdvice.getCountThrows());
}
@ -60,9 +68,7 @@ public class GroovyAspectIntegrationTests {
@Test
public void testGroovyBeanDynamic() {
context = new GenericXmlApplicationContext(getClass(), getClass().getSimpleName()+"-groovy-dynamic-context.xml");
TestService bean = context.getBean("groovyBean", TestService.class);
LogUserAdvice logAdvice = context.getBean(LogUserAdvice.class);
@ -70,8 +76,9 @@ public class GroovyAspectIntegrationTests {
try {
bean.sayHello();
fail("Expected exception");
} catch (RuntimeException e) {
assertEquals("GroovyServiceImpl", e.getMessage());
}
catch (RuntimeException ex) {
assertEquals("GroovyServiceImpl", ex.getMessage());
}
// No proxy here because the pointcut only applies to the concrete class, not the interface
assertEquals(0, logAdvice.getCountThrows());
@ -80,9 +87,7 @@ public class GroovyAspectIntegrationTests {
@Test
public void testGroovyBeanProxyTargetClass() {
context = new GenericXmlApplicationContext(getClass(), getClass().getSimpleName()+"-groovy-proxy-target-class-context.xml");
TestService bean = context.getBean("groovyBean", TestService.class);
LogUserAdvice logAdvice = context.getBean(LogUserAdvice.class);
@ -90,11 +95,19 @@ public class GroovyAspectIntegrationTests {
try {
bean.sayHello();
fail("Expected exception");
} catch (TestException e) {
assertEquals("GroovyServiceImpl", e.getMessage());
}
catch (TestException ex) {
assertEquals("GroovyServiceImpl", ex.getMessage());
}
assertEquals(1, logAdvice.getCountBefore());
assertEquals(1, logAdvice.getCountThrows());
}
@After
public void close() {
if (context != null) {
context.close();
}
}
}

View File

@ -1,18 +1,33 @@
/*
* 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scripting.groovy.GroovyScriptFactory;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.util.ClassUtils;
import static org.junit.Assert.*;
/**
* @author Dave Syer
*/
@ -25,7 +40,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 +52,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 +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())));
@ -66,7 +81,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())));
@ -93,9 +108,11 @@ public class GroovyAspectTests {
try {
bean.sayHello();
fail("Expected exception");
} catch (TestException e) {
assertEquals(message, e.getMessage());
}
catch (TestException ex) {
assertEquals(message, ex.getMessage());
}
assertEquals(1, logAdvice.getCountThrows());
}
}