moving .scripting.* unit tests from .testsuite -> .context
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2005 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.aop.framework;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.aop.MethodBeforeAdvice;
|
||||
|
||||
/**
|
||||
* Simple before advice example that we can use for counting checks.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public class CountingBeforeAdvice extends MethodCounter implements MethodBeforeAdvice {
|
||||
|
||||
public void before(Method m, Object[] args, Object target) throws Throwable {
|
||||
count(m);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.aop.framework;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Useful abstract superclass for counting advices etc.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public class MethodCounter implements Serializable {
|
||||
|
||||
/** Method name --> count, does not understand overloading */
|
||||
private HashMap map = new HashMap();
|
||||
|
||||
private int allCount;
|
||||
|
||||
protected void count(Method m) {
|
||||
count(m.getName());
|
||||
}
|
||||
|
||||
protected void count(String methodName) {
|
||||
Integer i = (Integer) map.get(methodName);
|
||||
i = (i != null) ? new Integer(i.intValue() + 1) : new Integer(1);
|
||||
map.put(methodName, i);
|
||||
++allCount;
|
||||
}
|
||||
|
||||
public int getCalls(String methodName) {
|
||||
Integer i = (Integer) map.get(methodName);
|
||||
return (i != null ? i.intValue() : 0);
|
||||
}
|
||||
|
||||
public int getCalls() {
|
||||
return allCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* A bit simplistic: just wants the same class.
|
||||
* Doesn't worry about counts.
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object other) {
|
||||
return (other != null && other.getClass() == this.getClass());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return getClass().hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2002-2006 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;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
*/
|
||||
public interface Calculator {
|
||||
|
||||
int add(int x, int y);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public interface CallCounter {
|
||||
|
||||
void before();
|
||||
|
||||
int getCalls();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2002-2006 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;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public interface ConfigurableMessenger extends Messenger {
|
||||
|
||||
void setMessage(String message);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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 org.springframework.beans.TestBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @since 08.08.2006
|
||||
*/
|
||||
public interface ContextScriptBean extends ScriptBean {
|
||||
|
||||
TestBean getTestBean();
|
||||
|
||||
ApplicationContext getApplicationContext();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2002-2006 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;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
*/
|
||||
public interface Messenger {
|
||||
|
||||
String getMessage();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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 org.aspectj.lang.ProceedingJoinPoint;
|
||||
|
||||
/**
|
||||
* Twee advice that 'scrambles' the return value
|
||||
* of a {@link Messenger} invocation.
|
||||
*
|
||||
* @author Rick Evans
|
||||
*/
|
||||
public final class MessengerScrambler {
|
||||
|
||||
public String scramble(ProceedingJoinPoint pjp) throws Throwable {
|
||||
String message = (String) pjp.proceed();
|
||||
return new StringBuffer(message).reverse().toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2006 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;
|
||||
|
||||
/**
|
||||
* Simple interface used in testing the scripted beans support.
|
||||
*
|
||||
* @author Rick Evans
|
||||
*/
|
||||
public interface ScriptBean {
|
||||
|
||||
String getName();
|
||||
|
||||
void setName(String name);
|
||||
|
||||
int getAge();
|
||||
|
||||
void setAge(int age);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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 org.springframework.beans.TestBean;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public interface TestBeanAwareMessenger extends ConfigurableMessenger {
|
||||
|
||||
TestBean getTestBean();
|
||||
|
||||
void setTestBean(TestBean testBean);
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
one sure is the loneliest number... that i'll ever know
|
||||
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.target.dynamic.Refreshable;
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
import org.springframework.scripting.Calculator;
|
||||
import org.springframework.scripting.ConfigurableMessenger;
|
||||
import org.springframework.scripting.Messenger;
|
||||
import org.springframework.scripting.ScriptCompilationException;
|
||||
import org.springframework.scripting.ScriptSource;
|
||||
import org.springframework.scripting.TestBeanAwareMessenger;
|
||||
import org.springframework.scripting.support.ScriptFactoryPostProcessor;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class BshScriptFactoryTests extends TestCase {
|
||||
|
||||
public void testStaticScript() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("bshContext.xml", getClass());
|
||||
|
||||
assertTrue(Arrays.asList(ctx.getBeanNamesForType(Calculator.class)).contains("calculator"));
|
||||
assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messenger"));
|
||||
|
||||
Calculator calc = (Calculator) ctx.getBean("calculator");
|
||||
Messenger messenger = (Messenger) ctx.getBean("messenger");
|
||||
|
||||
assertFalse("Scripted object should not be instance of Refreshable", calc instanceof Refreshable);
|
||||
assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
|
||||
|
||||
assertEquals(calc, calc);
|
||||
assertEquals(messenger, messenger);
|
||||
assertTrue(!messenger.equals(calc));
|
||||
assertTrue(messenger.hashCode() != calc.hashCode());
|
||||
assertTrue(!messenger.toString().equals(calc.toString()));
|
||||
|
||||
assertEquals(5, calc.add(2, 3));
|
||||
|
||||
String desiredMessage = "Hello World!";
|
||||
assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
|
||||
|
||||
assertTrue(ctx.getBeansOfType(Calculator.class).values().contains(calc));
|
||||
assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
|
||||
}
|
||||
|
||||
public void testStaticScriptWithNullReturnValue() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("bshContext.xml", getClass());
|
||||
assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messengerWithConfig"));
|
||||
|
||||
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerWithConfig");
|
||||
messenger.setMessage(null);
|
||||
assertNull(messenger.getMessage());
|
||||
assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
|
||||
}
|
||||
|
||||
public void testStaticScriptWithTwoInterfacesSpecified() throws Exception {
|
||||
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("bshContext.xml", getClass());
|
||||
assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messengerWithConfigExtra"));
|
||||
|
||||
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerWithConfigExtra");
|
||||
messenger.setMessage(null);
|
||||
assertNull(messenger.getMessage());
|
||||
assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
|
||||
|
||||
ctx.close();
|
||||
assertNull(messenger.getMessage());
|
||||
}
|
||||
|
||||
public void testStaticWithScriptReturningInstance() throws Exception {
|
||||
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("bshContext.xml", getClass());
|
||||
assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messengerInstance"));
|
||||
|
||||
Messenger messenger = (Messenger) ctx.getBean("messengerInstance");
|
||||
String desiredMessage = "Hello World!";
|
||||
assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
|
||||
assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
|
||||
|
||||
ctx.close();
|
||||
assertNull(messenger.getMessage());
|
||||
}
|
||||
|
||||
public void testStaticScriptImplementingInterface() throws Exception {
|
||||
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("bshContext.xml", getClass());
|
||||
assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messengerImpl"));
|
||||
|
||||
Messenger messenger = (Messenger) ctx.getBean("messengerImpl");
|
||||
String desiredMessage = "Hello World!";
|
||||
assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
|
||||
assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
|
||||
|
||||
ctx.close();
|
||||
assertNull(messenger.getMessage());
|
||||
}
|
||||
|
||||
public void testStaticPrototypeScript() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("bshContext.xml", getClass());
|
||||
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
|
||||
assertFalse("Shouldn't get proxy when refresh is disabled", AopUtils.isAopProxy(messenger));
|
||||
assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
|
||||
|
||||
assertNotSame(messenger, messenger2);
|
||||
assertSame(messenger.getClass(), messenger2.getClass());
|
||||
assertEquals("Hello World!", messenger.getMessage());
|
||||
assertEquals("Hello World!", messenger2.getMessage());
|
||||
messenger.setMessage("Bye World!");
|
||||
messenger2.setMessage("Byebye World!");
|
||||
assertEquals("Bye World!", messenger.getMessage());
|
||||
assertEquals("Byebye World!", messenger2.getMessage());
|
||||
}
|
||||
|
||||
public void testNonStaticScript() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("bshRefreshableContext.xml", getClass());
|
||||
Messenger messenger = (Messenger) ctx.getBean("messenger");
|
||||
|
||||
assertTrue("Should be a proxy for refreshable scripts", AopUtils.isAopProxy(messenger));
|
||||
assertTrue("Should be an instance of Refreshable", messenger instanceof Refreshable);
|
||||
|
||||
String desiredMessage = "Hello World!";
|
||||
assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
|
||||
|
||||
Refreshable refreshable = (Refreshable) messenger;
|
||||
refreshable.refresh();
|
||||
|
||||
assertEquals("Message is incorrect after refresh", desiredMessage, messenger.getMessage());
|
||||
assertEquals("Incorrect refresh count", 2, refreshable.getRefreshCount());
|
||||
}
|
||||
|
||||
public void testNonStaticPrototypeScript() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("bshRefreshableContext.xml", getClass());
|
||||
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
|
||||
assertTrue("Should be a proxy for refreshable scripts", AopUtils.isAopProxy(messenger));
|
||||
assertTrue("Should be an instance of Refreshable", messenger instanceof Refreshable);
|
||||
|
||||
assertEquals("Hello World!", messenger.getMessage());
|
||||
assertEquals("Hello World!", messenger2.getMessage());
|
||||
messenger.setMessage("Bye World!");
|
||||
messenger2.setMessage("Byebye World!");
|
||||
assertEquals("Bye World!", messenger.getMessage());
|
||||
assertEquals("Byebye World!", messenger2.getMessage());
|
||||
|
||||
Refreshable refreshable = (Refreshable) messenger;
|
||||
refreshable.refresh();
|
||||
|
||||
assertEquals("Hello World!", messenger.getMessage());
|
||||
assertEquals("Byebye World!", messenger2.getMessage());
|
||||
assertEquals("Incorrect refresh count", 2, refreshable.getRefreshCount());
|
||||
}
|
||||
|
||||
public void testScriptCompilationException() throws Exception {
|
||||
try {
|
||||
new ClassPathXmlApplicationContext("org/springframework/scripting/bsh/bshBrokenContext.xml");
|
||||
fail("Must throw exception for broken script file");
|
||||
}
|
||||
catch (NestedRuntimeException ex) {
|
||||
assertTrue(ex.contains(ScriptCompilationException.class));
|
||||
}
|
||||
}
|
||||
|
||||
public void testScriptThatCompilesButIsJustPlainBad() throws Exception {
|
||||
MockControl mock = MockControl.createControl(ScriptSource.class);
|
||||
ScriptSource script = (ScriptSource) mock.getMock();
|
||||
script.getScriptAsString();
|
||||
final String badScript = "String getMessage() { throw new IllegalArgumentException(); }";
|
||||
mock.setReturnValue(badScript);
|
||||
script.isModified();
|
||||
mock.setReturnValue(true);
|
||||
mock.replay();
|
||||
BshScriptFactory factory = new BshScriptFactory(
|
||||
ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript,
|
||||
new Class[] {Messenger.class});
|
||||
try {
|
||||
Messenger messenger = (Messenger) factory.getScriptedObject(script, new Class[]{Messenger.class});
|
||||
messenger.getMessage();
|
||||
fail("Must have thrown a BshScriptUtils.BshExecutionException.");
|
||||
}
|
||||
catch (BshScriptUtils.BshExecutionException expected) {
|
||||
}
|
||||
mock.verify();
|
||||
}
|
||||
|
||||
public void testCtorWithNullScriptSourceLocator() throws Exception {
|
||||
try {
|
||||
new BshScriptFactory(null, new Class[] {Messenger.class});
|
||||
fail("Must have thrown exception by this point.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCtorWithEmptyScriptSourceLocator() throws Exception {
|
||||
try {
|
||||
new BshScriptFactory("", new Class[] {Messenger.class});
|
||||
fail("Must have thrown exception by this point.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCtorWithWhitespacedScriptSourceLocator() throws Exception {
|
||||
try {
|
||||
new BshScriptFactory("\n ", new Class[] {Messenger.class});
|
||||
fail("Must have thrown exception by this point.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testResourceScriptFromTag() throws Exception {
|
||||
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("bsh-with-xsd.xml", getClass());
|
||||
TestBean testBean = (TestBean) ctx.getBean("testBean");
|
||||
|
||||
Collection beanNames = Arrays.asList(ctx.getBeanNamesForType(Messenger.class));
|
||||
assertTrue(beanNames.contains("messenger"));
|
||||
assertTrue(beanNames.contains("messengerImpl"));
|
||||
assertTrue(beanNames.contains("messengerInstance"));
|
||||
|
||||
Messenger messenger = (Messenger) ctx.getBean("messenger");
|
||||
assertEquals("Hello World!", messenger.getMessage());
|
||||
assertFalse(messenger instanceof Refreshable);
|
||||
|
||||
Messenger messengerImpl = (Messenger) ctx.getBean("messengerImpl");
|
||||
assertEquals("Hello World!", messengerImpl.getMessage());
|
||||
|
||||
Messenger messengerInstance = (Messenger) ctx.getBean("messengerInstance");
|
||||
assertEquals("Hello World!", messengerInstance.getMessage());
|
||||
|
||||
TestBeanAwareMessenger messengerByType = (TestBeanAwareMessenger) ctx.getBean("messengerByType");
|
||||
assertEquals(testBean, messengerByType.getTestBean());
|
||||
|
||||
TestBeanAwareMessenger messengerByName = (TestBeanAwareMessenger) ctx.getBean("messengerByName");
|
||||
assertEquals(testBean, messengerByName.getTestBean());
|
||||
|
||||
Collection beans = ctx.getBeansOfType(Messenger.class).values();
|
||||
assertTrue(beans.contains(messenger));
|
||||
assertTrue(beans.contains(messengerImpl));
|
||||
assertTrue(beans.contains(messengerInstance));
|
||||
assertTrue(beans.contains(messengerByType));
|
||||
assertTrue(beans.contains(messengerByName));
|
||||
|
||||
ctx.close();
|
||||
assertNull(messenger.getMessage());
|
||||
assertNull(messengerImpl.getMessage());
|
||||
assertNull(messengerInstance.getMessage());
|
||||
}
|
||||
|
||||
public void testPrototypeScriptFromTag() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("bsh-with-xsd.xml", getClass());
|
||||
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
|
||||
assertNotSame(messenger, messenger2);
|
||||
assertSame(messenger.getClass(), messenger2.getClass());
|
||||
assertEquals("Hello World!", messenger.getMessage());
|
||||
assertEquals("Hello World!", messenger2.getMessage());
|
||||
messenger.setMessage("Bye World!");
|
||||
messenger2.setMessage("Byebye World!");
|
||||
assertEquals("Bye World!", messenger.getMessage());
|
||||
assertEquals("Byebye World!", messenger2.getMessage());
|
||||
}
|
||||
|
||||
public void testInlineScriptFromTag() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("bsh-with-xsd.xml", getClass());
|
||||
Calculator calculator = (Calculator) ctx.getBean("calculator");
|
||||
assertNotNull(calculator);
|
||||
assertFalse(calculator instanceof Refreshable);
|
||||
}
|
||||
|
||||
public void testRefreshableFromTag() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("bsh-with-xsd.xml", getClass());
|
||||
Messenger messenger = (Messenger) ctx.getBean("refreshableMessenger");
|
||||
assertEquals("Hello World!", messenger.getMessage());
|
||||
assertTrue("Messenger should be Refreshable", messenger instanceof Refreshable);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
int add(int x, int y) {
|
||||
return x + y;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
String message;
|
||||
|
||||
boolean active;
|
||||
|
||||
void init() {
|
||||
active = true;
|
||||
}
|
||||
|
||||
String getMessage() {
|
||||
if (!active && message != null) throw new java.lang.IllegalStateException();
|
||||
return message;
|
||||
}
|
||||
|
||||
void setMessage(String aMessage) {
|
||||
message = aMessage;
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
message = null;
|
||||
active = false;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.scripting.TestBeanAwareMessenger;
|
||||
|
||||
public class MyMessenger implements TestBeanAwareMessenger {
|
||||
|
||||
private String message;
|
||||
|
||||
private TestBean testBean;
|
||||
|
||||
private boolean active;
|
||||
|
||||
public void init() {
|
||||
active = true;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
if (!active && message != null) throw new java.lang.IllegalStateException();
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String aMessage) {
|
||||
message = aMessage;
|
||||
}
|
||||
|
||||
public TestBean getTestBean() {
|
||||
return testBean;
|
||||
}
|
||||
|
||||
public void setTestBean(TestBean tb) {
|
||||
testBean = tb;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
message = null;
|
||||
active = false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import org.springframework.scripting.Messenger;
|
||||
|
||||
public class MyMessenger implements Messenger {
|
||||
|
||||
private String message;
|
||||
|
||||
private boolean active;
|
||||
|
||||
public void init() {
|
||||
active = true;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
if (!active && message != null) throw new java.lang.IllegalStateException();
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String aMessage) {
|
||||
message = aMessage;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
message = null;
|
||||
active = false;
|
||||
}
|
||||
}
|
||||
|
||||
return new MyMessenger() ;
|
||||
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd">
|
||||
|
||||
<lang:bsh id="messenger" script-source="classpath:org/springframework/scripting/bsh/Messenger.bsh"
|
||||
script-interfaces="org.springframework.scripting.Messenger"
|
||||
init-method="init" destroy-method="destroy">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:bsh>
|
||||
|
||||
<lang:bsh id="messengerPrototype" script-source="classpath:org/springframework/scripting/bsh/Messenger.bsh"
|
||||
script-interfaces="org.springframework.scripting.ConfigurableMessenger"
|
||||
scope="prototype" init-method="init" destroy-method="destroy">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:bsh>
|
||||
|
||||
<lang:bsh id="messengerImpl" script-source="classpath:org/springframework/scripting/bsh/MessengerImpl.bsh"
|
||||
init-method="init" destroy-method="destroy">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:bsh>
|
||||
|
||||
<lang:bsh id="messengerInstance" script-source="classpath:org/springframework/scripting/bsh/MessengerInstance.bsh"
|
||||
init-method="init" destroy-method="destroy">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:bsh>
|
||||
|
||||
<lang:bsh id="messengerByType" script-source="classpath:org/springframework/scripting/bsh/MessengerImpl.bsh"
|
||||
autowire="byType" dependency-check="objects" init-method="init" destroy-method="destroy">
|
||||
</lang:bsh>
|
||||
|
||||
<lang:bsh id="messengerByName" script-source="classpath:org/springframework/scripting/bsh/MessengerImpl.bsh"
|
||||
autowire="byName" init-method="init" destroy-method="destroy">
|
||||
</lang:bsh>
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.TestBean"/>
|
||||
|
||||
<lang:bsh id="calculator" script-interfaces="org.springframework.scripting.Calculator">
|
||||
<lang:inline-script>
|
||||
int add(int x, int y) {
|
||||
return x + y;
|
||||
}
|
||||
</lang:inline-script>
|
||||
</lang:bsh>
|
||||
|
||||
<lang:bsh id="refreshableMessenger" script-interfaces="org.springframework.scripting.Messenger"
|
||||
script-source="classpath:org/springframework/scripting/bsh/Messenger.bsh" refresh-check-delay="5000"
|
||||
init-method="init" destroy-method="destroy">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:bsh>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
|
||||
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="broken" class="org.springframework.scripting.bsh.BshScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/bsh/Broken.bsh"/>
|
||||
<constructor-arg value="org.springframework.scripting.Messenger"/>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans default-lazy-init="true">
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="calculator" class="org.springframework.scripting.bsh.BshScriptFactory">
|
||||
<constructor-arg>
|
||||
<value>inline:
|
||||
int add(int x, int y) {
|
||||
return x + y;
|
||||
}
|
||||
</value>
|
||||
</constructor-arg>
|
||||
<constructor-arg value="org.springframework.scripting.Calculator"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messenger" class="org.springframework.scripting.bsh.BshScriptFactory"
|
||||
init-method="init" destroy-method="destroy">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/bsh/Messenger.bsh"/>
|
||||
<constructor-arg value="org.springframework.scripting.Messenger"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messengerWithConfig" class="org.springframework.scripting.bsh.BshScriptFactory"
|
||||
init-method="init" destroy-method="destroy">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/bsh/Messenger.bsh"/>
|
||||
<constructor-arg value="org.springframework.scripting.ConfigurableMessenger"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messengerWithConfigExtra" class="org.springframework.scripting.bsh.BshScriptFactory"
|
||||
init-method="init" destroy-method="destroy">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/bsh/Messenger.bsh"/>
|
||||
<constructor-arg value="org.springframework.scripting.Messenger,org.springframework.scripting.ConfigurableMessenger"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messengerInstance" class="org.springframework.scripting.bsh.BshScriptFactory"
|
||||
init-method="init" destroy-method="destroy">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/bsh/MessengerInstance.bsh"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messengerInstanceWithExplicitInterface" class="org.springframework.scripting.bsh.BshScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/bsh/MessengerInstance.bsh"/>
|
||||
<constructor-arg value="org.springframework.scripting.Messenger"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messengerImpl" class="org.springframework.scripting.bsh.BshScriptFactory"
|
||||
init-method="init" destroy-method="destroy">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/bsh/MessengerImpl.bsh"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messengerImplWithExplicitInterface" class="org.springframework.scripting.bsh.BshScriptFactory"
|
||||
init-method="init">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/bsh/MessengerImpl.bsh"/>
|
||||
<constructor-arg value="org.springframework.scripting.Messenger"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messengerPrototype" class="org.springframework.scripting.bsh.BshScriptFactory" scope="prototype"
|
||||
init-method="init">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/bsh/MessengerImpl.bsh"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans default-lazy-init="true">
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor">
|
||||
<property name="defaultRefreshCheckDelay" value="1"/>
|
||||
</bean>
|
||||
|
||||
<bean id="calculator" class="org.springframework.scripting.bsh.BshScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/bsh/Calculator.bsh"/>
|
||||
<constructor-arg value="org.springframework.scripting.Calculator"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messenger" class="org.springframework.scripting.bsh.BshScriptFactory" init-method="init">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/bsh/MessengerImpl.bsh"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messengerPrototype" class="org.springframework.scripting.bsh.BshScriptFactory"
|
||||
scope="prototype" init-method="init">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/bsh/MessengerImpl.bsh"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.config;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface ITestBean {
|
||||
|
||||
boolean isInitialized();
|
||||
|
||||
boolean isDestroyed();
|
||||
|
||||
ITestBean getOtherBean();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.config;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class OtherTestBean implements ITestBean {
|
||||
|
||||
public ITestBean getOtherBean() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isDestroyed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.config;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.target.dynamic.AbstractRefreshableTargetSource;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class ScriptingDefaultsTests extends TestCase {
|
||||
|
||||
private static final String CONFIG =
|
||||
"org/springframework/scripting/config/scriptingDefaultsTests.xml";
|
||||
|
||||
|
||||
public void testDefaultRefreshCheckDelay() throws Exception {
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG);
|
||||
Advised advised = (Advised) context.getBean("testBean");
|
||||
AbstractRefreshableTargetSource targetSource =
|
||||
((AbstractRefreshableTargetSource) advised.getTargetSource());
|
||||
Field field = AbstractRefreshableTargetSource.class.getDeclaredField("refreshCheckDelay");
|
||||
field.setAccessible(true);
|
||||
long delay = ((Long) field.get(targetSource)).longValue();
|
||||
assertEquals(5000L, delay);
|
||||
}
|
||||
|
||||
public void testDefaultInitMethod() {
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG);
|
||||
ITestBean testBean = (ITestBean) context.getBean("testBean");
|
||||
assertTrue(testBean.isInitialized());
|
||||
}
|
||||
|
||||
public void testDefaultDestroyMethod() {
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(CONFIG);
|
||||
ITestBean testBean = (ITestBean) context.getBean("nonRefreshableTestBean");
|
||||
assertFalse(testBean.isDestroyed());
|
||||
context.close();
|
||||
assertTrue(testBean.isDestroyed());
|
||||
}
|
||||
|
||||
public void testDefaultAutowire() {
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG);
|
||||
ITestBean testBean = (ITestBean) context.getBean("testBean");
|
||||
ITestBean otherBean = (ITestBean) context.getBean("otherBean");
|
||||
assertEquals(otherBean, testBean.getOtherBean());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.springframework.scripting.config
|
||||
|
||||
class TestBean implements ITestBean {
|
||||
|
||||
ITestBean otherBean
|
||||
|
||||
boolean initialized
|
||||
|
||||
boolean destroyed
|
||||
|
||||
void setOtherBean(ITestBean otherBean) {
|
||||
this.otherBean = otherBean;
|
||||
}
|
||||
|
||||
void startup() { this.initialized = true }
|
||||
|
||||
void shutdown() { this.destroyed = true }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/lang
|
||||
http://www.springframework.org/schema/lang/spring-lang.xsd"
|
||||
default-autowire="byName"
|
||||
default-init-method="startup"
|
||||
default-destroy-method="shutdown">
|
||||
|
||||
<lang:defaults refresh-check-delay="5000"/>
|
||||
|
||||
<lang:groovy id="testBean" script-source="classpath:org/springframework/scripting/config/TestBean.groovy"/>
|
||||
|
||||
<lang:groovy id="nonRefreshableTestBean" refresh-check-delay="-1"
|
||||
script-source="classpath:org/springframework/scripting/config/TestBean.groovy"/>
|
||||
|
||||
<bean id="otherBean" class="org.springframework.scripting.config.OtherTestBean"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,14 @@
|
||||
I have eaten
|
||||
the plums
|
||||
that were in
|
||||
the icebox
|
||||
|
||||
and which
|
||||
you were probably
|
||||
saving
|
||||
for breakfast
|
||||
|
||||
Forgive me
|
||||
they were delicious
|
||||
so sweet
|
||||
and so cold
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.springframework.scripting.groovy;
|
||||
|
||||
import org.springframework.scripting.Calculator
|
||||
|
||||
class GroovyCalculator implements Calculator {
|
||||
|
||||
int add(int x, int y) {
|
||||
return x + y;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.springframework.scripting.groovy;
|
||||
|
||||
import org.springframework.scripting.CallCounter;
|
||||
|
||||
class GroovyCallCounter implements CallCounter {
|
||||
|
||||
int count = -100;
|
||||
|
||||
void init() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
void before() {
|
||||
count++;
|
||||
}
|
||||
|
||||
int getCalls() {
|
||||
return count;
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
count = -200;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.springframework.scripting.groovy;
|
||||
|
||||
import org.springframework.scripting.Calculator
|
||||
|
||||
class DelegatingCalculator implements Calculator {
|
||||
|
||||
def Calculator delegate;
|
||||
|
||||
int add(int x, int y) {
|
||||
//println "hello"
|
||||
//println this.metaClass.getClass()
|
||||
//println delegate.metaClass.getClass()
|
||||
//delegate.metaClass.invokeMethod("add", [x,y])
|
||||
|
||||
delegate.callMissingMethod()
|
||||
|
||||
return delegate.add(x,y)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.lang.reflect.Method;
|
||||
|
||||
import groovy.lang.GroovyClassLoader;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class GroovyClassLoadingTests extends TestCase {
|
||||
|
||||
public void testClassLoading() throws Exception {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
|
||||
GroovyClassLoader gcl = new GroovyClassLoader();
|
||||
Class class1 = gcl.parseClass("class TestBean { def myMethod() { \"foo\" } }");
|
||||
Class class2 = gcl.parseClass("class TestBean { def myMethod() { \"bar\" } }");
|
||||
|
||||
context.registerBeanDefinition("testBean", new RootBeanDefinition(class1));
|
||||
Object testBean1 = context.getBean("testBean");
|
||||
Method method1 = class1.getDeclaredMethod("myMethod", new Class[0]);
|
||||
Object result1 = ReflectionUtils.invokeMethod(method1, testBean1);
|
||||
assertEquals("foo", (String) result1);
|
||||
|
||||
// ### uncommenting the next line causes the test to pass for Spring > 2.0.2 ###
|
||||
//context.removeBeanDefinition("testBean");
|
||||
|
||||
context.registerBeanDefinition("testBean", new RootBeanDefinition(class2));
|
||||
Object testBean2 = context.getBean("testBean");
|
||||
Method method2 = class2.getDeclaredMethod("myMethod", new Class[0]);
|
||||
Object result2 = ReflectionUtils.invokeMethod(method2, testBean2);
|
||||
assertEquals("bar", (String) result2);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,476 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.*;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import groovy.lang.DelegatingMetaClass;
|
||||
import groovy.lang.GroovyObject;
|
||||
import junit.framework.TestCase;
|
||||
import org.easymock.MockControl;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.target.dynamic.Refreshable;
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
import org.springframework.scripting.Calculator;
|
||||
import org.springframework.scripting.CallCounter;
|
||||
import org.springframework.scripting.ConfigurableMessenger;
|
||||
import org.springframework.scripting.ContextScriptBean;
|
||||
import org.springframework.scripting.Messenger;
|
||||
import org.springframework.scripting.ScriptCompilationException;
|
||||
import org.springframework.scripting.ScriptSource;
|
||||
import org.springframework.scripting.support.ScriptFactoryPostProcessor;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Rick Evans
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Mark Fisher
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class GroovyScriptFactoryTests {
|
||||
|
||||
@Test
|
||||
public void testStaticScript() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
|
||||
|
||||
assertTrue(Arrays.asList(ctx.getBeanNamesForType(Calculator.class)).contains("calculator"));
|
||||
assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messenger"));
|
||||
|
||||
Calculator calc = (Calculator) ctx.getBean("calculator");
|
||||
Messenger messenger = (Messenger) ctx.getBean("messenger");
|
||||
|
||||
assertFalse("Shouldn't get proxy when refresh is disabled", AopUtils.isAopProxy(calc));
|
||||
assertFalse("Shouldn't get proxy when refresh is disabled", AopUtils.isAopProxy(messenger));
|
||||
|
||||
assertFalse("Scripted object should not be instance of Refreshable", calc instanceof Refreshable);
|
||||
assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
|
||||
|
||||
assertEquals(calc, calc);
|
||||
assertEquals(messenger, messenger);
|
||||
assertTrue(!messenger.equals(calc));
|
||||
assertTrue(messenger.hashCode() != calc.hashCode());
|
||||
assertTrue(!messenger.toString().equals(calc.toString()));
|
||||
|
||||
String desiredMessage = "Hello World!";
|
||||
assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
|
||||
|
||||
assertTrue(ctx.getBeansOfType(Calculator.class).values().contains(calc));
|
||||
assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStaticPrototypeScript() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
|
||||
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
|
||||
assertFalse("Shouldn't get proxy when refresh is disabled", AopUtils.isAopProxy(messenger));
|
||||
assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
|
||||
|
||||
assertNotSame(messenger, messenger2);
|
||||
assertSame(messenger.getClass(), messenger2.getClass());
|
||||
assertEquals("Hello World!", messenger.getMessage());
|
||||
assertEquals("Hello World!", messenger2.getMessage());
|
||||
messenger.setMessage("Bye World!");
|
||||
messenger2.setMessage("Byebye World!");
|
||||
assertEquals("Bye World!", messenger.getMessage());
|
||||
assertEquals("Byebye World!", messenger2.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStaticScriptWithInstance() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
|
||||
assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messengerInstance"));
|
||||
Messenger messenger = (Messenger) ctx.getBean("messengerInstance");
|
||||
|
||||
assertFalse("Shouldn't get proxy when refresh is disabled", AopUtils.isAopProxy(messenger));
|
||||
assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
|
||||
|
||||
String desiredMessage = "Hello World!";
|
||||
assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
|
||||
assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStaticScriptWithInlineDefinedInstance() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
|
||||
assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("messengerInstanceInline"));
|
||||
Messenger messenger = (Messenger) ctx.getBean("messengerInstanceInline");
|
||||
|
||||
assertFalse("Shouldn't get proxy when refresh is disabled", AopUtils.isAopProxy(messenger));
|
||||
assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
|
||||
|
||||
String desiredMessage = "Hello World!";
|
||||
assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
|
||||
assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonStaticScript() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovyRefreshableContext.xml", getClass());
|
||||
Messenger messenger = (Messenger) ctx.getBean("messenger");
|
||||
|
||||
assertTrue("Should be a proxy for refreshable scripts", AopUtils.isAopProxy(messenger));
|
||||
assertTrue("Should be an instance of Refreshable", messenger instanceof Refreshable);
|
||||
|
||||
String desiredMessage = "Hello World!";
|
||||
assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
|
||||
|
||||
Refreshable refreshable = (Refreshable) messenger;
|
||||
refreshable.refresh();
|
||||
|
||||
assertEquals("Message is incorrect after refresh.", desiredMessage, messenger.getMessage());
|
||||
assertEquals("Incorrect refresh count", 2, refreshable.getRefreshCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonStaticPrototypeScript() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovyRefreshableContext.xml", getClass());
|
||||
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
|
||||
assertTrue("Should be a proxy for refreshable scripts", AopUtils.isAopProxy(messenger));
|
||||
assertTrue("Should be an instance of Refreshable", messenger instanceof Refreshable);
|
||||
|
||||
assertEquals("Hello World!", messenger.getMessage());
|
||||
assertEquals("Hello World!", messenger2.getMessage());
|
||||
messenger.setMessage("Bye World!");
|
||||
messenger2.setMessage("Byebye World!");
|
||||
assertEquals("Bye World!", messenger.getMessage());
|
||||
assertEquals("Byebye World!", messenger2.getMessage());
|
||||
|
||||
Refreshable refreshable = (Refreshable) messenger;
|
||||
refreshable.refresh();
|
||||
|
||||
assertEquals("Hello World!", messenger.getMessage());
|
||||
assertEquals("Byebye World!", messenger2.getMessage());
|
||||
assertEquals("Incorrect refresh count", 2, refreshable.getRefreshCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScriptCompilationException() throws Exception {
|
||||
try {
|
||||
new ClassPathXmlApplicationContext("org/springframework/scripting/groovy/groovyBrokenContext.xml");
|
||||
fail("Should throw exception for broken script file");
|
||||
}
|
||||
catch (NestedRuntimeException ex) {
|
||||
assertTrue("Wrong root cause: " + ex, ex.contains(ScriptCompilationException.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScriptedClassThatDoesNotHaveANoArgCtor() throws Exception {
|
||||
MockControl mock = MockControl.createControl(ScriptSource.class);
|
||||
ScriptSource script = (ScriptSource) mock.getMock();
|
||||
script.getScriptAsString();
|
||||
final String badScript = "class Foo { public Foo(String foo) {}}";
|
||||
mock.setReturnValue(badScript);
|
||||
script.suggestedClassName();
|
||||
mock.setReturnValue("someName");
|
||||
mock.replay();
|
||||
GroovyScriptFactory factory = new GroovyScriptFactory(ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript);
|
||||
try {
|
||||
factory.getScriptedObject(script, new Class[]{});
|
||||
fail("Must have thrown a ScriptCompilationException (no public no-arg ctor in scripted class).");
|
||||
}
|
||||
catch (ScriptCompilationException expected) {
|
||||
assertTrue(expected.contains(InstantiationException.class));
|
||||
}
|
||||
mock.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScriptedClassThatHasNoPublicNoArgCtor() throws Exception {
|
||||
MockControl mock = MockControl.createControl(ScriptSource.class);
|
||||
ScriptSource script = (ScriptSource) mock.getMock();
|
||||
script.getScriptAsString();
|
||||
final String badScript = "class Foo { protected Foo() {}}";
|
||||
mock.setReturnValue(badScript);
|
||||
script.suggestedClassName();
|
||||
mock.setReturnValue("someName");
|
||||
mock.replay();
|
||||
GroovyScriptFactory factory = new GroovyScriptFactory(ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript);
|
||||
try {
|
||||
factory.getScriptedObject(script, new Class[]{});
|
||||
fail("Must have thrown a ScriptCompilationException (no oublic no-arg ctor in scripted class).");
|
||||
}
|
||||
catch (ScriptCompilationException expected) {
|
||||
assertTrue(expected.contains(IllegalAccessException.class));
|
||||
}
|
||||
mock.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithTwoClassesDefinedInTheOneGroovyFile_CorrectClassFirst() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("twoClassesCorrectOneFirst.xml", getClass());
|
||||
Messenger messenger = (Messenger) ctx.getBean("messenger");
|
||||
assertNotNull(messenger);
|
||||
assertEquals("Hello World!", messenger.getMessage());
|
||||
|
||||
// Check can cast to GroovyObject
|
||||
GroovyObject goo = (GroovyObject) messenger;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithTwoClassesDefinedInTheOneGroovyFile_WrongClassFirst() throws Exception {
|
||||
try {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("twoClassesWrongOneFirst.xml", getClass());
|
||||
ctx.getBean("messenger", Messenger.class);
|
||||
fail("Must have failed: two classes defined in GroovyScriptFactory source, non-Messenger class defined first.");
|
||||
}
|
||||
// just testing for failure here, hence catching Exception...
|
||||
catch (Exception expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCtorWithNullScriptSourceLocator() throws Exception {
|
||||
try {
|
||||
new GroovyScriptFactory(null);
|
||||
fail("Must have thrown exception by this point.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCtorWithEmptyScriptSourceLocator() throws Exception {
|
||||
try {
|
||||
new GroovyScriptFactory("");
|
||||
fail("Must have thrown exception by this point.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCtorWithWhitespacedScriptSourceLocator() throws Exception {
|
||||
try {
|
||||
new GroovyScriptFactory("\n ");
|
||||
fail("Must have thrown exception by this point.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithInlineScriptWithLeadingWhitespace() throws Exception {
|
||||
try {
|
||||
new ClassPathXmlApplicationContext("lwspBadGroovyContext.xml", getClass());
|
||||
fail("Must have thrown a BeanCreationException ('inline:' prefix was preceded by whitespace");
|
||||
}
|
||||
catch (BeanCreationException expected) {
|
||||
assertTrue(expected.contains(FileNotFoundException.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetScriptedObjectDoesNotChokeOnNullInterfacesBeingPassedIn() throws Exception {
|
||||
MockControl mock = MockControl.createControl(ScriptSource.class);
|
||||
ScriptSource scriptSource = (ScriptSource) mock.getMock();
|
||||
scriptSource.getScriptAsString();
|
||||
mock.setReturnValue("class Bar {}");
|
||||
scriptSource.suggestedClassName();
|
||||
mock.setReturnValue("someName");
|
||||
mock.replay();
|
||||
|
||||
GroovyScriptFactory factory = new GroovyScriptFactory("a script source locator (doesn't matter here)");
|
||||
Object scriptedObject = factory.getScriptedObject(scriptSource, null);
|
||||
assertNotNull(scriptedObject);
|
||||
mock.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetScriptedObjectDoesChokeOnNullScriptSourceBeingPassedIn() throws Exception {
|
||||
GroovyScriptFactory factory = new GroovyScriptFactory("a script source locator (doesn't matter here)");
|
||||
try {
|
||||
factory.getScriptedObject(null, null);
|
||||
fail("Must have thrown a NullPointerException as per contract ('null' ScriptSource supplied");
|
||||
}
|
||||
catch (NullPointerException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceScriptFromTag() throws Exception {
|
||||
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
|
||||
Messenger messenger = (Messenger) ctx.getBean("messenger");
|
||||
CallCounter countingAspect = (CallCounter) ctx.getBean("getMessageAspect");
|
||||
|
||||
assertTrue(AopUtils.isAopProxy(messenger));
|
||||
assertFalse(messenger instanceof Refreshable);
|
||||
assertEquals(0, countingAspect.getCalls());
|
||||
assertEquals("Hello World!", messenger.getMessage());
|
||||
assertEquals(1, countingAspect.getCalls());
|
||||
|
||||
ctx.close();
|
||||
assertEquals(-200, countingAspect.getCalls());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrototypeScriptFromTag() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
|
||||
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
|
||||
assertNotSame(messenger, messenger2);
|
||||
assertSame(messenger.getClass(), messenger2.getClass());
|
||||
assertEquals("Hello World!", messenger.getMessage());
|
||||
assertEquals("Hello World!", messenger2.getMessage());
|
||||
messenger.setMessage("Bye World!");
|
||||
messenger2.setMessage("Byebye World!");
|
||||
assertEquals("Bye World!", messenger.getMessage());
|
||||
assertEquals("Byebye World!", messenger2.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInlineScriptFromTag() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
|
||||
Calculator calculator = (Calculator) ctx.getBean("calculator");
|
||||
assertNotNull(calculator);
|
||||
assertFalse(calculator instanceof Refreshable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshableFromTag() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
|
||||
assertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.class)).contains("refreshableMessenger"));
|
||||
|
||||
Messenger messenger = (Messenger) ctx.getBean("refreshableMessenger");
|
||||
CallCounter countingAspect = (CallCounter) ctx.getBean("getMessageAspect");
|
||||
|
||||
assertTrue(AopUtils.isAopProxy(messenger));
|
||||
assertTrue(messenger instanceof Refreshable);
|
||||
assertEquals(0, countingAspect.getCalls());
|
||||
assertEquals("Hello World!", messenger.getMessage());
|
||||
assertEquals(1, countingAspect.getCalls());
|
||||
|
||||
assertTrue(ctx.getBeansOfType(Messenger.class).values().contains(messenger));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnonymousScriptDetected() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-with-xsd.xml", getClass());
|
||||
Map beans = ctx.getBeansOfType(Messenger.class);
|
||||
assertEquals(4, beans.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the SPR-2098 bug whereby no more than 1 property element could be
|
||||
* passed to a scripted bean :(
|
||||
*/
|
||||
@Test
|
||||
public void testCanPassInMoreThanOneProperty() {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-multiple-properties.xml", getClass());
|
||||
TestBean tb = (TestBean) ctx.getBean("testBean");
|
||||
|
||||
ContextScriptBean bean = (ContextScriptBean) ctx.getBean("bean");
|
||||
assertEquals("The first property ain't bein' injected.", "Sophie Marceau", bean.getName());
|
||||
assertEquals("The second property ain't bein' injected.", 31, bean.getAge());
|
||||
assertEquals(tb, bean.getTestBean());
|
||||
assertEquals(ctx, bean.getApplicationContext());
|
||||
|
||||
ContextScriptBean bean2 = (ContextScriptBean) ctx.getBean("bean2");
|
||||
assertEquals(tb, bean2.getTestBean());
|
||||
assertEquals(ctx, bean2.getApplicationContext());
|
||||
|
||||
try {
|
||||
ctx.getBean("bean3");
|
||||
fail("Should have thrown BeanCreationException");
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
// expected
|
||||
assertTrue(ex.contains(UnsatisfiedDependencyException.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaClassWithBeans() {
|
||||
testMetaClass("org/springframework/scripting/groovy/calculators.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaClassWithXsd() {
|
||||
testMetaClass("org/springframework/scripting/groovy/calculators-with-xsd.xml");
|
||||
}
|
||||
|
||||
private void testMetaClass(final String xmlFile) {
|
||||
// expect the exception we threw in the custom metaclass to show it got invoked
|
||||
try {
|
||||
ApplicationContext ctx =
|
||||
new ClassPathXmlApplicationContext(xmlFile);
|
||||
Calculator calc = (Calculator) ctx.getBean("delegatingCalculator");
|
||||
calc.add(1, 2);
|
||||
fail("expected IllegalStateException");
|
||||
} catch (IllegalStateException ex) {
|
||||
assertEquals("Gotcha", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFactoryBean() {
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
|
||||
Object factory = context.getBean("&factory");
|
||||
assertTrue(factory instanceof FactoryBean);
|
||||
Object result = context.getBean("factory");
|
||||
assertTrue(result instanceof String);
|
||||
assertEquals("test", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshableFactoryBean() {
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext("groovyContext.xml", getClass());
|
||||
Object factory = context.getBean("&refreshableFactory");
|
||||
assertTrue(factory instanceof FactoryBean);
|
||||
Object result = context.getBean("refreshableFactory");
|
||||
assertTrue(result instanceof String);
|
||||
assertEquals("test", result);
|
||||
}
|
||||
|
||||
|
||||
public static class TestCustomizer implements GroovyObjectCustomizer {
|
||||
|
||||
public void customize(GroovyObject goo) {
|
||||
DelegatingMetaClass dmc = new DelegatingMetaClass(goo.getMetaClass()) {
|
||||
public Object invokeMethod(Object arg0, String mName, Object[] arg2) {
|
||||
if (mName.indexOf("Missing") != -1) {
|
||||
throw new IllegalStateException("Gotcha");
|
||||
}
|
||||
else {
|
||||
return super.invokeMethod(arg0, mName, arg2);
|
||||
}
|
||||
}
|
||||
};
|
||||
dmc.initialize();
|
||||
goo.setMetaClass(dmc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.springframework.scripting.groovy;
|
||||
|
||||
import org.springframework.scripting.ConfigurableMessenger
|
||||
|
||||
class GroovyMessenger implements ConfigurableMessenger {
|
||||
|
||||
def String message;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.springframework.scripting.groovy;
|
||||
|
||||
import org.springframework.scripting.Messenger
|
||||
|
||||
class GroovyMessenger implements Messenger {
|
||||
|
||||
GroovyMessenger() {
|
||||
println "GroovyMessenger"
|
||||
}
|
||||
|
||||
def String message;
|
||||
}
|
||||
|
||||
return new GroovyMessenger();
|
||||
@@ -0,0 +1,23 @@
|
||||
import org.springframework.beans.TestBean
|
||||
import org.springframework.context.ApplicationContext
|
||||
import org.springframework.context.ApplicationContextAware
|
||||
import org.springframework.scripting.ContextScriptBean
|
||||
|
||||
class GroovyScriptBean implements ContextScriptBean, ApplicationContextAware {
|
||||
|
||||
private int age
|
||||
|
||||
int getAge() {
|
||||
return this.age
|
||||
}
|
||||
|
||||
void setAge(int age) {
|
||||
this.age = age
|
||||
}
|
||||
|
||||
def String name
|
||||
|
||||
def TestBean testBean;
|
||||
|
||||
def ApplicationContext applicationContext
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import org.springframework.beans.factory.FactoryBean
|
||||
|
||||
class TestFactoryBean implements FactoryBean {
|
||||
|
||||
public boolean isSingleton() {
|
||||
true
|
||||
}
|
||||
|
||||
public Class getObjectType() {
|
||||
String.class
|
||||
}
|
||||
|
||||
public Object getObject() {
|
||||
"test"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">
|
||||
|
||||
<lang:groovy id="calculator"
|
||||
script-source="classpath:org/springframework/scripting/groovy/Calculator.groovy"
|
||||
customizer-ref="testCustomizer" />
|
||||
|
||||
<bean id="testCustomizer" class="org.springframework.scripting.groovy.GroovyScriptFactoryTests$TestCustomizer"/>
|
||||
|
||||
<lang:groovy id="delegatingCalculator"
|
||||
script-source="classpath:org/springframework/scripting/groovy/DelegatingCalculator.groovy">
|
||||
<lang:property name="delegate" ref="calculator"/>
|
||||
</lang:groovy>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
|
||||
<bean id="calculator" class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/groovy/Calculator.groovy"/>
|
||||
<constructor-arg>
|
||||
<bean class="org.springframework.scripting.groovy.GroovyScriptFactoryTests$TestCustomizer" />
|
||||
</constructor-arg>
|
||||
|
||||
</bean>
|
||||
|
||||
<bean id="delegatingCalculator" class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/groovy/DelegatingCalculator.groovy"/>
|
||||
|
||||
<property name="delegate" ref="calculator"/>
|
||||
|
||||
</bean>
|
||||
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd">
|
||||
|
||||
<lang:groovy id="bean" script-source="classpath:org/springframework/scripting/groovy/ScriptBean.groovy" autowire="byType" dependency-check="all">
|
||||
<lang:property name="name" value="Sophie Marceau"/>
|
||||
<lang:property name="age" value="31"/>
|
||||
</lang:groovy>
|
||||
|
||||
<lang:groovy id="bean2" script-source="classpath:org/springframework/scripting/groovy/ScriptBean.groovy" autowire="byName">
|
||||
<lang:property name="name" value="Sophie Marceau"/>
|
||||
<lang:property name="age" value="31"/>
|
||||
</lang:groovy>
|
||||
|
||||
<lang:groovy id="bean3" script-source="classpath:org/springframework/scripting/groovy/ScriptBean.groovy" dependency-check="objects" scope="prototype">
|
||||
<lang:property name="name" value="Sophie Marceau"/>
|
||||
<lang:property name="age" value="31"/>
|
||||
</lang:groovy>
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.TestBean"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd">
|
||||
|
||||
<aop:config>
|
||||
<aop:aspect ref="getMessageAspect">
|
||||
<aop:before method="before" pointcut="execution(* org.springframework.scripting.Messenger.*(..))"/>
|
||||
</aop:aspect>
|
||||
</aop:config>
|
||||
|
||||
<lang:groovy id="getMessageAspect" script-source="classpath:org/springframework/scripting/groovy/CallCounter.groovy"
|
||||
init-method="init" destroy-method="destroy"/>
|
||||
|
||||
<lang:groovy id="messenger" script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:groovy>
|
||||
|
||||
<lang:groovy id="messengerPrototype" script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy"
|
||||
scope="prototype">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:groovy>
|
||||
|
||||
<lang:groovy id="calculator" depends-on="messenger" customizer-ref="customizer">
|
||||
<lang:inline-script>
|
||||
package org.springframework.scripting.groovy;
|
||||
import org.springframework.scripting.Calculator
|
||||
class GroovyCalculator implements Calculator {
|
||||
int add(int x, int y) {
|
||||
return x + y;
|
||||
}
|
||||
}
|
||||
</lang:inline-script>
|
||||
</lang:groovy>
|
||||
|
||||
<lang:groovy id="customizer">
|
||||
<lang:inline-script><![CDATA[
|
||||
import org.springframework.scripting.groovy.GroovyObjectCustomizer;
|
||||
|
||||
public class TestCustomizer implements GroovyObjectCustomizer {
|
||||
public void customize(GroovyObject o) {
|
||||
println "customizing ${o}.."
|
||||
}
|
||||
}]]>
|
||||
</lang:inline-script>
|
||||
</lang:groovy>
|
||||
|
||||
<lang:groovy id="refreshableMessenger" refresh-check-delay="5000"
|
||||
script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:groovy>
|
||||
|
||||
<lang:groovy script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:groovy>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
|
||||
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="broken" class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/groovy/Broken.groovyb"/>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/lang
|
||||
http://www.springframework.org/schema/lang/spring-lang.xsd"
|
||||
default-lazy-init="true">
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="calculator"
|
||||
class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
<constructor-arg>
|
||||
<value>inline:
|
||||
package org.springframework.scripting.groovy;
|
||||
import org.springframework.scripting.Calculator
|
||||
class GroovyCalculator implements Calculator {
|
||||
int add(int x, int y) {
|
||||
return x + y;
|
||||
}
|
||||
}
|
||||
</value>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="messenger"
|
||||
class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/groovy/Messenger.groovy"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messengerPrototype"
|
||||
class="org.springframework.scripting.groovy.GroovyScriptFactory"
|
||||
scope="prototype">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/groovy/Messenger.groovy"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messengerInstance"
|
||||
class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/groovy/MessengerInstance.groovy"/>
|
||||
<property name="message" ref="myMessage"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messengerInstanceInline"
|
||||
class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
<constructor-arg>
|
||||
<value>inline:
|
||||
package org.springframework.scripting.groovy;
|
||||
import org.springframework.scripting.Messenger
|
||||
class GroovyMessenger implements Messenger {
|
||||
def String message;
|
||||
}
|
||||
return new GroovyMessenger();
|
||||
</value>
|
||||
</constructor-arg>
|
||||
<property name="message" ref="myMessage"/>
|
||||
</bean>
|
||||
|
||||
<bean id="myMessage" class="java.lang.String">
|
||||
<constructor-arg value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<lang:groovy id="refreshableFactory" refresh-check-delay="5000"
|
||||
script-source="org/springframework/scripting/groovy/TestFactoryBean.groovy"/>
|
||||
|
||||
<lang:groovy id="factory" script-source="classpath:org/springframework/scripting/groovy/TestFactoryBean.groovy"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans default-lazy-init="true">
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor">
|
||||
<property name="defaultRefreshCheckDelay" value="1"/>
|
||||
</bean>
|
||||
|
||||
<bean id="calculator" class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/groovy/Calculator.groovy"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messenger" class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/groovy/Messenger.groovy"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messengerPrototype" class="org.springframework.scripting.groovy.GroovyScriptFactory" scope="prototype">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/groovy/Messenger.groovy"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
<beans>
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="messenger" class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
<constructor-arg>
|
||||
<!-- 'inline:' prefix is preceded by whitespace... -->
|
||||
<value>
|
||||
inline:
|
||||
|
||||
class Bingo {
|
||||
|
||||
@Property String message;
|
||||
}
|
||||
</value>
|
||||
</constructor-arg>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
<beans>
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="messenger" class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
<constructor-arg>
|
||||
<value>inline:
|
||||
package org.springframework.scripting.groovy;
|
||||
|
||||
import org.springframework.scripting.Messenger;
|
||||
|
||||
class GroovyMessenger implements Messenger {
|
||||
|
||||
def String message;
|
||||
}
|
||||
|
||||
class Bingo {
|
||||
|
||||
def String message;
|
||||
}
|
||||
</value>
|
||||
</constructor-arg>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
<beans>
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="messenger" class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
<constructor-arg>
|
||||
<value>inline:
|
||||
package org.springframework.scripting.groovy;
|
||||
|
||||
import org.springframework.scripting.Messenger;
|
||||
|
||||
class Bingo {
|
||||
|
||||
@Property String message;
|
||||
}
|
||||
|
||||
class GroovyMessenger implements Messenger {
|
||||
|
||||
@Property String message;
|
||||
}
|
||||
</value>
|
||||
</constructor-arg>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.jruby;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.CountingBeforeAdvice;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.scripting.Messenger;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
*/
|
||||
public class AdvisedJRubyScriptFactoryTests extends TestCase {
|
||||
|
||||
public void testAdviseWithProxyFactoryBean() throws Exception {
|
||||
ApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("advisedByProxyFactoryBean.xml", getClass());
|
||||
|
||||
Messenger bean = (Messenger) context.getBean("messenger");
|
||||
assertTrue("Bean is not a proxy", AopUtils.isAopProxy(bean));
|
||||
assertTrue("Bean is not an Advised object", bean instanceof Advised);
|
||||
|
||||
CountingBeforeAdvice advice = (CountingBeforeAdvice) context.getBean("advice");
|
||||
assertEquals(0, advice.getCalls());
|
||||
bean.getMessage();
|
||||
assertEquals(1, advice.getCalls());
|
||||
}
|
||||
|
||||
public void testAdviseWithBeanNameAutoProxyCreator() throws Exception {
|
||||
ApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("advisedByBeanNameAutoProxyCreator.xml", getClass());
|
||||
|
||||
Messenger bean = (Messenger) context.getBean("messenger");
|
||||
assertTrue("Bean is not a proxy", AopUtils.isAopProxy(bean));
|
||||
assertTrue("Bean is not an Advised object", bean instanceof Advised);
|
||||
|
||||
CountingBeforeAdvice advice = (CountingBeforeAdvice) context.getBean("advice");
|
||||
assertEquals(0, advice.getCalls());
|
||||
bean.getMessage();
|
||||
assertEquals(1, advice.getCalls());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
In A Station Of The Metro
|
||||
|
||||
the apparition of these faces in the crowd
|
||||
petals on a wet black bough
|
||||
@@ -0,0 +1,9 @@
|
||||
require 'java'
|
||||
|
||||
class RubyCalculator
|
||||
include org.springframework.scripting.Calculator
|
||||
|
||||
def add(x, y)
|
||||
x + y
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.jruby;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.target.dynamic.Refreshable;
|
||||
import org.springframework.beans.TestBean;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.scripting.Calculator;
|
||||
import org.springframework.scripting.ConfigurableMessenger;
|
||||
import org.springframework.scripting.Messenger;
|
||||
import org.springframework.scripting.ScriptCompilationException;
|
||||
import org.springframework.scripting.TestBeanAwareMessenger;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class JRubyScriptFactoryTests extends TestCase {
|
||||
|
||||
private static final String RUBY_SCRIPT_SOURCE_LOCATOR =
|
||||
"inline:require 'java'\n" +
|
||||
"class RubyBar\n" +
|
||||
"end\n" +
|
||||
"RubyBar.new";
|
||||
|
||||
|
||||
public void testStaticScript() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("jrubyContext.xml", getClass());
|
||||
Calculator calc = (Calculator) ctx.getBean("calculator");
|
||||
Messenger messenger = (Messenger) ctx.getBean("messenger");
|
||||
|
||||
assertFalse("Scripted object should not be instance of Refreshable", calc instanceof Refreshable);
|
||||
assertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
|
||||
|
||||
Assert.assertEquals(calc, calc);
|
||||
Assert.assertEquals(messenger, messenger);
|
||||
assertTrue(!messenger.equals(calc));
|
||||
assertNotSame(messenger.hashCode(), calc.hashCode());
|
||||
assertTrue(!messenger.toString().equals(calc.toString()));
|
||||
|
||||
String desiredMessage = "Hello World!";
|
||||
Assert.assertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
|
||||
}
|
||||
|
||||
public void testNonStaticScript() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("jrubyRefreshableContext.xml", getClass());
|
||||
Messenger messenger = (Messenger) ctx.getBean("messenger");
|
||||
|
||||
assertTrue("Should be a proxy for refreshable scripts", AopUtils.isAopProxy(messenger));
|
||||
assertTrue("Should be an instance of Refreshable", messenger instanceof Refreshable);
|
||||
|
||||
String desiredMessage = "Hello World!";
|
||||
Assert.assertEquals("Message is incorrect.", desiredMessage, messenger.getMessage());
|
||||
|
||||
Refreshable refreshable = (Refreshable) messenger;
|
||||
refreshable.refresh();
|
||||
|
||||
Assert.assertEquals("Message is incorrect after refresh.", desiredMessage, messenger.getMessage());
|
||||
assertEquals("Incorrect refresh count", 2, refreshable.getRefreshCount());
|
||||
}
|
||||
|
||||
public void testScriptCompilationException() throws Exception {
|
||||
try {
|
||||
new ClassPathXmlApplicationContext("jrubyBrokenContext.xml", getClass());
|
||||
fail("Should throw exception for broken script file");
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
assertTrue(ex.contains(ScriptCompilationException.class));
|
||||
}
|
||||
}
|
||||
|
||||
public void testCtorWithNullScriptSourceLocator() throws Exception {
|
||||
try {
|
||||
new JRubyScriptFactory(null, new Class[]{Messenger.class});
|
||||
fail("Must have thrown exception by this point.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCtorWithEmptyScriptSourceLocator() throws Exception {
|
||||
try {
|
||||
new JRubyScriptFactory("", new Class[]{Messenger.class});
|
||||
fail("Must have thrown exception by this point.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCtorWithWhitespacedScriptSourceLocator() throws Exception {
|
||||
try {
|
||||
new JRubyScriptFactory("\n ", new Class[]{Messenger.class});
|
||||
fail("Must have thrown exception by this point.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCtorWithNullScriptInterfacesArray() throws Exception {
|
||||
try {
|
||||
new JRubyScriptFactory(RUBY_SCRIPT_SOURCE_LOCATOR, null);
|
||||
fail("Must have thrown exception by this point.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCtorWithEmptyScriptInterfacesArray() throws Exception {
|
||||
try {
|
||||
new JRubyScriptFactory(RUBY_SCRIPT_SOURCE_LOCATOR, new Class[]{});
|
||||
fail("Must have thrown exception by this point.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testResourceScriptFromTag() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("jruby-with-xsd.xml", getClass());
|
||||
TestBean testBean = (TestBean) ctx.getBean("testBean");
|
||||
|
||||
Messenger messenger = (Messenger) ctx.getBean("messenger");
|
||||
Assert.assertEquals("Hello World!", messenger.getMessage());
|
||||
assertFalse(messenger instanceof Refreshable);
|
||||
|
||||
TestBeanAwareMessenger messengerByType = (TestBeanAwareMessenger) ctx.getBean("messengerByType");
|
||||
Assert.assertEquals(testBean, messengerByType.getTestBean());
|
||||
|
||||
TestBeanAwareMessenger messengerByName = (TestBeanAwareMessenger) ctx.getBean("messengerByName");
|
||||
Assert.assertEquals(testBean, messengerByName.getTestBean());
|
||||
}
|
||||
|
||||
public void testPrototypeScriptFromTag() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("jruby-with-xsd.xml", getClass());
|
||||
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
|
||||
|
||||
assertNotSame(messenger, messenger2);
|
||||
assertSame(messenger.getClass(), messenger2.getClass());
|
||||
Assert.assertEquals("Hello World!", messenger.getMessage());
|
||||
Assert.assertEquals("Hello World!", messenger2.getMessage());
|
||||
messenger.setMessage("Bye World!");
|
||||
messenger2.setMessage("Byebye World!");
|
||||
Assert.assertEquals("Bye World!", messenger.getMessage());
|
||||
Assert.assertEquals("Byebye World!", messenger2.getMessage());
|
||||
}
|
||||
|
||||
public void testInlineScriptFromTag() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("jruby-with-xsd.xml", getClass());
|
||||
Calculator calculator = (Calculator) ctx.getBean("calculator");
|
||||
assertNotNull(calculator);
|
||||
assertFalse(calculator instanceof Refreshable);
|
||||
}
|
||||
|
||||
public void testRefreshableFromTag() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("jruby-with-xsd.xml", getClass());
|
||||
Messenger messenger = (Messenger) ctx.getBean("refreshableMessenger");
|
||||
Assert.assertEquals("Hello World!", messenger.getMessage());
|
||||
assertTrue("Messenger should be Refreshable", messenger instanceof Refreshable);
|
||||
}
|
||||
|
||||
public void testThatMultipleScriptInterfacesAreSupported() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("jruby-with-xsd.xml", getClass());
|
||||
Messenger messenger = (Messenger) ctx.getBean("calculatingMessenger");
|
||||
Assert.assertEquals("Hello World!", messenger.getMessage());
|
||||
|
||||
// cool, now check that the Calculator interface is also exposed
|
||||
Calculator calc = (Calculator) messenger;
|
||||
Assert.assertEquals(0, calc.add(2, -2));
|
||||
}
|
||||
|
||||
public void testWithComplexArg() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("jrubyContext.xml", getClass());
|
||||
Printer printer = (Printer) ctx.getBean("printer");
|
||||
CountingPrintable printable = new CountingPrintable();
|
||||
printer.print(printable);
|
||||
assertEquals(1, printable.count);
|
||||
}
|
||||
|
||||
public void testWithPrimitiveArgsInReturnTypeAndParameters() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("jrubyContextForPrimitives.xml", getClass());
|
||||
PrimitiveAdder adder = (PrimitiveAdder) ctx.getBean("adder");
|
||||
assertEquals(2, adder.addInts(1, 1));
|
||||
assertEquals(4, adder.addShorts((short) 1, (short) 3));
|
||||
assertEquals(5, adder.addLongs(2L, 3L));
|
||||
assertEquals(5, new Float(adder.addFloats(2.0F, 3.1F)).intValue());
|
||||
assertEquals(5, new Double(adder.addDoubles(2.0, 3.1)).intValue());
|
||||
assertFalse(adder.resultIsPositive(-200, 1));
|
||||
assertEquals("ri", adder.concatenate('r', 'i'));
|
||||
assertEquals('c', adder.echo('c'));
|
||||
}
|
||||
|
||||
public void testWithWrapperArgsInReturnTypeAndParameters() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("jrubyContextForWrappers.xml", getClass());
|
||||
WrapperAdder adder = (WrapperAdder) ctx.getBean("adder");
|
||||
|
||||
assertEquals(new Integer(2), adder.addInts(new Integer(1), new Integer(1)));
|
||||
assertEquals(Integer.class, adder.addInts(new Integer(1), new Integer(1)).getClass());
|
||||
assertEquals(new Short((short) 4), adder.addShorts(new Short((short) 1), new Short((short) 3)));
|
||||
assertEquals(Short.class, adder.addShorts(new Short((short) 1), new Short((short) 3)).getClass());
|
||||
assertEquals(new Long(5L), adder.addLongs(new Long(2L), new Long(3L)));
|
||||
assertEquals(Long.class, adder.addLongs(new Long(2L), new Long(3L)).getClass());
|
||||
assertEquals(5, adder.addFloats(new Float(2.0F), new Float(3.1F)).intValue());
|
||||
assertEquals(Float.class, adder.addFloats(new Float(2.0F), new Float(3.1F)).getClass());
|
||||
assertEquals(5, new Double(adder.addDoubles(new Double(2.0), new Double(3.1)).intValue()).intValue());
|
||||
assertEquals(Double.class, adder.addDoubles(new Double(2.0), new Double(3.1)).getClass());
|
||||
assertFalse(adder.resultIsPositive(new Integer(-200), new Integer(1)).booleanValue());
|
||||
assertEquals(Boolean.class, adder.resultIsPositive(new Integer(-200), new Integer(1)).getClass());
|
||||
assertEquals("ri", adder.concatenate(new Character('r'), new Character('i')));
|
||||
assertEquals(String.class, adder.concatenate(new Character('r'), new Character('i')).getClass());
|
||||
assertEquals(new Character('c'), adder.echo(new Character('c')));
|
||||
assertEquals(Character.class, adder.echo(new Character('c')).getClass());
|
||||
Integer[] numbers = new Integer[]{new Integer(1), new Integer(2), new Integer(3), new Integer(4), new Integer(5)};
|
||||
assertEquals("12345", adder.concatArrayOfIntegerWrappers(numbers));
|
||||
assertEquals(String.class, adder.concatArrayOfIntegerWrappers(numbers).getClass());
|
||||
|
||||
Short[] shorts = adder.populate(new Short((short) 1), new Short((short) 2));
|
||||
assertEquals(2, shorts.length);
|
||||
assertNotNull(shorts[0]);
|
||||
assertEquals(new Short((short) 1), shorts[0]);
|
||||
assertNotNull(shorts[1]);
|
||||
assertEquals(new Short((short) 2), shorts[1]);
|
||||
|
||||
String[][] lol = adder.createListOfLists("1", "2", "3");
|
||||
assertNotNull(lol);
|
||||
assertEquals(3, lol.length);
|
||||
assertEquals("1", lol[0][0]);
|
||||
assertEquals("2", lol[1][0]);
|
||||
assertEquals("3", lol[2][0]);
|
||||
|
||||
Map singleValueMap = adder.toMap("key", "value");
|
||||
assertNotNull(singleValueMap);
|
||||
assertEquals(1, singleValueMap.size());
|
||||
assertEquals("key", singleValueMap.keySet().iterator().next());
|
||||
assertEquals("value", singleValueMap.values().iterator().next());
|
||||
|
||||
String[] expectedStrings = new String[]{"1", "2", "3"};
|
||||
Map map = adder.toMap("key", expectedStrings);
|
||||
assertNotNull(map);
|
||||
assertEquals(1, map.size());
|
||||
assertEquals("key", map.keySet().iterator().next());
|
||||
String[] strings = (String[]) map.values().iterator().next();
|
||||
for (int i = 0; i < expectedStrings.length; ++i) {
|
||||
assertEquals(expectedStrings[i], strings[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void testAOP() throws Exception {
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("jruby-aop.xml", getClass());
|
||||
Messenger messenger = (Messenger) ctx.getBean("messenger");
|
||||
Assert.assertEquals(new StringBuffer("Hello World!").reverse().toString(), messenger.getMessage());
|
||||
}
|
||||
|
||||
|
||||
private static final class CountingPrintable implements Printable {
|
||||
|
||||
public int count;
|
||||
|
||||
public String getContent() {
|
||||
this.count++;
|
||||
return "Hello World!";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
require 'java'
|
||||
|
||||
class RubyMessenger
|
||||
include org.springframework.scripting.Messenger
|
||||
|
||||
def setMessage(message)
|
||||
@@message = message
|
||||
end
|
||||
|
||||
def getMessage
|
||||
@@message
|
||||
end
|
||||
|
||||
def setTestBean(testBean)
|
||||
@@testBean = testBean
|
||||
end
|
||||
|
||||
def getTestBean
|
||||
@@testBean
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.springframework.scripting.jruby;
|
||||
|
||||
/**
|
||||
* http://opensource.atlassian.com/projects/spring/browse/SPR-3026
|
||||
*
|
||||
* @author Rick Evans
|
||||
*/
|
||||
public interface PrimitiveAdder {
|
||||
|
||||
int addInts(int x, int y);
|
||||
|
||||
short addShorts(short x, short y);
|
||||
|
||||
long addLongs(long x, long y);
|
||||
|
||||
float addFloats(float x, float y);
|
||||
|
||||
double addDoubles(double x, double y);
|
||||
|
||||
boolean resultIsPositive(int x, int y);
|
||||
|
||||
String concatenate(char c, char d);
|
||||
|
||||
char echo(char c);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2002-2006 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.jruby;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public interface Printable {
|
||||
|
||||
String getContent();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2002-2006 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.jruby;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public interface Printer {
|
||||
|
||||
void print(Printable arg);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
require 'java'
|
||||
|
||||
class RubyPrinter
|
||||
include org.springframework.scripting.jruby.Printer
|
||||
|
||||
def print(obj)
|
||||
puts obj.getContent
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.jruby;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* http://opensource.atlassian.com/projects/spring/browse/SPR-3038
|
||||
*
|
||||
* @author Rick Evans
|
||||
*/
|
||||
public interface WrapperAdder {
|
||||
|
||||
Integer addInts(Integer x, Integer y);
|
||||
|
||||
Short addShorts(Short x, Short y);
|
||||
|
||||
Long addLongs(Long x, Long y);
|
||||
|
||||
Float addFloats(Float x, Float y);
|
||||
|
||||
Double addDoubles(Double x, Double y);
|
||||
|
||||
Boolean resultIsPositive(Integer x, Integer y);
|
||||
|
||||
String concatenate(Character c, Character d);
|
||||
|
||||
Character echo(Character c);
|
||||
|
||||
String concatArrayOfIntegerWrappers(Integer[] numbers);
|
||||
|
||||
Short[] populate(Short one, Short two);
|
||||
|
||||
String[][] createListOfLists(String one, String second, String third);
|
||||
|
||||
Map toMap(String key, Object value);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="apc" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
|
||||
<property name="beanNames" value="messenger"/>
|
||||
<property name="interceptorNames" value="advice"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messenger" class="org.springframework.scripting.jruby.JRubyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/jruby/Messenger.rb"/>
|
||||
<constructor-arg value="org.springframework.scripting.Messenger"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="advice" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="messengerTarget" class="org.springframework.scripting.jruby.JRubyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/jruby/Messenger.rb"/>
|
||||
<constructor-arg value="org.springframework.scripting.Messenger"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messenger" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="target" ref="messengerTarget"/>
|
||||
<property name="interceptorNames" value="advice"/>
|
||||
</bean>
|
||||
|
||||
<bean id="advice" class="org.springframework.aop.framework.CountingBeforeAdvice"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.0.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
|
||||
|
||||
<lang:jruby id="messenger"
|
||||
script-interfaces="org.springframework.scripting.Messenger"
|
||||
script-source="classpath:org/springframework/scripting/jruby/Messenger.rb">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:jruby>
|
||||
|
||||
<aop:config>
|
||||
<aop:pointcut id="messengerOps"
|
||||
expression="execution(String org.springframework.scripting.Messenger.*())"/>
|
||||
<aop:aspect id="scramblerAspect" ref="scrambler">
|
||||
<aop:around pointcut-ref="messengerOps"
|
||||
method="scramble"/>
|
||||
</aop:aspect>
|
||||
</aop:config>
|
||||
|
||||
<bean id="scrambler" class="org.springframework.scripting.MessengerScrambler"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:lang="http://www.springframework.org/schema/lang"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd">
|
||||
|
||||
<lang:jruby id="messenger"
|
||||
script-source="classpath:org/springframework/scripting/jruby/Messenger.rb"
|
||||
script-interfaces="org.springframework.scripting.Messenger">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:jruby>
|
||||
|
||||
<lang:jruby id="messengerPrototype"
|
||||
script-source="classpath:org/springframework/scripting/jruby/Messenger.rb"
|
||||
script-interfaces="org.springframework.scripting.ConfigurableMessenger" scope="prototype">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:jruby>
|
||||
|
||||
<lang:jruby id="messengerByType"
|
||||
script-source="classpath:org/springframework/scripting/jruby/Messenger.rb"
|
||||
script-interfaces="org.springframework.scripting.TestBeanAwareMessenger" scope="prototype"
|
||||
autowire="byType" dependency-check="objects">
|
||||
</lang:jruby>
|
||||
|
||||
<lang:jruby id="messengerByName"
|
||||
script-source="classpath:org/springframework/scripting/jruby/Messenger.rb"
|
||||
script-interfaces="org.springframework.scripting.TestBeanAwareMessenger" scope="prototype"
|
||||
autowire="byName">
|
||||
</lang:jruby>
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.TestBean"/>
|
||||
|
||||
<lang:jruby id="calculator"
|
||||
script-interfaces="org.springframework.scripting.Calculator">
|
||||
<lang:inline-script>
|
||||
require 'java'
|
||||
|
||||
class RubyCalculator
|
||||
include org.springframework.scripting.Calculator
|
||||
|
||||
def add(x, y)
|
||||
x + y
|
||||
end
|
||||
end
|
||||
</lang:inline-script>
|
||||
</lang:jruby>
|
||||
|
||||
<lang:jruby id="refreshableMessenger"
|
||||
script-source="classpath:org/springframework/scripting/jruby/Messenger.rb"
|
||||
script-interfaces="org.springframework.scripting.Messenger"
|
||||
refresh-check-delay="5000">
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:jruby>
|
||||
|
||||
<!-- just checking that multiple script interfaces are supported -->
|
||||
<lang:jruby id="calculatingMessenger"
|
||||
script-interfaces="org.springframework.scripting.Calculator, org.springframework.scripting.Messenger">
|
||||
<lang:inline-script><![CDATA[require 'java'
|
||||
|
||||
class RubyCalculatingMessenger
|
||||
|
||||
def add(x, y)
|
||||
x + y
|
||||
end
|
||||
|
||||
def setMessage(message)
|
||||
@@message = message
|
||||
end
|
||||
|
||||
def getMessage
|
||||
@@message
|
||||
end
|
||||
|
||||
end
|
||||
]]></lang:inline-script>
|
||||
<lang:property name="message" value="Hello World!"/>
|
||||
</lang:jruby>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
|
||||
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="broken" class="org.springframework.scripting.jruby.JRubyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/jruby/Broken.rb"/>
|
||||
<constructor-arg value="org.springframework.scripting.Messenger"/>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="calculator" class="org.springframework.scripting.jruby.JRubyScriptFactory">
|
||||
<constructor-arg>
|
||||
<value>inline:
|
||||
require 'java'
|
||||
|
||||
class RubyCalculator
|
||||
include org.springframework.scripting.Calculator
|
||||
|
||||
def add(x, y)
|
||||
x + y
|
||||
end
|
||||
end
|
||||
</value>
|
||||
</constructor-arg>
|
||||
<constructor-arg value="org.springframework.scripting.Calculator"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messenger" class="org.springframework.scripting.jruby.JRubyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/jruby/Messenger.rb"/>
|
||||
<constructor-arg value="org.springframework.scripting.Messenger"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
<bean id="printer" class="org.springframework.scripting.jruby.JRubyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/jruby/Printer.rb"/>
|
||||
<constructor-arg value="org.springframework.scripting.jruby.Printer"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="adder" class="org.springframework.scripting.jruby.JRubyScriptFactory">
|
||||
<constructor-arg>
|
||||
<value><![CDATA[inline:
|
||||
require 'java'
|
||||
|
||||
class RubyPrimitiveAdder
|
||||
include org.springframework.scripting.jruby.PrimitiveAdder
|
||||
|
||||
def addInts(x, y)
|
||||
x + y
|
||||
end
|
||||
|
||||
def addShorts(x, y)
|
||||
x + y
|
||||
end
|
||||
|
||||
def addLongs(x, y)
|
||||
x + y
|
||||
end
|
||||
|
||||
def addFloats(x, y)
|
||||
x + y
|
||||
end
|
||||
|
||||
def addDoubles(x, y)
|
||||
x + y
|
||||
end
|
||||
|
||||
def resultIsPositive(x, y)
|
||||
(x + y) > 0
|
||||
end
|
||||
|
||||
def concatenate(c, d)
|
||||
return ("" << c) << d;
|
||||
end
|
||||
|
||||
def echo(c)
|
||||
c
|
||||
end
|
||||
|
||||
end
|
||||
]]></value>
|
||||
</constructor-arg>
|
||||
<constructor-arg value="org.springframework.scripting.jruby.PrimitiveAdder"/>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="adder" class="org.springframework.scripting.jruby.JRubyScriptFactory">
|
||||
<constructor-arg>
|
||||
<value><![CDATA[inline:
|
||||
require 'java'
|
||||
|
||||
class RubyWrapperAdder
|
||||
include org.springframework.scripting.jruby.WrapperAdder
|
||||
|
||||
def addInts(x, y)
|
||||
x + y
|
||||
end
|
||||
|
||||
def addShorts(x, y)
|
||||
x + y
|
||||
end
|
||||
|
||||
def addLongs(x, y)
|
||||
x + y
|
||||
end
|
||||
|
||||
def addFloats(x, y)
|
||||
x + y
|
||||
end
|
||||
|
||||
def addDoubles(x, y)
|
||||
x + y
|
||||
end
|
||||
|
||||
def resultIsPositive(x, y)
|
||||
(x + y) > 0
|
||||
end
|
||||
|
||||
def concatenate(c, d)
|
||||
return ("" << c) << d;
|
||||
end
|
||||
|
||||
def echo(c)
|
||||
c
|
||||
end
|
||||
|
||||
def concatArrayOfIntegerWrappers(numbers)
|
||||
buffer = ""
|
||||
numbers.each do |number|
|
||||
buffer << number.to_s
|
||||
end
|
||||
return buffer
|
||||
end
|
||||
|
||||
def populate(x, y)
|
||||
[x, y]
|
||||
end
|
||||
|
||||
def createListOfLists(x, y, z)
|
||||
[[x], [y], [z]]
|
||||
end
|
||||
|
||||
def toMap(key, value)
|
||||
{key => value}
|
||||
end
|
||||
|
||||
end
|
||||
]]></value>
|
||||
</constructor-arg>
|
||||
<constructor-arg value="org.springframework.scripting.jruby.WrapperAdder"/>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor">
|
||||
<property name="defaultRefreshCheckDelay" value="1"/>
|
||||
</bean>
|
||||
|
||||
<bean id="calculator" class="org.springframework.scripting.jruby.JRubyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/jruby/Calculator.rb"/>
|
||||
<constructor-arg value="org.springframework.scripting.Calculator"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messenger" class="org.springframework.scripting.jruby.JRubyScriptFactory">
|
||||
<constructor-arg value="classpath:org/springframework/scripting/jruby/Messenger.rb"/>
|
||||
<constructor-arg value="org.springframework.scripting.Messenger"/>
|
||||
<property name="message" value="Hello World!"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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 junit.framework.TestCase;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
|
||||
/**
|
||||
* @author Rick Evans
|
||||
*/
|
||||
public class RefreshableScriptTargetSourceTests extends TestCase {
|
||||
|
||||
public void testCreateWithNullScriptSource() throws Exception {
|
||||
MockControl mockFactory = MockControl.createNiceControl(BeanFactory.class);
|
||||
mockFactory.replay();
|
||||
try {
|
||||
new RefreshableScriptTargetSource((BeanFactory) mockFactory.getMock(), "a.bean", null, null, false);
|
||||
fail("Must have failed when passed a null ScriptSource.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
mockFactory.verify();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.ByteArrayInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
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 {
|
||||
MockControl mock = MockControl.createControl(Resource.class);
|
||||
Resource resource = (Resource) mock.getMock();
|
||||
resource.lastModified();
|
||||
mock.setThrowable(new IOException());
|
||||
mock.replay();
|
||||
|
||||
ResourceScriptSource scriptSource = new ResourceScriptSource(resource);
|
||||
long lastModified = scriptSource.retrieveLastModifiedTime();
|
||||
assertEquals(0, lastModified);
|
||||
mock.verify();
|
||||
}
|
||||
|
||||
public void testBeginsInModifiedState() throws Exception {
|
||||
MockControl mock = MockControl.createControl(Resource.class);
|
||||
Resource resource = (Resource) mock.getMock();
|
||||
mock.replay();
|
||||
|
||||
ResourceScriptSource scriptSource = new ResourceScriptSource(resource);
|
||||
assertTrue(scriptSource.isModified());
|
||||
mock.verify();
|
||||
}
|
||||
|
||||
public void testLastModifiedWorksWithResourceThatDoesNotSupportFileBasedReading() throws Exception {
|
||||
MockControl mock = MockControl.createControl(Resource.class);
|
||||
Resource resource = (Resource) mock.getMock();
|
||||
// underlying File is asked for so that the last modified time can be checked...
|
||||
resource.lastModified();
|
||||
mock.setReturnValue(100, 2);
|
||||
// does not support File-based reading; delegates to InputStream-style reading...
|
||||
resource.getFile();
|
||||
mock.setThrowable(new FileNotFoundException());
|
||||
resource.getInputStream();
|
||||
mock.setReturnValue(new ByteArrayInputStream(new byte[0]));
|
||||
// And then mock the file changing; i.e. the File says it has been modified
|
||||
resource.lastModified();
|
||||
mock.setReturnValue(200);
|
||||
mock.replay();
|
||||
|
||||
ResourceScriptSource scriptSource = new ResourceScriptSource(resource);
|
||||
assertTrue("ResourceScriptSource must start off in the 'isModified' state (it obviously isn't).", scriptSource.isModified());
|
||||
scriptSource.getScriptAsString();
|
||||
assertFalse("ResourceScriptSource must not report back as being modified if the underlying File resource is not reporting a changed lastModified time.", scriptSource.isModified());
|
||||
// Must now report back as having been modified
|
||||
assertTrue("ResourceScriptSource must report back as being modified if the underlying File resource is reporting a changed lastModified time.", scriptSource.isModified());
|
||||
mock.verify();
|
||||
}
|
||||
|
||||
public void testLastModifiedWorksWithResourceThatDoesNotSupportFileBasedAccessAtAll() throws Exception {
|
||||
Resource resource = new ByteArrayResource(new byte[0]);
|
||||
ResourceScriptSource scriptSource = new ResourceScriptSource(resource);
|
||||
assertTrue("ResourceScriptSource must start off in the 'isModified' state (it obviously isn't).", scriptSource.isModified());
|
||||
scriptSource.getScriptAsString();
|
||||
assertFalse("ResourceScriptSource must not report back as being modified if the underlying File resource is not reporting a changed lastModified time.", scriptSource.isModified());
|
||||
// Must now continue to report back as not having been modified 'cos the Resource does not support access as a File (and so the lastModified date cannot be determined).
|
||||
assertFalse("ResourceScriptSource must not report back as being modified if the underlying File resource is not reporting a changed lastModified time.", scriptSource.isModified());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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 junit.framework.TestCase;
|
||||
import org.easymock.MockControl;
|
||||
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.scripting.Messenger;
|
||||
import org.springframework.scripting.ScriptCompilationException;
|
||||
import org.springframework.scripting.groovy.GroovyScriptFactory;
|
||||
|
||||
/**
|
||||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class ScriptFactoryPostProcessorTests extends TestCase {
|
||||
|
||||
private static final String MESSAGE_TEXT = "Bingo";
|
||||
|
||||
private static final String MESSENGER_BEAN_NAME = "messenger";
|
||||
|
||||
private static final String PROCESSOR_BEAN_NAME = "processor";
|
||||
|
||||
private static final String CHANGED_SCRIPT = "package org.springframework.scripting.groovy\n" +
|
||||
"import org.springframework.scripting.Messenger\n" +
|
||||
"class GroovyMessenger implements Messenger {\n" +
|
||||
" private String message = \"Bingo\"\n" +
|
||||
" public String getMessage() {\n" +
|
||||
// quote the returned message (this is the change)...
|
||||
" return \"'\" + this.message + \"'\"\n" +
|
||||
" }\n" +
|
||||
" public void setMessage(String message) {\n" +
|
||||
" this.message = message\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
private static final String EXPECTED_CHANGED_MESSAGE_TEXT = "'" + MESSAGE_TEXT + "'";
|
||||
|
||||
private static final int DEFAULT_SECONDS_TO_PAUSE = 1;
|
||||
|
||||
private static final String DELEGATING_SCRIPT = "inline:package org.springframework.scripting;\n" +
|
||||
"class DelegatingMessenger implements Messenger {\n" +
|
||||
" private Messenger wrappedMessenger;\n" +
|
||||
" public String getMessage() {\n" +
|
||||
" return this.wrappedMessenger.getMessage()\n" +
|
||||
" }\n" +
|
||||
" public void setMessenger(Messenger wrappedMessenger) {\n" +
|
||||
" this.wrappedMessenger = wrappedMessenger\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
|
||||
public void testDoesNothingWhenPostProcessingNonScriptFactoryTypeBeforeInstantiation() throws Exception {
|
||||
assertNull(new ScriptFactoryPostProcessor().postProcessBeforeInstantiation(getClass(), "a.bean"));
|
||||
}
|
||||
|
||||
public void testThrowsExceptionIfGivenNonAbstractBeanFactoryImplementation() throws Exception {
|
||||
MockControl mock = MockControl.createControl(BeanFactory.class);
|
||||
mock.replay();
|
||||
try {
|
||||
new ScriptFactoryPostProcessor().setBeanFactory((BeanFactory) mock.getMock());
|
||||
fail("Must have thrown exception by this point.");
|
||||
}
|
||||
catch (IllegalStateException expected) {
|
||||
}
|
||||
mock.verify();
|
||||
}
|
||||
|
||||
public void testChangeScriptWithRefreshableBeanFunctionality() throws Exception {
|
||||
BeanDefinition processorBeanDefinition = createScriptFactoryPostProcessor(true);
|
||||
BeanDefinition scriptedBeanDefinition = createScriptedGroovyBean();
|
||||
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
ctx.registerBeanDefinition(PROCESSOR_BEAN_NAME, processorBeanDefinition);
|
||||
ctx.registerBeanDefinition(MESSENGER_BEAN_NAME, scriptedBeanDefinition);
|
||||
ctx.refresh();
|
||||
|
||||
Messenger messenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
|
||||
assertEquals(MESSAGE_TEXT, messenger.getMessage());
|
||||
// cool; now let's change the script and check the refresh behaviour...
|
||||
pauseToLetRefreshDelayKickIn(DEFAULT_SECONDS_TO_PAUSE);
|
||||
StaticScriptSource source = getScriptSource(ctx);
|
||||
source.setScript(CHANGED_SCRIPT);
|
||||
Messenger refreshedMessenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
|
||||
// the updated script surrounds the message in quotes before returning...
|
||||
assertEquals(EXPECTED_CHANGED_MESSAGE_TEXT, refreshedMessenger.getMessage());
|
||||
}
|
||||
|
||||
public void testChangeScriptWithNoRefreshableBeanFunctionality() throws Exception {
|
||||
BeanDefinition processorBeanDefinition = createScriptFactoryPostProcessor(false);
|
||||
BeanDefinition scriptedBeanDefinition = createScriptedGroovyBean();
|
||||
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
ctx.registerBeanDefinition(PROCESSOR_BEAN_NAME, processorBeanDefinition);
|
||||
ctx.registerBeanDefinition(MESSENGER_BEAN_NAME, scriptedBeanDefinition);
|
||||
ctx.refresh();
|
||||
|
||||
Messenger messenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
|
||||
assertEquals(MESSAGE_TEXT, messenger.getMessage());
|
||||
// cool; now let's change the script and check the refresh behaviour...
|
||||
pauseToLetRefreshDelayKickIn(DEFAULT_SECONDS_TO_PAUSE);
|
||||
StaticScriptSource source = getScriptSource(ctx);
|
||||
source.setScript(CHANGED_SCRIPT);
|
||||
Messenger refreshedMessenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
|
||||
assertEquals("Script seems to have been refreshed (must not be as no refreshCheckDelay set on ScriptFactoryPostProcessor)",
|
||||
MESSAGE_TEXT, refreshedMessenger.getMessage());
|
||||
}
|
||||
|
||||
public void testRefreshedScriptReferencePropagatesToCollaborators() throws Exception {
|
||||
BeanDefinition processorBeanDefinition = createScriptFactoryPostProcessor(true);
|
||||
BeanDefinition scriptedBeanDefinition = createScriptedGroovyBean();
|
||||
BeanDefinitionBuilder collaboratorBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultMessengerService.class);
|
||||
collaboratorBuilder.addPropertyReference(MESSENGER_BEAN_NAME, MESSENGER_BEAN_NAME);
|
||||
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
ctx.registerBeanDefinition(PROCESSOR_BEAN_NAME, processorBeanDefinition);
|
||||
ctx.registerBeanDefinition(MESSENGER_BEAN_NAME, scriptedBeanDefinition);
|
||||
final String collaboratorBeanName = "collaborator";
|
||||
ctx.registerBeanDefinition(collaboratorBeanName, collaboratorBuilder.getBeanDefinition());
|
||||
ctx.refresh();
|
||||
|
||||
Messenger messenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
|
||||
assertEquals(MESSAGE_TEXT, messenger.getMessage());
|
||||
// cool; now let's change the script and check the refresh behaviour...
|
||||
pauseToLetRefreshDelayKickIn(DEFAULT_SECONDS_TO_PAUSE);
|
||||
StaticScriptSource source = getScriptSource(ctx);
|
||||
source.setScript(CHANGED_SCRIPT);
|
||||
Messenger refreshedMessenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
|
||||
// the updated script surrounds the message in quotes before returning...
|
||||
assertEquals(EXPECTED_CHANGED_MESSAGE_TEXT, refreshedMessenger.getMessage());
|
||||
// ok, is this change reflected in the reference that the collaborator has?
|
||||
DefaultMessengerService collaborator = (DefaultMessengerService) ctx.getBean(collaboratorBeanName);
|
||||
assertEquals(EXPECTED_CHANGED_MESSAGE_TEXT, collaborator.getMessage());
|
||||
}
|
||||
|
||||
public void testReferencesAcrossAContainerHierarchy() throws Exception {
|
||||
GenericApplicationContext businessContext = new GenericApplicationContext();
|
||||
businessContext.registerBeanDefinition("messenger", BeanDefinitionBuilder.rootBeanDefinition(StubMessenger.class).getBeanDefinition());
|
||||
businessContext.refresh();
|
||||
|
||||
BeanDefinitionBuilder scriptedBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition(GroovyScriptFactory.class);
|
||||
scriptedBeanBuilder.addConstructorArgValue(DELEGATING_SCRIPT);
|
||||
scriptedBeanBuilder.addPropertyReference("messenger", "messenger");
|
||||
|
||||
GenericApplicationContext presentationCtx = new GenericApplicationContext(businessContext);
|
||||
presentationCtx.registerBeanDefinition("needsMessenger", scriptedBeanBuilder.getBeanDefinition());
|
||||
presentationCtx.registerBeanDefinition("scriptProcessor", createScriptFactoryPostProcessor(true));
|
||||
presentationCtx.refresh();
|
||||
}
|
||||
|
||||
public void testScriptHavingAReferenceToAnotherBean() throws Exception {
|
||||
// just tests that the (singleton) script-backed bean is able to be instantiated with references to its collaborators
|
||||
new ClassPathXmlApplicationContext("org/springframework/scripting/support/groovyReferences.xml");
|
||||
}
|
||||
|
||||
public void testForRefreshedScriptHavingErrorPickedUpOnFirstCall() throws Exception {
|
||||
BeanDefinition processorBeanDefinition = createScriptFactoryPostProcessor(true);
|
||||
BeanDefinition scriptedBeanDefinition = createScriptedGroovyBean();
|
||||
BeanDefinitionBuilder collaboratorBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultMessengerService.class);
|
||||
collaboratorBuilder.addPropertyReference(MESSENGER_BEAN_NAME, MESSENGER_BEAN_NAME);
|
||||
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
ctx.registerBeanDefinition(PROCESSOR_BEAN_NAME, processorBeanDefinition);
|
||||
ctx.registerBeanDefinition(MESSENGER_BEAN_NAME, scriptedBeanDefinition);
|
||||
final String collaboratorBeanName = "collaborator";
|
||||
ctx.registerBeanDefinition(collaboratorBeanName, collaboratorBuilder.getBeanDefinition());
|
||||
ctx.refresh();
|
||||
|
||||
Messenger messenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
|
||||
assertEquals(MESSAGE_TEXT, messenger.getMessage());
|
||||
// cool; now let's change the script and check the refresh behaviour...
|
||||
pauseToLetRefreshDelayKickIn(DEFAULT_SECONDS_TO_PAUSE);
|
||||
StaticScriptSource source = getScriptSource(ctx);
|
||||
// needs The Sundays compiler; must NOT throw any exception here...
|
||||
source.setScript("I keep hoping you are the same as me, and I'll send you letters and come to your house for tea");
|
||||
Messenger refreshedMessenger = (Messenger) ctx.getBean(MESSENGER_BEAN_NAME);
|
||||
try {
|
||||
refreshedMessenger.getMessage();
|
||||
fail("Must have thrown an Exception (invalid script)");
|
||||
}
|
||||
catch (FatalBeanException expected) {
|
||||
assertTrue(expected.contains(ScriptCompilationException.class));
|
||||
}
|
||||
}
|
||||
|
||||
public void testPrototypeScriptedBean() throws Exception {
|
||||
GenericApplicationContext ctx = new GenericApplicationContext();
|
||||
ctx.registerBeanDefinition("messenger", BeanDefinitionBuilder.rootBeanDefinition(StubMessenger.class).getBeanDefinition());
|
||||
|
||||
BeanDefinitionBuilder scriptedBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition(GroovyScriptFactory.class);
|
||||
scriptedBeanBuilder.setSingleton(false);
|
||||
scriptedBeanBuilder.addConstructorArgValue(DELEGATING_SCRIPT);
|
||||
scriptedBeanBuilder.addPropertyReference("messenger", "messenger");
|
||||
|
||||
final String BEAN_WITH_DEPENDENCY_NAME = "needsMessenger";
|
||||
ctx.registerBeanDefinition(BEAN_WITH_DEPENDENCY_NAME, scriptedBeanBuilder.getBeanDefinition());
|
||||
ctx.registerBeanDefinition("scriptProcessor", createScriptFactoryPostProcessor(true));
|
||||
ctx.refresh();
|
||||
|
||||
Messenger messenger1 = (Messenger) ctx.getBean(BEAN_WITH_DEPENDENCY_NAME);
|
||||
Messenger messenger2 = (Messenger) ctx.getBean(BEAN_WITH_DEPENDENCY_NAME);
|
||||
assertNotSame(messenger1, messenger2);
|
||||
}
|
||||
|
||||
private static StaticScriptSource getScriptSource(GenericApplicationContext ctx) throws Exception {
|
||||
ScriptFactoryPostProcessor processor = (ScriptFactoryPostProcessor) ctx.getBean(PROCESSOR_BEAN_NAME);
|
||||
BeanDefinition bd = processor.scriptBeanFactory.getBeanDefinition("scriptedObject.messenger");
|
||||
return (StaticScriptSource) bd.getConstructorArgumentValues().getIndexedArgumentValue(0, StaticScriptSource.class).getValue();
|
||||
}
|
||||
|
||||
private static BeanDefinition createScriptFactoryPostProcessor(boolean isRefreshable) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ScriptFactoryPostProcessor.class);
|
||||
if (isRefreshable) {
|
||||
builder.addPropertyValue("defaultRefreshCheckDelay", new Long(1));
|
||||
}
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
private static BeanDefinition createScriptedGroovyBean() {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(GroovyScriptFactory.class);
|
||||
builder.addConstructorArgValue("inline:package org.springframework.scripting;\n" +
|
||||
"class GroovyMessenger implements Messenger {\n" +
|
||||
" private String message = \"Bingo\"\n" +
|
||||
" public String getMessage() {\n" +
|
||||
" return this.message\n" +
|
||||
" }\n" +
|
||||
" public void setMessage(String message) {\n" +
|
||||
" this.message = message\n" +
|
||||
" }\n" +
|
||||
"}");
|
||||
builder.addPropertyValue("message", MESSAGE_TEXT);
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
private static void pauseToLetRefreshDelayKickIn(int secondsToPause) {
|
||||
try {
|
||||
Thread.sleep(secondsToPause * 1000);
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class DefaultMessengerService {
|
||||
|
||||
private Messenger messenger;
|
||||
|
||||
public void setMessenger(Messenger messenger) {
|
||||
this.messenger = messenger;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return this.messenger.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2002-2006 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 junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for the StaticScriptSource class.
|
||||
*
|
||||
* @author Rick Evans
|
||||
*/
|
||||
public final class StaticScriptSourceTests extends TestCase {
|
||||
|
||||
private static final String SCRIPT_TEXT = "print($hello) if $true;";
|
||||
|
||||
|
||||
public void testCreateWithNullScript() throws Exception {
|
||||
try {
|
||||
new StaticScriptSource(null);
|
||||
fail("Must have failed when passed a null script string.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateWithEmptyScript() throws Exception {
|
||||
try {
|
||||
new StaticScriptSource("");
|
||||
fail("Must have failed when passed an empty script string.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateWithWhitespaceOnlyScript() throws Exception {
|
||||
try {
|
||||
new StaticScriptSource(" \n\n\t \t\n");
|
||||
fail("Must have failed when passed a whitespace-only script string.");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testIsModifiedIsTrueByDefault() throws Exception {
|
||||
StaticScriptSource source = new StaticScriptSource(SCRIPT_TEXT);
|
||||
assertTrue("Script must be flagged as 'modified' when first created.", source.isModified());
|
||||
}
|
||||
|
||||
public void testGettingScriptTogglesIsModified() throws Exception {
|
||||
StaticScriptSource source = new StaticScriptSource(SCRIPT_TEXT);
|
||||
source.getScriptAsString();
|
||||
assertFalse("Script must be flagged as 'not modified' after script is read.", source.isModified());
|
||||
}
|
||||
|
||||
public void testGettingScriptViaToStringDoesNotToggleIsModified() throws Exception {
|
||||
StaticScriptSource source = new StaticScriptSource(SCRIPT_TEXT);
|
||||
boolean isModifiedState = source.isModified();
|
||||
source.toString();
|
||||
assertEquals("Script's 'modified' flag must not change after script is read via toString().", isModifiedState, source.isModified());
|
||||
}
|
||||
|
||||
public void testIsModifiedToggledWhenDifferentScriptIsSet() throws Exception {
|
||||
StaticScriptSource source = new StaticScriptSource(SCRIPT_TEXT);
|
||||
source.setScript("use warnings;");
|
||||
assertTrue("Script must be flagged as 'modified' when different script is passed in.", source.isModified());
|
||||
}
|
||||
|
||||
public void testIsModifiedNotToggledWhenSameScriptIsSet() throws Exception {
|
||||
StaticScriptSource source = new StaticScriptSource(SCRIPT_TEXT);
|
||||
source.setScript(SCRIPT_TEXT);
|
||||
assertFalse("Script must not be flagged as 'modified' when same script is passed in.", source.isModified());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2002-2006 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 org.springframework.scripting.ConfigurableMessenger;
|
||||
|
||||
/**
|
||||
* @author Rick Evans
|
||||
*/
|
||||
public final class StubMessenger implements ConfigurableMessenger {
|
||||
|
||||
private String message = "I used to be smart... now I'm just stupid.";
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
|
||||
|
||||
<bean id="messenger" class="org.springframework.scripting.groovy.GroovyScriptFactory">
|
||||
<constructor-arg>
|
||||
<value>inline:package org.springframework.scripting;
|
||||
|
||||
import org.springframework.scripting.Messenger
|
||||
|
||||
class DelegatingMessenger implements Messenger {
|
||||
|
||||
private Messenger wrappedMessenger;
|
||||
|
||||
public String getMessage() {
|
||||
this.wrappedMessenger.getMessage();
|
||||
}
|
||||
|
||||
public void setMessenger(Messenger wrappedMessenger) {
|
||||
this.wrappedMessenger = wrappedMessenger;
|
||||
}
|
||||
}</value>
|
||||
</constructor-arg>
|
||||
<property name="messenger" ref="wrappedMessenger"/>
|
||||
</bean>
|
||||
|
||||
<bean id="wrappedMessenger" class="org.springframework.scripting.support.StubMessenger"/>
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user