1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.net.ftp;
19
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertTrue;
22
23 import java.io.ByteArrayInputStream;
24 import java.io.ByteArrayOutputStream;
25 import java.io.File;
26 import java.io.IOException;
27 import java.nio.charset.StandardCharsets;
28 import java.nio.file.Files;
29 import java.nio.file.Path;
30 import java.nio.file.Paths;
31 import java.time.Instant;
32 import java.util.ArrayList;
33 import java.util.List;
34
35 import org.apache.commons.io.FileUtils;
36 import org.apache.ftpserver.FtpServer;
37 import org.apache.ftpserver.FtpServerFactory;
38 import org.apache.ftpserver.ftplet.Authority;
39 import org.apache.ftpserver.ftplet.FtpException;
40 import org.apache.ftpserver.ftplet.UserManager;
41 import org.apache.ftpserver.listener.Listener;
42 import org.apache.ftpserver.listener.ListenerFactory;
43 import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
44 import org.apache.ftpserver.usermanager.impl.BaseUser;
45 import org.apache.ftpserver.usermanager.impl.WritePermission;
46 import org.junit.jupiter.api.AfterEach;
47 import org.junit.jupiter.api.BeforeEach;
48 import org.junit.jupiter.params.ParameterizedTest;
49 import org.junit.jupiter.params.provider.ValueSource;
50
51 public class FTPClientTransferModeTest {
52
53 private static final class FtpServerAndPort {
54
55 private final int port;
56 private final FtpServer ftpServer;
57
58 FtpServerAndPort(final FtpServer ftpServer, final int port) {
59 this.port = port;
60 this.ftpServer = ftpServer;
61 }
62 }
63
64 @FunctionalInterface
65 interface Runner {
66 void run(int port, String user, String password) throws Exception;
67 }
68
69 private static final String DEFAULT_HOME = "ftp_root/";
70
71 private static UserManager initUserManager(final String username, final String password) throws FtpException {
72
73 final PropertiesUserManagerFactory propertiesUserManagerFactory = new PropertiesUserManagerFactory();
74 final UserManager userManager = propertiesUserManagerFactory.createUserManager();
75 final BaseUser user = new BaseUser();
76 user.setName(username);
77 user.setPassword(password);
78
79 final List<Authority> authorities = new ArrayList<>();
80 authorities.add(new WritePermission());
81 user.setAuthorities(authorities);
82
83 new File(DEFAULT_HOME).mkdirs();
84 user.setHomeDirectory(DEFAULT_HOME);
85 userManager.save(user);
86 return userManager;
87 }
88
89 private static void runWithFTPserver(final Runner runner) throws Exception {
90 final String userName = "test";
91 final String password = "test";
92 final FtpServerAndPort ftpServerAndPort = setupPlainFTPserver(userName, password);
93 try {
94 runner.run(ftpServerAndPort.port, userName, password);
95 } finally {
96 ftpServerAndPort.ftpServer.stop();
97 }
98 }
99
100 private static FtpServerAndPort setupPlainFTPserver(final String username, final String password) throws FtpException {
101 final FtpServerFactory serverFactory = new FtpServerFactory();
102
103
104 serverFactory.setUserManager(initUserManager(username, password));
105
106 final ListenerFactory factory = new ListenerFactory();
107
108 factory.setPort(0);
109
110
111 final Listener listener = factory.createListener();
112 serverFactory.addListener("default", listener);
113
114
115 final FtpServer server = serverFactory.createServer();
116 server.start();
117
118 return new FtpServerAndPort(server, listener.getPort());
119 }
120
121 @BeforeEach
122 protected void setUp() throws IOException {
123 FileUtils.deleteDirectory(new File(DEFAULT_HOME));
124 }
125
126 @AfterEach
127 protected void tearDown() throws Exception {
128 FileUtils.deleteDirectory(new File(DEFAULT_HOME));
129 }
130
131 @ParameterizedTest
132 @ValueSource(ints = {FTP.DEFLATE_TRANSFER_MODE})
133 public void testRetrievingFiles(final int transferMode) throws Exception {
134 new File(DEFAULT_HOME).mkdirs();
135 final String filename = "test_download.txt";
136 final String fileContent = "Created at " + Instant.now();
137 Files.write(Paths.get(DEFAULT_HOME).resolve(filename), fileContent.getBytes(StandardCharsets.UTF_8));
138
139 runWithFTPserver((port, user, password) -> {
140 final FTPClient client = new FTPClient();
141 try {
142 client.connect("localhost", port);
143 client.login(user, password);
144 assertTrue(client.setFileTransferMode(transferMode));
145
146 final FTPFile[] files = client.listFiles();
147 assertEquals(1, files.length);
148
149 final ByteArrayOutputStream bos = new ByteArrayOutputStream();
150 assertTrue(client.retrieveFile(files[0].getName(), bos));
151 assertEquals(fileContent, new String(bos.toByteArray(), StandardCharsets.UTF_8));
152 } finally {
153 client.logout();
154 }
155 });
156 }
157
158 @ParameterizedTest
159 @ValueSource(ints = {FTP.DEFLATE_TRANSFER_MODE})
160 public void testStoringFiles(final int transferMode) throws Exception {
161 runWithFTPserver((port, user, password) -> {
162 final FTPClient client = new FTPClient();
163 try {
164 client.connect("localhost", port);
165 client.login(user, password);
166 assertTrue(client.setFileTransferMode(transferMode));
167
168 final FTPFile[] filesBeforeUpload = client.listFiles();
169 assertEquals(0, filesBeforeUpload.length);
170
171 final String fileName = "test_upload.txt";
172 final String fileContent = "Created at " + Instant.now();
173 assertTrue(client.storeFile(fileName, new ByteArrayInputStream(fileContent.getBytes(StandardCharsets.UTF_8))));
174
175 final FTPFile[] filesAfterUpload = client.listFiles();
176 assertEquals(1, filesAfterUpload.length);
177
178 final Path p = Paths.get(DEFAULT_HOME, fileName);
179 assertEquals(fileContent, new String(Files.readAllBytes(p), StandardCharsets.UTF_8));
180 } finally {
181 client.logout();
182 }
183 });
184 }
185
186 }