From 7174e8840b6f20eabdd39a4f594ce44cd15a1221 Mon Sep 17 00:00:00 2001 From: Gregory Bragg Date: Fri, 27 May 2022 11:02:26 -0400 Subject: [PATCH] Add XSD for new SMB components * Add namespace handler support for new XSD configs * Add JUnit tests for outbound gateway XML config * Add JUnit tests for streaming inbound adapter XML config * Add Javadoc to new parser classes as per PR feedback * Some code clean up --- .../smb/config/SmbNamespaceHandler.java | 3 + .../smb/config/SmbOutboundGatewayParser.java | 55 ++ ...bStreamingInboundChannelAdapterParser.java | 64 ++ .../smb/config/spring-integration-smb.xsd | 601 ++++++++++++++---- .../SmbOutboundGatewayParserTests-context.xml | 138 ++++ .../config/SmbOutboundGatewayParserTests.java | 195 ++++++ ...boundChannelAdapterParserTests-context.xml | 49 ++ ...amingInboundChannelAdapterParserTests.java | 122 ++++ src/reference/asciidoc/smb.adoc | 87 ++- 9 files changed, 1196 insertions(+), 118 deletions(-) create mode 100644 spring-integration-smb/src/main/java/org/springframework/integration/smb/config/SmbOutboundGatewayParser.java create mode 100644 spring-integration-smb/src/main/java/org/springframework/integration/smb/config/SmbStreamingInboundChannelAdapterParser.java create mode 100644 spring-integration-smb/src/test/java/org/springframework/integration/smb/config/SmbOutboundGatewayParserTests-context.xml create mode 100644 spring-integration-smb/src/test/java/org/springframework/integration/smb/config/SmbOutboundGatewayParserTests.java create mode 100644 spring-integration-smb/src/test/java/org/springframework/integration/smb/config/SmbStreamingInboundChannelAdapterParserTests-context.xml create mode 100644 spring-integration-smb/src/test/java/org/springframework/integration/smb/config/SmbStreamingInboundChannelAdapterParserTests.java diff --git a/spring-integration-smb/src/main/java/org/springframework/integration/smb/config/SmbNamespaceHandler.java b/spring-integration-smb/src/main/java/org/springframework/integration/smb/config/SmbNamespaceHandler.java index fd28a2e826..ff9348f5dd 100644 --- a/spring-integration-smb/src/main/java/org/springframework/integration/smb/config/SmbNamespaceHandler.java +++ b/spring-integration-smb/src/main/java/org/springframework/integration/smb/config/SmbNamespaceHandler.java @@ -23,6 +23,7 @@ import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHa * * @author Markus Spann * @author Artem Bilan + * @author Gregory Bragg * * @since 6.0 */ @@ -30,7 +31,9 @@ public class SmbNamespaceHandler extends AbstractIntegrationNamespaceHandler { public void init() { registerBeanDefinitionParser("inbound-channel-adapter", new SmbInboundChannelAdapterParser()); + registerBeanDefinitionParser("inbound-streaming-channel-adapter", new SmbStreamingInboundChannelAdapterParser()); registerBeanDefinitionParser("outbound-channel-adapter", new SmbOutboundChannelAdapterParser()); + registerBeanDefinitionParser("outbound-gateway", new SmbOutboundGatewayParser()); } } diff --git a/spring-integration-smb/src/main/java/org/springframework/integration/smb/config/SmbOutboundGatewayParser.java b/spring-integration-smb/src/main/java/org/springframework/integration/smb/config/SmbOutboundGatewayParser.java new file mode 100644 index 0000000000..be69e637f8 --- /dev/null +++ b/spring-integration-smb/src/main/java/org/springframework/integration/smb/config/SmbOutboundGatewayParser.java @@ -0,0 +1,55 @@ +/* + * Copyright 2022 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 + * + * https://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.smb.config; + +import org.springframework.integration.file.config.AbstractRemoteFileOutboundGatewayParser; +import org.springframework.integration.file.remote.RemoteFileOperations; +import org.springframework.integration.smb.filters.SmbRegexPatternFileListFilter; +import org.springframework.integration.smb.filters.SmbSimplePatternFileListFilter; +import org.springframework.integration.smb.outbound.SmbOutboundGateway; +import org.springframework.integration.smb.session.SmbRemoteFileTemplate; + +/** + * Parser for the SMB 'outbound-gateway' element. + * + * @author Gregory Bragg + * + * @since 6.0 + */ +public class SmbOutboundGatewayParser extends AbstractRemoteFileOutboundGatewayParser { + + @Override + public String getGatewayClassName() { + return SmbOutboundGateway.class.getName(); + } + + @Override + protected String getSimplePatternFileListFilterClassName() { + return SmbSimplePatternFileListFilter.class.getName(); + } + + @Override + protected String getRegexPatternFileListFilterClassName() { + return SmbRegexPatternFileListFilter.class.getName(); + } + + @Override + protected Class> getTemplateClass() { + return SmbRemoteFileTemplate.class; + } + +} diff --git a/spring-integration-smb/src/main/java/org/springframework/integration/smb/config/SmbStreamingInboundChannelAdapterParser.java b/spring-integration-smb/src/main/java/org/springframework/integration/smb/config/SmbStreamingInboundChannelAdapterParser.java new file mode 100644 index 0000000000..03472b2cdd --- /dev/null +++ b/spring-integration-smb/src/main/java/org/springframework/integration/smb/config/SmbStreamingInboundChannelAdapterParser.java @@ -0,0 +1,64 @@ +/* + * Copyright 2022 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 + * + * https://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.smb.config; + +import org.springframework.integration.core.MessageSource; +import org.springframework.integration.file.config.AbstractRemoteFileStreamingInboundChannelAdapterParser; +import org.springframework.integration.file.filters.AbstractPersistentAcceptOnceFileListFilter; +import org.springframework.integration.file.filters.FileListFilter; +import org.springframework.integration.file.remote.RemoteFileOperations; +import org.springframework.integration.smb.filters.SmbPersistentAcceptOnceFileListFilter; +import org.springframework.integration.smb.filters.SmbRegexPatternFileListFilter; +import org.springframework.integration.smb.filters.SmbSimplePatternFileListFilter; +import org.springframework.integration.smb.inbound.SmbStreamingMessageSource; +import org.springframework.integration.smb.session.SmbRemoteFileTemplate; + +/** + * Parser for the SMB 'inbound-streaming-channel-adapter' element. + * + * @author Gregory Bragg + * + * @since 6.0 + */ +public class SmbStreamingInboundChannelAdapterParser extends AbstractRemoteFileStreamingInboundChannelAdapterParser { + + @Override + protected Class> getTemplateClass() { + return SmbRemoteFileTemplate.class; + } + + @Override + protected Class> getMessageSourceClass() { + return SmbStreamingMessageSource.class; + } + + @Override + protected Class> getSimplePatternFileListFilterClass() { + return SmbSimplePatternFileListFilter.class; + } + + @Override + protected Class> getRegexPatternFileListFilterClass() { + return SmbRegexPatternFileListFilter.class; + } + + @Override + protected Class> getPersistentAcceptOnceFileListFilterClass() { + return SmbPersistentAcceptOnceFileListFilter.class; + } + +} diff --git a/spring-integration-smb/src/main/resources/org/springframework/integration/smb/config/spring-integration-smb.xsd b/spring-integration-smb/src/main/resources/org/springframework/integration/smb/config/spring-integration-smb.xsd index 6a85beab96..7a4b257edf 100644 --- a/spring-integration-smb/src/main/resources/org/springframework/integration/smb/config/spring-integration-smb.xsd +++ b/spring-integration-smb/src/main/resources/org/springframework/integration/smb/config/spring-integration-smb.xsd @@ -3,77 +3,49 @@ xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tool="http://www.springframework.org/schema/tool" xmlns:integration="http://www.springframework.org/schema/integration" + xmlns:int-file="http://www.springframework.org/schema/integration/file" targetNamespace="http://www.springframework.org/schema/integration/smb" - elementFormDefault="qualified" - attributeFormDefault="unqualified"> + elementFormDefault="qualified"> + schemaLocation="https://www.springframework.org/schema/integration/spring-integration.xsd"/> + - - + - + - + - + - - + + - - - - Identifies directory path (e.g., "/temp/mytransfers/") - where file will be transferred to. - - - - - - - Allows you to provide SpEL expression which will - compute directory path where file will be - transferred to (e.g., "headers.['remote_dir'] + '/myTransfers'"); - - - - - - - Allows you to provide remote file/directory separator - character. DEFAULT: '/' - - - - - - - Extension used when uploading files. We change - it right after we know it's uploaded. - - - Allows you to specify a reference to a - [org.springframework.integration.file.FileNameGenerator] bean. + 'org.springframework.integration.file.FileNameGenerator' bean. @@ -87,7 +59,7 @@ Allows you to provide SpEL expression which will compute file name of the remote file (e.g., assuming - payload is java.io.File "payload.getName() + '.transfered'"); + payload is java.io.File "payload.getName() + '.transferred'"); @@ -106,6 +78,14 @@ + + + + Allows you to specify Charset (e.g., US-ASCII, ISO-8859-1, UTF-8). + [UTF-8] is the default. + + + @@ -116,36 +96,17 @@ - - + - + - - - - - Allows you to provide file name pattern to determine - the file names that needs to be scanned and is - based on simple pattern matching algorithm - (e.g., "*.txt, fo*.txt" etc.) - - - - - - - Allows you to provide Regular Expression to determine - the file names that needs to be scanned. (e.g., "f[o]+\.txt" etc.) - - - - - - - - - - - - Allows you to specify a reference to - [org.springframework.integration.file.filters.FileListFilter] bean. - - - - - - - Extension used when downloading files. We change - it right after we know it's downloaded. - - - - - - - Identifies directory path (e.g., "/temp/mytransfers") - where file will be transferred FROM. - - - - - - - Allows you to provide remote file/directory separator - character. DEFAULT: '/' - - - + type="org.springframework.integration.file.filters.FileListFilter"/> @@ -229,7 +153,7 @@ - + Specify whether to delete the remote source file after copying. @@ -237,33 +161,476 @@ + + + + Allows you to specify Charset (e.g., US-ASCII, ISO-8859-1, UTF-8). + [UTF-8] is the default. + + + + - + + + + Configures a 'SourcePollingChannelAdapter' Endpoint for the + 'org.springframework.integration.smb.inbound.SmbInboundStreamingMessageSource'. + + + + + + + + + + + + + + + + + + + Configures a Consumer Endpoint for the + 'org.springframework.integration.smb.outbound.SmbOutboundGateway' + used to issue SMB commands. + + + + + + + + + + + + + + SMB command. + + + + + + + + + + + + + + + The 'MessageSessionCallback' bean reference to perform custom operation(s) on 'Session' + with 'requestMessage'. + + + + + + + SMB command options; for ls, -1 means just + return the file names + (otherwise file + metadata is returned, -dirs + means include directories (not included by + default), + -links means + include links (not included by default); for get, -P means + preserve + timestamp from remote file. + + + + + + + SpEL expression representing the path in the + command (e.g. ls path to list the files in directory path). + + + + + + + SpEL expression representing the path for the + new filename when using the 'mv' command. + Defaults to "headers.['file_renameTo']". + + + + + + + + + + + + Identifies the request channel attached to this gateway. + + + + + + + + + + + + Identifies the reply channel attached to this gateway. + + + + + + + + + + + + + + + + + Allows you to specify a reference to + [org.springframework.integration.file.filters.FileListFilter] + bean. This filter acts against the remote server view when using the 'ls' + or 'mget' commands. + Only one of 'filter', 'filename-pattern', or 'filename-regex' is allowed. + + + + + + + + + + + + Allows you to provide file name pattern to + determine the file names retrieved by the 'ls' and 'mget' commands + and is based on simple pattern matching algorithm (e.g., "*.txt, fo*.txt" etc.) + Only one of 'filter', 'filename-pattern', or 'filename-regex' is allowed. + + + + + + + Allows you to provide Regular Expression to + determine the file names retrieved by the 'ls' and 'mget' commands. + (e.g., "f[o]+\.txt" etc.) + Only one of 'filter', 'filename-pattern', or 'filename-regex' is allowed. + + + + + + + + + + + + Allows you to specify a reference to + [org.springframework.integration.file.filters.FileListFilter] + bean. This filter acts on the local file system when using the 'mput' command. + Only one of 'mput-filter', 'mput-pattern', or 'mput-regex' is allowed. + + + + + + + + + + + + Allows you to provide file name pattern to + determine the file names sent by the 'mput' command + and is based on simple pattern matching algorithm (e.g., "*.txt, fo*.txt" etc.) + Only one of 'mput-filter', 'mput-pattern', or 'mput-regex' is allowed. + + + + + + + Allows you to provide Regular Expression to + determine the file names sent by the 'mput' command (e.g., "f[o]+\.txt" etc.) + Only one of 'mput-filter', 'mput-pattern', or 'mput-regex' is allowed. + + + + + + + Allows you to provide a SpEL expression to + generate the file name of the local (transferred) file. + The root object of the SpEL + evaluation is the request Message, but the name of the original + remote file is also provided as the 'remoteFileName' variable. + For example, a valid expression would be: + "#remoteFileName.toUpperCase() + headers.foo". + Only used with 'get' and 'mget' commands. + + + + + + + Identifies directory path (e.g., "/local/mytransfers") where file will be + transferred TO. + This attribute is mutually exclusive with 'local-directory-expression'. + + + + + + + Specifies SpEL expression to + generate the directory path where file will be + transferred TO, when using 'get' and 'mget' commands. + The root object of the SpEL evaluation is the request Message, + but the name of the source + remote directory is also provided as the 'remoteDirectory' variable. + For example, a valid expression might be: + "'/local/' + #remoteDirectory.toUpperCase() + headers.foo". + Only used with 'get' and 'mget' commands. + This attribute is mutually exclusive with 'local-directory'. + + + + + + + Tells this adapter if local directory must be auto-created if it doesn't exist. + Default is TRUE. + + + + + + + Specifies the order for invocation when this + endpoint is connected as a subscriber to a channel. + This is particularly relevant when that channel is using a "failover" + dispatching strategy, or when a failure in the delivery to one + subscriber should signal that the message should not be sent to + subscribers with a higher 'order' attribute. + It has no effect when this endpoint itself is a Polling Consumer for a channel with + a queue. + + + + + + + Specify whether this outbound gateway must return a non-null value. This value is + 'true' by default, and a ReplyRequiredException will be thrown when + the underlying service returns a null value. + + + + + + + + + + + + + + + + + + + + + + + + Identifies channel attached to this adapter. + The channel to which messages will be sent by this adapter. + + + + + + + Allows you to provide a file name pattern to + determine the file names that need to be scanned. + This is based on simple pattern matching (e.g., "*.txt, fo*.txt" etc.) + + + + + + + Allows you to provide a Regular Expression to + determine the file names that need to be scanned (e.g., "f[o]+\.txt" etc.) + + + + + + + + + + + + Allows you to specify a reference to a + [org.springframework.integration.file.filters.FileListFilter] + bean. This filter is applied to files on the remote server and + only files that pass the filter are retrieved. + + + + + + + + + + + + + + + + + + + + + + + + + Identifies channel attached to this adapter. + The channel to which messages will be sent by this adapter. + + + + + + + Identifies the remote temporary directory path (e.g., "/remote/temp/mytransfers") + + + + + + + + + + - + - - + + - Allows you to specify Charset (e.g., US-ASCII, ISO-8859-1, UTF-8). - [UTF-8] is the default. + Allows you to provide remote file/directory separator character. DEFAULT: '/' - + + + + Identifies the remote directory path (e.g., "/remote/mytransfers") + Mutually exclusive with 'remote-directory-expression'. + + + + + + + Specify a SpEL expression which + will be used to evaluate the directory + path to where the files will be transferred + (e.g., "headers.['remote_dir'] + '/myTransfers'" for outbound endpoints) + There is no root object (message) for inbound endpoints + (e.g., "@someBean.fetchDirectory"); + + + + + + + + + Extension used when downloading files. We change it right after we know it's downloaded. + + + + + diff --git a/spring-integration-smb/src/test/java/org/springframework/integration/smb/config/SmbOutboundGatewayParserTests-context.xml b/spring-integration-smb/src/test/java/org/springframework/integration/smb/config/SmbOutboundGatewayParserTests-context.xml new file mode 100644 index 0000000000..6652cee18d --- /dev/null +++ b/spring-integration-smb/src/test/java/org/springframework/integration/smb/config/SmbOutboundGatewayParserTests-context.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-smb/src/test/java/org/springframework/integration/smb/config/SmbOutboundGatewayParserTests.java b/spring-integration-smb/src/test/java/org/springframework/integration/smb/config/SmbOutboundGatewayParserTests.java new file mode 100644 index 0000000000..18fab7a55e --- /dev/null +++ b/spring-integration-smb/src/test/java/org/springframework/integration/smb/config/SmbOutboundGatewayParserTests.java @@ -0,0 +1,195 @@ +/* + * Copyright 2002-2022 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 + * + * https://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.smb.config; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.lang.reflect.Method; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.expression.Expression; +import org.springframework.integration.endpoint.AbstractEndpoint; +import org.springframework.integration.file.FileNameGenerator; +import org.springframework.integration.file.filters.RegexPatternFileListFilter; +import org.springframework.integration.file.filters.SimplePatternFileListFilter; +import org.springframework.integration.file.remote.gateway.AbstractRemoteFileOutboundGateway.Command; +import org.springframework.integration.file.remote.gateway.AbstractRemoteFileOutboundGateway.Option; +import org.springframework.integration.file.remote.session.CachingSessionFactory; +import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice; +import org.springframework.integration.smb.outbound.SmbOutboundGateway; +import org.springframework.integration.test.util.TestUtils; +import org.springframework.messaging.Message; +import org.springframework.messaging.support.GenericMessage; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.util.ReflectionUtils; + +/** + * Unit tests follow original logic for testing SFTP module, + * adapted for SMB module. + * + * @author Gary Russell + * @author Gunnar Hillert + * @author Artem Bilan + * @author Gregory Bragg + * + * @since 6.0 + */ +@SpringJUnitConfig +@DirtiesContext +public class SmbOutboundGatewayParserTests { + + @Autowired + AbstractEndpoint gateway1; + + @Autowired + AbstractEndpoint gateway2; + + @Autowired + AbstractEndpoint gateway3; + + @Autowired + AbstractEndpoint gateway4; + + @Autowired + AbstractEndpoint advised; + + @Autowired + AbstractEndpoint noExpressionLS; + + @Autowired + AbstractEndpoint noExpressionPUT; + + @Autowired + AbstractEndpoint noExpressionGET; + + @Autowired + FileNameGenerator generator; + + private static volatile int adviceCalled; + + @Test + public void testGateway1() { + SmbOutboundGateway gateway = TestUtils.getPropertyValue(gateway1, + "handler", SmbOutboundGateway.class); + assertThat(TestUtils.getPropertyValue(gateway, "remoteFileTemplate.remoteFileSeparator")).isEqualTo("X"); + assertThat(TestUtils.getPropertyValue(gateway, "remoteFileTemplate.sessionFactory")).isNotNull(); + assertThat(TestUtils.getPropertyValue(gateway, "outputChannel")).isNotNull(); + assertThat(TestUtils.getPropertyValue(gateway, "localDirectoryExpression.literalValue")) + .isEqualTo("local-test-dir"); + assertThat((Boolean) TestUtils.getPropertyValue(gateway, "autoCreateLocalDirectory")).isFalse(); + assertThat(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class)).isTrue(); + assertThat(TestUtils.getPropertyValue(gateway, "filter")).isNotNull(); + assertThat(TestUtils.getPropertyValue(gateway, "command")).isEqualTo(Command.LS); + @SuppressWarnings("unchecked") + Set