Add Java DSL for SMB module
* Added supporting classes for DSL, fixed checkstyle build errors * Added JUnit tests for DSL package * Updated Java Doc with instructions to setup an external SMB share * Updated AsciiDoc to include instructions on Java DSL configurations * Updated implementation based on PR review feedback * Clean up the code * Add more info to `whats-new.adoc` for these SMB changes
This commit is contained in:
committed by
Artem Bilan
parent
1790f235b7
commit
ac6af716e1
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.dsl;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.springframework.integration.file.remote.MessageSessionCallback;
|
||||
import org.springframework.integration.file.remote.RemoteFileTemplate;
|
||||
import org.springframework.integration.file.remote.session.SessionFactory;
|
||||
import org.springframework.integration.file.support.FileExistsMode;
|
||||
import org.springframework.integration.smb.outbound.SmbOutboundGateway;
|
||||
import org.springframework.integration.smb.session.SmbRemoteFileTemplate;
|
||||
|
||||
import jcifs.smb.SmbFile;
|
||||
|
||||
/**
|
||||
* The factory for SMB components.
|
||||
*
|
||||
* @author Gregory Bragg
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public final class Smb {
|
||||
|
||||
/**
|
||||
* A {@link SmbInboundChannelAdapterSpec} factory for an inbound channel adapter spec.
|
||||
* @param sessionFactory the session factory.
|
||||
* @return the spec.
|
||||
*/
|
||||
public static SmbInboundChannelAdapterSpec inboundAdapter(SessionFactory<SmbFile> sessionFactory) {
|
||||
return inboundAdapter(sessionFactory, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link SmbInboundChannelAdapterSpec} factory for an inbound channel adapter spec.
|
||||
* @param sessionFactory the session factory.
|
||||
* @param receptionOrderComparator the comparator.
|
||||
* @return the spec.
|
||||
*/
|
||||
public static SmbInboundChannelAdapterSpec inboundAdapter(SessionFactory<SmbFile> sessionFactory,
|
||||
Comparator<File> receptionOrderComparator) {
|
||||
|
||||
return new SmbInboundChannelAdapterSpec(sessionFactory, receptionOrderComparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link SmbStreamingInboundChannelAdapterSpec} factory for an inbound channel
|
||||
* adapter spec.
|
||||
* @param remoteFileTemplate the remote file template.
|
||||
* @return the spec.
|
||||
*/
|
||||
public static SmbStreamingInboundChannelAdapterSpec inboundStreamingAdapter(
|
||||
RemoteFileTemplate<SmbFile> remoteFileTemplate) {
|
||||
|
||||
return inboundStreamingAdapter(remoteFileTemplate, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link SmbStreamingInboundChannelAdapterSpec} factory for an inbound channel
|
||||
* adapter spec.
|
||||
* @param remoteFileTemplate the remote file template.
|
||||
* @param receptionOrderComparator the comparator.
|
||||
* @return the spec.
|
||||
*/
|
||||
public static SmbStreamingInboundChannelAdapterSpec inboundStreamingAdapter(
|
||||
RemoteFileTemplate<SmbFile> remoteFileTemplate,
|
||||
Comparator<SmbFile> receptionOrderComparator) {
|
||||
|
||||
return new SmbStreamingInboundChannelAdapterSpec(remoteFileTemplate, receptionOrderComparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link SmbMessageHandlerSpec} factory for an outbound channel adapter spec.
|
||||
* @param sessionFactory the session factory.
|
||||
* @return the spec.
|
||||
*/
|
||||
public static SmbMessageHandlerSpec outboundAdapter(SessionFactory<SmbFile> sessionFactory) {
|
||||
return new SmbMessageHandlerSpec(sessionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link SmbMessageHandlerSpec} factory for an outbound channel adapter spec.
|
||||
* @param sessionFactory the session factory.
|
||||
* @param fileExistsMode the file exists mode.
|
||||
* @return the spec.
|
||||
*/
|
||||
public static SmbMessageHandlerSpec outboundAdapter(SessionFactory<SmbFile> sessionFactory,
|
||||
FileExistsMode fileExistsMode) {
|
||||
|
||||
return outboundAdapter(new SmbRemoteFileTemplate(sessionFactory), fileExistsMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link SmbMessageHandlerSpec} factory for an outbound channel adapter spec.
|
||||
* @param smbRemoteFileTemplate the remote file template.
|
||||
* @return the spec.
|
||||
*/
|
||||
public static SmbMessageHandlerSpec outboundAdapter(SmbRemoteFileTemplate smbRemoteFileTemplate) {
|
||||
return new SmbMessageHandlerSpec(smbRemoteFileTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link SmbMessageHandlerSpec} factory for an outbound channel adapter spec.
|
||||
* @param smbRemoteFileTemplate the remote file template.
|
||||
* @param fileExistsMode the file exists mode.
|
||||
* @return the spec.
|
||||
*/
|
||||
public static SmbMessageHandlerSpec outboundAdapter(SmbRemoteFileTemplate smbRemoteFileTemplate,
|
||||
FileExistsMode fileExistsMode) {
|
||||
|
||||
return new SmbMessageHandlerSpec(smbRemoteFileTemplate, fileExistsMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a {@link SmbOutboundGatewaySpec} based on the
|
||||
* {@link MessageSessionCallback}.
|
||||
* @param sessionFactory the {@link SessionFactory} to connect to.
|
||||
* @param messageSessionCallback the {@link MessageSessionCallback} to perform SMB.
|
||||
* operation(s) with the {@code Message} context.
|
||||
* @return the {@link SmbOutboundGatewaySpec}
|
||||
* @see MessageSessionCallback
|
||||
*/
|
||||
public static SmbOutboundGatewaySpec outboundGateway(SessionFactory<SmbFile> sessionFactory,
|
||||
MessageSessionCallback<SmbFile, ?> messageSessionCallback) {
|
||||
|
||||
return new SmbOutboundGatewaySpec(new SmbOutboundGateway(sessionFactory, messageSessionCallback));
|
||||
}
|
||||
|
||||
private Smb() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.dsl;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.springframework.integration.file.dsl.RemoteFileInboundChannelAdapterSpec;
|
||||
import org.springframework.integration.file.filters.CompositeFileListFilter;
|
||||
import org.springframework.integration.file.filters.FileListFilter;
|
||||
import org.springframework.integration.file.remote.session.SessionFactory;
|
||||
import org.springframework.integration.metadata.SimpleMetadataStore;
|
||||
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.SmbInboundFileSynchronizer;
|
||||
import org.springframework.integration.smb.inbound.SmbInboundFileSynchronizingMessageSource;
|
||||
|
||||
import jcifs.smb.SmbFile;
|
||||
|
||||
/**
|
||||
* A {@link RemoteFileInboundChannelAdapterSpec} for an {@link SmbInboundFileSynchronizingMessageSource}.
|
||||
*
|
||||
* @author Gregory Bragg
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public class SmbInboundChannelAdapterSpec
|
||||
extends RemoteFileInboundChannelAdapterSpec<SmbFile, SmbInboundChannelAdapterSpec,
|
||||
SmbInboundFileSynchronizingMessageSource> {
|
||||
|
||||
protected SmbInboundChannelAdapterSpec(SessionFactory<SmbFile> sessionFactory, Comparator<File> comparator) {
|
||||
super(new SmbInboundFileSynchronizer(sessionFactory));
|
||||
this.target = new SmbInboundFileSynchronizingMessageSource(this.synchronizer, comparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a simple pattern to match remote files.
|
||||
* @param pattern the pattern.
|
||||
* @see SmbSimplePatternFileListFilter
|
||||
* @see #filter(org.springframework.integration.file.filters.FileListFilter)
|
||||
*/
|
||||
@Override
|
||||
public SmbInboundChannelAdapterSpec patternFilter(String pattern) {
|
||||
return filter(composeFilters(new SmbSimplePatternFileListFilter(pattern)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a regular expression to match remote files.
|
||||
* @param regex the expression.
|
||||
* @see SmbRegexPatternFileListFilter
|
||||
* @see #filter(org.springframework.integration.file.filters.FileListFilter)
|
||||
*/
|
||||
@Override
|
||||
public SmbInboundChannelAdapterSpec regexFilter(String regex) {
|
||||
return filter(composeFilters(new SmbRegexPatternFileListFilter(regex)));
|
||||
}
|
||||
|
||||
private CompositeFileListFilter<SmbFile> composeFilters(FileListFilter<SmbFile> fileListFilter) {
|
||||
CompositeFileListFilter<SmbFile> compositeFileListFilter = new CompositeFileListFilter<>();
|
||||
compositeFileListFilter.addFilters(fileListFilter,
|
||||
new SmbPersistentAcceptOnceFileListFilter(new SimpleMetadataStore(), "smbMessageSource"));
|
||||
return compositeFileListFilter;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.dsl;
|
||||
|
||||
import org.springframework.integration.file.dsl.FileTransferringMessageHandlerSpec;
|
||||
import org.springframework.integration.file.remote.session.SessionFactory;
|
||||
import org.springframework.integration.file.support.FileExistsMode;
|
||||
import org.springframework.integration.smb.outbound.SmbMessageHandler;
|
||||
import org.springframework.integration.smb.session.SmbRemoteFileTemplate;
|
||||
|
||||
import jcifs.smb.SmbFile;
|
||||
|
||||
/**
|
||||
* A {@link FileTransferringMessageHandlerSpec} for SMB.
|
||||
*
|
||||
* @author Gregory Bragg
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public class SmbMessageHandlerSpec extends FileTransferringMessageHandlerSpec<SmbFile, SmbMessageHandlerSpec> {
|
||||
|
||||
protected SmbMessageHandlerSpec(SessionFactory<SmbFile> sessionFactory) {
|
||||
this.target = new SmbMessageHandler(sessionFactory);
|
||||
}
|
||||
|
||||
protected SmbMessageHandlerSpec(SmbRemoteFileTemplate smbRemoteFileTemplate) {
|
||||
this.target = new SmbMessageHandler(smbRemoteFileTemplate);
|
||||
}
|
||||
|
||||
protected SmbMessageHandlerSpec(SmbRemoteFileTemplate smbRemoteFileTemplate, FileExistsMode fileExistsMode) {
|
||||
this.target = new SmbMessageHandler(smbRemoteFileTemplate, fileExistsMode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.dsl;
|
||||
|
||||
import org.springframework.integration.file.dsl.RemoteFileOutboundGatewaySpec;
|
||||
import org.springframework.integration.smb.filters.SmbRegexPatternFileListFilter;
|
||||
import org.springframework.integration.smb.filters.SmbSimplePatternFileListFilter;
|
||||
import org.springframework.integration.smb.outbound.SmbOutboundGateway;
|
||||
|
||||
import jcifs.smb.SmbFile;
|
||||
|
||||
/**
|
||||
* A {@link RemoteFileOutboundGatewaySpec} for SMB.
|
||||
*
|
||||
* @author Gregory Bragg
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public class SmbOutboundGatewaySpec extends RemoteFileOutboundGatewaySpec<SmbFile, SmbOutboundGatewaySpec> {
|
||||
|
||||
protected SmbOutboundGatewaySpec(SmbOutboundGateway outboundGateway) {
|
||||
super(outboundGateway);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see SmbSimplePatternFileListFilter
|
||||
*/
|
||||
@Override
|
||||
public SmbOutboundGatewaySpec patternFileNameFilter(String pattern) {
|
||||
return filter(new SmbSimplePatternFileListFilter(pattern));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see SmbRegexPatternFileListFilter
|
||||
*/
|
||||
@Override
|
||||
public SmbOutboundGatewaySpec regexFileNameFilter(String regex) {
|
||||
return filter(new SmbRegexPatternFileListFilter(regex));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.dsl;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.springframework.integration.file.dsl.RemoteFileStreamingInboundChannelAdapterSpec;
|
||||
import org.springframework.integration.file.filters.CompositeFileListFilter;
|
||||
import org.springframework.integration.file.filters.FileListFilter;
|
||||
import org.springframework.integration.file.remote.RemoteFileTemplate;
|
||||
import org.springframework.integration.metadata.SimpleMetadataStore;
|
||||
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 jcifs.smb.SmbFile;
|
||||
|
||||
/**
|
||||
* A {@link RemoteFileStreamingInboundChannelAdapterSpec} for a {@link SmbStreamingMessageSource}.
|
||||
*
|
||||
* @author Gregory Bragg
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public class SmbStreamingInboundChannelAdapterSpec
|
||||
extends RemoteFileStreamingInboundChannelAdapterSpec<SmbFile, SmbStreamingInboundChannelAdapterSpec,
|
||||
SmbStreamingMessageSource> {
|
||||
|
||||
protected SmbStreamingInboundChannelAdapterSpec(RemoteFileTemplate<SmbFile> remoteFileTemplate,
|
||||
Comparator<SmbFile> comparator) {
|
||||
|
||||
this.target = new SmbStreamingMessageSource(remoteFileTemplate, comparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a simple pattern to match remote files (e.g. '*.txt').
|
||||
* @param pattern the pattern.
|
||||
* @see SmbSimplePatternFileListFilter
|
||||
* @see #filter(org.springframework.integration.file.filters.FileListFilter)
|
||||
*/
|
||||
@Override
|
||||
public SmbStreamingInboundChannelAdapterSpec patternFilter(String pattern) {
|
||||
return filter(composeFilters(new SmbSimplePatternFileListFilter(pattern)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a regular expression to match remote files (e.g. '[0-9].*.txt').
|
||||
* @param regex the expression.
|
||||
* @see SmbRegexPatternFileListFilter
|
||||
* @see #filter(org.springframework.integration.file.filters.FileListFilter)
|
||||
*/
|
||||
@Override
|
||||
public SmbStreamingInboundChannelAdapterSpec regexFilter(String regex) {
|
||||
return filter(composeFilters(new SmbRegexPatternFileListFilter(regex)));
|
||||
}
|
||||
|
||||
private CompositeFileListFilter<SmbFile> composeFilters(FileListFilter<SmbFile> fileListFilter) {
|
||||
CompositeFileListFilter<SmbFile> compositeFileListFilter = new CompositeFileListFilter<>();
|
||||
compositeFileListFilter.addFilters(fileListFilter,
|
||||
new SmbPersistentAcceptOnceFileListFilter(new SimpleMetadataStore(), "smbStreamingMessageSource"));
|
||||
return compositeFileListFilter;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Provides SMB Components for the Java DSL.
|
||||
*/
|
||||
package org.springframework.integration.smb.dsl;
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.inbound;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.integration.file.remote.AbstractFileInfo;
|
||||
import org.springframework.integration.file.remote.AbstractRemoteFileStreamingMessageSource;
|
||||
import org.springframework.integration.file.remote.RemoteFileTemplate;
|
||||
import org.springframework.integration.metadata.SimpleMetadataStore;
|
||||
import org.springframework.integration.smb.filters.SmbPersistentAcceptOnceFileListFilter;
|
||||
import org.springframework.integration.smb.session.SmbFileInfo;
|
||||
|
||||
import jcifs.smb.SmbException;
|
||||
import jcifs.smb.SmbFile;
|
||||
|
||||
/**
|
||||
* Message source for streaming SMB remote file contents.
|
||||
*
|
||||
* @author Gregory Bragg
|
||||
*
|
||||
* @since 6.0
|
||||
*
|
||||
*/
|
||||
public class SmbStreamingMessageSource extends AbstractRemoteFileStreamingMessageSource<SmbFile> {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SmbStreamingMessageSource.class);
|
||||
|
||||
/**
|
||||
* Construct an instance with the supplied template.
|
||||
* @param template the template.
|
||||
*/
|
||||
public SmbStreamingMessageSource(RemoteFileTemplate<SmbFile> template) {
|
||||
this(template, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance with the supplied template and comparator.
|
||||
* Note: the comparator is applied each time the remote directory is listed
|
||||
* which only occurs when the previous list is exhausted.
|
||||
* @param template the template.
|
||||
* @param comparator the comparator.
|
||||
*/
|
||||
public SmbStreamingMessageSource(RemoteFileTemplate<SmbFile> template, Comparator<SmbFile> comparator) {
|
||||
super(template, comparator);
|
||||
doSetFilter(new SmbPersistentAcceptOnceFileListFilter(new SimpleMetadataStore(), "smbStreamingMessageSource"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComponentType() {
|
||||
return "smb:inbound-streaming-channel-adapter";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractFileInfo<SmbFile>> asFileInfoList(Collection<SmbFile> files) {
|
||||
List<AbstractFileInfo<SmbFile>> canonicalFiles = new ArrayList<>();
|
||||
for (SmbFile file : files) {
|
||||
canonicalFiles.add(new SmbFileInfo(file));
|
||||
}
|
||||
return canonicalFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDirectory(SmbFile file) {
|
||||
try {
|
||||
return file != null && file.isDirectory();
|
||||
}
|
||||
catch (SmbException se) {
|
||||
logger.error("Unable to determine if this SmbFile represents a directory", se);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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.outbound;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.integration.file.remote.AbstractFileInfo;
|
||||
import org.springframework.integration.file.remote.MessageSessionCallback;
|
||||
import org.springframework.integration.file.remote.RemoteFileTemplate;
|
||||
import org.springframework.integration.file.remote.gateway.AbstractRemoteFileOutboundGateway;
|
||||
import org.springframework.integration.file.remote.session.SessionFactory;
|
||||
import org.springframework.integration.smb.session.SmbFileInfo;
|
||||
import org.springframework.integration.smb.session.SmbRemoteFileTemplate;
|
||||
|
||||
import jcifs.smb.SmbException;
|
||||
import jcifs.smb.SmbFile;
|
||||
|
||||
/**
|
||||
* Outbound Gateway for performing remote file operations via SMB.
|
||||
*
|
||||
* @author Gregory Bragg
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public class SmbOutboundGateway extends AbstractRemoteFileOutboundGateway<SmbFile> {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SmbOutboundGateway.class);
|
||||
|
||||
/**
|
||||
* Construct an instance using the provided session factory and callback for
|
||||
* performing operations on the session.
|
||||
* @param sessionFactory the session factory.
|
||||
* @param messageSessionCallback the callback.
|
||||
*/
|
||||
public SmbOutboundGateway(SessionFactory<SmbFile> sessionFactory,
|
||||
MessageSessionCallback<SmbFile, ?> messageSessionCallback) {
|
||||
|
||||
this(new SmbRemoteFileTemplate(sessionFactory), messageSessionCallback);
|
||||
remoteFileTemplateExplicitlySet(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance with the supplied remote file template and callback
|
||||
* for performing operations on the session.
|
||||
* @param remoteFileTemplate the remote file template.
|
||||
* @param messageSessionCallback the callback.
|
||||
*/
|
||||
public SmbOutboundGateway(RemoteFileTemplate<SmbFile> remoteFileTemplate,
|
||||
MessageSessionCallback<SmbFile, ?> messageSessionCallback) {
|
||||
|
||||
super(remoteFileTemplate, messageSessionCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComponentType() {
|
||||
return "smb:outbound-gateway";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDirectory(SmbFile file) {
|
||||
try {
|
||||
return file.isDirectory();
|
||||
}
|
||||
catch (SmbException se) {
|
||||
logger.error("Unable to determine if this SmbFile represents a directory", se);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Symbolic links are currently not supported in the JCIFS v2.x.x
|
||||
* dependent library, so this method will always return false.
|
||||
* @return false
|
||||
*/
|
||||
@Override
|
||||
protected boolean isLink(SmbFile file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFilename(SmbFile file) {
|
||||
return file.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFilename(AbstractFileInfo<SmbFile> file) {
|
||||
return file.getFilename();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getModified(SmbFile file) {
|
||||
return file.getLastModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractFileInfo<SmbFile>> asFileInfoList(Collection<SmbFile> files) {
|
||||
List<AbstractFileInfo<SmbFile>> canonicalFiles = new ArrayList<>();
|
||||
for (SmbFile file : files) {
|
||||
canonicalFiles.add(new SmbFileInfo(file));
|
||||
}
|
||||
return canonicalFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmbFile enhanceNameWithSubDirectory(SmbFile file, String directory) {
|
||||
try {
|
||||
file.renameTo(new SmbFile(file, directory), true);
|
||||
return file;
|
||||
}
|
||||
catch (SmbException | MalformedURLException | UnknownHostException e) {
|
||||
logger.error("Unable to enhance file name with a sub directory path", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.session;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.integration.file.remote.AbstractFileInfo;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import jcifs.internal.dtyp.ACE;
|
||||
import jcifs.smb.SmbException;
|
||||
import jcifs.smb.SmbFile;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.integration.file.remote.FileInfo} implementation for
|
||||
* SMB.
|
||||
*
|
||||
* @author Gregory Bragg
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public class SmbFileInfo extends AbstractFileInfo<SmbFile> {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SmbFileInfo.class);
|
||||
|
||||
private final SmbFile smbFile;
|
||||
|
||||
public SmbFileInfo(SmbFile smbFile) {
|
||||
Assert.notNull(smbFile, "SmbFile must not be null");
|
||||
this.smbFile = smbFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory() {
|
||||
try {
|
||||
return this.smbFile.isDirectory();
|
||||
}
|
||||
catch (SmbException se) {
|
||||
logger.error("Unable to determine if this SmbFile represents a directory", se);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Symbolic links are currently not supported in the JCIFS v2.x.x
|
||||
* dependent library, so this method will always return false.
|
||||
* @return false
|
||||
*/
|
||||
@Override
|
||||
public boolean isLink() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
try {
|
||||
return this.smbFile.length();
|
||||
}
|
||||
catch (SmbException se) {
|
||||
logger.error("Unable to determine file size", se);
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getModified() {
|
||||
return this.smbFile.getLastModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return this.smbFile.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* An Access Control Entry (ACE) is an element in a security descriptor
|
||||
* such as those associated with files and directories. The Windows OS
|
||||
* determines which users have the necessary permissions to access objects
|
||||
* based on these entries.
|
||||
* @return a list of Access Control Entry (ACE) objects representing
|
||||
* the security descriptor associated with this file or directory.
|
||||
*/
|
||||
@Override
|
||||
public String getPermissions() {
|
||||
ACE[] aceArray = null;
|
||||
try {
|
||||
aceArray = this.smbFile.getSecurity(true);
|
||||
}
|
||||
catch (IOException se) {
|
||||
logger.error("Unable to determine security descriptor information for this SmbFile", se);
|
||||
}
|
||||
return (aceArray == null) ? null : Arrays.toString(aceArray);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmbFile getFileInfo() {
|
||||
return this.smbFile;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
|
||||
import org.springframework.integration.file.remote.RemoteFileTestSupport;
|
||||
import org.springframework.integration.file.remote.session.CachingSessionFactory;
|
||||
import org.springframework.integration.file.remote.session.SessionFactory;
|
||||
import org.springframework.integration.smb.session.SmbSessionFactory;
|
||||
|
||||
import jcifs.DialectVersion;
|
||||
import jcifs.smb.SmbFile;
|
||||
|
||||
/**
|
||||
* Provides a connection to an external SMB Server for test cases.
|
||||
*
|
||||
* The constants need to be updated with the 'real' server settings for testing.
|
||||
*
|
||||
* @author Gregory Bragg
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
|
||||
@Disabled("Actual SMB share must be configured in class [SmbTestSupport].")
|
||||
public class SmbTestSupport extends RemoteFileTestSupport {
|
||||
|
||||
public static final String HOST = "localhost";
|
||||
|
||||
public static final String SHARE_AND_DIR = "smb-share/";
|
||||
|
||||
public static final String USERNAME = "sambaguest";
|
||||
|
||||
public static final String PASSWORD = "sambaguest";
|
||||
|
||||
private static SmbSessionFactory smbSessionFactory;
|
||||
|
||||
@BeforeAll
|
||||
public static void connectToSMBServer() {
|
||||
smbSessionFactory = new SmbSessionFactory();
|
||||
smbSessionFactory.setHost(HOST);
|
||||
smbSessionFactory.setUsername(USERNAME);
|
||||
smbSessionFactory.setPassword(PASSWORD);
|
||||
smbSessionFactory.setShareAndDir(SHARE_AND_DIR);
|
||||
smbSessionFactory.setSmbMinVersion(DialectVersion.SMB210);
|
||||
smbSessionFactory.setSmbMaxVersion(DialectVersion.SMB311);
|
||||
}
|
||||
|
||||
public static SessionFactory<SmbFile> sessionFactory() {
|
||||
return new CachingSessionFactory<>(smbSessionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String prefix() {
|
||||
return "smb";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* 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.dsl;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.IntegrationMessageHeaderAccessor;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.config.EnableIntegration;
|
||||
import org.springframework.integration.config.EnableIntegrationManagement;
|
||||
import org.springframework.integration.config.IntegrationManagementConfigurer;
|
||||
import org.springframework.integration.core.MessageSource;
|
||||
import org.springframework.integration.dsl.IntegrationFlow;
|
||||
import org.springframework.integration.dsl.IntegrationFlows;
|
||||
import org.springframework.integration.dsl.Pollers;
|
||||
import org.springframework.integration.dsl.StandardIntegrationFlow;
|
||||
import org.springframework.integration.dsl.context.IntegrationFlowContext;
|
||||
import org.springframework.integration.dsl.context.IntegrationFlowContext.IntegrationFlowRegistration;
|
||||
import org.springframework.integration.file.DefaultDirectoryScanner;
|
||||
import org.springframework.integration.file.DirectoryScanner;
|
||||
import org.springframework.integration.file.FileHeaders;
|
||||
import org.springframework.integration.file.remote.RemoteFileTemplate;
|
||||
import org.springframework.integration.file.support.FileExistsMode;
|
||||
import org.springframework.integration.smb.SmbTestSupport;
|
||||
import org.springframework.integration.smb.inbound.SmbInboundFileSynchronizingMessageSource;
|
||||
import org.springframework.integration.smb.inbound.SmbStreamingMessageSource;
|
||||
import org.springframework.integration.smb.session.SmbRemoteFileTemplate;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import jcifs.smb.SmbException;
|
||||
import jcifs.smb.SmbFile;
|
||||
|
||||
/**
|
||||
* The actual SMB share must be configured in class 'SmbTestSupport'
|
||||
* with the 'real' server settings for testing.
|
||||
*
|
||||
* You must create the following folder structures in your SMB share
|
||||
* for a successful completion of these unit tests:
|
||||
*
|
||||
* <pre class="code">
|
||||
* smbSource/
|
||||
* |-- smbSource1.txt - contains 'source1'
|
||||
* |-- smbSource2.txt - contains 'source2'
|
||||
* |-- SMBSOURCE1.TXT.a
|
||||
* |-- SMBSOURCE2.TXT.a
|
||||
* |-- subSmbSource/
|
||||
* |-- subSmbSource1.txt - contains 'subSource1'
|
||||
* smbTarget/
|
||||
* </pre>
|
||||
*
|
||||
* The intent is tests retrieve from smbSource and verify arrival in localTarget or
|
||||
* send from localSource and verify arrival in remoteTarget.
|
||||
*
|
||||
* @author Gregory Bragg
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
|
||||
@SpringJUnitConfig
|
||||
@DirtiesContext
|
||||
@Disabled("Actual SMB share must be configured in class [SmbTestSupport].")
|
||||
public class SmbTests extends SmbTestSupport {
|
||||
|
||||
@Autowired
|
||||
private IntegrationFlowContext flowContext;
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
private IntegrationManagementConfigurer integrationManagementConfigurer;
|
||||
|
||||
@Test
|
||||
public void testSmbInboundFlow() throws IOException {
|
||||
QueueChannel out = new QueueChannel();
|
||||
DirectoryScanner scanner = new DefaultDirectoryScanner();
|
||||
IntegrationFlow flow = IntegrationFlows.from(Smb.inboundAdapter(sessionFactory())
|
||||
.preserveTimestamp(true)
|
||||
.remoteDirectory("smbSource")
|
||||
.maxFetchSize(10)
|
||||
.scanner(scanner)
|
||||
.regexFilter(".*\\.txt$")
|
||||
.localFilename(f -> f.toUpperCase() + ".a")
|
||||
.localDirectory(getTargetLocalDirectory()),
|
||||
e -> e.id("smbInboundAdapter").poller(Pollers.fixedDelay(100)))
|
||||
.channel(out)
|
||||
.get();
|
||||
IntegrationFlowRegistration registration = this.flowContext.registration(flow).register();
|
||||
Map<?, ?> components =
|
||||
TestUtils.getPropertyValue(registration, "integrationFlow.integrationComponents", Map.class);
|
||||
Iterator<?> iterator = components.keySet().iterator();
|
||||
iterator.next();
|
||||
Object spcafb = iterator.next();
|
||||
assertThat(TestUtils.getPropertyValue(spcafb, "source.fileSource.scanner")).isSameAs(scanner);
|
||||
Message<?> message = out.receive(10_000);
|
||||
assertThat(message).isNotNull();
|
||||
assertThat(message.getHeaders())
|
||||
.containsKeys(FileHeaders.REMOTE_HOST_PORT, FileHeaders.REMOTE_DIRECTORY, FileHeaders.REMOTE_FILE);
|
||||
Object payload = message.getPayload();
|
||||
assertThat(payload).isInstanceOf(File.class);
|
||||
File file = (File) payload;
|
||||
assertThat(file.getName()).isIn("SMBSOURCE1.TXT.a", "SMBSOURCE2.TXT.a");
|
||||
assertThat(file.getAbsolutePath()).contains("localTarget");
|
||||
|
||||
message = out.receive(10_000);
|
||||
assertThat(message).isNotNull();
|
||||
file = (File) message.getPayload();
|
||||
assertThat(file.getName()).isIn("SMBSOURCE1.TXT.a", "SMBSOURCE2.TXT.a");
|
||||
assertThat(file.getAbsolutePath()).contains("localTarget");
|
||||
|
||||
assertThat(out.receive(10)).isNull();
|
||||
|
||||
MessageSource<?> source = context.getBean(SmbInboundFileSynchronizingMessageSource.class);
|
||||
assertThat(TestUtils.getPropertyValue(source, "maxFetchSize")).isEqualTo(10);
|
||||
|
||||
registration.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmbInboundStreamFlow() throws Exception {
|
||||
QueueChannel out = new QueueChannel();
|
||||
StandardIntegrationFlow flow = IntegrationFlows.from(
|
||||
Smb.inboundStreamingAdapter(new SmbRemoteFileTemplate(sessionFactory()))
|
||||
.remoteDirectory("smbSource")
|
||||
.maxFetchSize(11)
|
||||
.regexFilter(".*\\.txt$"),
|
||||
e -> e.id("smbInboundAdapter").poller(Pollers.fixedDelay(100)))
|
||||
.channel(out)
|
||||
.get();
|
||||
IntegrationFlowRegistration registration = this.flowContext.registration(flow).register();
|
||||
Message<?> message = out.receive(10_000);
|
||||
assertThat(message).isNotNull();
|
||||
assertThat(message.getPayload()).isInstanceOf(InputStream.class);
|
||||
assertThat(message.getHeaders().get(FileHeaders.REMOTE_FILE)).isIn("smbSource1.txt", "smbSource2.txt");
|
||||
assertThat(message.getHeaders().get(
|
||||
FileHeaders.REMOTE_HOST_PORT, String.class)).contains(sessionFactory().getSession().getHostPort());
|
||||
new IntegrationMessageHeaderAccessor(message).getCloseableResource().close();
|
||||
|
||||
message = out.receive(10_000);
|
||||
assertThat(message).isNotNull();
|
||||
assertThat(message.getPayload()).isInstanceOf(InputStream.class);
|
||||
assertThat(message.getHeaders().get(FileHeaders.REMOTE_FILE)).isIn("smbSource1.txt", "smbSource2.txt");
|
||||
new IntegrationMessageHeaderAccessor(message).getCloseableResource().close();
|
||||
|
||||
MessageSource<?> source = context.getBean(SmbStreamingMessageSource.class);
|
||||
assertThat(TestUtils.getPropertyValue(source, "maxFetchSize")).isEqualTo(11);
|
||||
registration.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmbOutboundFlow() {
|
||||
IntegrationFlow flow = f -> f
|
||||
.handle(Smb.outboundAdapter(sessionFactory(), FileExistsMode.REPLACE)
|
||||
.useTemporaryFileName(false)
|
||||
.fileNameExpression("headers['" + FileHeaders.FILENAME + "']")
|
||||
.remoteDirectory("smbTarget"));
|
||||
IntegrationFlowRegistration registration = this.flowContext.registration(flow).register();
|
||||
String fileName = "foo.file";
|
||||
Message<ByteArrayInputStream> message = MessageBuilder
|
||||
.withPayload(new ByteArrayInputStream("foo".getBytes(StandardCharsets.UTF_8)))
|
||||
.setHeader(FileHeaders.FILENAME, fileName)
|
||||
.build();
|
||||
registration.getInputChannel().send(message);
|
||||
RemoteFileTemplate<SmbFile> template = new RemoteFileTemplate<>(sessionFactory());
|
||||
SmbFile[] files = template.execute(session ->
|
||||
session.list(getTargetRemoteDirectory().getName()));
|
||||
assertThat(files.length).isEqualTo(1);
|
||||
try {
|
||||
assertThat(files[0].length()).isEqualTo(3);
|
||||
}
|
||||
catch (SmbException se) {
|
||||
se.printStackTrace();
|
||||
}
|
||||
|
||||
registration.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmbOutboundFlowWithSmbRemoteTemplate() {
|
||||
|
||||
SmbRemoteFileTemplate smbTemplate = new SmbRemoteFileTemplate(sessionFactory());
|
||||
IntegrationFlow flow = f -> f
|
||||
.handle(Smb.outboundAdapter(smbTemplate)
|
||||
.useTemporaryFileName(false)
|
||||
.fileNameExpression("headers['" + FileHeaders.FILENAME + "']")
|
||||
.remoteDirectory("smbTarget"));
|
||||
IntegrationFlowRegistration registration = this.flowContext.registration(flow).register();
|
||||
String fileName = "foo.file";
|
||||
Message<ByteArrayInputStream> message = MessageBuilder
|
||||
.withPayload(new ByteArrayInputStream("foo".getBytes(StandardCharsets.UTF_8)))
|
||||
.setHeader(FileHeaders.FILENAME, fileName)
|
||||
.build();
|
||||
registration.getInputChannel().send(message);
|
||||
SmbFile[] files = smbTemplate.execute(session ->
|
||||
session.list(getTargetRemoteDirectory().getName()));
|
||||
assertThat(files.length).isEqualTo(1);
|
||||
try {
|
||||
assertThat(files[0].length()).isEqualTo(3);
|
||||
}
|
||||
catch (SmbException se) {
|
||||
se.printStackTrace();
|
||||
}
|
||||
|
||||
registration.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmbOutboundFlowWithSmbRemoteTemplateAndMode() {
|
||||
|
||||
SmbRemoteFileTemplate smbTemplate = new SmbRemoteFileTemplate(sessionFactory());
|
||||
IntegrationFlow flow = f -> f
|
||||
.handle(Smb.outboundAdapter(smbTemplate, FileExistsMode.APPEND)
|
||||
.useTemporaryFileName(false)
|
||||
.fileNameExpression("headers['" + FileHeaders.FILENAME + "']")
|
||||
.remoteDirectory("smbTarget"));
|
||||
IntegrationFlowRegistration registration = this.flowContext.registration(flow).register();
|
||||
String fileName = "foo.file";
|
||||
Message<ByteArrayInputStream> message1 = MessageBuilder
|
||||
.withPayload(new ByteArrayInputStream("foo".getBytes(StandardCharsets.UTF_8)))
|
||||
.setHeader(FileHeaders.FILENAME, fileName)
|
||||
.build();
|
||||
Message<ByteArrayInputStream> message2 = MessageBuilder
|
||||
.withPayload(new ByteArrayInputStream("foo".getBytes(StandardCharsets.UTF_8)))
|
||||
.setHeader(FileHeaders.FILENAME, fileName)
|
||||
.build();
|
||||
registration.getInputChannel().send(message1);
|
||||
registration.getInputChannel().send(message2);
|
||||
SmbFile[] files = smbTemplate.execute(session ->
|
||||
session.list(getTargetRemoteDirectory().getName()));
|
||||
assertThat(files.length).isEqualTo(1);
|
||||
try {
|
||||
assertThat(files[0].length()).isEqualTo(9);
|
||||
}
|
||||
catch (SmbException se) {
|
||||
se.printStackTrace();
|
||||
}
|
||||
|
||||
registration.destroy();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableIntegration
|
||||
@EnableIntegrationManagement
|
||||
public static class ContextConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -122,6 +122,55 @@ public MessageSource<File> smbMessageSource() {
|
||||
|
||||
For XML configuration the `<int-smb:inbound-channel-adapter>` component is provided.
|
||||
|
||||
==== Configuring with the Java DSL
|
||||
|
||||
The following Spring Boot application shows an example of how to configure the inbound adapter with the Java DSL:
|
||||
|
||||
====
|
||||
[source, java]
|
||||
----
|
||||
@SpringBootApplication
|
||||
public class SmbJavaApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(SmbJavaApplication.class)
|
||||
.web(false)
|
||||
.run(args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SmbSessionFactory smbSessionFactory() {
|
||||
SmbSessionFactory smbSession = new SmbSessionFactory();
|
||||
smbSession.setHost("myHost");
|
||||
smbSession.setPort(445);
|
||||
smbSession.setDomain("myDomain");
|
||||
smbSession.setUsername("myUser");
|
||||
smbSession.setPassword("myPassword");
|
||||
smbSession.setShareAndDir("myShareAndDir");
|
||||
smbSession.setSmbMinVersion(DialectVersion.SMB210);
|
||||
smbSession.setSmbMaxVersion(DialectVersion.SMB311);
|
||||
return smbSession;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow smbInboundFlow() {
|
||||
return IntegrationFlows
|
||||
.from(Smb.inboundAdapter(smbSessionFactory())
|
||||
.preserveTimestamp(true)
|
||||
.remoteDirectory("smbSource")
|
||||
.regexFilter(".*\\.txt$")
|
||||
.localFilename(f -> f.toUpperCase() + ".a")
|
||||
.localDirectory(new File("d:\\smb_files")),
|
||||
e -> e.id("smbInboundAdapter")
|
||||
.autoStartup(true)
|
||||
.poller(Pollers.fixedDelay(5000)))
|
||||
.handle(m -> System.out.println(m.getPayload()))
|
||||
.get();
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
[[smb-outbound]]
|
||||
=== SMB Outbound Channel Adapter
|
||||
|
||||
@@ -142,3 +191,58 @@ public MessageHandler smbMessageHandler(SmbSessionFactory smbSessionFactory) {
|
||||
return handler;
|
||||
}
|
||||
----
|
||||
|
||||
==== Configuring with the Java DSL
|
||||
|
||||
The following Spring Boot application shows an example of how to configure the outbound adapter using the Java DSL:
|
||||
|
||||
====
|
||||
[source, java]
|
||||
----
|
||||
@SpringBootApplication
|
||||
@IntegrationComponentScan
|
||||
public class SmbJavaApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
ConfigurableApplicationContext context =
|
||||
new SpringApplicationBuilder(SmbJavaApplication.class)
|
||||
.web(false)
|
||||
.run(args);
|
||||
MyGateway gateway = context.getBean(MyGateway.class);
|
||||
gateway.sendToSmb(new File("/foo/bar.txt"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SmbSessionFactory smbSessionFactory() {
|
||||
SmbSessionFactory smbSession = new SmbSessionFactory();
|
||||
smbSession.setHost("myHost");
|
||||
smbSession.setPort(445);
|
||||
smbSession.setDomain("myDomain");
|
||||
smbSession.setUsername("myUser");
|
||||
smbSession.setPassword("myPassword");
|
||||
smbSession.setShareAndDir("myShareAndDir");
|
||||
smbSession.setSmbMinVersion(DialectVersion.SMB210);
|
||||
smbSession.setSmbMaxVersion(DialectVersion.SMB311);
|
||||
return smbSession;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow smbOutboundFlow() {
|
||||
return IntegrationFlows.from("toSmbChannel")
|
||||
.handle(Smb.outboundAdapter(smbSessionFactory(), FileExistsMode.REPLACE)
|
||||
.useTemporaryFileName(false)
|
||||
.fileNameExpression("headers['" + FileHeaders.FILENAME + "']")
|
||||
.remoteDirectory("smbTarget")
|
||||
).get();
|
||||
}
|
||||
|
||||
@MessagingGateway
|
||||
public interface MyGateway {
|
||||
|
||||
@Gateway(requestChannel = "toSmbChannel")
|
||||
void sendToSmb(File file);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
@@ -26,7 +26,9 @@ See <<./graphql.adoc#graphql,GraphQL Support>> for more information.
|
||||
[[x6.0-smb]]
|
||||
=== SMB Support
|
||||
|
||||
SMB support has been added from the Spring Integration Extensions project.
|
||||
SMB support has been added from the Spring Integration Extensions project, including support for Java .
|
||||
The Java DSL (see `org.springframework.integration.smb.dsl.Smb` factory) also has been added to this module.
|
||||
An `SmbStreamingMessageSource` and `SmbOutboundGateway` implementation are introduced.
|
||||
See <<./smb.adoc#smb,SMB Support>> for more information.
|
||||
|
||||
[[x6.0-general]]
|
||||
|
||||
Reference in New Issue
Block a user