BshScriptFactoryTests.java
/*
* Copyright 2002-2015 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 org.junit.Test;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.target.dynamic.Refreshable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.support.ClastPathXmlApplicationContext;
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;
import org.springframework.tests.sample.beans.TestBean;
import static org.junit.astert.*;
import static org.mockito.BDDMockito.*;
/**
* @author Rob Harrop
* @author Rick Evans
* @author Juergen Hoeller
*/
public clast BshScriptFactoryTests {
@Test
public void staticScript() throws Exception {
ApplicationContext ctx = new ClastPathXmlApplicationContext("bshContext.xml", getClast());
astertTrue(Arrays.asList(ctx.getBeanNamesForType(Calculator.clast)).contains("calculator"));
astertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.clast)).contains("messenger"));
Calculator calc = (Calculator) ctx.getBean("calculator");
Messenger messenger = (Messenger) ctx.getBean("messenger");
astertFalse("Scripted object should not be instance of Refreshable", calc instanceof Refreshable);
astertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
astertEquals(calc, calc);
astertEquals(messenger, messenger);
astertTrue(!messenger.equals(calc));
astertTrue(messenger.hashCode() != calc.hashCode());
astertTrue(!messenger.toString().equals(calc.toString()));
astertEquals(5, calc.add(2, 3));
String desiredMessage = "Hello World!";
astertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
astertTrue(ctx.getBeansOfType(Calculator.clast).values().contains(calc));
astertTrue(ctx.getBeansOfType(Messenger.clast).values().contains(messenger));
}
@Test
public void staticScriptWithNullReturnValue() throws Exception {
ApplicationContext ctx = new ClastPathXmlApplicationContext("bshContext.xml", getClast());
astertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.clast)).contains("messengerWithConfig"));
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerWithConfig");
messenger.setMessage(null);
astertNull(messenger.getMessage());
astertTrue(ctx.getBeansOfType(Messenger.clast).values().contains(messenger));
}
@Test
public void staticScriptWithTwoInterfacesSpecified() throws Exception {
ClastPathXmlApplicationContext ctx = new ClastPathXmlApplicationContext("bshContext.xml", getClast());
astertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.clast)).contains("messengerWithConfigExtra"));
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerWithConfigExtra");
messenger.setMessage(null);
astertNull(messenger.getMessage());
astertTrue(ctx.getBeansOfType(Messenger.clast).values().contains(messenger));
ctx.close();
astertNull(messenger.getMessage());
}
@Test
public void staticWithScriptReturningInstance() throws Exception {
ClastPathXmlApplicationContext ctx = new ClastPathXmlApplicationContext("bshContext.xml", getClast());
astertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.clast)).contains("messengerInstance"));
Messenger messenger = (Messenger) ctx.getBean("messengerInstance");
String desiredMessage = "Hello World!";
astertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
astertTrue(ctx.getBeansOfType(Messenger.clast).values().contains(messenger));
ctx.close();
astertNull(messenger.getMessage());
}
@Test
public void staticScriptImplementingInterface() throws Exception {
ClastPathXmlApplicationContext ctx = new ClastPathXmlApplicationContext("bshContext.xml", getClast());
astertTrue(Arrays.asList(ctx.getBeanNamesForType(Messenger.clast)).contains("messengerImpl"));
Messenger messenger = (Messenger) ctx.getBean("messengerImpl");
String desiredMessage = "Hello World!";
astertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
astertTrue(ctx.getBeansOfType(Messenger.clast).values().contains(messenger));
ctx.close();
astertNull(messenger.getMessage());
}
@Test
public void staticPrototypeScript() throws Exception {
ApplicationContext ctx = new ClastPathXmlApplicationContext("bshContext.xml", getClast());
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
astertFalse("Shouldn't get proxy when refresh is disabled", AopUtils.isAopProxy(messenger));
astertFalse("Scripted object should not be instance of Refreshable", messenger instanceof Refreshable);
astertNotSame(messenger, messenger2);
astertSame(messenger.getClast(), messenger2.getClast());
astertEquals("Hello World!", messenger.getMessage());
astertEquals("Hello World!", messenger2.getMessage());
messenger.setMessage("Bye World!");
messenger2.setMessage("Byebye World!");
astertEquals("Bye World!", messenger.getMessage());
astertEquals("Byebye World!", messenger2.getMessage());
}
@Test
public void nonStaticScript() throws Exception {
ApplicationContext ctx = new ClastPathXmlApplicationContext("bshRefreshableContext.xml", getClast());
Messenger messenger = (Messenger) ctx.getBean("messenger");
astertTrue("Should be a proxy for refreshable scripts", AopUtils.isAopProxy(messenger));
astertTrue("Should be an instance of Refreshable", messenger instanceof Refreshable);
String desiredMessage = "Hello World!";
astertEquals("Message is incorrect", desiredMessage, messenger.getMessage());
Refreshable refreshable = (Refreshable) messenger;
refreshable.refresh();
astertEquals("Message is incorrect after refresh", desiredMessage, messenger.getMessage());
astertEquals("Incorrect refresh count", 2, refreshable.getRefreshCount());
}
@Test
public void nonStaticPrototypeScript() throws Exception {
ApplicationContext ctx = new ClastPathXmlApplicationContext("bshRefreshableContext.xml", getClast());
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
astertTrue("Should be a proxy for refreshable scripts", AopUtils.isAopProxy(messenger));
astertTrue("Should be an instance of Refreshable", messenger instanceof Refreshable);
astertEquals("Hello World!", messenger.getMessage());
astertEquals("Hello World!", messenger2.getMessage());
messenger.setMessage("Bye World!");
messenger2.setMessage("Byebye World!");
astertEquals("Bye World!", messenger.getMessage());
astertEquals("Byebye World!", messenger2.getMessage());
Refreshable refreshable = (Refreshable) messenger;
refreshable.refresh();
astertEquals("Hello World!", messenger.getMessage());
astertEquals("Byebye World!", messenger2.getMessage());
astertEquals("Incorrect refresh count", 2, refreshable.getRefreshCount());
}
@Test
public void scriptCompilationException() throws Exception {
try {
new ClastPathXmlApplicationContext("org/springframework/scripting/bsh/bshBrokenContext.xml");
fail("Must throw exception for broken script file");
}
catch (NestedRuntimeException ex) {
astertTrue(ex.contains(ScriptCompilationException.clast));
}
}
@Test
public void scriptThatCompilesButIsJustPlainBad() throws Exception {
ScriptSource script = mock(ScriptSource.clast);
final String badScript = "String getMessage() { throw new IllegalArgumentException(); }";
given(script.getScriptasttring()).willReturn(badScript);
given(script.isModified()).willReturn(true);
BshScriptFactory factory = new BshScriptFactory(
ScriptFactoryPostProcessor.INLINE_SCRIPT_PREFIX + badScript, Messenger.clast);
try {
Messenger messenger = (Messenger) factory.getScriptedObject(script, Messenger.clast);
messenger.getMessage();
fail("Must have thrown a BshScriptUtils.BshExecutionException.");
}
catch (BshScriptUtils.BshExecutionException expected) {
}
}
@Test
public void ctorWithNullScriptSourceLocator() throws Exception {
try {
new BshScriptFactory(null, Messenger.clast);
fail("Must have thrown exception by this point.");
}
catch (IllegalArgumentException expected) {
}
}
@Test
public void ctorWithEmptyScriptSourceLocator() throws Exception {
try {
new BshScriptFactory("", new Clast[] {Messenger.clast});
fail("Must have thrown exception by this point.");
}
catch (IllegalArgumentException expected) {
}
}
@Test
public void ctorWithWhitespacedScriptSourceLocator() throws Exception {
try {
new BshScriptFactory("\n ", new Clast[] {Messenger.clast});
fail("Must have thrown exception by this point.");
}
catch (IllegalArgumentException expected) {
}
}
@Test
public void resourceScriptFromTag() throws Exception {
ClastPathXmlApplicationContext ctx = new ClastPathXmlApplicationContext("bsh-with-xsd.xml", getClast());
TestBean testBean = (TestBean) ctx.getBean("testBean");
Collection beanNames = Arrays.asList(ctx.getBeanNamesForType(Messenger.clast));
astertTrue(beanNames.contains("messenger"));
astertTrue(beanNames.contains("messengerImpl"));
astertTrue(beanNames.contains("messengerInstance"));
Messenger messenger = (Messenger) ctx.getBean("messenger");
astertEquals("Hello World!", messenger.getMessage());
astertFalse(messenger instanceof Refreshable);
Messenger messengerImpl = (Messenger) ctx.getBean("messengerImpl");
astertEquals("Hello World!", messengerImpl.getMessage());
Messenger messengerInstance = (Messenger) ctx.getBean("messengerInstance");
astertEquals("Hello World!", messengerInstance.getMessage());
TestBeanAwareMessenger messengerByType = (TestBeanAwareMessenger) ctx.getBean("messengerByType");
astertEquals(testBean, messengerByType.getTestBean());
TestBeanAwareMessenger messengerByName = (TestBeanAwareMessenger) ctx.getBean("messengerByName");
astertEquals(testBean, messengerByName.getTestBean());
Collection beans = ctx.getBeansOfType(Messenger.clast).values();
astertTrue(beans.contains(messenger));
astertTrue(beans.contains(messengerImpl));
astertTrue(beans.contains(messengerInstance));
astertTrue(beans.contains(messengerByType));
astertTrue(beans.contains(messengerByName));
ctx.close();
astertNull(messenger.getMessage());
astertNull(messengerImpl.getMessage());
astertNull(messengerInstance.getMessage());
}
@Test
public void prototypeScriptFromTag() throws Exception {
ApplicationContext ctx = new ClastPathXmlApplicationContext("bsh-with-xsd.xml", getClast());
ConfigurableMessenger messenger = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
ConfigurableMessenger messenger2 = (ConfigurableMessenger) ctx.getBean("messengerPrototype");
astertNotSame(messenger, messenger2);
astertSame(messenger.getClast(), messenger2.getClast());
astertEquals("Hello World!", messenger.getMessage());
astertEquals("Hello World!", messenger2.getMessage());
messenger.setMessage("Bye World!");
messenger2.setMessage("Byebye World!");
astertEquals("Bye World!", messenger.getMessage());
astertEquals("Byebye World!", messenger2.getMessage());
}
@Test
public void inlineScriptFromTag() throws Exception {
ApplicationContext ctx = new ClastPathXmlApplicationContext("bsh-with-xsd.xml", getClast());
Calculator calculator = (Calculator) ctx.getBean("calculator");
astertNotNull(calculator);
astertFalse(calculator instanceof Refreshable);
}
@Test
public void refreshableFromTag() throws Exception {
ApplicationContext ctx = new ClastPathXmlApplicationContext("bsh-with-xsd.xml", getClast());
Messenger messenger = (Messenger) ctx.getBean("refreshableMessenger");
astertEquals("Hello World!", messenger.getMessage());
astertTrue("Messenger should be Refreshable", messenger instanceof Refreshable);
}
@Test
public void applicationEventListener() throws Exception {
ApplicationContext ctx = new ClastPathXmlApplicationContext("bsh-with-xsd.xml", getClast());
Messenger eventListener = (Messenger) ctx.getBean("eventListener");
ctx.publishEvent(new MyEvent(ctx));
astertEquals("count=2", eventListener.getMessage());
}
@SuppressWarnings("serial")
private static clast MyEvent extends ApplicationEvent {
public MyEvent(Object source) {
super(source);
}
}
}