From d75e1d9093e50bd3ed4c6bc25d508c16ca74780e Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 12 Dec 2008 15:23:24 +0000 Subject: [PATCH] Minimizing class loading in parsers and using the parser context error handling capabilities rather than throwing Exceptions or using assertions. This facilitates proper tooling support (INT-114). --- .../FileInboundChannelAdapterParser.java | 46 ++++--- .../FileOutboundChannelAdapterParser.java | 9 +- ...lAdapterWithPatternParserTests-context.xml | 23 ++++ ...dChannelAdapterWithPatternParserTests.java | 125 ++++++++++++++++++ 4 files changed, 184 insertions(+), 19 deletions(-) create mode 100644 org.springframework.integration.file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPatternParserTests-context.xml create mode 100644 org.springframework.integration.file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPatternParserTests.java diff --git a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/config/FileInboundChannelAdapterParser.java b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/config/FileInboundChannelAdapterParser.java index 0f2426bb73..25a604da17 100644 --- a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/config/FileInboundChannelAdapterParser.java +++ b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/config/FileInboundChannelAdapterParser.java @@ -16,19 +16,15 @@ package org.springframework.integration.file.config; -import java.util.regex.Pattern; - import org.w3c.dom.Element; +import org.springframework.beans.factory.config.BeanDefinition; +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.ManagedList; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.AbstractPollingInboundChannelAdapterParser; -import org.springframework.integration.file.AcceptOnceFileListFilter; -import org.springframework.integration.file.CompositeFileListFilter; -import org.springframework.integration.file.PatternMatchingFileListFilter; -import org.springframework.integration.file.FileReadingMessageSource; -import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** @@ -39,9 +35,14 @@ import org.springframework.util.StringUtils; */ public class FileInboundChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser { + private static final String PACKAGE_NAME = "org.springframework.integration.file"; + + @Override + @SuppressWarnings("unchecked") protected String parseSource(Element element, ParserContext parserContext) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FileReadingMessageSource.class); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( + PACKAGE_NAME + ".FileReadingMessageSource"); String directory = element.getAttribute("directory"); if (StringUtils.hasText(directory)) { builder.addPropertyValue("inputDirectory", directory); @@ -52,15 +53,30 @@ public class FileInboundChannelAdapterParser extends AbstractPollingInboundChann } String filenamePattern = element.getAttribute("filename-pattern"); if (StringUtils.hasText(filenamePattern)) { - Assert.isTrue(!StringUtils.hasText(filter), - "at most one of 'filter' and 'filename-pattern' may be provided"); - AcceptOnceFileListFilter acceptOnceFilter = new AcceptOnceFileListFilter(); - Pattern pattern = Pattern.compile(filenamePattern); - PatternMatchingFileListFilter patternFilter = new PatternMatchingFileListFilter(pattern); - CompositeFileListFilter compositeFilter = new CompositeFileListFilter(acceptOnceFilter, patternFilter); - builder.addPropertyValue("filter", compositeFilter); + if (StringUtils.hasText(filter)) { + parserContext.getReaderContext().error( + "At most one of 'filter' and 'filename-pattern' may be provided.", element); + } + String acceptOnceFilterBeanName = this.parseFilter("AcceptOnceFileListFilter", null, parserContext); + String patternFilterBeanName = this.parseFilter("PatternMatchingFileListFilter", filenamePattern, parserContext); + ManagedList filters = new ManagedList(); + filters.add(new RuntimeBeanReference(acceptOnceFilterBeanName)); + filters.add(new RuntimeBeanReference(patternFilterBeanName)); + String compositeFilterBeanName = this.parseFilter("CompositeFileListFilter", filters, parserContext); + builder.addPropertyReference("filter", compositeFilterBeanName); } return BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry()); } + private String parseFilter(String shortClassName, Object constructorArgValue, ParserContext parserContext) { + BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.genericBeanDefinition( + PACKAGE_NAME + "." + shortClassName); + filterBuilder.getBeanDefinition().setRole(BeanDefinition.ROLE_SUPPORT); + if (constructorArgValue != null) { + filterBuilder.addConstructorArgValue(constructorArgValue); + } + return BeanDefinitionReaderUtils.registerWithGeneratedName( + filterBuilder.getBeanDefinition(), parserContext.getRegistry()); + } + } diff --git a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java index b5d6078bb1..851f40be00 100644 --- a/org.springframework.integration.file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java +++ b/org.springframework.integration.file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java @@ -22,8 +22,6 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser; -import org.springframework.integration.file.FileWritingMessageHandler; -import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** @@ -36,8 +34,11 @@ public class FileOutboundChannelAdapterParser extends AbstractOutboundChannelAda @Override protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { String directory = element.getAttribute("directory"); - Assert.hasText(directory, "directory is required"); - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FileWritingMessageHandler.class); + if (!StringUtils.hasText(directory)) { + parserContext.getReaderContext().error("directory is required", element); + } + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( + "org.springframework.integration.file.FileWritingMessageHandler"); builder.addConstructorArgValue(directory); String fileNameGenerator = element.getAttribute("filename-generator"); if (StringUtils.hasText(fileNameGenerator)) { diff --git a/org.springframework.integration.file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPatternParserTests-context.xml b/org.springframework.integration.file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPatternParserTests-context.xml new file mode 100644 index 0000000000..ef96569e0a --- /dev/null +++ b/org.springframework.integration.file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPatternParserTests-context.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/org.springframework.integration.file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPatternParserTests.java b/org.springframework.integration.file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPatternParserTests.java new file mode 100644 index 0000000000..e61c420afc --- /dev/null +++ b/org.springframework.integration.file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPatternParserTests.java @@ -0,0 +1,125 @@ +/* + * 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.integration.file.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.Set; +import java.util.regex.Pattern; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.DirectFieldAccessor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.channel.SubscribableChannel; +import org.springframework.integration.endpoint.AbstractEndpoint; +import org.springframework.integration.file.AcceptOnceFileListFilter; +import org.springframework.integration.file.CompositeFileListFilter; +import org.springframework.integration.file.FileListFilter; +import org.springframework.integration.file.FileReadingMessageSource; +import org.springframework.integration.file.PatternMatchingFileListFilter; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Mark Fisher + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class FileInboundChannelAdapterWithPatternParserTests { + + @Autowired(required=true) + private SubscribableChannel channel; + + @Autowired(required=true) + private AbstractEndpoint endpoint; + + private DirectFieldAccessor accessor; + + + @Autowired(required=true) + public void setSource(FileReadingMessageSource source) { + this.accessor = new DirectFieldAccessor(source); + } + + @Test + public void channelName() { + assertEquals("adapterWithPattern", channel.getName()); + } + + @Test + public void autoStartupDisabled() { + assertFalse(this.endpoint.isRunning()); + Boolean autoStartupValue = (Boolean) new DirectFieldAccessor(endpoint).getPropertyValue("autoStartup"); + assertFalse(autoStartupValue); + } + + @Test + public void inputDirectory() { + assertEquals(System.getProperty("java.io.tmpdir"), ((File) accessor.getPropertyValue("inputDirectory")).getPath()); + } + + @Test + public void compositeFilterType() { + assertTrue(accessor.getPropertyValue("filter") instanceof CompositeFileListFilter); + } + + @Test + @SuppressWarnings("unchecked") + public void compositeFilterSetSize() { + Set filters = (Set) new DirectFieldAccessor( + accessor.getPropertyValue("filter")).getPropertyValue("fileFilters"); + assertEquals(2, filters.size()); + } + + @Test + @SuppressWarnings("unchecked") + public void acceptOnceFilter() { + Set filters = (Set) new DirectFieldAccessor( + accessor.getPropertyValue("filter")).getPropertyValue("fileFilters"); + boolean hasAcceptOnceFilter = false; + for (FileListFilter filter : filters) { + if (filter instanceof AcceptOnceFileListFilter) { + hasAcceptOnceFilter = true; + } + } + assertTrue("expected AcceptOnceFileListFilter", hasAcceptOnceFilter); + } + + @Test + @SuppressWarnings("unchecked") + public void patternFilter() { + Set filters = (Set) new DirectFieldAccessor( + accessor.getPropertyValue("filter")).getPropertyValue("fileFilters"); + Pattern pattern = null; + for (FileListFilter filter : filters) { + if (filter instanceof PatternMatchingFileListFilter) { + pattern = (Pattern) new DirectFieldAccessor(filter).getPropertyValue("pattern"); + } + } + assertNotNull("expected PatternMatchingFileListFilter", pattern); + assertEquals(".*\\.txt", pattern.toString()); + assertFalse(pattern.matcher("foo").matches()); + assertTrue(pattern.matcher("foo.txt").matches()); + } + +}