Java tutorial
/* * Copyright (C) 2013 zANGETSu * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package com.ibm.soatf.component.ftp; import com.ibm.soatf.component.AbstractSoaTFComponent; import com.ibm.soatf.component.SOATFCompType; import com.ibm.soatf.component.file.FileComponent; import com.ibm.soatf.config.iface.IfaceExecBlock; import com.ibm.soatf.config.iface.ftp.FTPConfig; import com.ibm.soatf.config.iface.ftp.Security; import com.ibm.soatf.config.master.FTPServers.FtpServer.Directories; import com.ibm.soatf.config.master.FTPServers.FtpServer.FtpServerInstance; import com.ibm.soatf.config.master.Operation; import com.ibm.soatf.flow.FlowExecutor; import com.ibm.soatf.flow.FrameworkExecutionException; import com.ibm.soatf.flow.OperationResult; import com.ibm.soatf.gui.ProgressMonitor; import com.ibm.soatf.tool.FileSystem; import com.ibm.soatf.tool.Utils; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import com.jcraft.jsch.SftpException; import it.sauronsoftware.ftp4j.FTPAbortedException; import it.sauronsoftware.ftp4j.FTPClient; import it.sauronsoftware.ftp4j.FTPDataTransferException; import it.sauronsoftware.ftp4j.FTPException; import it.sauronsoftware.ftp4j.FTPFile; import it.sauronsoftware.ftp4j.FTPIllegalReplyException; import it.sauronsoftware.ftp4j.FTPListParseException; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Iterator; import java.util.Vector; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.TrueFileFilter; import org.apache.commons.io.filefilter.WildcardFileFilter; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * * @author Ladislav Jech <archenroot@gmail.com> */ public class FTPComponent extends AbstractSoaTFComponent { private static final Logger logger = LogManager.getLogger(FTPComponent.class); private final FtpServerInstance ftpMasterConfig; //private final FTPConfig ftpConfiguration; private final FTPConfig.File ftpFile; private final Directories directories; private String hostName; private int port; private String user; private String password; private Security security; private String stageDirectory; private String errorDirectory; private String archiveDirectory; private String fileContent; private String fileName; private String actualFileUsed; private final OperationResult cor; public FTPComponent(IfaceExecBlock ifaceExecBlock, FtpServerInstance ftpMasterConfig, FTPConfig.File ftpFile, Directories directories, File workingDir) { super(SOATFCompType.FTP); this.ftpMasterConfig = ftpMasterConfig; //this.ftpConfiguration = ftpInterfaceConfig; this.ftpFile = ftpFile; this.actualFileUsed = ""; this.directories = directories; this.workingDir = workingDir; cor = OperationResult.getInstance(); constructComponent(); } /*public FTPComponent(ComponentResult componentOperationResult) { super(SOATFCompType.FTP, componentOperationResult); this.hostName = "zarik"; this.port = "21"; this.user = "anonymous"; this.password = "aaa"; this.security = Security.NONE; this.stageDirectory = "salmon/out"; this.errorDirectory = "salmon/error"; this.archiveDirectory = "salmon/archive"; //this.filePattern = this.ftpConfiguration.getFilePattern(); this.fileName = "test.data"; workingDirectoryPath = "C:\\test\\"; }*/ @Override protected final void constructComponent() { this.hostName = this.ftpMasterConfig.getHostName(); this.port = this.ftpMasterConfig.getPort(); this.user = this.ftpMasterConfig.getUser(); this.password = this.ftpMasterConfig.getPassword(); this.security = Security.valueOf(this.ftpMasterConfig.getSecurity()); this.stageDirectory = directories.getStageDirectory(); this.errorDirectory = directories.getErrorDirectory(); this.archiveDirectory = directories.getArchiveDirectory(); /* * Fast workaround related to multiple data sources */ //this.fileContent = this.ftpConfiguration.getFileContent(); //this.fileName = this.ftpConfiguration.getFileName(); this.fileContent = this.ftpFile.getFileContent(); //if (this.fileContent != null) fileContent = fileContent.trim(); this.fileName = this.ftpFile.getFileName(); } @Override public void executeOperation(Operation operation) throws FrameworkExecutionException { //cor.setOperation(operation); //nastavuje konstruktor abstractoperation /*if (!FTP_OPERATIONS.contains(operation)) { final String msg = "Unsupported operation: " + operation.getName().value() + ". Valid operations are: " + FTP_OPERATIONS; logger.error(msg); cor.addMsg(msg); cor.setOverallResultSuccess(false); } else {*/ actualFileUsed = generateFile(this.workingDir, this.fileName, this.fileContent).getName();//(this.workingDir, this.fileName, this.fileContent).getName(); switch (operation.getName()) { case FTP_DOWNLOAD_FILE: ftpDownloadFile(); break; case FTP_UPLOAD_FILE: //generateFile(); ftpUploadFile(); break; case FTP_CHECK_DELIVERED_FOLDER_FOR_FILE: checkFolderForFile(this.archiveDirectory); break; case FTP_CHECK_ERROR_FOLDER_FOR_FILE: checkFolderForFile(this.errorDirectory); break; case FTP_SEARCH_FOR_FILE: checkFolderForFile(this.stageDirectory); break; default: logger.info("Operation execution not yet implemented: " + operation.getName().value()); cor.addMsg("Operation: " + operation.getName().value() + " is valid, but not yet implemented"); } } private void ftpDownloadFile() throws FtpComponentException { FTPClient client = null; try { switch (security) { case NONE: /* * This implementation is just for testing purposes, there are currently 2 libraries for FTP, SFTP, FTPS and FTPES. * Once I will wrap them into one client object, the usage will change. */ client = new FTPClient(); client.connect(this.hostName, this.port); client.login(this.user, this.password); client.changeDirectory(this.stageDirectory); File localFile = new File(workingDir, actualFileUsed); client.download(fileName, localFile); logger.info("File with name '" + fileName + "' was downloaded from: " + this.stageDirectory); cor.addMsg("File with name '" + fileName + "' was downloaded from: " + this.stageDirectory); cor.markSuccessful(); break; default: final String msg = "Security type not supported: " + security; logger.info(msg); cor.addMsg(msg); throw new FtpComponentException(msg); } } catch (IllegalStateException | FTPException | IOException | FTPIllegalReplyException | FTPDataTransferException | FTPAbortedException ftpex) { final String msg = "Error while downloading the file."; cor.addMsg(msg); throw new FtpComponentException(msg, ftpex); } finally { if (client != null) { try { client.disconnect(true); } catch (IllegalStateException | IOException | FTPIllegalReplyException | FTPException ex) { ; } } } } private void checkFolderForFile(String folderName) throws FtpComponentException { FTPClient client = null; if (actualFileUsed == null) { final String msg = "File name was not set."; cor.addMsg(msg); throw new FtpComponentException(msg); } switch (security) { case NONE: try { ProgressMonitor.init(5, "Connecting to FTP server..."); client = new FTPClient(); client.connect(this.hostName, this.port); ProgressMonitor.increment("Logging in..."); client.login(this.user, this.password); ProgressMonitor.increment("Changing directory..."); client.changeDirectory(folderName); ProgressMonitor.increment("Listing files..."); FTPFile[] fileArray = client.list(); boolean found = false; for (FTPFile file : fileArray) { String name = file.getName(); if (name != null && (name.equals(actualFileUsed) || name.endsWith("__" + actualFileUsed))) { found = true; break; } } if (found) { logger.info("File with name '" + actualFileUsed + "' was found in directory: " + folderName); cor.addMsg("File with name '" + actualFileUsed + "' was found in directory: " + folderName); cor.markSuccessful(); } else { final String message = "File with name '" + actualFileUsed + "' was not found in directory: " + folderName; logger.info(message); cor.addMsg(message); String additionalMessage = null; client.changeDirectory(this.stageDirectory); fileArray = client.list(); for (int i = 0; i < fileArray.length; i++) { FTPFile file = fileArray[i]; String name = file.getName(); if (name != null && (name.equals(actualFileUsed) || name.endsWith("__" + actualFileUsed))) { additionalMessage = "The file was found in the original directory, it seems not to be polled at all.\n"; break; } } if (additionalMessage == null) { client.changeDirectory(this.errorDirectory); fileArray = client.list(); for (int i = 0; i < fileArray.length; i++) { FTPFile file = fileArray[i]; String name = file.getName(); if (name != null && (name.equals(actualFileUsed) || name.endsWith("__" + actualFileUsed))) { additionalMessage = "The file was found in the error directory. There was an error while processing the file."; break; } } } if (additionalMessage == null) { client.changeDirectory(this.archiveDirectory); fileArray = client.list(); for (int i = 0; i < fileArray.length; i++) { FTPFile file = fileArray[i]; String name = file.getName(); if (name != null && (name.equals(actualFileUsed) || name.endsWith("__" + actualFileUsed))) { additionalMessage = "The file was found in the archive directory. File was processed without any errors."; break; } } } cor.addMsg(additionalMessage); throw new FtpComponentException(message); } break; } catch (FTPException | FTPIllegalReplyException | IllegalStateException | IOException | FTPDataTransferException | FTPAbortedException | FTPListParseException ftpex) { final String msg = "FTP error while trying to search in the remote folder"; cor.addMsg(msg); throw new FtpComponentException(msg, ftpex); } finally { ProgressMonitor.increment("Disconnecting..."); if (client != null) { try { client.disconnect(true); } catch (IllegalStateException | IOException | FTPIllegalReplyException | FTPException ex) { ; } } } case SSH: Session session = null; ChannelSftp channelSftp = null; try { JSch jsch = new JSch(); String sshMsg = "Creating SSH session..."; ProgressMonitor.init(6, sshMsg); logger.info(sshMsg); cor.addMsg(sshMsg, null); session = jsch.getSession(this.user, this.hostName, this.port); session.setPassword(this.password); session.setConfig(FileComponent.CONFIG); sshMsg = "SSH session created."; logger.info(sshMsg); cor.addMsg(sshMsg, null); sshMsg = "Connecting to SSH session..."; ProgressMonitor.increment(sshMsg); logger.info(sshMsg); cor.addMsg(sshMsg, null); session.connect(); sshMsg = "Connected to SSH session."; logger.info(sshMsg); cor.addMsg(sshMsg, null); sshMsg = "Opening SSH channel..."; ProgressMonitor.increment(sshMsg); logger.info(sshMsg); cor.addMsg(sshMsg, null); channelSftp = (ChannelSftp) session.openChannel("sftp"); sshMsg = "SSH channel opened."; logger.info(sshMsg); cor.addMsg(sshMsg, null); sshMsg = "Connecting to SSH channel..."; ProgressMonitor.increment(sshMsg); logger.info(sshMsg); cor.addMsg(sshMsg, null); channelSftp.connect(); sshMsg = "Connected to SSH channel."; logger.info(sshMsg); cor.addMsg(sshMsg); Vector ls; sshMsg = "Listing '" + folderName + "' content..."; ProgressMonitor.increment("Listing directory content..."); logger.info(sshMsg); cor.addMsg(sshMsg); ls = channelSftp.ls(folderName); if (!Utils.isEmpty(ls)) { for (Object object : ls) { ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) object; final String name = entry.getFilename(); if (name != null && (name.equals(actualFileUsed) || name.endsWith("__" + actualFileUsed))) { //if (entry.getFilename().matches(fileName)) { String msg = "File '" + actualFileUsed + "' found in '" + folderName + "'"; logger.info(msg); cor.addMsg(msg); cor.markSuccessful(); return; } } } sshMsg = "File '" + actualFileUsed + "' not found in '" + folderName + "'"; cor.addMsg(sshMsg); String additionalMessage = null; ls = channelSftp.ls(this.stageDirectory); if (!Utils.isEmpty(ls)) { for (Object object : ls) { ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) object; final String name = entry.getFilename(); if (name != null && (name.equals(actualFileUsed) || name.endsWith("__" + actualFileUsed))) { additionalMessage = "The file was found in the original directory, it seems not to be polled at all.\n"; break; } } } if (additionalMessage == null) { ls = channelSftp.ls(this.errorDirectory); if (!Utils.isEmpty(ls)) { for (Object object : ls) { ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) object; final String name = entry.getFilename(); if (name != null && (name.equals(actualFileUsed) || name.endsWith("__" + actualFileUsed))) { additionalMessage = "The file was found in the error directory. There was an error while processing the file."; break; } } } } if (additionalMessage == null) { ls = channelSftp.ls(this.archiveDirectory); if (!Utils.isEmpty(ls)) { for (Object object : ls) { ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) object; final String name = entry.getFilename(); if (name != null && (name.equals(actualFileUsed) || name.endsWith("__" + actualFileUsed))) { additionalMessage = "The file was found in the archive directory. File was processed without any errors."; break; } } } } cor.addMsg(additionalMessage); throw new FtpComponentException(sshMsg); } catch (JSchException | SftpException ftpex) { final String msg = "FTP error while trying to search in the remote folder"; cor.addMsg(msg); throw new FtpComponentException(msg, ftpex); } finally { ProgressMonitor.increment("Disconnecting..."); FileComponent.disconnect(session, channelSftp); } default: final String msg = "Security type not supported: " + security; logger.info(msg); cor.addMsg(msg); throw new FtpComponentException(msg); } } private void ftpUploadFile() throws FtpComponentException { FTPClient client = null; File localFile = new File(workingDir, actualFileUsed); switch (this.security) { case NONE: try { /* * This implementation is just for testing purposes, there are currently 2 libraries for FTP, SFTP, FTPS and FTPES. * Once I will wrap them into one client object, the usage will change. */ ProgressMonitor.init(5, "Connecting to FTP server..."); client = new FTPClient(); client.connect(this.hostName, this.port); ProgressMonitor.increment("Logging in..."); client.login(this.user, this.password); ProgressMonitor.increment("Changing directory..."); client.changeDirectory(this.stageDirectory); ProgressMonitor.increment("Uploading file..."); client.upload(localFile); logger.info("File with name '" + actualFileUsed + "' was uploaded: " + this.stageDirectory); cor.addMsg("File with name '" + actualFileUsed + "' was uploaded to: " + this.stageDirectory); cor.markSuccessful(); } catch (IllegalStateException | IOException | FTPIllegalReplyException | FTPException | FTPDataTransferException | FTPAbortedException ftpex) { final String msg = "FTP error while uploading the file."; cor.addMsg(msg); throw new FtpComponentException(msg, ftpex); } finally { ProgressMonitor.increment("Disconnecting..."); if (client != null) { try { client.disconnect(true); } catch (IllegalStateException | IOException | FTPIllegalReplyException | FTPException ex) { ; } } } break; case SSH: String sshMsg; Session session = null; ChannelSftp channelSftp = null; try { JSch jsch = new JSch(); sshMsg = "Creating SSH session..."; ProgressMonitor.init(8, sshMsg); logger.info(sshMsg); cor.addMsg(sshMsg, null); session = jsch.getSession(this.user, this.hostName, this.port); session.setPassword(this.password); session.setConfig(FileComponent.CONFIG); sshMsg = "SSH session created."; logger.info(sshMsg); cor.addMsg(sshMsg, null); sshMsg = "Connecting to SSH session..."; ProgressMonitor.increment(sshMsg); logger.info(sshMsg); cor.addMsg(sshMsg, null); session.connect(); sshMsg = "Connected to SSH session."; logger.info(sshMsg); cor.addMsg(sshMsg, null); sshMsg = "Opening SSH channel..."; ProgressMonitor.increment(sshMsg); logger.info(sshMsg); cor.addMsg(sshMsg, null); channelSftp = (ChannelSftp) session.openChannel("sftp"); sshMsg = "SSH channel opened."; logger.info(sshMsg); cor.addMsg(sshMsg, null); sshMsg = "Connecting to SSH channel..."; ProgressMonitor.increment(sshMsg); logger.info(sshMsg); cor.addMsg(sshMsg); channelSftp.connect(); sshMsg = "Connected to SSH channel."; logger.info(sshMsg); cor.addMsg(sshMsg); sshMsg = "Changing to '" + this.stageDirectory + "' directory..."; ProgressMonitor.increment("Changing directory..."); logger.info(sshMsg); cor.addMsg(sshMsg); channelSftp.cd(this.stageDirectory); sshMsg = "Directory changed."; logger.info(sshMsg); cor.addMsg(sshMsg); final FileInputStream fis; String destFile = (this.stageDirectory + "/" + actualFileUsed).replaceAll("//", "/"); //ensure that variable doesn't contain double slash sshMsg = "Opening file '%s' for transfer. Destination file is: " + destFile; ProgressMonitor.increment("Opening file for transfer..."); cor.addMsg(sshMsg, "<a href='file://" + localFile.getAbsolutePath() + "'>" + localFile.getAbsolutePath() + "</a>", FileSystem.getRelativePath(localFile)); fis = new FileInputStream(localFile); sshMsg = "Transferring file..."; ProgressMonitor.increment(sshMsg); logger.info(sshMsg); cor.addMsg(sshMsg, null); channelSftp.put(fis, actualFileUsed); sshMsg = "File transfer finished successfully."; logger.info(sshMsg); cor.addMsg(sshMsg); cor.markSuccessful(); } catch (JSchException | SftpException | FileNotFoundException ftpex) { final String msg = "FTP error while uploading the file."; cor.addMsg(msg); throw new FtpComponentException(msg, ftpex); } finally { ProgressMonitor.increment("Disconnecting..."); FileComponent.disconnect(session, channelSftp); } break; default: logger.info("Security type not supported: " + security); cor.addMsg("Security type " + security + " is valid, but not implemented yet."); } } private File generateFile(File path, String fileName, String fileContent) throws FtpComponentException { File localFile = new File(path, Utils.insertTimestampToFilename(fileName, FlowExecutor.getActualRunDate())); if (localFile.exists()) { return localFile; } Writer writer = null; try { writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(localFile), "utf-8")); writer.write(fileContent); writer.flush(); } catch (IOException ex) { //TODO } finally { if (writer != null) { try { writer.close(); } catch (IOException ex) { ; } } } return localFile; } public File getFile(File workingDirectory, String fileName, String fileContent) throws FtpComponentException { String pattern = "*_" + fileName; Iterator<File> it = FileUtils.iterateFiles(workingDirectory, new WildcardFileFilter(pattern), TrueFileFilter.INSTANCE); int count = 0; File f = null; while (it.hasNext()) { ++count; f = it.next(); } if (count == 0) { f = generateFile(workingDirectory, fileName, fileContent); } if (count > 1) { //TODO } return f; } @Override protected void destructComponent() { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } }