package org.kisst.gft.ssh;
import com.jcraft.jsch.*;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import org.kisst.gft.filetransfer.FileCouldNotBeMovedException;
import org.kisst.gft.filetransfer.FileServerConnection;
import org.kisst.util.FileUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.LinkedHashMap;
import java.util.Vector;
public class SshFileServerConnection implements FileServerConnection {
private static final Logger logger = LoggerFactory.getLogger(SshFileServerConnection.class);
private final Session session;
private final ChannelSftp sftp;
private final SshFileServer fileserver;
private final SshHost host;
public SshFileServerConnection(SshFileServer fileserver) {
this.fileserver = fileserver;
this.host=fileserver.getSshHost();
session = Ssh.openSession(host);
logger.info("Opening session on host: {}",host);
try {
sftp = (ChannelSftp) session.openChannel("sftp");
sftp.connect();
} catch (JSchException e) { throw new RuntimeException(e);}
}
public ChannelSftp getSftpChannel() { return sftp; }
@Override
public void close() {
logger.info("Closing session on host: {}",host);
sftp.disconnect();
session.disconnect();
}
public boolean fileExists(String path) {
path=fileserver.unixPath(path);
try {
SftpATTRS result = sftp.lstat(path);
return result != null;
}
catch (SftpException e) {
if (e.id==2) // && e.getMessage().equals("SfsStatusCode.NoSuchFile")) {
return false;
throw new RuntimeException(e+" for file "+path,e); }
}
public void deleteFile(String path) {
path=fileserver.unixPath(path);
try {
sftp.rm(path);
} catch (SftpException e) { throw new RuntimeException(e+" for file "+path,e); }
}
public long fileSize(String path) { return getFileAttributes(path).size; }
public long lastModified(String path) { return getFileAttributes(path).modifyTimeMilliSecs; }
public boolean isDirectory(String path) { return getFileAttributes(path).isDirectory; }
public boolean isLocked(String path) {
path=fileserver.unixPath(path);
try {
sftp.rename(path, path);
return false;
}
catch (SftpException e) { e.printStackTrace(); return true; } // TODO: check specific Exception
}
public FileAttributes getFileAttributes(String path) {
path=fileserver.unixPath(path);
try {
SftpATTRS attr = sftp.lstat(path);
return new FileAttributes(1000L*attr.getATime(), 1000L*attr.getMTime(), attr.isDir(), attr.getSize());
} catch (SftpException e) { throw new RuntimeException(e+" for file "+path,e); }
}
@Override
@SuppressWarnings("unchecked")
public LinkedHashMap<String, FileAttributes> getDirectoryEntries(String path) {
try {
path=fileserver.unixPath(path);
logger.info("getting remote diretory: {}",path);
Vector<LsEntry> vv = sftp.ls(path);
logger.info("found {} entries",vv.size());
LinkedHashMap<String,FileAttributes> result = new LinkedHashMap<String,FileAttributes>();
for (LsEntry entry: vv) {
logger.debug("found entry {} - {}",entry.getFilename(), entry.getLongname());
SftpATTRS attr = entry.getAttrs();
result.put(entry.getFilename(),
new FileAttributes(attr.getATime(), attr.getMTime(), attr.isDir(), attr.getSize()));
}
return result;
}
catch (SftpException e) { throw new RuntimeException(e+" for directory "+path,e); }
}
public void move(String path, String newpath) {
path=fileserver.unixPath(path);
newpath=fileserver.unixPath(newpath);
try {
sftp.rename(path, newpath);
}
catch (SftpException e) { throw new FileCouldNotBeMovedException(path, e); }
}
public void getToLocalFile(String remotepath, String localpath) {
remotepath=fileserver.unixPath(remotepath);
try {
logger.info("copy file from remote {} to local {}",remotepath,localpath);
sftp.get(remotepath, localpath);
}
catch (SftpException e) { throw new RuntimeException(e+" for file "+remotepath,e); }
}
public String getFileContentAsString(String remotepath) {
remotepath=fileserver.unixPath(remotepath);
InputStreamReader reader = null;
try {
logger.info("get file from remote {} ",remotepath);
reader = new InputStreamReader(sftp.get(remotepath));
return FileUtil.loadString(reader);
}
catch (SftpException e) { throw new RuntimeException(e+" for file "+remotepath,e); }
finally {
if (reader!=null) {
try {
reader.close();
}
catch (IOException e) { throw new RuntimeException(e);}
}
}
}
public void putStringAsFileContent(String remotepath, String content) {
remotepath=fileserver.unixPath(remotepath);
OutputStreamWriter writer = null;
try {
logger.info("put content to remote {} ",remotepath);
writer = new OutputStreamWriter(sftp.put(remotepath));
writer.write(content);
}
catch (SftpException e) { throw new RuntimeException(e+" for file "+remotepath,e); }
catch (IOException e) { throw new RuntimeException(e+" for file "+remotepath,e); }
finally {
if (writer!=null) {
try {
writer.close();
}
catch (IOException e) { throw new RuntimeException(e+" for file "+remotepath,e);}
}
}
}
@Override
public void putFromLocalFile(String localpath, String remotepath) {
remotepath=fileserver.unixPath(remotepath);
try {
logger.info("copy file from local {} to remote {}",localpath,remotepath);
sftp.put(localpath, remotepath);
}
catch (SftpException e) { throw new RuntimeException(e+" for file "+remotepath,e); }
}
}