INT-1727 added initial support to allow customization of Groovy bindings
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.integration.groovy;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*/
|
||||
public abstract class BeanFactoryAwareScriptVariableSource implements BeanFactoryAware, ScriptVariableSource {
|
||||
protected volatile BeanFactory beanFactory;
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
}
|
||||
@@ -36,14 +36,20 @@ public class GroovyScriptExecutingMessageProcessor extends AbstractScriptExecuti
|
||||
private final MessageContextBindingCustomizer customizer = new MessageContextBindingCustomizer();
|
||||
|
||||
private final ScriptSource scriptSource;
|
||||
|
||||
|
||||
private final ScriptVariableSource scriptVariableSource;
|
||||
|
||||
/**
|
||||
* Create a processor for the given {@link ScriptSource}.
|
||||
*/
|
||||
public GroovyScriptExecutingMessageProcessor(ScriptSource scriptSource) {
|
||||
this(scriptSource, null);
|
||||
}
|
||||
|
||||
public GroovyScriptExecutingMessageProcessor(ScriptSource scriptSource, ScriptVariableSource scriptVariableSource) {
|
||||
Assert.notNull(scriptSource, "scriptSource must not be null");
|
||||
this.scriptSource = scriptSource;
|
||||
this.scriptVariableSource = scriptVariableSource;
|
||||
this.scriptFactory = new GroovyScriptFactory(this.getClass().getSimpleName(), this.customizer);
|
||||
}
|
||||
|
||||
@@ -57,9 +63,12 @@ public class GroovyScriptExecutingMessageProcessor extends AbstractScriptExecuti
|
||||
protected Object executeScript(ScriptSource scriptSource, Message<?> message) throws Exception {
|
||||
synchronized (this) {
|
||||
this.customizer.setMessage(message);
|
||||
if (this.scriptVariableSource != null){
|
||||
this.customizer.setResolvedScriptVariables(this.scriptVariableSource.resolveScriptVariables());
|
||||
}
|
||||
Object result = this.scriptFactory.getScriptedObject(scriptSource, null);
|
||||
return (result instanceof GString) ? result.toString() : result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ class MessageContextBindingCustomizer implements GroovyObjectCustomizer {
|
||||
private volatile Message<?> message;
|
||||
|
||||
private final GroovyObjectCustomizer customizer;
|
||||
|
||||
private volatile Map<String, ?> resolvedScriptVariables;
|
||||
|
||||
|
||||
public MessageContextBindingCustomizer() {
|
||||
@@ -51,20 +53,29 @@ class MessageContextBindingCustomizer implements GroovyObjectCustomizer {
|
||||
}
|
||||
|
||||
|
||||
public void setResolvedScriptVariables(Map<String, ?> resolvedScriptVariables) {
|
||||
this.resolvedScriptVariables = resolvedScriptVariables;
|
||||
}
|
||||
|
||||
public void setMessage(Message<?> message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public void customize(GroovyObject goo) {
|
||||
Assert.state(goo instanceof Script, "Expected a Script");
|
||||
if (this.customizer != null) {
|
||||
this.customizer.customize(goo);
|
||||
Binding binding = ((Script) goo).getBinding();
|
||||
if (resolvedScriptVariables != null){
|
||||
for (String key : resolvedScriptVariables.keySet()) {
|
||||
binding.setVariable(key, this.resolvedScriptVariables.get(key));
|
||||
}
|
||||
}
|
||||
if (this.message != null) {
|
||||
Binding binding = ((Script) goo).getBinding();
|
||||
binding.setVariable("payload", this.message.getPayload());
|
||||
binding.setVariable("headers", this.message.getHeaders());
|
||||
}
|
||||
if (this.customizer != null){
|
||||
this.customizer.customize(goo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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.integration.groovy;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*/
|
||||
public interface ScriptVariableSource {
|
||||
|
||||
Map<String, Object> resolveScriptVariables();
|
||||
}
|
||||
@@ -22,10 +22,13 @@ import static org.junit.Assert.assertFalse;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.io.AbstractResource;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.groovy.config.RefreshableResourceScriptSource;
|
||||
@@ -60,6 +63,29 @@ public class GroovyScriptExecutingMessageProcessorTests {
|
||||
Object result = processor.processMessage(message);
|
||||
assertEquals("payload is foo, header is bar"+count, result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleExecutionWithScriptVariableSource() throws Exception {
|
||||
int count = countHolder.getAndIncrement();
|
||||
String script = "return \"payload is $payload, header is $headers.testHeader and date is $date\"";
|
||||
Message<?> message = MessageBuilder.withPayload("foo").setHeader("testHeader", "bar"+count).build();
|
||||
TestResource resource = new TestResource(script, "simpleTest");
|
||||
ScriptSource scriptSource = new ResourceScriptSource(resource);
|
||||
Object result = null;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
ScriptVariableSource scriptVariableSource = new ScriptVariableSource() {
|
||||
public Map<String, Object> resolveScriptVariables() {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("date", System.nanoTime());
|
||||
return map;
|
||||
}
|
||||
};
|
||||
MessageProcessor<Object> processor = new GroovyScriptExecutingMessageProcessor(scriptSource, scriptVariableSource);
|
||||
Object newResult = processor.processMessage(message);
|
||||
assertFalse(newResult.equals(result)); // make sure that we get different nanotime verifying that resolveScriptVariables() is invoked
|
||||
result = newResult;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLastModified() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user