From 0e9a93ef424576d03382b9290b81df48c45902d2 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Mon, 10 Dec 2007 23:09:42 +0000 Subject: [PATCH] Added basic namespace support. --- .../src/main/java/META-INF/spring.handlers | 1 + .../src/main/java/META-INF/spring.schemas | 1 + .../integration/config/ChannelParser.java | 56 ++++++++ .../integration/config/EndpointParser.java | 127 ++++++++++++++++++ .../config/IntegrationNamespaceHandler.java | 33 +++++ .../config/spring-integration-1.0.xsd | 67 +++++++++ .../config/ChannelParserTests.java | 44 ++++++ .../config/EndpointParserTests.java | 61 +++++++++ .../integration/config/TestBean.java | 47 +++++++ .../integration/config/TestHandler.java | 52 +++++++ .../integration/config/channelParserTests.xml | 12 ++ .../config/genericEndpointTests.xml | 22 +++ .../config/handlerAdapterEndpointTests.xml | 22 +++ 13 files changed, 545 insertions(+) create mode 100644 spring-eai-core/src/main/java/META-INF/spring.handlers create mode 100644 spring-eai-core/src/main/java/META-INF/spring.schemas create mode 100644 spring-eai-core/src/main/java/org/springframework/integration/config/ChannelParser.java create mode 100644 spring-eai-core/src/main/java/org/springframework/integration/config/EndpointParser.java create mode 100644 spring-eai-core/src/main/java/org/springframework/integration/config/IntegrationNamespaceHandler.java create mode 100644 spring-eai-core/src/main/java/org/springframework/integration/config/spring-integration-1.0.xsd create mode 100644 spring-eai-core/src/test/java/org/springframework/integration/config/ChannelParserTests.java create mode 100644 spring-eai-core/src/test/java/org/springframework/integration/config/EndpointParserTests.java create mode 100644 spring-eai-core/src/test/java/org/springframework/integration/config/TestBean.java create mode 100644 spring-eai-core/src/test/java/org/springframework/integration/config/TestHandler.java create mode 100644 spring-eai-core/src/test/java/org/springframework/integration/config/channelParserTests.xml create mode 100644 spring-eai-core/src/test/java/org/springframework/integration/config/genericEndpointTests.xml create mode 100644 spring-eai-core/src/test/java/org/springframework/integration/config/handlerAdapterEndpointTests.xml diff --git a/spring-eai-core/src/main/java/META-INF/spring.handlers b/spring-eai-core/src/main/java/META-INF/spring.handlers new file mode 100644 index 0000000000..b6de0cb6fe --- /dev/null +++ b/spring-eai-core/src/main/java/META-INF/spring.handlers @@ -0,0 +1 @@ +http\://www.springframework.org/schema/integration=org.springframework.integration.config.IntegrationNamespaceHandler \ No newline at end of file diff --git a/spring-eai-core/src/main/java/META-INF/spring.schemas b/spring-eai-core/src/main/java/META-INF/spring.schemas new file mode 100644 index 0000000000..bc2146688a --- /dev/null +++ b/spring-eai-core/src/main/java/META-INF/spring.schemas @@ -0,0 +1 @@ +http\://www.springframework.org/schema/integration/spring-integration-1.0.xsd=org/springframework/integration/config/spring-integration-1.0.xsd \ No newline at end of file diff --git a/spring-eai-core/src/main/java/org/springframework/integration/config/ChannelParser.java b/spring-eai-core/src/main/java/org/springframework/integration/config/ChannelParser.java new file mode 100644 index 0000000000..6f972b31b3 --- /dev/null +++ b/spring-eai-core/src/main/java/org/springframework/integration/config/ChannelParser.java @@ -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.integration.config; + +import org.w3c.dom.Element; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.integration.channel.PointToPointChannel; +import org.springframework.util.StringUtils; + +/** + * Parser for the channel element of the integration namespace. + * + * @author Mark Fisher + */ +public class ChannelParser implements BeanDefinitionParser { + + private static final String ID_ATTRIBUTE = "id"; + + private static final String CAPACITY_ATTRIBUTE = "capacity"; + + + public BeanDefinition parse(Element element, ParserContext parserContext) { + RootBeanDefinition channelDef = new RootBeanDefinition(PointToPointChannel.class); + channelDef.setSource(parserContext.extractSource(element)); + String capacity = element.getAttribute(CAPACITY_ATTRIBUTE); + if (StringUtils.hasText(capacity)) { + channelDef.getConstructorArgumentValues().addGenericArgumentValue(Integer.parseInt(capacity)); + } + String beanName = element.getAttribute(ID_ATTRIBUTE); + if (!StringUtils.hasText(beanName)) { + beanName = parserContext.getReaderContext().generateBeanName(channelDef); + } + parserContext.registerBeanComponent(new BeanComponentDefinition(channelDef, beanName)); + return channelDef; + } + +} diff --git a/spring-eai-core/src/main/java/org/springframework/integration/config/EndpointParser.java b/spring-eai-core/src/main/java/org/springframework/integration/config/EndpointParser.java new file mode 100644 index 0000000000..28bbd90523 --- /dev/null +++ b/spring-eai-core/src/main/java/org/springframework/integration/config/EndpointParser.java @@ -0,0 +1,127 @@ +/* + * 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.integration.config; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.integration.bus.ConsumerPolicy; +import org.springframework.integration.endpoint.GenericMessageEndpoint; +import org.springframework.integration.endpoint.MessageHandlerAdapter; +import org.springframework.util.StringUtils; + +/** + * Parser for the endpoint element of the integration namespace. + * + * @author Mark Fisher + */ +public class EndpointParser implements BeanDefinitionParser { + + private static final String ID_ATTRIBUTE = "id"; + + private static final String INPUT_CHANNEL_ATTRIBUTE = "input-channel"; + + private static final String INPUT_CHANNEL_PROPERTY = "inputChannelName"; + + private static final String DEFAULT_OUTPUT_CHANNEL_ATTRIBUTE = "default-output-channel"; + + private static final String DEFAULT_OUTPUT_CHANNEL_PROPERTY = "defaultOutputChannelName"; + + private static final String HANDLER_REF_ATTRIBUTE = "handler"; + + private static final String HANDLER_METHOD_ATTRIBUTE = "handler-method"; + + private static final String HANDLER_PROPERTY = "handler"; + + private static final String OBJECT_PROPERTY = "object"; + + private static final String METHOD_PROPERTY = "method"; + + private static final String PERIOD_ATTRIBUTE = "period"; + + private static final String PERIOD_PROPERTY = "period"; + + private static final String CONSUMER_ELEMENT = "consumer"; + + private static final String CONSUMER_POLICY_PROPERTY = "consumerPolicy"; + + + public BeanDefinition parse(Element element, ParserContext parserContext) { + RootBeanDefinition endpointDef = new RootBeanDefinition(GenericMessageEndpoint.class); + endpointDef.setSource(parserContext.extractSource(element)); + String inputChannel = element.getAttribute(INPUT_CHANNEL_ATTRIBUTE); + if (StringUtils.hasText(inputChannel)) { + endpointDef.getPropertyValues().addPropertyValue(INPUT_CHANNEL_PROPERTY, inputChannel); + } + String defaultOutputChannel = element.getAttribute(DEFAULT_OUTPUT_CHANNEL_ATTRIBUTE); + if (StringUtils.hasText(defaultOutputChannel)) { + endpointDef.getPropertyValues().addPropertyValue(DEFAULT_OUTPUT_CHANNEL_PROPERTY, defaultOutputChannel); + } + String handlerRef = element.getAttribute(HANDLER_REF_ATTRIBUTE); + if (StringUtils.hasText(handlerRef)) { + String handlerMethod = element.getAttribute(HANDLER_METHOD_ATTRIBUTE); + if (StringUtils.hasText(handlerMethod)) { + BeanDefinition handlerAdapterDef = new RootBeanDefinition(MessageHandlerAdapter.class); + handlerAdapterDef.getPropertyValues().addPropertyValue(OBJECT_PROPERTY, new RuntimeBeanReference(handlerRef)); + handlerAdapterDef.getPropertyValues().addPropertyValue(METHOD_PROPERTY, handlerMethod); + String adapterBeanName = parserContext.getReaderContext().generateBeanName(handlerAdapterDef); + parserContext.registerBeanComponent(new BeanComponentDefinition(handlerAdapterDef, adapterBeanName)); + endpointDef.getPropertyValues().addPropertyValue(HANDLER_PROPERTY, new RuntimeBeanReference(adapterBeanName)); + } + else { + endpointDef.getPropertyValues().addPropertyValue(HANDLER_PROPERTY, new RuntimeBeanReference(handlerRef)); + } + } + String beanName = element.getAttribute(ID_ATTRIBUTE); + if (!StringUtils.hasText(beanName)) { + beanName = parserContext.getReaderContext().generateBeanName(endpointDef); + } + NodeList childNodes = element.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node child = childNodes.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + String localName = child.getLocalName(); + if (CONSUMER_ELEMENT.equals(localName)) { + String consumerBeanName = parseConsumer((Element) child, parserContext); + endpointDef.getPropertyValues().addPropertyValue( + CONSUMER_POLICY_PROPERTY, new RuntimeBeanReference(consumerBeanName)); + } + } + } + parserContext.registerBeanComponent(new BeanComponentDefinition(endpointDef, beanName)); + return endpointDef; + } + + private String parseConsumer(Element element, ParserContext parserContext) { + RootBeanDefinition consumerDef = new RootBeanDefinition(ConsumerPolicy.class); + String period = element.getAttribute(PERIOD_ATTRIBUTE); + if (StringUtils.hasText(period)) { + consumerDef.getPropertyValues().addPropertyValue(PERIOD_PROPERTY, Integer.parseInt(period)); + } + String beanName = parserContext.getReaderContext().generateBeanName(consumerDef); + parserContext.registerBeanComponent(new BeanComponentDefinition(consumerDef, beanName)); + return beanName; + } + +} diff --git a/spring-eai-core/src/main/java/org/springframework/integration/config/IntegrationNamespaceHandler.java b/spring-eai-core/src/main/java/org/springframework/integration/config/IntegrationNamespaceHandler.java new file mode 100644 index 0000000000..4d6f0c5b11 --- /dev/null +++ b/spring-eai-core/src/main/java/org/springframework/integration/config/IntegrationNamespaceHandler.java @@ -0,0 +1,33 @@ +/* + * 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.integration.config; + +import org.springframework.beans.factory.xml.NamespaceHandlerSupport; + +/** + * Handler for the integration namespace. + * + * @author Mark Fisher + */ +public class IntegrationNamespaceHandler extends NamespaceHandlerSupport { + + public void init() { + registerBeanDefinitionParser("channel", new ChannelParser()); + registerBeanDefinitionParser("endpoint", new EndpointParser()); + } + +} diff --git a/spring-eai-core/src/main/java/org/springframework/integration/config/spring-integration-1.0.xsd b/spring-eai-core/src/main/java/org/springframework/integration/config/spring-integration-1.0.xsd new file mode 100644 index 0000000000..037e5f1e50 --- /dev/null +++ b/spring-eai-core/src/main/java/org/springframework/integration/config/spring-integration-1.0.xsd @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + Defines a message channel. + + + + + + + + + + + + + + + Defines a message endpoint. + + + + + + + + + + + + + + + + + + + + + Defines a consumer policy. + + + + + + + \ No newline at end of file diff --git a/spring-eai-core/src/test/java/org/springframework/integration/config/ChannelParserTests.java b/spring-eai-core/src/test/java/org/springframework/integration/config/ChannelParserTests.java new file mode 100644 index 0000000000..568b5a7fc5 --- /dev/null +++ b/spring-eai-core/src/test/java/org/springframework/integration/config/ChannelParserTests.java @@ -0,0 +1,44 @@ +/* + * 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.integration.config; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.channel.MessageChannel; +import org.springframework.integration.message.DocumentMessage; + +/** + * @author Mark Fisher + */ +public class ChannelParserTests { + + @Test + public void testSimpleChannelWithDefaults() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "channelParserTests.xml", this.getClass()); + MessageChannel channel = (MessageChannel) context.getBean("testChannel"); + for (int i = 0; i < 10; i++) { + boolean result = channel.send(new DocumentMessage(1, "test"), 10); + assertTrue(result); + } + assertFalse(channel.send(new DocumentMessage(1, "test"), 3)); + } +} diff --git a/spring-eai-core/src/test/java/org/springframework/integration/config/EndpointParserTests.java b/spring-eai-core/src/test/java/org/springframework/integration/config/EndpointParserTests.java new file mode 100644 index 0000000000..5b5d0bd630 --- /dev/null +++ b/spring-eai-core/src/test/java/org/springframework/integration/config/EndpointParserTests.java @@ -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.integration.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.concurrent.TimeUnit; + +import org.junit.Test; + +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.channel.MessageChannel; +import org.springframework.integration.message.DocumentMessage; + +/** + * @author Mark Fisher + */ +public class EndpointParserTests { + + @Test + public void testSimpleEndpoint() throws InterruptedException { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "genericEndpointTests.xml", this.getClass()); + context.start(); + MessageChannel channel = (MessageChannel) context.getBean("testChannel"); + TestHandler handler = (TestHandler) context.getBean("testHandler"); + assertNull(handler.getMessageString()); + channel.send(new DocumentMessage(1, "test")); + handler.getLatch().await(50, TimeUnit.MILLISECONDS); + assertEquals("test", handler.getMessageString()); + } + + @Test + public void testHandlerAdapterEndpoint() throws InterruptedException { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "handlerAdapterEndpointTests.xml", this.getClass()); + context.start(); + MessageChannel channel = (MessageChannel) context.getBean("testChannel"); + TestBean bean = (TestBean) context.getBean("testBean"); + assertNull(bean.getMessage()); + channel.send(new DocumentMessage(1, "test")); + bean.getLatch().await(50, TimeUnit.MILLISECONDS); + assertEquals("test", bean.getMessage()); + } + +} diff --git a/spring-eai-core/src/test/java/org/springframework/integration/config/TestBean.java b/spring-eai-core/src/test/java/org/springframework/integration/config/TestBean.java new file mode 100644 index 0000000000..24e5eaf84b --- /dev/null +++ b/spring-eai-core/src/test/java/org/springframework/integration/config/TestBean.java @@ -0,0 +1,47 @@ +/* + * 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.integration.config; + +import java.util.concurrent.CountDownLatch; + +/** + * @author Mark Fisher + */ +public class TestBean { + + private String message; + + private CountDownLatch latch; + + + public TestBean(int countdown) { + this.latch = new CountDownLatch(countdown); + } + + public CountDownLatch getLatch() { + return this.latch; + } + + public void store(String message) { + this.message = message; + latch.countDown(); + } + + public String getMessage() { + return this.message; + } +} diff --git a/spring-eai-core/src/test/java/org/springframework/integration/config/TestHandler.java b/spring-eai-core/src/test/java/org/springframework/integration/config/TestHandler.java new file mode 100644 index 0000000000..8c4c6274c2 --- /dev/null +++ b/spring-eai-core/src/test/java/org/springframework/integration/config/TestHandler.java @@ -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.integration.config; + +import java.util.concurrent.CountDownLatch; + +import org.springframework.integration.handler.MessageHandler; +import org.springframework.integration.message.Message; + +/** + * @author Mark Fisher + */ +public class TestHandler implements MessageHandler { + + private String messageString; + + private CountDownLatch latch; + + + public TestHandler(int countdown) { + this.latch = new CountDownLatch(countdown); + } + + public Message handle(Message message) { + this.messageString = (String) message.getPayload(); + this.latch.countDown(); + return null; + } + + public String getMessageString() { + return this.messageString; + } + + public CountDownLatch getLatch() { + return this.latch; + } + +} diff --git a/spring-eai-core/src/test/java/org/springframework/integration/config/channelParserTests.xml b/spring-eai-core/src/test/java/org/springframework/integration/config/channelParserTests.xml new file mode 100644 index 0000000000..3e14d73a70 --- /dev/null +++ b/spring-eai-core/src/test/java/org/springframework/integration/config/channelParserTests.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/spring-eai-core/src/test/java/org/springframework/integration/config/genericEndpointTests.xml b/spring-eai-core/src/test/java/org/springframework/integration/config/genericEndpointTests.xml new file mode 100644 index 0000000000..a965cb6da8 --- /dev/null +++ b/spring-eai-core/src/test/java/org/springframework/integration/config/genericEndpointTests.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/spring-eai-core/src/test/java/org/springframework/integration/config/handlerAdapterEndpointTests.xml b/spring-eai-core/src/test/java/org/springframework/integration/config/handlerAdapterEndpointTests.xml new file mode 100644 index 0000000000..63baced08d --- /dev/null +++ b/spring-eai-core/src/test/java/org/springframework/integration/config/handlerAdapterEndpointTests.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + +