All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ow2.petals.bc.ftp.connection.WrappedFTPClient Maven / Gradle / Ivy

There is a newer version: 3.9.0
Show newest version
/**
 * Copyright (c) 2007-2012 EBM WebSourcing, 2012-2016 Linagora
 * 
 * This program/library 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.
 * 
 * This program/library 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 Lesser General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program/library; If not, see http://www.gnu.org/licenses/
 * for the GNU Lesser General Public License version 2.1.
 */
package org.ow2.petals.bc.ftp.connection;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.activation.DataHandler;
import javax.activation.FileTypeMap;
import javax.mail.util.ByteArrayDataSource;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.ow2.petals.component.framework.util.FileNamePatternUtil;
import org.ow2.petals.component.framework.util.XMLUtil;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import com.ebmwebsourcing.easycommons.lang.StringHelper;

/**
 * This class handles a connection to the FTP server with the specified configuration parameter.
 * @author Mathieu CARROLLE - EBM WebSourcing
 */
public class WrappedFTPClient extends FTPClient {

    private final FTPConnectionInfo connectionInfo;

    private final transient Logger logger;

    public WrappedFTPClient(final FTPConnectionInfo connectionInfo, final Logger logger) {
        super();
        this.connectionInfo = connectionInfo;
        this.logger = logger;
    }

    /**
     * This method sets :
     * 
    *
  • the working directory
  • *
  • the data connection mode (Active or Passive)
  • *
  • the type of transfer (ASCII or Binary)
  • *
* * @throws IOException */ public void configureConnection() throws IOException { // Working directory boolean cd = true; if (!StringHelper.isNullOrEmpty(connectionInfo.getDirectory())) { cd = this.changeWorkingDirectory(connectionInfo.getDirectory()); } if (cd == false) { throw new IOException("Failed to change directory. Target directory : [" + connectionInfo.getDirectory() + "]"); } logger.fine("FTP server working directory is : " + this.printWorkingDirectory()); // connection mode if (connectionInfo.isPassiveMode()) { this.enterLocalPassiveMode(); logger.fine("enter Passive mode"); } // transfer mode if (connectionInfo.isAsciiTransferType()) { this.setFileType(FTP.ASCII_FILE_TYPE); logger.fine("ascii transfer mode enable"); } else if (connectionInfo.isBinaryTransferType()) { this.setFileType(FTP.BINARY_FILE_TYPE); logger.fine("binary transfer mode enable"); } } /** * Deleted the specified remote file. * * @param remoteFile * Remote file to delete * @throws IOException * @throws InterruptedException */ public void del(final String remoteFile) throws IOException { int numberOfTries = 0; int maxTries = connectionInfo.getAttempt(); boolean deleted = false; while (!deleted) { numberOfTries++; if (numberOfTries > maxTries) { throw new IOException("Error occurred while deleting '" + remoteFile + "' file from the FTP server"); } try { if (this.logger.isLoggable(Level.FINE)) { logger.fine("start deleting '" + remoteFile + "' file from the FTP server"); } deleted = this.deleteFile(remoteFile); } catch (IOException e) { if (numberOfTries == maxTries) { throw e; } else { this.logger.warning("An attempt to delete the file '" + remoteFile + "' failed : " + e.getMessage()); } try { Thread.sleep(connectionInfo.getDelay()); } catch (InterruptedException ex1) { throw new IOException(ex1); } } } } /** * Get a file content from a FTP server. * * @param server * the server * @param port * the port * @param login * the login * @param password * the password * @param filePattern * the remote file * * @return String * @throws InterruptedException * @throws SAXException * @throws FTPBCException * impossible to get: The file does not exist */ public Document get(final String filePattern) throws IOException { Document doc = null; int numberOfTries = 0; final int maxTries = connectionInfo.getAttempt(); while (doc == null) { numberOfTries++; if (numberOfTries > maxTries) { throw new IOException("Error occurred while getting '" + filePattern + "' file from the FTP server"); } try { logger.fine("start getting '" + filePattern + "' file from the FTP server"); final FTPFile[] files = this.listFiles(filePattern); if (files != null && files.length > 0) { doc = getAsDocument(files[0].getName()); } else { throw new IOException("Can not find the specified resource"); } } catch (IOException e) { if (numberOfTries == maxTries) { throw e; } else { this.logger.warning("An attempt to get the file '" + filePattern + "' failed : " + e.getMessage()); } try { Thread.sleep(connectionInfo.getDelay()); } catch (InterruptedException ex1) { throw new IOException(ex1); } } } return doc; } public FTPConnectionInfo getConnectionInfo() { return connectionInfo; } /** * Get a file content from a FTP server. * * @param server * the server * @param port * the port * @param login * the login * @param password * the password * @param filePatternWildCard * the remote file * * @return String * @throws InterruptedException * @throws FTPBCException * impossible to get: The file does not exist */ public DataHandler getFileAsAttachment(final String filePatternWildCard) throws IOException { DataHandler data = null; int numberOfTries = 0; final int maxTries = connectionInfo.getAttempt(); while (data == null) { numberOfTries++; if (numberOfTries > maxTries) { throw new IOException("Error occurred while getting '" + filePatternWildCard + "' file from the FTP server"); } try { logger.fine("start getting '" + filePatternWildCard + "' file from the FTP server"); FTPFile[] files = this.listFiles(filePatternWildCard); if (files != null && files.length > 0) { data = getAsDataHandler(files[0]); } else { throw new IOException("Can not find the specified resource"); } } catch (IOException e) { if (numberOfTries == maxTries) { throw e; } else { this.logger.warning("An attempt to get the file '" + filePatternWildCard + "' failed : " + e.getMessage()); } try { Thread.sleep(connectionInfo.getDelay()); } catch (InterruptedException e1) { throw new IOException(e1); } } } return data; } /** * Connect and log the FTP client with the current configuration * * @throws IOException */ public void connectAndLog() throws IOException { logger.fine("create FTP connection to " + connectionInfo.getServer()); // set encoding before connect to the fTP server this.setControlEncoding(connectionInfo.getEncoding()); this.connect(connectionInfo.getServer(), connectionInfo.getPort()); int reply = this.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { this.disconnect(); throw new IOException("connection to FTP server failed."); } // Login boolean logged = this.login(connectionInfo.getUser(), connectionInfo.getPassword()); if (!logged) { throw new IOException("authentication failed."); } logger.fine(connectionInfo.toString()); } /** * List files from FTP server * * @return * @throws IOException * @throws InterruptedException */ public List listFolderContent() throws IOException { List fileList = new ArrayList(); boolean listAllFiles = false; int numberOfTries = 0; int maxTries = connectionInfo.getAttempt(); while (!listAllFiles) { try { logger.fine("start listing a directory from the FTP server"); for (FTPFile file : this.listFiles()) { if (file.isFile()) { fileList.add(file.getName()); } } listAllFiles = true; } catch (IOException e) { numberOfTries++; if (numberOfTries == maxTries) { throw e; } else { this.logger .warning("An attempt to list a directory failed : " + e.getMessage()); } try { Thread.sleep(connectionInfo.getDelay()); } catch (InterruptedException ex1) { throw new IOException(ex1); } } } return fileList; } public void mDel(List remoteFiles) throws IOException { int numberOfTries = 0; int maxTries = connectionInfo.getAttempt(); boolean deletedAllFile = false; while (!deletedAllFile) { try { if (this.logger.isLoggable(Level.FINE)) { logger.fine("start deleting '" + remoteFiles.toString() + "' file from the FTP server"); } for (String pathname : remoteFiles) { this.deleteFile(pathname); } deletedAllFile = true; } catch (IOException e) { if (numberOfTries == maxTries) { throw e; } else { this.logger.warning("An attempt to delete the file '" + remoteFiles + "' failed : " + e.getMessage()); } try { Thread.sleep(connectionInfo.getDelay()); } catch (InterruptedException ex1) { throw new IOException(ex1); } } } } /** * This method will only get files, it does not include subpath * * @param filePatternWildCardList * @return * @throws IOException * @throws InterruptedException */ public Map mGet(final List filePatternWildCardList) throws IOException { boolean getAllFiles = false; int numberOfTries = 0; int maxTries = connectionInfo.getAttempt(); Map datahandlers = new HashMap<>(); // Construct the fileFilters to match files read from the FTP directory final List fileNameFilters = new LinkedList<>(); for (final String string : filePatternWildCardList) { fileNameFilters.add(FileNamePatternUtil.buildFileNameFilterFromWildCard( string)); } final FilenameFilter filter = FileNamePatternUtil.buildFileNameFilterFromFilters(fileNameFilters); while (!getAllFiles) { try { if (this.logger.isLoggable(Level.FINE)) { logger.fine("start getting files from the FTP server"); } for (FTPFile file : this.listFiles()) { if (file.isFile() && filter.accept(null, file.getName())) { datahandlers.put(file.getName(), getAsDataHandler(file)); } } getAllFiles = true; } catch (IOException e) { numberOfTries++; if (numberOfTries >= maxTries) { throw e; } else { this.logger.warning("An attempt to get a file failed : " + e.getMessage()); } try { Thread.sleep(connectionInfo.getDelay()); } catch (InterruptedException ex1) { throw new IOException(ex1); } } } return datahandlers; } /** * Put files on the FTP server. * * @param attachments * @return * @throws IOException * @throws InterruptedException */ public void mPut(Map attachments) throws IOException { int numberOfTries = 0; int maxTries = connectionInfo.getAttempt(); boolean transmit; boolean isFileExist; for (Entry entry : attachments.entrySet()) { transmit = false; isFileExist = false; while (!transmit) { if (numberOfTries == maxTries) { throw new IOException("Error occurred while storing '" + entry.getKey() + "' file on the FTP server"); } try { logger.fine("start sending '" + entry.getKey() + "' file on the FTP server"); isFileExist = this.fileExistOnRemoteDirectory(entry.getKey()); if (!isFileExist || this.connectionInfo.isOverwrite()) { InputStream stream = entry.getValue().getInputStream(); transmit = this.storeFile(entry.getKey(), stream); stream.close(); } else { // hack to stop retry policy numberOfTries = maxTries; throw new IOException("File [" + entry.getKey() + "] already exists"); } if (transmit) { logger.fine("'" + entry.getKey() + "' sent on the FTP server"); } else { numberOfTries++; } } catch (IOException e) { numberOfTries++; if (numberOfTries >= maxTries) { throw e; } else { this.logger.warning("An attempt to put the file '" + entry.getKey() + "' failed : " + e.getMessage()); } try { Thread.sleep(connectionInfo.getDelay()); } catch (InterruptedException ex1) { throw new IOException(ex1); } } } } } /** * Put the file on the FTP server. * * @param fileName * @param content * @return * @throws IOException * @throws InterruptedException */ public void putString(final String fileName, String content) throws IOException { boolean transmit = false; boolean fileExist = false; int numberOfTries = 0; int maxTries = connectionInfo.getAttempt(); while (!transmit) { numberOfTries++; if (numberOfTries > maxTries) { throw new IOException("Error occurred while storing '" + fileName + "' file on the FTP server"); } try { logger.fine("start sending '" + fileName + "' file on the FTP server"); fileExist = this.fileExistOnRemoteDirectory(fileName); if (!fileExist || this.connectionInfo.isOverwrite()) { OutputStream ops = this.storeFileStream(fileName); ops.write(content.getBytes()); ops.flush(); ops.close(); transmit = this.completePendingCommand(); } else { // hack to stop retry policy numberOfTries = maxTries; throw new IOException("File [" + fileName + "] already exists"); } } catch (IOException e) { if (numberOfTries >= maxTries) { throw e; } else { this.logger.warning("An attempt to put the file '" + fileName + "' failed : " + e.getMessage()); } try { Thread.sleep(connectionInfo.getDelay()); } catch (InterruptedException ex1) { throw new IOException(ex1); } } } logger.fine("'" + fileName + "' sent on the FTP server"); } /*** * Search if the file exist on the remote directory * * @param srcFileName * Name of the file * @param client * @return true if the file exist on the remote directory (case-sensitive) * @throws IOException */ private boolean fileExistOnRemoteDirectory(String srcFileName) throws IOException { boolean fileExist = false; String[] remoteFileNames = this.listNames(); for (String remoteFileName : remoteFileNames) { if (remoteFileName.equals(srcFileName)) { fileExist = true; break; } } return fileExist; } /** * The ftp-client MUST be connected. This method DOES NOT close the * ftp-client * * @param remoteFile * @param client * a ftpclient, MUST be CONNECTED * @return the retrieved file, as a datahandler * @throws IOException * the file is not found or FTP access problem */ private DataHandler getAsDataHandler(FTPFile remoteFile) throws IOException { logger.fine("start receiving file " + remoteFile.getName() + " from FTP server"); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream( (int) remoteFile.getSize()); try { this.retrieveFile(remoteFile.getName(), outputStream); outputStream.flush(); } catch (IOException e) { throw e; } finally { outputStream.close(); } logger.fine(remoteFile.getName() + " file received from FTP server"); final ByteArrayDataSource datasource = new ByteArrayDataSource(outputStream.toByteArray(), FileTypeMap.getDefaultFileTypeMap().getContentType(remoteFile.getName())); datasource.setName(remoteFile.getName()); final DataHandler result = new DataHandler(datasource); logger.fine(remoteFile.getName() + " set as DataHandler"); return result; } /** * Extract the content of the specified XML file and returned it as XML * document * * @param remoteFile * @return the retrieved file, as a Document * @throws IOException * the file is not found or FTP access problem */ private Document getAsDocument(String remoteFileName) throws IOException { final Document doc; if (this.logger.isLoggable(Level.FINE)) { logger.fine("start receiving file " + remoteFileName + " from FTP server"); } final ByteArrayOutputStream bos = new ByteArrayOutputStream(); this.retrieveFile(remoteFileName, bos); bos.flush(); final ByteArrayInputStream is = new ByteArrayInputStream(bos.toByteArray()); try { doc = XMLUtil.loadDocument(is); } catch (SAXException e) { throw new IOException("processed file '" + remoteFileName + "' is not a valid xml file : " + e.getMessage()); } finally { bos.close(); is.close(); } if (this.logger.isLoggable(Level.FINE)) { logger.fine(remoteFileName + " file received from FTP server and set as document"); } return doc; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy