use of com.jcraft.jsch.ChannelSftp in project nifi by apache.
the class SFTPTransfer method getRemoteFileInfo.
@Override
@SuppressWarnings("unchecked")
public FileInfo getRemoteFileInfo(final FlowFile flowFile, final String path, String filename) throws IOException {
final ChannelSftp sftp = getChannel(flowFile);
final String fullPath;
if (path == null) {
fullPath = filename;
int slashpos = filename.lastIndexOf('/');
if (slashpos >= 0 && !filename.endsWith("/")) {
filename = filename.substring(slashpos + 1);
}
} else {
fullPath = path + "/" + filename;
}
final Vector<LsEntry> vector;
try {
vector = sftp.ls(fullPath);
} catch (final SftpException e) {
// ls throws exception if filename is not present
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
return null;
} else {
throw new IOException("Failed to obtain file listing for " + fullPath, e);
}
}
LsEntry matchingEntry = null;
for (final LsEntry entry : vector) {
if (entry.getFilename().equalsIgnoreCase(filename)) {
matchingEntry = entry;
break;
}
}
return newFileInfo(matchingEntry, path);
}
use of com.jcraft.jsch.ChannelSftp in project nifi by apache.
the class SFTPTransfer method ensureDirectoryExists.
@Override
public void ensureDirectoryExists(final FlowFile flowFile, final File directoryName) throws IOException {
final ChannelSftp channel = getChannel(flowFile);
final String remoteDirectory = directoryName.getAbsolutePath().replace("\\", "/").replaceAll("^.\\:", "");
// eating any exceptions thrown (like if the directory already exists).
if (disableDirectoryListing) {
try {
channel.mkdir(remoteDirectory);
} catch (SftpException e) {
if (e.id != ChannelSftp.SSH_FX_FAILURE) {
throw new IOException("Could not blindly create remote directory due to " + e.getMessage(), e);
}
}
return;
}
// end if disableDirectoryListing
boolean exists;
try {
channel.stat(remoteDirectory);
exists = true;
} catch (final SftpException e) {
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
// No Such File
exists = false;
} else {
throw new IOException("Failed to determine if remote directory exists at " + remoteDirectory + " due to " + e, e);
}
}
if (!exists) {
// first ensure parent directories exist before creating this one
if (directoryName.getParent() != null && !directoryName.getParentFile().equals(new File(File.separator))) {
ensureDirectoryExists(flowFile, directoryName.getParentFile());
}
logger.debug("Remote Directory {} does not exist; creating it", new Object[] { remoteDirectory });
try {
channel.mkdir(remoteDirectory);
logger.debug("Created {}", new Object[] { remoteDirectory });
} catch (final SftpException e) {
throw new IOException("Failed to create remote directory " + remoteDirectory + " due to " + e, e);
}
}
}
use of com.jcraft.jsch.ChannelSftp in project nifi by apache.
the class SFTPTransfer method getListing.
private void getListing(final String path, final int depth, final int maxResults, final List<FileInfo> listing) throws IOException {
if (maxResults < 1 || listing.size() >= maxResults) {
return;
}
if (depth >= 100) {
logger.warn(this + " had to stop recursively searching directories at a recursive depth of " + depth + " to avoid memory issues");
return;
}
final boolean ignoreDottedFiles = ctx.getProperty(FileTransfer.IGNORE_DOTTED_FILES).asBoolean();
final boolean recurse = ctx.getProperty(FileTransfer.RECURSIVE_SEARCH).asBoolean();
final String fileFilterRegex = ctx.getProperty(FileTransfer.FILE_FILTER_REGEX).getValue();
final Pattern pattern = (fileFilterRegex == null) ? null : Pattern.compile(fileFilterRegex);
final String pathFilterRegex = ctx.getProperty(FileTransfer.PATH_FILTER_REGEX).getValue();
final Pattern pathPattern = (!recurse || pathFilterRegex == null) ? null : Pattern.compile(pathFilterRegex);
final String remotePath = ctx.getProperty(FileTransfer.REMOTE_PATH).evaluateAttributeExpressions().getValue();
// check if this directory path matches the PATH_FILTER_REGEX
boolean pathFilterMatches = true;
if (pathPattern != null) {
Path reldir = path == null ? Paths.get(".") : Paths.get(path);
if (remotePath != null) {
reldir = Paths.get(remotePath).relativize(reldir);
}
if (reldir != null && !reldir.toString().isEmpty()) {
if (!pathPattern.matcher(reldir.toString().replace("\\", "/")).matches()) {
pathFilterMatches = false;
}
}
}
final ChannelSftp sftp = getChannel(null);
final boolean isPathMatch = pathFilterMatches;
final List<LsEntry> subDirs = new ArrayList<>();
try {
final LsEntrySelector filter = new LsEntrySelector() {
@Override
public int select(final LsEntry entry) {
final String entryFilename = entry.getFilename();
// files regardless of ignoring dot files
if (entryFilename.equals(".") || entryFilename.equals("..")) {
return LsEntrySelector.CONTINUE;
}
// ignoring them
if (ignoreDottedFiles && entryFilename.startsWith(".")) {
return LsEntrySelector.CONTINUE;
}
// if is a directory and we're supposed to recurse
if (recurse && entry.getAttrs().isDir()) {
subDirs.add(entry);
return LsEntrySelector.CONTINUE;
}
// FILE_FILTER_REGEX - then let's add it
if (!entry.getAttrs().isDir() && !entry.getAttrs().isLink() && isPathMatch) {
if (pattern == null || pattern.matcher(entryFilename).matches()) {
listing.add(newFileInfo(entry, path));
}
}
if (listing.size() >= maxResults) {
return LsEntrySelector.BREAK;
}
return LsEntrySelector.CONTINUE;
}
};
if (path == null || path.trim().isEmpty()) {
sftp.ls(".", filter);
} else {
sftp.ls(path, filter);
}
} catch (final SftpException e) {
final String pathDesc = path == null ? "current directory" : path;
switch(e.id) {
case ChannelSftp.SSH_FX_NO_SUCH_FILE:
throw new FileNotFoundException("Could not perform listing on " + pathDesc + " because could not find the file on the remote server");
case ChannelSftp.SSH_FX_PERMISSION_DENIED:
throw new PermissionDeniedException("Could not perform listing on " + pathDesc + " due to insufficient permissions");
default:
throw new IOException("Failed to obtain file listing for " + pathDesc, e);
}
}
for (final LsEntry entry : subDirs) {
final String entryFilename = entry.getFilename();
final File newFullPath = new File(path, entryFilename);
final String newFullForwardPath = newFullPath.getPath().replace("\\", "/");
try {
getListing(newFullForwardPath, depth + 1, maxResults, listing);
} catch (final IOException e) {
logger.error("Unable to get listing from " + newFullForwardPath + "; skipping this subdirectory", e);
}
}
}
use of com.jcraft.jsch.ChannelSftp in project nifi by apache.
the class SFTPTransfer method put.
@Override
public String put(final FlowFile flowFile, final String path, final String filename, final InputStream content) throws IOException {
final ChannelSftp sftp = getChannel(flowFile);
// destination path + filename
final String fullPath = (path == null) ? filename : (path.endsWith("/")) ? path + filename : path + "/" + filename;
// temporary path + filename
String tempFilename = ctx.getProperty(TEMP_FILENAME).evaluateAttributeExpressions(flowFile).getValue();
if (tempFilename == null) {
final boolean dotRename = ctx.getProperty(DOT_RENAME).asBoolean();
tempFilename = dotRename ? "." + filename : filename;
}
final String tempPath = (path == null) ? tempFilename : (path.endsWith("/")) ? path + tempFilename : path + "/" + tempFilename;
try {
sftp.put(content, tempPath);
} catch (final SftpException e) {
throw new IOException("Unable to put content to " + fullPath + " due to " + e, e);
}
final String lastModifiedTime = ctx.getProperty(LAST_MODIFIED_TIME).evaluateAttributeExpressions(flowFile).getValue();
if (lastModifiedTime != null && !lastModifiedTime.trim().isEmpty()) {
try {
final DateFormat formatter = new SimpleDateFormat(FILE_MODIFY_DATE_ATTR_FORMAT, Locale.US);
final Date fileModifyTime = formatter.parse(lastModifiedTime);
int time = (int) (fileModifyTime.getTime() / 1000L);
sftp.setMtime(tempPath, time);
} catch (final Exception e) {
logger.error("Failed to set lastModifiedTime on {} to {} due to {}", new Object[] { tempPath, lastModifiedTime, e });
}
}
final String permissions = ctx.getProperty(PERMISSIONS).evaluateAttributeExpressions(flowFile).getValue();
if (permissions != null && !permissions.trim().isEmpty()) {
try {
int perms = numberPermissions(permissions);
if (perms >= 0) {
sftp.chmod(perms, tempPath);
}
} catch (final Exception e) {
logger.error("Failed to set permission on {} to {} due to {}", new Object[] { tempPath, permissions, e });
}
}
final String owner = ctx.getProperty(REMOTE_OWNER).evaluateAttributeExpressions(flowFile).getValue();
if (owner != null && !owner.trim().isEmpty()) {
try {
sftp.chown(Integer.parseInt(owner), tempPath);
} catch (final Exception e) {
logger.error("Failed to set owner on {} to {} due to {}", new Object[] { tempPath, owner, e });
}
}
final String group = ctx.getProperty(REMOTE_GROUP).evaluateAttributeExpressions(flowFile).getValue();
if (group != null && !group.trim().isEmpty()) {
try {
sftp.chgrp(Integer.parseInt(group), tempPath);
} catch (final Exception e) {
logger.error("Failed to set group on {} to {} due to {}", new Object[] { tempPath, group, e });
}
}
if (!filename.equals(tempFilename)) {
try {
sftp.rename(tempPath, fullPath);
} catch (final SftpException e) {
try {
sftp.rm(tempPath);
throw new IOException("Failed to rename dot-file to " + fullPath + " due to " + e, e);
} catch (final SftpException e1) {
throw new IOException("Failed to rename dot-file to " + fullPath + " and failed to delete it when attempting to clean up", e1);
}
}
}
return fullPath;
}
use of com.jcraft.jsch.ChannelSftp in project nifi by apache.
the class SFTPUtils method connectSftp.
public static SFTPConnection connectSftp(final SFTPConfiguration conf) throws JSchException, SftpException, IOException {
final JSch jsch = new JSch();
final Session session = SFTPUtils.createSession(conf, jsch);
final ChannelSftp sftp = (ChannelSftp) session.openChannel("sftp");
sftp.connect();
return new SFTPConnection(session, sftp);
}
Aggregations