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