package th.co.muangthai.endrprint.controller.service.ftp; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; import org.apache.commons.net.ftp.FTPSClient; import org.apache.log4j.Logger; public class FTPSecureUtil { private static final String KEYSTORE_PASS = "changeit"; private static final String KEYSTORE_FILE_NAME = "/ftp-cacerts.jks"; private static final String DEFAULT_PROTOCOL = "SSL"; public static FTPSClient connectSecure(String hostname, int port, String username, String password) throws Exception { Logger log = Logger.getLogger(FTPSecureUtil.class); try { FTPSClient ftps = new FTPSClient(DEFAULT_PROTOCOL, true); ftps.setRemoteVerificationEnabled(true); // ftps.setConnectTimeout(60000); ftps.setDataTimeout(600000); KeyManager keyManager = getKeyManagers()[0]; TrustManager trustManager = getTrustManagers()[0]; ftps.setKeyManager(keyManager); ftps.setTrustManager(trustManager); // ftps.addProtocolCommandListener(new LogCommandListener(log)); log.debug("Connecting to " + hostname + " port " + port + "."); ftps.connect(hostname, port); log.debug("Connected to " + hostname + " port " + port + "."); int reply = ftps.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftps.disconnect(); log.error("FTP server refused connection."); } if (!ftps.login(username, password)) { ftps.logout(); } // not suport PRIVATE MODE for NAT/ROUTER and production firewall //ftps.execPROT("P"); // PRODUCTION Need to enter Local Passive Mode log.debug("enterLocalPassiveMode"); ftps.enterLocalPassiveMode(); //ftps.enterLocalPassiveMode(); return ftps; } catch (Exception ex) { log.error("Secure FTP connection error " + ex.getMessage(), ex); throw ex; } } public static FTPSClient connectSecure(String hostname, int port, String username, String password,String mode,String protType) throws Exception { Logger log = Logger.getLogger(FTPSecureUtil.class); try { FTPSClient ftps = new FTPSClient(DEFAULT_PROTOCOL, true); ftps.setRemoteVerificationEnabled(true); // ftps.setConnectTimeout(1000); ftps.setDataTimeout(10000); KeyManager keyManager = getKeyManagers()[0]; TrustManager trustManager = getTrustManagers()[0]; ftps.setKeyManager(keyManager); ftps.setTrustManager(trustManager); // ftps.addProtocolCommandListener(new LogCommandListener(log)); log.debug("Connecting to " + hostname + " port " + port + "."); ftps.connect(hostname, port); log.debug("Connected to " + hostname + " port " + port + "."); int reply = ftps.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftps.disconnect(); log.error("FTP server refused connection."); } if (!ftps.login(username, password)) { ftps.logout(); } // //ftps.execPBSZ(0); if("P".equalsIgnoreCase(protType)){ ftps.execPROT("P"); } //ftps.enterRemoteActiveMode(InetAddress.getLocalHost(), 10990); //ftps.enterRemotePassiveMode(); if("LP".equalsIgnoreCase(mode)){ log.debug("enterLocalPassiveMode"); ftps.enterLocalPassiveMode(); }else if("RP".equalsIgnoreCase(mode)){ log.debug("enterRemotePassiveMode"); ftps.enterRemotePassiveMode(); //ftps.enterRemoteActiveMode(InetAddress.getByName(hostname), 10990); } return ftps; } catch (Exception ex) { log.error("Secure FTP connection error " + ex.getMessage(), ex); throw ex; } } private static void disconnect(FTPSClient ftps) { if (ftps != null) { try { ftps.logout(); } catch (Exception e) { //do nothing } try { ftps.disconnect(); } catch (Exception f) { // do nothing } } } public static boolean getMultipleFile(String hostname, int port, String username, String password, String[] remoteFileName, String localPath) { Logger log = Logger.getLogger(FTPSecureUtil.class); FTPSClient ftps = null; try { log.debug("opening ftp server " + hostname + " port " + port); ftps = FTPSecureUtil.connectSecure(hostname, port, username, password); if (ftps != null && ftps.isConnected()) { ftps.setFileType(FTP.BINARY_FILE_TYPE); for (int i = 0; i < remoteFileName.length; i++) { try { String remoteFile = remoteFileName[i]; String actualFileName = remoteFile.substring(remoteFile.lastIndexOf("/") + 1, remoteFile.length()); File localFile = new File(localPath + "/" + actualFileName); OutputStream output = new FileOutputStream(localFile); if (!ftps.retrieveFile(remoteFile, output)) { log.debug("Download file " + remoteFile + " Failed......"); } else { log.debug("Download file " + remoteFile + " Success......"); } output.close(); } catch (Exception e) { log.error("Download file error " + e.getMessage(), e); } } return true; } else { return false; } } catch (Exception e) { log.error("getMultipleFile error " + e.getMessage(), e); return false; } finally { disconnect(ftps); } } public static boolean getFile(String hostname, int port, String username, String password, String remoteFileName, String localPath) { Logger log = Logger.getLogger(FTPSecureUtil.class); FTPSClient ftps = null; try { log.debug("opening ftp server " + hostname + " port " + port); ftps = FTPSecureUtil.connectSecure(hostname, port, username, password); if (ftps != null && ftps.isConnected()) { ftps.setFileType(FTP.BINARY_FILE_TYPE); try { String remoteFile = remoteFileName; String actualFileName = remoteFile.substring(remoteFile.lastIndexOf("/") + 1, remoteFile.length()); File localFile = new File(localPath + "/" + actualFileName); OutputStream output = new FileOutputStream(localFile); if (!ftps.retrieveFile(remoteFile, output)) { log.debug("Download file " + remoteFile + " Failed......"); output.close(); return false; } else { log.debug("Download file " + remoteFile + " Success......"); output.close(); return true; } } catch (Exception e) { log.error("Download file error " + e.getMessage(), e); } return true; } else { return false; } } catch (Exception e) { log.error("getMultipleFile error " + e.getMessage(), e); return false; } finally { disconnect(ftps); } } public static boolean putMultipleFile(String hostname, int port, String username, String password, String remotePath, String[] localFileNames) { Logger log = Logger.getLogger(FTPSecureUtil.class); FTPSClient ftps = null; boolean error = false; try { log.debug("opening ftp server " + hostname + " port " + port); ftps = connectSecure(hostname, port, username, password); if (ftps != null && ftps.isConnected()) { ftps.setFileType(FTP.BINARY_FILE_TYPE); try { if (!ftps.changeWorkingDirectory(remotePath)) { log.debug(remotePath + " dose not exist trying to create new directory......"); int mkdCode = ftps.mkd(remotePath); if (FTPReply.isPositiveCompletion(mkdCode)) { log.debug(" trying to change directory to " + remotePath); error = !ftps.changeWorkingDirectory(remotePath); if (error) { log.error("can not change working directory to " + remotePath); } else { log.debug("change working directory to " + remotePath + " success."); } } else { error = true; } } } catch (IOException e) { log.debug(remotePath + " dose not exist trying to create new directory......"); int mkdCode = ftps.mkd(remotePath); if (FTPReply.isPositiveCompletion(mkdCode)) { log.debug(" trying to change directory to " + remotePath); error = !ftps.changeWorkingDirectory(remotePath); if (error) { log.error("can not change working directory to " + remotePath); } else { log.debug("change working directory to " + remotePath + " success."); } } else { error = true; } } for (int i = 0; i < localFileNames.length; i++) { try { String actualFileName = localFileNames[i]; log.debug("uploading file from " + actualFileName); File localFile = new File(actualFileName); String remoteFile = localFile.getName();//actualFileName.substring(actualFileName.lastIndexOf("/")+1, actualFileName.length()); try { if(!ftps.deleteFile(remotePath + "/" + remoteFile)){ log.error("delete ftps file "+remotePath + "/" + remoteFile+" failed."); } } catch (Exception e) { log.error("delete ftps file error " + e.getMessage()); } DataInputStream input = new DataInputStream(new FileInputStream(localFile)); if (ftps.storeFile(remoteFile, input)) { log.debug("uploaded file " + localFile.getAbsolutePath() + " to " + remotePath + "/" + remoteFile +" done."); } else { } input.close(); } catch (Exception e) { log.error("upload file error " + e.getMessage(), e); } } return true; } else { return false; } } catch (Exception e) { e.printStackTrace(); log.error("putMultipleFile error " + e.getMessage(), e); return false; } finally { disconnect(ftps); } } public static List listFile(String hostname, int port, String username, String password, String remotePath) { Logger log = Logger.getLogger(FTPSecureUtil.class); List list = new ArrayList(); FTPSClient ftps = null; try { log.debug("opening ftp server " + hostname + " port " + port); ftps = connectSecure(hostname, port, username, password); if (ftps != null && ftps.isConnected()) { //ftp.cd(remotePath); ftps.setFileType(FTP.BINARY_FILE_TYPE); //ftps.changeWorkingDirectory(remotePath); //ftps.pwd(); FTPFile[] listNames = ftps.listFiles(remotePath); list = new ArrayList(); if (listNames != null && listNames.length > 0) { log.debug("File on ftps " + remotePath + " founds."); for (int i = 0; i < listNames.length; i++) { FTPFile fname = listNames[i]; log.debug("File: " + fname.getName()); list.add(remotePath + "/" + fname.getName()); } } else { log.debug("File on ftps " + remotePath + " not found."); } return list; } else { return list; } } catch (Exception e) { e.printStackTrace(); log.error(e); return null; } finally { disconnect(ftps); } } public static void main(String args[]){ try { FTPSClient ftps = FTPSecureUtil.connectSecure("10.28.103.145", 990, "fbi", "fbi", "LP",""); FTPFile[] ftpFiles = ftps.listFiles(); for (int i = 0; i < ftpFiles.length; i++) { FTPFile fTPFile = ftpFiles[i]; System.out.println(fTPFile.getName()); } } catch (Exception ex) { ex.printStackTrace(); } } // private static SSLContext getSSLContext() throws KeyManagementException, KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, UnrecoverableKeyException, IOException { // TrustManager[] tm = getTrustManagers(); // //log.debug("Init SSL Context"); // SSLContext sslContext = SSLContext.getInstance("SSLv3"); // sslContext.init(null, tm, null); // // return sslContext; // } private static KeyManager[] getKeyManagers() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException { KeyStore ks = KeyStore.getInstance("JKS"); //ks.load(new FileInputStream(KEYSTORE_FILE_NAME), KEYSTORE_PASS.toCharArray()); ks.load(FTPSecureUtil.class.getResourceAsStream(KEYSTORE_FILE_NAME), KEYSTORE_PASS.toCharArray()); KeyManagerFactory tmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); tmf.init(ks, KEYSTORE_PASS.toCharArray()); return tmf.getKeyManagers(); } private static TrustManager[] getTrustManagers() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException { KeyStore ks = KeyStore.getInstance("JKS"); //ks.load(new FileInputStream(KEYSTORE_FILE_NAME), KEYSTORE_PASS.toCharArray()); ks.load(FTPSecureUtil.class.getResourceAsStream(KEYSTORE_FILE_NAME), KEYSTORE_PASS.toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); tmf.init(ks); return tmf.getTrustManagers(); } }