View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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         // Init user
104         serverFactory.setUserManager(initUserManager(username, password));
105 
106         final ListenerFactory factory = new ListenerFactory();
107         // Automatically assign port.
108         factory.setPort(0);
109 
110         // replace the default listener
111         final Listener listener = factory.createListener();
112         serverFactory.addListener("default", listener);
113 
114         // start the server
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 }