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

fi.evolver.utils.ftp.RemoteConnection Maven / Gradle / Ivy

There is a newer version: 3.5.0
Show newest version
package fi.evolver.utils.ftp;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fi.evolver.utils.CharsetUtils;
import fi.evolver.utils.CommunicationException;


public abstract class RemoteConnection implements AutoCloseable {
	private static final Logger LOG = LoggerFactory.getLogger(RemoteConnection.class);

	private Deque dirStack = new ArrayDeque<>();

	public abstract List list(Pattern filter) throws CommunicationException;

	public List listFiles(Pattern filter) throws CommunicationException {
		return list(filter, false);
	}

	public List listDirs(Pattern filter) throws CommunicationException {
		return list(filter, true);
	}

	private List list(Pattern filter, boolean dirs) throws CommunicationException {
		List all = list(filter);
		List results = new ArrayList<>();
		for (RemoteFile file: all) {
			if (file.isDirectory() == dirs)
				results.add(file);
		}
		return results;
	}

	public abstract InputStream download(String remote) throws CommunicationException;

	public InputStream download(RemoteFile file) throws CommunicationException {
		return download(file.getName());
	}

	public String download(RemoteFile file, Charset charset) throws CommunicationException {
		try (InputStreamReader reader = new InputStreamReader(download(file.getName()), charset)) {
			String result = IOUtils.toString(reader);
			if ("UTF-8".equals(charset.name()))
				result = CharsetUtils.removeUtfBom(result);
			return result;
		}
		catch (IOException e) {
			throw new CommunicationException(e, "Failed downloading file %s", file);
		}
	}


	public abstract void rename(String from, String to) throws CommunicationException;

	public abstract void upload(String remote, InputStream local) throws CommunicationException;

	public void upload(String remote, InputStream local, String temp) throws CommunicationException {
		upload(remote, local, temp, false);
	}

	public void upload(String remote, InputStream local, String temp, boolean overwrite) throws CommunicationException {
		RemoteFile sameFilename = stat(remote);
		if (sameFilename != null && sameFilename.isDirectory())
			throw new CommunicationException("Uploading failed. May not overwrite a directory: %s", remote);
		if (!overwrite && sameFilename != null)
			throw new CommunicationException("Uploading failed. Found file with same filename: %s and overwrite == false", remote);

		if (sameFilename != null && temp == null)
			rm(remote);
		upload(temp == null ? remote : temp, local);
		if (temp != null) {
			if (sameFilename != null)
				rm(remote);
			rename(temp, remote);
		}
	}

	public void upload(String remote, String data, Charset charset, String temp) throws CommunicationException {
		upload(remote, new ByteArrayInputStream(data.getBytes(charset)), temp);
	}

	public abstract String pwd() throws CommunicationException;

	public abstract void cd(String directory) throws CommunicationException;

	public abstract void rm(String remote) throws CommunicationException;

	public abstract void rmdir(String remote) throws CommunicationException;

	public abstract void mkdir(String remote) throws CommunicationException;

	public void mkdirs(String remote) throws CommunicationException {
		dirStack.push(pwd());
		if (remote.startsWith("/"))
			cd("/");

		Deque dirs = new ArrayDeque<>(Arrays.asList(remote.replaceFirst("^/", "").replaceFirst("/$", "").split("/")));
		while (!dirs.isEmpty()) {
			try {
				cd(dirs.peekFirst());
				dirs.removeFirst();
			}
			catch (CommunicationException e) {
				LOG.debug("Could not enter directory {}: need to create", dirs.peekFirst(), e);
				break;
			}
		}

		for (String dir: dirs) {
			mkdir(dir);
			cd(dir);
		}

		cd(dirStack.pop());
	}

	public RemoteFile stat(String remote) throws CommunicationException {
		List files = list(Pattern.compile(Pattern.quote(remote)));
		if (files.size() > 1)
			throw new CommunicationException("Got multiple results for %s: %s", remote, files);
		return files.isEmpty() ? null : files.get(0);
	}


	public void pushd(String directory) throws CommunicationException {
		dirStack.push(pwd());
		cd(directory);
	}

	public void popd() throws CommunicationException {
		if (dirStack.isEmpty())
			throw new IllegalStateException("The directory stack is empty");
		cd(dirStack.pop());
	}


	public void delete(RemoteFile... files) throws CommunicationException {
		for (RemoteFile file: files) {
			if (file.isDirectory())
				rmdir(file.getName());
			else
				rm(file.getName());
		}
	}

	@Override
    public abstract void close() throws CommunicationException;

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy