From 5461d778378c1729b8495f739d6d0a5708a93eb5 Mon Sep 17 00:00:00 2001 From: David Liu Date: Thu, 7 Aug 2014 12:13:22 +0800 Subject: [PATCH 1/2] INT-2120:RemoteFileTemplate - Phase III JIRA: https://jira.spring.io/browse/INT-3205 * add SftpSessionFactoryResolver, DefaultSessionFactoryResolver, SftpSessionFactoryResolver * add constructor in RemoteFileTemplate that take SessionFactoryResolver as parameter * add test --- .../file/remote/RemoteFileTemplate.java | 21 ++++- .../DefaultSessionFactoryResolver.java | 59 ++++++++++++++ .../session/SessionFactoryResolver.java | 27 +++++++ .../ftp/session/FtpRemoteFileTemplate.java | 4 + .../session/FtpSessionFactoryResolver.java | 79 +++++++++++++++++++ .../session/FtpRemoteFileTemplateTests.java | 58 ++++++++++++++ .../sftp/session/SftpRemoteFileTemplate.java | 5 ++ .../session/SftpSessionFactoryResolver.java | 79 +++++++++++++++++++ .../integration/sftp/TestSftpServer.java | 4 + .../session/SftpRemoteFileTemplateTests.java | 27 +++++++ 10 files changed, 362 insertions(+), 1 deletion(-) create mode 100644 spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/DefaultSessionFactoryResolver.java create mode 100644 spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/SessionFactoryResolver.java create mode 100644 spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSessionFactoryResolver.java create mode 100644 spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSessionFactoryResolver.java 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..9684bb4f7b5 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,11 +89,22 @@ public class RemoteFileTemplate implements RemoteFileOperations, Initializ private volatile BeanFactory beanFactory; + private volatile SessionFactoryResolver resolver; + public RemoteFileTemplate(SessionFactory sessionFactory) { Assert.notNull(sessionFactory, "sessionFactory must not be null"); this.sessionFactory = sessionFactory; } + public RemoteFileTemplate(SessionFactoryResolver resolver) { + if(resolver == null) { + this.resolver = new DefaultSessionFactoryResolver(); + } + else { + this.resolver = resolver; + } + } + public void setAutoCreateDirectory(boolean autoCreateDirectory) { this.autoCreateDirectory = autoCreateDirectory; } @@ -200,6 +213,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..b2ea3f57ee6 --- /dev/null +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/DefaultSessionFactoryResolver.java @@ -0,0 +1,59 @@ +/* + * 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.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.SpelParserConfiguration; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.messaging.Message; + +/** + * @author David Liu + * @since 4.1 + * + */ +public class DefaultSessionFactoryResolver implements SessionFactoryResolver, BeanFactoryAware { + + 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; + + public void setSessionFactory(String expression) { + this.sessionFactoryExpression = expressionParser.parseExpression(expression); + } + + @SuppressWarnings("unchecked") + @Override + public SessionFactory resolve(Message message) { + if(beanFactory != null) { + return beanFactory.getBean(this.sessionFactoryExpression.getValue(message).toString(), 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..cf002d0ddae --- /dev/null +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/session/SessionFactoryResolver.java @@ -0,0 +1,27 @@ +/* + * 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; + +/** + * @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..0a50940ad52 --- /dev/null +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSessionFactoryResolver.java @@ -0,0 +1,79 @@ +/* + * 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.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.SpelParserConfiguration; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.integration.file.remote.session.SessionFactory; +import org.springframework.integration.file.remote.session.SessionFactoryResolver; +import org.springframework.messaging.Message; + +/** + * @author David Liu + * @since 4.1 + * + */ +public class FtpSessionFactoryResolver implements SessionFactoryResolver{ + + private final static String DEFAULTHOSTEXPRESSIONSTRING = "headers['ftp_host']"; + + private final static String DEFAULTUSEREXPRESSIONSTRING = "headers['ftp_username']"; + + private final static String DEFAULTPASSWORDEXPRESSIONSTRING = "headers['ftp_password']"; + + private final static String DEFAULTPORTEXPRESSIONSTRING = "headers['ftp_port']"; + + private final ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(true, true)); + + private volatile Expression headerExpression = expressionParser.parseExpression(DEFAULTHOSTEXPRESSIONSTRING); + + private volatile Expression userNameExpression = expressionParser.parseExpression(DEFAULTUSEREXPRESSIONSTRING); + + private volatile Expression passwordExpression = expressionParser.parseExpression(DEFAULTPASSWORDEXPRESSIONSTRING); + + private volatile Expression portExpression = expressionParser.parseExpression(DEFAULTPORTEXPRESSIONSTRING); + + + 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); + } + + @SuppressWarnings("unchecked") + @Override + public SessionFactory resolve(Message message) { + DefaultFtpSessionFactory sessionFactory = new DefaultFtpSessionFactory(); + sessionFactory.setHost(this.headerExpression.getValue(message).toString()); + sessionFactory.setUsername(this.userNameExpression.getValue(message).toString()); + sessionFactory.setPassword(this.passwordExpression.getValue(message).toString()); + sessionFactory.setPort(Integer.valueOf(this.portExpression.getValue(message).toString())); + 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..f5ce3749680 --- /dev/null +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSessionFactoryResolver.java @@ -0,0 +1,79 @@ +/* + * 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.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.SpelParserConfiguration; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.integration.file.remote.session.SessionFactory; +import org.springframework.integration.file.remote.session.SessionFactoryResolver; +import org.springframework.messaging.Message; + +/** + * @author David Liu + * @since 4.1 + * + */ +public class SftpSessionFactoryResolver implements SessionFactoryResolver{ + + private final static String DEFAULTHOSTEXPRESSIONSTRING = "headers['ftp_host']"; + + private final static String DEFAULTUSEREXPRESSIONSTRING = "headers['ftp_username']"; + + private final static String DEFAULTPASSWORDEXPRESSIONSTRING = "headers['ftp_password']"; + + private final static String DEFAULTPORTEXPRESSIONSTRING = "headers['ftp_port']"; + + private final ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(true, true)); + + private volatile Expression headerExpression = expressionParser.parseExpression(DEFAULTHOSTEXPRESSIONSTRING); + + private volatile Expression userNameExpression = expressionParser.parseExpression(DEFAULTUSEREXPRESSIONSTRING); + + private volatile Expression passwordExpression = expressionParser.parseExpression(DEFAULTPASSWORDEXPRESSIONSTRING); + + private volatile Expression portExpression = expressionParser.parseExpression(DEFAULTPORTEXPRESSIONSTRING); + + + 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); + } + + @SuppressWarnings("unchecked") + @Override + public SessionFactory resolve(Message message) { + DefaultSftpSessionFactory sessionFactory = new DefaultSftpSessionFactory(); + sessionFactory.setHost(this.headerExpression.getValue(message).toString()); + sessionFactory.setUser(this.userNameExpression.getValue(message).toString()); + sessionFactory.setPassword(this.passwordExpression.getValue(message).toString()); + sessionFactory.setPort(Integer.valueOf(this.portExpression.getValue(message).toString())); + 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..eec991f096c 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,28 @@ 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")); + } } From 4e2198fab335abfcd6d2cafdbef6fcb3831932e9 Mon Sep 17 00:00:00 2001 From: David Liu Date: Sat, 9 Aug 2014 08:53:06 +0800 Subject: [PATCH 2/2] INT-2120: fix as Artem's comments --- .../file/remote/RemoteFileTemplate.java | 4 +- .../DefaultSessionFactoryResolver.java | 22 ++++++++-- .../session/SessionFactoryResolver.java | 4 ++ .../session/FtpSessionFactoryResolver.java | 41 +++++++++++++------ .../session/SftpSessionFactoryResolver.java | 41 +++++++++++++------ .../session/SftpRemoteFileTemplateTests.java | 1 + 6 files changed, 83 insertions(+), 30 deletions(-) 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 9684bb4f7b5..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 @@ -89,11 +89,12 @@ public class RemoteFileTemplate implements RemoteFileOperations, Initializ private volatile BeanFactory beanFactory; - private volatile SessionFactoryResolver resolver; + 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) { @@ -103,6 +104,7 @@ public RemoteFileTemplate(SessionFactoryResolver resolver) { else { this.resolver = resolver; } + sessionFactory = null; } public void setAutoCreateDirectory(boolean autoCreateDirectory) { 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 index b2ea3f57ee6..a82f591bef3 100644 --- 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 @@ -18,18 +18,23 @@ 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 { +public class DefaultSessionFactoryResolver implements SessionFactoryResolver, BeanFactoryAware, IntegrationEvaluationContextAware{ private final static String SESSIONFACTORY = "headers['sessionFactory']"; @@ -39,15 +44,25 @@ public class DefaultSessionFactoryResolver implements SessionFactoryResolver< 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(beanFactory != null) { - return beanFactory.getBean(this.sessionFactoryExpression.getValue(message).toString(), SessionFactory.class); + 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; } @@ -56,4 +71,5 @@ public SessionFactory resolve(Message message) { 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 index cf002d0ddae..4495c6778fe 100644 --- 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 @@ -18,10 +18,14 @@ 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/FtpSessionFactoryResolver.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/session/FtpSessionFactoryResolver.java index 0a50940ad52..88a9d292d8e 100644 --- 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 @@ -15,39 +15,45 @@ */ 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{ +public class FtpSessionFactoryResolver implements SessionFactoryResolver, IntegrationEvaluationContextAware{ - private final static String DEFAULTHOSTEXPRESSIONSTRING = "headers['ftp_host']"; + private final static String DEFAULT_HOST_EXPRESSION_STRING = "headers['ftp_host']"; - private final static String DEFAULTUSEREXPRESSIONSTRING = "headers['ftp_username']"; + private final static String DEFAULT_USER_EXPRESSION_STRING = "headers['ftp_username']"; - private final static String DEFAULTPASSWORDEXPRESSIONSTRING = "headers['ftp_password']"; + private final static String DEFAULT_PASSWORD_EXPRESSION_STRING = "headers['ftp_password']"; - private final static String DEFAULTPORTEXPRESSIONSTRING = "headers['ftp_port']"; + 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(DEFAULTHOSTEXPRESSIONSTRING); + private volatile Expression headerExpression = expressionParser.parseExpression(DEFAULT_HOST_EXPRESSION_STRING); - private volatile Expression userNameExpression = expressionParser.parseExpression(DEFAULTUSEREXPRESSIONSTRING); + private volatile Expression userNameExpression = expressionParser.parseExpression(DEFAULT_USER_EXPRESSION_STRING); - private volatile Expression passwordExpression = expressionParser.parseExpression(DEFAULTPASSWORDEXPRESSIONSTRING); + private volatile Expression passwordExpression = expressionParser.parseExpression(DEFAULT_PASSWORD_EXPRESSION_STRING); - private volatile Expression portExpression = expressionParser.parseExpression(DEFAULTPORTEXPRESSIONSTRING); + private volatile Expression portExpression = expressionParser.parseExpression(DEFAULT_PORT_EXPRESSION_STRING); + private EvaluationContext evaluationContext; public void setHostExpression(String hostExpression) { this.headerExpression = expressionParser.parseExpression(hostExpression); @@ -65,14 +71,23 @@ 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(this.headerExpression.getValue(message).toString()); - sessionFactory.setUsername(this.userNameExpression.getValue(message).toString()); - sessionFactory.setPassword(this.passwordExpression.getValue(message).toString()); - sessionFactory.setPort(Integer.valueOf(this.portExpression.getValue(message).toString())); + 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-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 index f5ce3749680..8f36ca76bfb 100644 --- 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 @@ -15,39 +15,45 @@ */ 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{ +public class SftpSessionFactoryResolver implements SessionFactoryResolver, IntegrationEvaluationContextAware{ - private final static String DEFAULTHOSTEXPRESSIONSTRING = "headers['ftp_host']"; + private final static String DEFAULT_HOST_EXPRESSION_STRING = "headers['ftp_host']"; - private final static String DEFAULTUSEREXPRESSIONSTRING = "headers['ftp_username']"; + private final static String DEFAULT_USER_EXPRESSION_STRING = "headers['ftp_username']"; - private final static String DEFAULTPASSWORDEXPRESSIONSTRING = "headers['ftp_password']"; + private final static String DEFAULT_PASSWORD_EXPRESSION_STRING = "headers['ftp_password']"; - private final static String DEFAULTPORTEXPRESSIONSTRING = "headers['ftp_port']"; + 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(DEFAULTHOSTEXPRESSIONSTRING); + private volatile Expression headerExpression = expressionParser.parseExpression(DEFAULT_HOST_EXPRESSION_STRING); - private volatile Expression userNameExpression = expressionParser.parseExpression(DEFAULTUSEREXPRESSIONSTRING); + private volatile Expression userNameExpression = expressionParser.parseExpression(DEFAULT_USER_EXPRESSION_STRING); - private volatile Expression passwordExpression = expressionParser.parseExpression(DEFAULTPASSWORDEXPRESSIONSTRING); + private volatile Expression passwordExpression = expressionParser.parseExpression(DEFAULT_PASSWORD_EXPRESSION_STRING); - private volatile Expression portExpression = expressionParser.parseExpression(DEFAULTPORTEXPRESSIONSTRING); + private volatile Expression portExpression = expressionParser.parseExpression(DEFAULT_PORT_EXPRESSION_STRING); + private EvaluationContext evaluationContext; public void setHostExpression(String hostExpression) { this.headerExpression = expressionParser.parseExpression(hostExpression); @@ -65,14 +71,23 @@ 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(this.headerExpression.getValue(message).toString()); - sessionFactory.setUser(this.userNameExpression.getValue(message).toString()); - sessionFactory.setPassword(this.passwordExpression.getValue(message).toString()); - sessionFactory.setPort(Integer.valueOf(this.portExpression.getValue(message).toString())); + 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/session/SftpRemoteFileTemplateTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpRemoteFileTemplateTests.java index eec991f096c..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 @@ -142,4 +142,5 @@ public Boolean doInSession(Session session) throws IOException { template.append(message); assertTrue(template.exists("foo/foobar.txt")); } + }