
fi.evolver.utils.ftp.RemoteConnection Maven / Gradle / Ivy
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