INT-1576,INT-1579,INT-2025: added spring-integration-scripting and fixed HeaderEnricher issue
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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.config.xml;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.beans.factory.xml.XmlReaderContext;
|
||||
import org.springframework.scripting.support.StaticScriptSource;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author David Turanski
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractScriptParser extends AbstractSingleBeanDefinitionParser {
|
||||
protected static final String LOCATION_ATTRIBUTE = "location";
|
||||
|
||||
protected static final String REFRESH_CHECK_DELAY_ATTRIBUTE = "refresh-check-delay";
|
||||
|
||||
protected boolean shouldGenerateIdAsFallback() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract String getBeanClassName(Element element);
|
||||
|
||||
protected abstract String getScriptSourceClassName();
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
String scriptLocation = element.getAttribute(LOCATION_ATTRIBUTE);
|
||||
String scriptText = DomUtils.getTextValue(element);
|
||||
if (!(StringUtils.hasText(scriptLocation) ^ StringUtils.hasText(scriptText))) {
|
||||
parserContext.getReaderContext().error("Either the 'location' attribute or inline script text must be provided, but not both.", element);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Element> variableElements = DomUtils.getChildElementsByTagName(element, "variable");
|
||||
String scriptVariableGeneratorName = element.getAttribute("script-variable-generator");
|
||||
|
||||
if (StringUtils.hasText(scriptText) && (variableElements.size() > 0 || StringUtils.hasText(scriptVariableGeneratorName))) {
|
||||
parserContext.getReaderContext().error("Variable bindings or custom ScriptVariableGenerator are not allowed when using an inline groovy script. " +
|
||||
"Specify location of the script via 'location' attribute instead", element);
|
||||
return;
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(scriptVariableGeneratorName) && variableElements.size() > 0) {
|
||||
parserContext.getReaderContext().error("'script-variable-generator' and 'variable' sub-elements are mutually exclusive.", element);
|
||||
return;
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(scriptLocation)) {
|
||||
builder.addConstructorArgValue(this.resolveScriptLocation(element, parserContext.getReaderContext(), scriptLocation));
|
||||
}
|
||||
else {
|
||||
if (getScriptSourceClassName() != null){
|
||||
builder.addConstructorArgValue(new StaticScriptSource(scriptText, getScriptSourceClassName()));
|
||||
} else {
|
||||
builder.addConstructorArgValue(new StaticScriptSource(scriptText));
|
||||
}
|
||||
}
|
||||
if (!StringUtils.hasText(scriptVariableGeneratorName)) {
|
||||
BeanDefinitionBuilder scriptVariableGeneratorBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition("org.springframework.integration.scripting.DefaultScriptVariableGenerator");
|
||||
ManagedMap<String, Object> variableMap = new ManagedMap<String, Object>();
|
||||
for (Element childElement : variableElements) {
|
||||
String variableName = childElement.getAttribute("name");
|
||||
String variableValue = childElement.getAttribute("value");
|
||||
String variableRef = childElement.getAttribute("ref");
|
||||
if (!(StringUtils.hasText(variableValue) ^ StringUtils.hasText(variableRef))) {
|
||||
parserContext.getReaderContext().error("Exactly one of the 'ref' attribute or 'value' attribute, " +
|
||||
" is required for element " +
|
||||
IntegrationNamespaceUtils.createElementDescription(element) + ".", element);
|
||||
}
|
||||
if (StringUtils.hasText(variableValue)) {
|
||||
variableMap.put(variableName, variableValue);
|
||||
}
|
||||
else {
|
||||
variableMap.put(variableName, new RuntimeBeanReference(variableRef));
|
||||
}
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(variableMap)) {
|
||||
scriptVariableGeneratorBuilder.addConstructorArgValue(variableMap);
|
||||
}
|
||||
scriptVariableGeneratorName = BeanDefinitionReaderUtils.registerWithGeneratedName(
|
||||
scriptVariableGeneratorBuilder.getBeanDefinition(), parserContext.getRegistry());
|
||||
}
|
||||
builder.addConstructorArgReference(scriptVariableGeneratorName);
|
||||
postProcess(builder, element, parserContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override this no-op method to provide additional configuration.
|
||||
*/
|
||||
protected void postProcess(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) {
|
||||
}
|
||||
|
||||
private Object resolveScriptLocation(Element element, XmlReaderContext readerContext, String scriptLocation) {
|
||||
String refreshDelayText = element.getAttribute(REFRESH_CHECK_DELAY_ATTRIBUTE);
|
||||
String beanClassName = "org.springframework.integration.scripting.RefreshableResourceScriptSource";
|
||||
BeanDefinitionBuilder resourceScriptSourceBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(beanClassName);
|
||||
resourceScriptSourceBuilder.addConstructorArgValue(scriptLocation);
|
||||
if (StringUtils.hasText(refreshDelayText)) {
|
||||
resourceScriptSourceBuilder.addConstructorArgValue(refreshDelayText);
|
||||
}
|
||||
else {
|
||||
resourceScriptSourceBuilder.addConstructorArgValue(-1L);
|
||||
}
|
||||
return resourceScriptSourceBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.scripting;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.scripting.ScriptSource;
|
||||
import org.springframework.scripting.support.ResourceScriptSource;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class RefreshableResourceScriptSource implements ScriptSource {
|
||||
|
||||
private final long refreshDelay;
|
||||
|
||||
private final ResourceScriptSource source;
|
||||
|
||||
private final AtomicLong lastModifiedChecked = new AtomicLong(System.currentTimeMillis());
|
||||
|
||||
private volatile String script;
|
||||
|
||||
|
||||
public RefreshableResourceScriptSource(Resource resource, long refreshDelay) {
|
||||
this.refreshDelay = refreshDelay;
|
||||
this.source = new ResourceScriptSource(resource);
|
||||
try {
|
||||
this.script = this.source.getScriptAsString();
|
||||
}
|
||||
catch (IOException e) {
|
||||
this.lastModifiedChecked.set(0);
|
||||
}
|
||||
}
|
||||
|
||||
public String getScriptAsString() throws IOException {
|
||||
this.script = source.getScriptAsString();
|
||||
return this.script;
|
||||
}
|
||||
|
||||
public String suggestedClassName() {
|
||||
return this.source.suggestedClassName();
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
if (this.refreshDelay < 0) {
|
||||
return false;
|
||||
}
|
||||
long time = System.currentTimeMillis();
|
||||
if (this.refreshDelay == 0 || (time - this.lastModifiedChecked.get()) > this.refreshDelay) {
|
||||
this.lastModifiedChecked.set(time);
|
||||
return this.source.isModified();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsd:schema
|
||||
xmlns="http://www.springframework.org/schema/integration/scripting"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:integration="http://www.springframework.org/schema/integration"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/integration"
|
||||
schemaLocation="http://www.springframework.org/schema/integration/spring-integration-2.0.xsd" />
|
||||
|
||||
|
||||
<xsd:complexType name="ScriptType" mixed="true" abstract="true">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="variable" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Allows you to define custom script variable bindings. The use of this
|
||||
sub-element is mutually
|
||||
exclusive with the 'script-variable-generator' attribute.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="name" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Name of the script variable.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="value" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Value of the script variable as a literal.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="ref" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Value of the script variable as a bean reference.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:expected-type type="java.lang.Object" />
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="location">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Resource location path for the Script. Either this or an inline script
|
||||
as body text should be provided, but not both.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="script-variable-generator" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Reference to the ScriptVariableGenerator bean. This attribute is mutually
|
||||
exclusive with any 'variable' sub-elements.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:expected-type
|
||||
type="org.springframework.integration.scripting.ScriptVariableGenerator" />
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
|
||||
<xsd:attribute name="refresh-check-delay">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Refresh delay for the script contents if specified as a resource
|
||||
location (defaults to -1, never refresh).
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
</xsd:schema>
|
||||
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/integration/groovy"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:integration="http://www.springframework.org/schema/integration"
|
||||
targetNamespace="http://www.springframework.org/schema/integration/groovy"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:include
|
||||
schemaLocation="http://www.springframework.org/schema/integration/scripting/spring-integration-scripting-core-2.1.xsd"
|
||||
/>
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/integration" schemaLocation="http://www.springframework.org/schema/integration/spring-integration-2.0.xsd" />
|
||||
|
||||
<xsd:element name="script" type="GroovyScript">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Configures an inner bean that will generate a
|
||||
Groovy Script.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="GroovyScript">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="ScriptType">
|
||||
<xsd:attribute name="customizer" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Reference to a GroovyObjectCustomizer bean to be applied to this script.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:expected-type
|
||||
type="org.springframework.scripting.groovy.GroovyObjectCustomizer" />
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
|
||||
<xsd:element name="control-bus">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Control bus that accepts messages in the form of Groovy scripts. The scripts should be provided as
|
||||
String payload in incoming messages. The variable bindings will include any @ManagedResource, Lifecycle,
|
||||
or CustomizableThreadCreator instances from within the ApplicationContext.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:all minOccurs="0" maxOccurs="1">
|
||||
<xsd:element ref="integration:poller" minOccurs="0"
|
||||
maxOccurs="1" />
|
||||
</xsd:all>
|
||||
<xsd:attributeGroup ref="integration:inputOutputChannelGroup" />
|
||||
<xsd:attribute name="customizer" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Reference to a GroovyObjectCustomizer bean to be
|
||||
applied to each script payload.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:expected-type
|
||||
type="org.springframework.scripting.groovy.GroovyObjectCustomizer" />
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
</xsd:schema>
|
||||
Reference in New Issue
Block a user