diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java index eeff5a674d1..fbda6efd0a7 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java @@ -34,8 +34,10 @@ import org.springframework.integration.file.DefaultFileNameGenerator; import org.springframework.integration.file.FileNameGenerator; import org.springframework.integration.file.remote.session.CachingSessionFactory; +import org.springframework.integration.file.remote.session.DefaultSessionFactoryResolver; import org.springframework.integration.file.remote.session.Session; import org.springframework.integration.file.remote.session.SessionFactory; +import org.springframework.integration.file.remote.session.SessionFactoryResolver; import org.springframework.integration.file.support.FileExistsMode; import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor; import org.springframework.messaging.Message; @@ -61,7 +63,7 @@ public class RemoteFileTemplate implements RemoteFileOperations, Initializ /** * the {@link SessionFactory} for acquiring remote file Sessions. */ - protected final SessionFactory sessionFactory; + protected SessionFactory sessionFactory; private volatile String temporaryFileSuffix =".writing"; @@ -87,9 +89,22 @@ public class RemoteFileTemplate implements RemoteFileOperations, Initializ private volatile BeanFactory beanFactory; + private final SessionFactoryResolver resolver; + public RemoteFileTemplate(SessionFactory sessionFactory) { Assert.notNull(sessionFactory, "sessionFactory must not be null"); this.sessionFactory = sessionFactory; + resolver = null; + } + + public RemoteFileTemplate(SessionFactoryResolver resolver) { + if(resolver == null) { + this.resolver = new DefaultSessionFactoryResolver(); + } + else { + this.resolver = resolver; + } + sessionFactory = null; } public void setAutoCreateDirectory(boolean autoCreateDirectory) { @@ -200,6 +215,12 @@ public String send(final Message message, String subDirectory, FileExistsMode } private String send(final Message message, final String subDirectory, final FileExistsMode mode) { + if(resolver != null) { + SessionFactory tmpSessionFactory = this.resolver.resolve(message); + if(tmpSessionFactory != null) { + this.sessionFactory = tmpSessionFactory; + } + } Assert.notNull(this.directoryExpressionProcessor, "'remoteDirectoryExpression' is required"); Assert.isTrue(!FileExistsMode.APPEND.equals(mode) || !this.useTemporaryFileName, "Cannot append when using a temporary file name"); diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/DefaultSessionFactoryResolver.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/DefaultSessionFactoryResolver.java new file mode 100644 index 00000000000..a82f591bef3 --- /dev/null +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/DefaultSessionFactoryResolver.java @@ -0,0 +1,75 @@ +/* + * Copyright 2014 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.remote.session; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.SpelParserConfiguration; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.integration.expression.IntegrationEvaluationContextAware; +import org.springframework.messaging.Message; + +/** + * Default {@link SessionFactoryResolver}; Used to resolve sessionfactory from message sent + * containing sessionfactory bean name. + * + * @author David Liu + * @since 4.1 + * + */ +public class DefaultSessionFactoryResolver implements SessionFactoryResolver, BeanFactoryAware, IntegrationEvaluationContextAware{ + + private final static String SESSIONFACTORY = "headers['sessionFactory']"; + + private final ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(true, true)); + + private volatile Expression sessionFactoryExpression = expressionParser.parseExpression(SESSIONFACTORY); + + private volatile BeanFactory beanFactory; + + private EvaluationContext evaluationContext; + + public void setSessionFactory(String expression) { + this.sessionFactoryExpression = expressionParser.parseExpression(expression); + } + + @Override + public void setIntegrationEvaluationContext(EvaluationContext evaluationContext) { + this.evaluationContext = evaluationContext; + } + + @SuppressWarnings("unchecked") + @Override + public SessionFactory resolve(Message message) { + if(this.beanFactory != null) { + if(evaluationContext != null) { + return this.beanFactory.getBean(this.sessionFactoryExpression.getValue(evaluationContext, message, String.class), SessionFactory.class); + } + return this.beanFactory.getBean(this.sessionFactoryExpression.getValue(message, String.class), SessionFactory.class); + } + return null; + } + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = beanFactory; + } + +} diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/SessionFactoryResolver.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/SessionFactoryResolver.java new file mode 100644 index 00000000000..4495c6778fe --- /dev/null +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/SessionFactoryResolver.java @@ -0,0 +1,31 @@ +/* + * Copyright 2014 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.remote.session; + +import org.springframework.messaging.Message; + +/** + * A resolver to resolve sessionfactory from sending message + * + * @author David Liu + * @since 4.1 + * + */ +public interface SessionFactoryResolver { + + SessionFactory resolve(Message message); + +} diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplate.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplate.java index 2f0c61ffba4..1f2f64f4d1c 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplate.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplate.java @@ -25,6 +25,7 @@ import org.springframework.integration.file.remote.SessionCallback; import org.springframework.integration.file.remote.session.Session; import org.springframework.integration.file.remote.session.SessionFactory; +import org.springframework.integration.file.remote.session.SessionFactoryResolver; import org.springframework.messaging.MessagingException; /** @@ -40,6 +41,9 @@ public class FtpRemoteFileTemplate extends RemoteFileTemplate { public FtpRemoteFileTemplate(SessionFactory sessionFactory) { super(sessionFactory); } + public FtpRemoteFileTemplate(SessionFactoryResolver resolver) { + super(resolver); + } @SuppressWarnings("unchecked") @Override diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSessionFactoryResolver.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSessionFactoryResolver.java new file mode 100644 index 00000000000..88a9d292d8e --- /dev/null +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSessionFactoryResolver.java @@ -0,0 +1,94 @@ +/* + * Copyright 2014 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.ftp.session; + +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.SpelParserConfiguration; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.integration.expression.IntegrationEvaluationContextAware; +import org.springframework.integration.file.remote.session.SessionFactory; +import org.springframework.integration.file.remote.session.SessionFactoryResolver; +import org.springframework.messaging.Message; + +/** + * Ftp {@link SessionFactoryResolver}; Used to resolve sessionfactory from message sent + * containing host, username, password, name. + * + * @author David Liu + * @since 4.1 + * + */ +public class FtpSessionFactoryResolver implements SessionFactoryResolver, IntegrationEvaluationContextAware{ + + private final static String DEFAULT_HOST_EXPRESSION_STRING = "headers['ftp_host']"; + + private final static String DEFAULT_USER_EXPRESSION_STRING = "headers['ftp_username']"; + + private final static String DEFAULT_PASSWORD_EXPRESSION_STRING = "headers['ftp_password']"; + + private final static String DEFAULT_PORT_EXPRESSION_STRING = "headers['ftp_port']"; + + private final ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(true, true)); + + private volatile Expression headerExpression = expressionParser.parseExpression(DEFAULT_HOST_EXPRESSION_STRING); + + private volatile Expression userNameExpression = expressionParser.parseExpression(DEFAULT_USER_EXPRESSION_STRING); + + private volatile Expression passwordExpression = expressionParser.parseExpression(DEFAULT_PASSWORD_EXPRESSION_STRING); + + private volatile Expression portExpression = expressionParser.parseExpression(DEFAULT_PORT_EXPRESSION_STRING); + + private EvaluationContext evaluationContext; + + public void setHostExpression(String hostExpression) { + this.headerExpression = expressionParser.parseExpression(hostExpression); + } + + public void setUserNameExpression(String userExpression) { + this.userNameExpression = expressionParser.parseExpression(userExpression); + } + + public void setPasswordExpression(String passwordExpression) { + this.passwordExpression = expressionParser.parseExpression(passwordExpression); + } + + public void setPortExpression(String portExpression) { + this.portExpression = expressionParser.parseExpression(portExpression); + } + + @Override + public void setIntegrationEvaluationContext(EvaluationContext evaluationContext) { + this.evaluationContext = evaluationContext; + } + + @SuppressWarnings("unchecked") + @Override + public SessionFactory resolve(Message message) { + DefaultFtpSessionFactory sessionFactory = new DefaultFtpSessionFactory(); + sessionFactory.setHost(evaluationContext != null ? this.headerExpression.getValue(evaluationContext, message, String.class) + : this.headerExpression.getValue(message, String.class)); + sessionFactory.setUsername(evaluationContext != null ? this.userNameExpression.getValue(evaluationContext, message, String.class) + : this.userNameExpression.getValue(message, String.class)); + sessionFactory.setPassword(evaluationContext != null ? this.passwordExpression.getValue(evaluationContext, message, String.class) + : this.passwordExpression.getValue(message, String.class)); + sessionFactory.setPort(evaluationContext != null ? this.portExpression.getValue(evaluationContext, message, Integer.class) + : this.portExpression.getValue(message, Integer.class)); + return (SessionFactory) sessionFactory; + } + +} diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplateTests.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplateTests.java index 97bfb679242..cee0f0f6f1d 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplateTests.java +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/session/FtpRemoteFileTemplateTests.java @@ -29,13 +29,18 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.expression.common.LiteralExpression; import org.springframework.integration.file.DefaultFileNameGenerator; import org.springframework.integration.file.remote.ClientCallbackWithoutResult; import org.springframework.integration.file.remote.SessionCallback; import org.springframework.integration.file.remote.SessionCallbackWithoutResult; +import org.springframework.integration.file.remote.session.DefaultSessionFactoryResolver; import org.springframework.integration.file.remote.session.Session; +import org.springframework.integration.file.support.FileExistsMode; import org.springframework.integration.ftp.TestFtpServer; +import org.springframework.integration.support.MessageBuilder; +import org.springframework.messaging.Message; import org.springframework.messaging.support.GenericMessage; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -55,6 +60,9 @@ public class FtpRemoteFileTemplateTests { @Autowired private DefaultFtpSessionFactory sessionFactory; + @Autowired + private ApplicationContext ctx; + @Before @After public void setup() { @@ -109,4 +117,54 @@ public void doInSessionWithoutResult(Session session) throws IOExceptio assertFalse(template.exists("foo")); } + @Test + public void testFtpSessionFactoryResolver() { + Message message = MessageBuilder.withPayload("foo").setHeader("ftp_host", "localhost"). + setHeader("ftp_username", "foo").setHeader("ftp_password", "foo").setHeader("ftp_port", sessionFactory.port).build(); + DefaultFileNameGenerator fileNameGenerator = new DefaultFileNameGenerator(); + fileNameGenerator.setExpression("'foobar.txt'"); + FtpRemoteFileTemplate template = new FtpRemoteFileTemplate(new FtpSessionFactoryResolver()); + template.setFileNameGenerator(fileNameGenerator); + template.setRemoteDirectoryExpression(new LiteralExpression("foo/")); + template.setUseTemporaryFileName(false); + template.send(message,"foo/",FileExistsMode.IGNORE); + template.execute(new SessionCallback() { + + @Override + public Boolean doInSession(Session session) throws IOException { + session.mkdir("foo/"); + return session.mkdir("foo/foo/"); + } + + }); + template.send(message,"foo/",FileExistsMode.REPLACE); + assertTrue(template.exists("foo/foo/foobar.txt")); + } + + @Test + public void testDefaultSessionFactoryResolver() { + Message message = MessageBuilder.withPayload("foo").setHeader("sessionFactory", "ftpSessionFactory").build(); + DefaultFileNameGenerator fileNameGenerator = new DefaultFileNameGenerator(); + fileNameGenerator.setExpression("'foobar.txt'"); + DefaultSessionFactoryResolver resolver = new DefaultSessionFactoryResolver(); + resolver.setBeanFactory(ctx); + FtpRemoteFileTemplate template = new FtpRemoteFileTemplate(resolver); + template.setFileNameGenerator(fileNameGenerator); + template.setRemoteDirectoryExpression(new LiteralExpression("foo/")); + template.setUseTemporaryFileName(false); + template.send(message,"foo/",FileExistsMode.IGNORE); + template.execute(new SessionCallback() { + + @Override + public Boolean doInSession(Session session) throws IOException { + session.mkdir("foo/"); + return session.mkdir("foo/foo/"); + } + + }); + template.send(message,"foo/",FileExistsMode.REPLACE); + assertTrue(template.exists("foo/foo/foobar.txt")); + } + + } diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplate.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplate.java index 1a32b8e1e64..f0c66255431 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplate.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplate.java @@ -22,6 +22,7 @@ import org.springframework.integration.file.remote.SessionCallback; import org.springframework.integration.file.remote.session.Session; import org.springframework.integration.file.remote.session.SessionFactory; +import org.springframework.integration.file.remote.session.SessionFactoryResolver; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.ChannelSftp.LsEntry; @@ -41,6 +42,10 @@ public SftpRemoteFileTemplate(SessionFactory sessionFactory) { super(sessionFactory); } + public SftpRemoteFileTemplate(SessionFactoryResolver resolver) { + super(resolver); + } + @SuppressWarnings("unchecked") @Override public T executeWithClient(final ClientCallback callback) { diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSessionFactoryResolver.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSessionFactoryResolver.java new file mode 100644 index 00000000000..8f36ca76bfb --- /dev/null +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSessionFactoryResolver.java @@ -0,0 +1,94 @@ +/* + * Copyright 2014 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.sftp.session; + +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.SpelParserConfiguration; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.integration.expression.IntegrationEvaluationContextAware; +import org.springframework.integration.file.remote.session.SessionFactory; +import org.springframework.integration.file.remote.session.SessionFactoryResolver; +import org.springframework.messaging.Message; + +/** + * Sftp {@link SessionFactoryResolver}; Used to resolve sessionfactory from message sent + * containing host, username, password, name. + * + * @author David Liu + * @since 4.1 + * + */ +public class SftpSessionFactoryResolver implements SessionFactoryResolver, IntegrationEvaluationContextAware{ + + private final static String DEFAULT_HOST_EXPRESSION_STRING = "headers['ftp_host']"; + + private final static String DEFAULT_USER_EXPRESSION_STRING = "headers['ftp_username']"; + + private final static String DEFAULT_PASSWORD_EXPRESSION_STRING = "headers['ftp_password']"; + + private final static String DEFAULT_PORT_EXPRESSION_STRING = "headers['ftp_port']"; + + private final ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(true, true)); + + private volatile Expression headerExpression = expressionParser.parseExpression(DEFAULT_HOST_EXPRESSION_STRING); + + private volatile Expression userNameExpression = expressionParser.parseExpression(DEFAULT_USER_EXPRESSION_STRING); + + private volatile Expression passwordExpression = expressionParser.parseExpression(DEFAULT_PASSWORD_EXPRESSION_STRING); + + private volatile Expression portExpression = expressionParser.parseExpression(DEFAULT_PORT_EXPRESSION_STRING); + + private EvaluationContext evaluationContext; + + public void setHostExpression(String hostExpression) { + this.headerExpression = expressionParser.parseExpression(hostExpression); + } + + public void setUserNameExpression(String userExpression) { + this.userNameExpression = expressionParser.parseExpression(userExpression); + } + + public void setPasswordExpression(String passwordExpression) { + this.passwordExpression = expressionParser.parseExpression(passwordExpression); + } + + public void setPortExpression(String portExpression) { + this.portExpression = expressionParser.parseExpression(portExpression); + } + + @Override + public void setIntegrationEvaluationContext(EvaluationContext evaluationContext) { + this.evaluationContext = evaluationContext; + } + + @SuppressWarnings("unchecked") + @Override + public SessionFactory resolve(Message message) { + DefaultSftpSessionFactory sessionFactory = new DefaultSftpSessionFactory(); + sessionFactory.setHost(evaluationContext != null ? this.headerExpression.getValue(evaluationContext, message, String.class) + : this.headerExpression.getValue(message, String.class)); + sessionFactory.setUser(evaluationContext != null ? this.userNameExpression.getValue(evaluationContext, message, String.class) + : this.userNameExpression.getValue(message, String.class)); + sessionFactory.setPassword(evaluationContext != null ? this.passwordExpression.getValue(evaluationContext, message, String.class) + : this.passwordExpression.getValue(message, String.class)); + sessionFactory.setPort(evaluationContext != null ? this.portExpression.getValue(evaluationContext, message, Integer.class) + : this.portExpression.getValue(message, Integer.class)); + return (SessionFactory) sessionFactory; + } + +} diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/TestSftpServer.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/TestSftpServer.java index a9965f4b789..0121b6fe9b5 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/TestSftpServer.java +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/TestSftpServer.java @@ -151,6 +151,10 @@ public String getVirtualUserDir() { server.start(); } + public int getPort() { + return port; + } + @Override public void destroy() throws Exception { this.server.stop(); diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplateTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplateTests.java index 6279d1fb1cc..a8f6b443891 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplateTests.java +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplateTests.java @@ -33,8 +33,11 @@ import org.springframework.integration.file.remote.SessionCallback; import org.springframework.integration.file.remote.SessionCallbackWithoutResult; import org.springframework.integration.file.remote.session.Session; +import org.springframework.integration.file.support.FileExistsMode; import org.springframework.integration.sftp.TestSftpServer; import org.springframework.integration.sftp.TestSftpServerConfig; +import org.springframework.integration.support.MessageBuilder; +import org.springframework.messaging.Message; import org.springframework.messaging.support.GenericMessage; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; @@ -115,4 +118,29 @@ public void doInSessionWithoutResult(Session session) throws IOExceptio assertFalse(template.exists("foo")); } + @Test + public void testSftpSessionFactoryResolver() { + SftpRemoteFileTemplate template = new SftpRemoteFileTemplate(new SftpSessionFactoryResolver()); + Message message = MessageBuilder.withPayload("foo").setHeader("ftp_host", "localhost").setHeader("ftp_username", "foo"). + setHeader("ftp_password", "foo").setHeader("ftp_port", sftpServer.getPort()).build(); + DefaultFileNameGenerator fileNameGenerator = new DefaultFileNameGenerator(); + fileNameGenerator.setExpression("'foobar.txt'"); + template.setFileNameGenerator(fileNameGenerator); + template.setRemoteDirectoryExpression(new LiteralExpression("foo/")); + template.setUseTemporaryFileName(false); + + template.send(message, FileExistsMode.IGNORE); + + template.execute(new SessionCallback() { + + @Override + public Boolean doInSession(Session session) throws IOException { + return session.mkdir("foo/"); + } + + }); + template.append(message); + assertTrue(template.exists("foo/foobar.txt")); + } + }