/*
* Copyright (C) 2014 GG-Net GmbH - Oliver Günther
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package eu.ggnet.dwoss.misc.op.listings;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.util.Collection;
import org.apache.commons.net.ProtocolCommandEvent;
import org.apache.commons.net.ProtocolCommandListener;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.ggnet.dwoss.mandator.api.service.FtpConfiguration.ConnectionConfig;
import eu.ggnet.dwoss.mandator.api.service.FtpConfiguration.UploadCommand;
import eu.ggnet.saft.api.progress.IMonitor;
import eu.ggnet.dwoss.progress.SubMonitor;
/**
* Plain Logic for file transfer operations.
*
* @author oliver.guenther
*/
public class FtpTransfer {
private final static ProtocolCommandListener PROTOCOL_TO_LOGGER = new ProtocolCommandListener() {
@Override
public void protocolCommandSent(ProtocolCommandEvent event) {
L.info(event.getMessage());
}
@Override
public void protocolReplyReceived(ProtocolCommandEvent event) {
L.info(event.getMessage());
}
};
private final static Logger L = LoggerFactory.getLogger(FtpTransfer.class);
/**
* Uploads a some files to a remove ftp host.
* <p/>
* @param config the config for he connection.
* @param uploads the upload commands
* @param monitor an optional monitor.
* @throws java.net.SocketException
* @throws java.io.IOException
*/
public static void upload(ConnectionConfig config, IMonitor monitor, UploadCommand... uploads) throws SocketException, IOException {
if ( uploads == null || uploads.length == 0 ) return;
SubMonitor m = SubMonitor.convert(monitor, "FTP Transfer", toWorkSize(uploads) + 4);
m.message("verbinde");
m.start();
FTPClient ftp = new FTPClient();
ftp.addProtocolCommandListener(PROTOCOL_TO_LOGGER);
try {
ftp.connect(config.getHost(), config.getPort());
if ( !FTPReply.isPositiveCompletion(ftp.getReplyCode()) ) throw new IOException("FTPReply.isPositiveCompletion(ftp.getReplyCode()) = false");
if ( !ftp.login(config.getUser(), config.getPass()) ) throw new IOException("Login with " + config.getUser() + " not successful");
L.info("Connected to {} idenfied by {}", config.getHost(), ftp.getSystemType());
ftp.setFileType(FTP.BINARY_FILE_TYPE);
ftp.enterLocalPassiveMode();
for (UploadCommand upload : uploads) {
m.worked(1, "uploading to " + upload.getPath());
ftp.changeWorkingDirectory(upload.getPath());
deleteFilesByType(ftp, upload.getDeleteFileTypes());
for (File file : upload.getFiles()) {
m.worked(1, "uploading to " + upload.getPath() + " file " + file.getName());
try (InputStream input = new FileInputStream(file)) {
if ( !ftp.storeFile(file.getName(), input) ) throw new IOException("Cannot store file " + file + " on server!");
}
}
}
m.finish();
} finally {
// just cleaning up
try {
ftp.logout();
} catch (IOException e) {
}
if ( ftp.isConnected() ) {
try {
ftp.disconnect();
} catch (IOException f) {
}
}
}
}
private static void deleteFilesByType(FTPClient ftp, Collection<String> fileTypesToDelete) throws IOException {
if ( fileTypesToDelete == null || fileTypesToDelete.isEmpty() ) return;
FTPFile[] existingFiles = ftp.listFiles();
if ( existingFiles == null || existingFiles.length == 0 ) return;
for (String type : fileTypesToDelete) {
for (FTPFile ftpFile : existingFiles) {
if ( ftpFile == null ) continue;
if ( ftpFile.getName().toLowerCase().endsWith(type) ) {
if ( !ftp.deleteFile(ftpFile.getName()) ) {
throw new IOException("Could not delete " + ftpFile.getName());
}
}
}
}
}
private static int toWorkSize(UploadCommand[] uploads) {
int size = uploads.length;
for (UploadCommand upload : uploads) {
size += upload.getFiles().size();
}
return size;
}
}