Java tutorial
/** * Copyright (c) 2014 by the original author or authors. * * This code is free software; you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package ch.sdi.core.impl.ftp; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.apache.ftpserver.FtpServer; import org.apache.ftpserver.FtpServerFactory; import org.apache.ftpserver.ftplet.Authority; import org.apache.ftpserver.ftplet.FtpException; import org.apache.ftpserver.ftplet.UserManager; import org.apache.ftpserver.listener.Listener; import org.apache.ftpserver.listener.ListenerFactory; import org.apache.ftpserver.ssl.SslConfigurationFactory; import org.apache.ftpserver.usermanager.impl.BaseUser; import org.apache.ftpserver.usermanager.impl.WritePermission; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.StreamUtils; import ch.sdi.core.TestUtils; import ch.sdi.core.impl.ftp.FtpExecutor; import ch.sdi.core.intf.SdiMainProperties; /** * Tests the FtpExecutor with anonymous login, username/password without SLL and with implicite SSL by * uploading two files (test resources) to the target "./../testTarget" * <p> * The test opens an embedded FTPServer as counterpart for our FTPClient. For SSL the server needs a * certificate which it finds in src\test\Resources\keystore.jks (password is "password"). * <p> * * @version 1.0 (22.11.2014) * @author Heri */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { FtpExecutor.class }) public class FtpExecutorTest implements ApplicationContextAware { /** */ private static final String TEST_TARGET_DIR_LOCAL = "./../testTarget/"; /** logger for this class */ private static Logger myLog = LogManager.getLogger(FtpExecutorTest.class); @Autowired private ConfigurableEnvironment myEnv; private FtpExecutor myClassUnderTest; private static String myTargetDirLocal; private static List<Authority> myFtpAuthorities; private FtpServerFactory myServerFactory; private static ApplicationContext myCtx = null; @Override public void setApplicationContext(ApplicationContext aCtx) throws BeansException { myCtx = aCtx; } /** * @throws java.lang.Exception */ @BeforeClass public static void setUpStatic() throws Exception { myTargetDirLocal = new File(TEST_TARGET_DIR_LOCAL).getCanonicalPath() + File.separator; myFtpAuthorities = new ArrayList<Authority>(); myFtpAuthorities.add(new WritePermission()); } /** * @throws java.lang.Exception */ @AfterClass public static void setTearDownStatic() throws Exception { } /** * @throws java.lang.Exception */ @Before public void setUp() throws Exception { myClassUnderTest = myCtx.getBean(FtpExecutor.class); myServerFactory = new FtpServerFactory(); } /** * Test method for {@link ch.sdi.core.impl.ftp.FtpExecutor#executeUpload(java.io.InputStream, java.lang.String)}. */ @Test public void testInitBySpring() throws Throwable { myLog.debug("Testing self-initialize by Spring context"); String targetDir = myTargetDirLocal; cleanTargetDir(targetDir); Map<String, InputStream> filesToUpload = createFileUploadMap(targetDir); TestUtils.addToEnvironment(myEnv, SdiMainProperties.KEY_FTP_CMD_LINE, "-A localhost"); registerFtpUser("anonymous", System.getProperty("user.name") + "@" + InetAddress.getLocalHost().getHostName()); FtpServer server = startFtpServer(); try { // omit call to init in order to auto initialize by spring context myClassUnderTest.connectAndLogin(); myClassUnderTest.uploadFiles(filesToUpload); myClassUnderTest.logoutAndDisconnect(); assertFilesUploaded(createFileUploadMap(targetDir)); } finally { if (server != null) { myLog.debug("stopping the embedded FTP server"); server.stop(); } // if myServer != null } } /** * Test method for {@link ch.sdi.core.impl.ftp.FtpExecutor#executeUpload(java.io.InputStream, java.lang.String)}. */ @Test public void testUploadAnonymous() throws Throwable { myLog.debug("Testing Anonymous login"); String targetDir = myTargetDirLocal; cleanTargetDir(targetDir); Map<String, InputStream> filesToUpload = createFileUploadMap(targetDir); List<String> args = new ArrayList<String>(); args.add("-bla"); // invalid option should be ignored args.add("-A"); // anonymous args.add("localhost"); registerFtpUser("anonymous", System.getProperty("user.name") + "@" + InetAddress.getLocalHost().getHostName()); FtpServer server = startFtpServer(); try { myClassUnderTest.init(args.toArray(new String[args.size()])); myClassUnderTest.connectAndLogin(); myClassUnderTest.uploadFiles(filesToUpload); myClassUnderTest.logoutAndDisconnect(); assertFilesUploaded(createFileUploadMap(targetDir)); } finally { if (server != null) { myLog.debug("stopping the embedded FTP server"); server.stop(); } // if myServer != null } } /** * Test method for {@link ch.sdi.core.impl.ftp.FtpExecutor#executeUpload(java.io.InputStream, java.lang.String)}. */ @Test public void testUploadLogin() throws Throwable { myLog.debug("Testing normal login"); String targetDir = myTargetDirLocal; cleanTargetDir(targetDir); Map<String, InputStream> filesToUpload = createFileUploadMap(targetDir); List<String> args = new ArrayList<String>(); args.add("localhost"); args.add("heri"); // user args.add("heri"); // pw registerFtpUser("heri", "heri"); FtpServer server = startFtpServer(); try { myClassUnderTest.init(args.toArray(new String[args.size()])); myClassUnderTest.connectAndLogin(); myClassUnderTest.uploadFiles(filesToUpload); myClassUnderTest.logoutAndDisconnect(); assertFilesUploaded(createFileUploadMap(targetDir)); } finally { if (server != null) { myLog.debug("stopping the embedded FTP server"); server.stop(); } // if myServer != null } } /** * Test method for {@link ch.sdi.core.impl.ftp.FtpExecutor#executeUpload(java.io.InputStream, java.lang.String)}. */ @Test public void testUploadLoginSSLImplicite() throws Throwable { myLog.debug("Testing SSL login (implicite)"); String targetDir = myTargetDirLocal; cleanTargetDir(targetDir); Map<String, InputStream> filesToUpload = createFileUploadMap(targetDir); List<String> args = new ArrayList<String>(); args.add("-p"); args.add("false"); // activate implicite SSL args.add("localhost"); args.add("heri"); // user args.add("heri"); // pw ListenerFactory listenerFactory = new ListenerFactory(); // define SSL configuration SslConfigurationFactory ssl = new SslConfigurationFactory(); ssl.setKeystoreFile(new File("keystore.jks")); // this is in core/test/resources and contains one // selfsigned certificate ssl.setKeystorePassword("password"); listenerFactory.setSslConfiguration(ssl.createSslConfiguration()); listenerFactory.setImplicitSsl(false); // replace the default listener Listener listenerOrg = myServerFactory.getListener("default"); try { myServerFactory.addListener("default", listenerFactory.createListener()); registerFtpUser("heri", "heri"); FtpServer server = startFtpServer(); try { myClassUnderTest.init(args.toArray(new String[args.size()])); myClassUnderTest.connectAndLogin(); myClassUnderTest.uploadFiles(filesToUpload); myClassUnderTest.logoutAndDisconnect(); assertFilesUploaded(createFileUploadMap(targetDir)); } finally { if (server != null) { myLog.debug("stopping the embedded FTP server"); server.stop(); } // if myServer != null } } finally { myServerFactory.addListener("default", listenerOrg); } } /** * @param aCreateFileUploadMap */ private void assertFilesUploaded(Map<String, InputStream> aCreateFileUploadMap) { for (String targetFileName : aCreateFileUploadMap.keySet()) { assertFileUpdloaded(targetFileName, aCreateFileUploadMap.get(targetFileName)); } } /** * @param aTargetFileName * @param aInputStream */ private void assertFileUpdloaded(String aTargetFileName, InputStream aInputStream) { File target = new File(aTargetFileName); Assert.assertTrue(target.exists()); byte[] input = copyStreamToByteArray(aInputStream); byte[] output = null; try { output = copyStreamToByteArray(new FileInputStream(target)); } catch (FileNotFoundException t) { myLog.error("Should not occur", t); Assert.fail("FileNotFoundException while opening file " + target.getPath()); } Assert.assertArrayEquals(input, output); } /** * @param aInputStream * @return */ private byte[] copyStreamToByteArray(InputStream aInputStream) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { StreamUtils.copy(aInputStream, baos); } catch (IOException t) { Assert.fail("IOException while copying stream. " + t); } byte[] input = baos.toByteArray(); return input; } /** * @param aTargetDir */ private void cleanTargetDir(String aTargetDir) { File[] list = new File(aTargetDir).listFiles(); for (File file : list) { file.delete(); } } /** * @param aUsername * @param aPassword * @throws FtpException */ private void registerFtpUser(String aUsername, String aPassword) throws FtpException { BaseUser user = new BaseUser(); user.setName(aUsername); user.setPassword(aPassword); user.setAuthorities(myFtpAuthorities); UserManager userManager = myServerFactory.getUserManager(); userManager.save(user); } /** * @return * @throws FtpException */ private FtpServer startFtpServer() throws FtpException { FtpServer result; result = myServerFactory.createServer(); myLog.debug("starting an embedded FTP server"); result.start(); return result; } /** * @param aTargetDir * @return */ private Map<String, InputStream> createFileUploadMap(String aTargetDir) { Map<String, InputStream> filesToUpload = new TreeMap<String, InputStream>(); filesToUpload.put(aTargetDir + "sdimain_test.properties", ClassLoader.getSystemResourceAsStream("sdimain.properties")); filesToUpload.put(aTargetDir + "log4j2.xml", ClassLoader.getSystemResourceAsStream("log4j2.xml")); return filesToUpload; } }