Skip to content

Commit 47cae46

Browse files
authored
GH-3370: Remove synchronized from RemoteFileUtils (#3380)
* GH-3370: Remove synchronized from RemoteFileUtils Fixes #3370 The `synchronized` on the `RemoteFileUtils.makeDirectories()` makes an application too slow, especially when we deal with different paths in different sessions * Remove the `synchronized` from that method and rework `SftpSession.mkdir()` to return `false` when "A file cannot be created if it already exists" exception is thrown from the server. Essentially make an `exists()` call to be sure that an exception is really related to "file-already-exists" answer from the server **Cherry-pick to 5.3.x, 5.2.x & 4.3.x** * * Re-throw an exception in the `SftpSession.mkdir()` when error code is not `4` or remote dir does not exist * * Check `session.mkdir()` result in the `RemoteFileUtils` to throw an `IOException` when `false` * * Fix mock test to return `true` for `mkdir` instead of `null`
1 parent 6c2a4c9 commit 47cae46

File tree

5 files changed

+23
-12
lines changed

5 files changed

+23
-12
lines changed

spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileUtils.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
2828
* Utility methods for supporting remote file operations.
2929
*
3030
* @author Gary Russell
31+
* @author Artem Bilan
3132
*
3233
* @since 3.0
3334
*
@@ -46,13 +47,11 @@ private RemoteFileUtils() {
4647
* @param logger The logger.
4748
* @throws IOException Any IOException.
4849
*/
49-
public static synchronized <F> void makeDirectories(String path, Session<F> session, String remoteFileSeparator,
50+
public static <F> void makeDirectories(String path, Session<F> session, String remoteFileSeparator,
5051
Log logger) throws IOException {
5152

5253
if (!session.exists(path)) {
53-
5454
int nextSeparatorIndex = path.lastIndexOf(remoteFileSeparator);
55-
5655
if (nextSeparatorIndex > -1) {
5756
List<String> pathsToCreate = new LinkedList<>();
5857
while (nextSeparatorIndex > -1) {
@@ -71,13 +70,19 @@ public static synchronized <F> void makeDirectories(String path, Session<F> sess
7170
if (logger.isDebugEnabled()) {
7271
logger.debug("Creating '" + pathToCreate + "'");
7372
}
74-
session.mkdir(pathToCreate);
73+
tryCreateRemoteDirectory(session, pathToCreate);
7574
}
7675
}
7776
else {
78-
session.mkdir(path);
77+
tryCreateRemoteDirectory(session, path);
7978
}
8079
}
8180
}
8281

82+
private static void tryCreateRemoteDirectory(Session<?> session, String path) throws IOException {
83+
if (!session.mkdir(path)) {
84+
throw new IOException("Could not create a remote directory: " + path);
85+
}
86+
}
87+
8388
}

spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -121,6 +121,7 @@ public AbstractRemoteFileOutboundGateway(SessionFactory<F> sessionFactory,
121121
MessageSessionCallback<F, ?> messageSessionCallback) {
122122

123123
this(new RemoteFileTemplate<>(sessionFactory), messageSessionCallback);
124+
remoteFileTemplateExplicitlySet(false);
124125
}
125126

126127
/**
@@ -165,6 +166,7 @@ public AbstractRemoteFileOutboundGateway(SessionFactory<F> sessionFactory, Comma
165166
@Nullable String expression) {
166167

167168
this(new RemoteFileTemplate<>(sessionFactory), command, expression);
169+
remoteFileTemplateExplicitlySet(false);
168170
}
169171

170172
/**
@@ -516,6 +518,9 @@ protected void doInit() {
516518
}
517519

518520
populateBeanFactoryIntoComponentsIfAny();
521+
if (!this.remoteFileTemplateExplicitlySet) {
522+
this.remoteFileTemplate.afterPropertiesSet();
523+
}
519524
}
520525

521526
private void populateBeanFactoryIntoComponentsIfAny() {

spring-integration-file/src/test/java/org/springframework/integration/file/remote/gateway/RemoteFileOutboundGatewayTests.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ public void testMoveWithMkDirs() throws Exception {
295295
final List<String> madeDirs = new ArrayList<>();
296296
doAnswer(invocation -> {
297297
madeDirs.add(invocation.getArgument(0));
298-
return null;
298+
return true;
299299
}).when(session).mkdir(anyString());
300300
when(sessionFactory.getSession()).thenReturn(session);
301301
Message<String> requestMessage = MessageBuilder.withPayload("foo")
@@ -939,7 +939,6 @@ public void testMputCollection() throws Exception {
939939
Session<TestLsEntry> session = mock(Session.class);
940940
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway(sessionFactory, "mput", "payload");
941941
gw.setRemoteDirectoryExpression(new LiteralExpression("foo/"));
942-
gw.setBeanFactory(mock(BeanFactory.class));
943942
gw.afterPropertiesSet();
944943
when(sessionFactory.getSession()).thenReturn(session);
945944
final AtomicReference<String> written = new AtomicReference<>();

spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,10 @@ public boolean mkdir(String remoteDirectory) throws IOException {
252252
try {
253253
this.channel.mkdir(remoteDirectory);
254254
}
255-
catch (SftpException e) {
256-
throw new NestedIOException("failed to create remote directory '" + remoteDirectory + "'.", e);
255+
catch (SftpException ex) {
256+
if (ex.id != ChannelSftp.SSH_FX_FAILURE || !exists(remoteDirectory)) {
257+
throw new NestedIOException("failed to create remote directory '" + remoteDirectory + "'.", ex);
258+
}
257259
}
258260
return true;
259261
}

spring-integration-sftp/src/test/java/org/springframework/integration/sftp/outbound/SftpOutboundTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ public void testMkDir() throws Exception {
219219
final List<String> madeDirs = new ArrayList<>();
220220
doAnswer(invocation -> {
221221
madeDirs.add(invocation.getArgument(0));
222-
return null;
222+
return true;
223223
}).when(session).mkdir(anyString());
224224
handler.handleMessage(new GenericMessage<>("qux"));
225225
assertThat(madeDirs.size()).isEqualTo(3);

0 commit comments

Comments
 (0)