diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileUtils.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileUtils.java index 9147d9d5275..f5203d397c6 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileUtils.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2020 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. @@ -27,6 +27,8 @@ /** * Utility methods for supporting remote file operations. * @author Gary Russell + * @author Artem Bilan + * * @since 3.0 * */ @@ -45,13 +47,11 @@ private RemoteFileUtils() { * @param logger The logger. * @throws IOException Any IOException. */ - public static synchronized void makeDirectories(String path, Session session, String remoteFileSeparator, + public static void makeDirectories(String path, Session session, String remoteFileSeparator, Log logger) throws IOException { if (!session.exists(path)) { - int nextSeparatorIndex = path.lastIndexOf(remoteFileSeparator); - if (nextSeparatorIndex > -1) { List pathsToCreate = new LinkedList(); while (nextSeparatorIndex > -1) { @@ -70,13 +70,19 @@ public static synchronized void makeDirectories(String path, Session sess if (logger.isDebugEnabled()) { logger.debug("Creating '" + pathToCreate + "'"); } - session.mkdir(pathToCreate); + tryCreateRemoteDirectory(session, pathToCreate); } } else { - session.mkdir(path); + tryCreateRemoteDirectory(session, path); } } } + private static void tryCreateRemoteDirectory(Session session, String path) throws IOException { + if (!session.mkdir(path)) { + throw new IOException("Could not create a remote directory: " + path); + } + } + } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java index 64c4cf3fcc2..04bea84adbe 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2020 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. @@ -510,14 +510,13 @@ protected void doInit() { if (Command.MGET.equals(this.command)) { Assert.isTrue(!(this.options.contains(Option.SUBDIRS)), "Cannot use " + Option.SUBDIRS.toString() + " when using 'mget' use " - + Option.RECURSIVE.toString() + " to obtain files in subdirectories"); + + Option.RECURSIVE.toString() + " to obtain files in subdirectories"); } if (getBeanFactory() != null) { if (this.fileNameProcessor != null) { this.fileNameProcessor.setBeanFactory(getBeanFactory()); } - this.renameProcessor.setBeanFactory(getBeanFactory()); this.remoteFileTemplate.setBeanFactory(getBeanFactory()); } @@ -527,20 +526,20 @@ protected void doInit() { protected Object handleRequestMessage(final Message requestMessage) { if (this.command != null) { switch (this.command) { - case LS: - return doLs(requestMessage); - case GET: - return doGet(requestMessage); - case MGET: - return doMget(requestMessage); - case RM: - return doRm(requestMessage); - case MV: - return doMv(requestMessage); - case PUT: - return doPut(requestMessage); - case MPUT: - return doMput(requestMessage); + case LS: + return doLs(requestMessage); + case GET: + return doGet(requestMessage); + case MGET: + return doMget(requestMessage); + case RM: + return doRm(requestMessage); + case MV: + return doMv(requestMessage); + case PUT: + return doPut(requestMessage); + case MPUT: + return doMput(requestMessage); } } return this.remoteFileTemplate.execute(new SessionCallback() { @@ -570,8 +569,8 @@ public List doInSession(Session session) throws IOException { } }); return this.getMessageBuilderFactory().withPayload(payload) - .setHeader(FileHeaders.REMOTE_DIRECTORY, dir) - .build(); + .setHeader(FileHeaders.REMOTE_DIRECTORY, dir) + .build(); } private Object doGet(final Message requestMessage) { @@ -621,9 +620,9 @@ public List doInSession(Session session) throws IOException { } }); return this.getMessageBuilderFactory().withPayload(payload) - .setHeader(FileHeaders.REMOTE_DIRECTORY, remoteDir) - .setHeader(FileHeaders.REMOTE_FILE, remoteFilename) - .build(); + .setHeader(FileHeaders.REMOTE_DIRECTORY, remoteDir) + .setHeader(FileHeaders.REMOTE_FILE, remoteFilename) + .build(); } private Object doRm(Message requestMessage) { @@ -634,13 +633,13 @@ private Object doRm(Message requestMessage) { boolean payload = this.remoteFileTemplate.remove(remoteFilePath); return this.getMessageBuilderFactory().withPayload(payload) - .setHeader(FileHeaders.REMOTE_DIRECTORY, remoteDir) - .setHeader(FileHeaders.REMOTE_FILE, remoteFilename) - .build(); + .setHeader(FileHeaders.REMOTE_DIRECTORY, remoteDir) + .setHeader(FileHeaders.REMOTE_FILE, remoteFilename) + .build(); } private Object doMv(Message requestMessage) { - String remoteFilePath = this.fileNameProcessor.processMessage(requestMessage); + String remoteFilePath = this.fileNameProcessor.processMessage(requestMessage); String remoteFilename = getRemoteFilename(remoteFilePath); String remoteDir = getRemoteDirectory(remoteFilePath, remoteFilename); String remoteFileNewPath = this.renameProcessor.processMessage(requestMessage); @@ -648,10 +647,10 @@ private Object doMv(Message requestMessage) { this.remoteFileTemplate.rename(remoteFilePath, remoteFileNewPath); return this.getMessageBuilderFactory().withPayload(Boolean.TRUE) - .setHeader(FileHeaders.REMOTE_DIRECTORY, remoteDir) - .setHeader(FileHeaders.REMOTE_FILE, remoteFilename) - .setHeader(FileHeaders.RENAME_TO, remoteFileNewPath) - .build(); + .setHeader(FileHeaders.REMOTE_DIRECTORY, remoteDir) + .setHeader(FileHeaders.REMOTE_FILE, remoteFilename) + .setHeader(FileHeaders.RENAME_TO, remoteFileNewPath) + .build(); } private String doPut(Message requestMessage) { @@ -722,7 +721,7 @@ private List putLocalDirectory(Message requestMessage, File file, Str else if (this.options.contains(Option.RECURSIVE)) { String newSubDirectory = (StringUtils.hasText(subDirectory) ? subDirectory + this.remoteFileTemplate.getRemoteFileSeparator() : "") - + filteredFile.getName(); + + filteredFile.getName(); replies.addAll(this.putLocalDirectory(requestMessage, filteredFile, newSubDirectory)); } } @@ -795,7 +794,7 @@ private List listFilesInRemoteDir(Session session, String directory, Strin } } if (recursion && this.isDirectory(file) && !(".".equals(fileName)) && !("..".equals(fileName))) { - lsFiles.addAll(listFilesInRemoteDir(session, directory, subDirectory + fileName + lsFiles.addAll(listFilesInRemoteDir(session, directory, subDirectory + fileName + this.remoteFileTemplate.getRemoteFileSeparator())); } } @@ -858,7 +857,7 @@ protected void purgeDots(List lsFiles) { * @throws IOException Any IOException. */ protected File get(Message message, Session session, String remoteDir, String remoteFilePath, - String remoteFilename, boolean lsFirst) throws IOException { + String remoteFilename, boolean lsFirst) throws IOException { F[] files = null; if (lsFirst) { files = session.list(remoteFilePath); @@ -931,7 +930,7 @@ else if (FileExistsMode.IGNORE != fileExistsMode) { } protected List mGet(Message message, Session session, String remoteDirectory, - String remoteFilename) throws IOException { + String remoteFilename) throws IOException { if (this.options.contains(Option.RECURSIVE)) { if (logger.isWarnEnabled() && !("*".equals(remoteFilename))) { logger.warn("File name pattern must be '*' when using recursion"); @@ -1018,7 +1017,7 @@ private List mGetWithRecursion(Message message, Session session, Str String fileName = this.getRemoteFilename(fullFileName); String actualRemoteDirectory = this.getRemoteDirectory(fullFileName, fileName); File file = get(message, session, actualRemoteDirectory, - fullFileName, fileName, false); + fullFileName, fileName, false); if (this.options.contains(Option.PRESERVE_TIMESTAMP)) { file.setLastModified(getModified(lsEntry.getFileInfo())); } diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java index 31583dcde46..7cf079e9be5 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java @@ -323,7 +323,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable { @Override public Object answer(InvocationOnMock invocation) throws Throwable { madeDirs.add((String) invocation.getArguments()[0]); - return null; + return true; } }).when(session).mkdir(anyString()); when(sessionFactory.getSession()).thenReturn(session); diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java index 94c7f17f6c2..d05048bf269 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java @@ -229,8 +229,10 @@ public boolean mkdir(String remoteDirectory) throws IOException { try { this.channel.mkdir(remoteDirectory); } - catch (SftpException e) { - throw new NestedIOException("failed to create remote directory '" + remoteDirectory + "'.", e); + catch (SftpException ex) { + if (ex.id != ChannelSftp.SSH_FX_FAILURE || !exists(remoteDirectory)) { + throw new NestedIOException("failed to create remote directory '" + remoteDirectory + "'.", ex); + } } return true; } diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpOutboundTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpOutboundTests.java index ed7523f6b2d..16fca0c628b 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpOutboundTests.java +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpOutboundTests.java @@ -216,7 +216,7 @@ public void testMkDir() throws Exception { @Override public Object answer(InvocationOnMock invocation) throws Throwable { madeDirs.add((String) invocation.getArguments()[0]); - return null; + return true; } }).when(session).mkdir(anyString()); handler.handleMessage(new GenericMessage("qux"));