Files
VisualSapfor/src/TestingSystem/DVM/UserConnection.java

238 lines
9.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package TestingSystem.DVM;
import Common.Constants;
import Common.Global;
import Common.Utils.Utils;
import Common.Utils.Validators.ShellParser;
import GlobalData.Machine.Machine;
import GlobalData.RemoteFile.RemoteFile;
import GlobalData.User.User;
import Visual_DVM_2021.Passes.PassException;
import com.jcraft.jsch.*;
import javafx.util.Pair;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Vector;
public class UserConnection {
public ChannelSftp sftpChannel = null;
public ChannelShell shellChannel = null;
//--
JSch jsch = null;
Session session = null;
//---
PipedInputStream in = null;
PipedOutputStream out = null;
//---
PipedOutputStream pin = null;
PipedInputStream pout = null;
InputStreamReader fromServer = null;
//---
public UserConnection(Machine machine, User user) throws Exception {
session = (jsch = new JSch()).getSession(user.login, machine.address, machine.port);
session.setPassword(user.password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect(0);
//-->
//создать канал для файлов
sftpChannel = (ChannelSftp) session.openChannel("sftp");
sftpChannel.connect();
//-->
//создать канал для команд
shellChannel = (ChannelShell) session.openChannel("shell");
in = new PipedInputStream();
out = new PipedOutputStream();
shellChannel.setInputStream(in);
shellChannel.setOutputStream(out);
pin = new PipedOutputStream(in);
pout = new PipedInputStream(out);
shellChannel.connect();
//-
fromServer = new InputStreamReader(pout);
ShellParser.setUserName(user.login);
ShellParser.ReadInvitation(fromServer); //прочитать первое приглашение от машины.
}
public void Disconnect() {
if (in != null) {
try {
in.close();
} catch (Exception exception) {
Global.Log.PrintException(exception);
}
}
if (out != null) {
try {
out.close();
} catch (Exception exception) {
Global.Log.PrintException(exception);
}
}
if (pin != null) {
try {
pin.close();
} catch (Exception exception) {
Global.Log.PrintException(exception);
}
}
if (pout != null) {
try {
pout.close();
} catch (Exception exception) {
Global.Log.PrintException(exception);
}
}
if (fromServer != null) {
try {
fromServer.close();
} catch (Exception exception) {
Global.Log.PrintException(exception);
}
}
if (sftpChannel != null) sftpChannel.disconnect();
if (shellChannel != null) shellChannel.disconnect();
if (session != null) session.disconnect();
//----------------------
sftpChannel = null;
shellChannel = null;
jsch = null;
session = null;
//---
in = null;
out = null;
//---
pin = null;
pout = null;
fromServer = null;
System.gc();
}
//--
//todo из за мусора результатом пользоваться в общем случае невозможно.
//следует перенаправлять вывод в какой нибудь временный файл на сервере.
public String ShellCommand(String command) throws Exception {
StringBuilder result = new StringBuilder();
pin.write((command + "\r\n").getBytes());
ShellParser.ReadInvitation(fromServer); //первое приглашение после эхо. возможен мусор.
result.append(ShellParser.getCommandResult(fromServer)); //возможный результат и второе приглашение.
String[] data = result.toString().split("\n");
return (data.length > 0) ? data[data.length - 1] : result.toString();
}
public void getSingleFile(String src, String dst) throws Exception {
sftpChannel.get(src, dst);
}
public long getFileKBSize(String path) throws Exception {
long size = sftpChannel.lstat(path).getSize();
return size / 1024;
}
public void getSingleFileWithMaxSize(RemoteFile src, File dst, int maxSize) throws Exception {
if ((maxSize == 0) || getFileKBSize(src.full_name) <= maxSize) {
getSingleFile(src.full_name, dst.getAbsolutePath());
} else {
Utils.WriteToFile(dst, "Размер файла превышает " + maxSize + " KB.\n" + "Файл не загружен. Его можно просмотреть на машине по адресу\n" + Utils.Brackets(src.full_name));
}
}
public void putSingleFile(File src, RemoteFile dst) throws Exception {
sftpChannel.put(src.getAbsolutePath(), dst.full_name);
}
//-
public void MKDIR(RemoteFile dir) throws Exception {
if (!Exists(dir)) sftpChannel.mkdir(dir.full_name);
}
//-
public void RMDIR(String dir) throws Exception {
if (!dir.isEmpty() && !dir.equals("/") && !dir.equals("\\") && !dir.equals("*")) {
ShellCommand("rm -rf " + Utils.DQuotes(dir));
} else throw new PassException("Недопустимый путь для удаления папки " + Utils.DQuotes(dir));
}
//-
public void SynchronizeSubDirsR(File local_dir, RemoteFile remote_dir) throws Exception {
File[] local_subdirs = local_dir.listFiles(File::isDirectory);
File[] local_files = local_dir.listFiles(File::isFile);
//------------------------------------------------------------------------
LinkedHashMap<String, RemoteFile> remote_subdirs = new LinkedHashMap<>();
LinkedHashMap<String, RemoteFile> remote_files = new LinkedHashMap<>();
Vector<ChannelSftp.LsEntry> files = sftpChannel.ls(remote_dir.full_name);
for (ChannelSftp.LsEntry file : files) {
if (file.getAttrs().isDir()) {
if (!file.getFilename().equals(".") && !file.getFilename().equals(".."))
remote_subdirs.put(file.getFilename(), new RemoteFile(remote_dir.full_name, file.getFilename(), true));
} else {
RemoteFile rf = new RemoteFile(remote_dir.full_name, file.getFilename());
rf.updateTime = RemoteFile.convertUpdateTime(file.getAttrs().getMTime());
remote_files.put(file.getFilename(), rf);
}
}
if (local_subdirs != null) {
for (File lsd : local_subdirs) {
if (!lsd.getName().equals(Constants.data)) {
RemoteFile rsd = null;
if (!remote_subdirs.containsKey(lsd.getName()))
sftpChannel.mkdir((rsd = new RemoteFile(remote_dir.full_name, lsd.getName(), true)).full_name);
else rsd = remote_subdirs.get(lsd.getName());
SynchronizeSubDirsR(lsd, rsd);
}
}
}
if (local_files != null) {
for (File lf : local_files) {
RemoteFile rf = null;
if (!remote_files.containsKey(lf.getName())) {
rf = new RemoteFile(remote_dir.full_name, lf.getName());
putSingleFile(lf, rf);
} else {
rf = remote_files.get(lf.getName());
if (lf.lastModified() > rf.updateTime) {
putSingleFile(lf, rf);
}
}
}
}
}
public void writeToFile(String text, RemoteFile dst) throws Exception {
sftpChannel.put(new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8)), dst.full_name);
sftpChannel.chmod(0777, dst.full_name);
}
public String readFromFile(RemoteFile src) throws Exception {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
sftpChannel.get(src.full_name, outputStream);
return outputStream.toString(StandardCharsets.UTF_8.name());
}
//--
public boolean Exists(String file_full_name) throws Exception {
try {
sftpChannel.lstat(file_full_name);
return true;
} catch (SftpException e) {
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
// file doesn't exist
return false;
} else {
// something else went wrong
throw e;
}
}
}
public boolean Exists(RemoteFile file) throws Exception {
return Exists(file.full_name);
}
//--
public Pair<RemoteFile, RemoteFile> performScript(RemoteFile directory, String... commands) throws Exception {
RemoteFile script_file = new RemoteFile(directory, Constants.script);
RemoteFile out = new RemoteFile(directory, Constants.out_file);
RemoteFile err = new RemoteFile(directory, Constants.err_file);
//
Vector<RemoteFile> files = new Vector<>();
files.add(script_file);
files.add(out);
files.add(err);
for (RemoteFile file : files) {
if (Exists(file))
sftpChannel.rm(file.full_name);
}
//--
writeToFile("cd " + Utils.DQuotes(directory.full_name)+"\n"+ String.join("\n", commands), script_file);
//--
ShellCommand(script_file.full_name + " 1>" + Utils.DQuotes(out.full_name) + " 2>" + Utils.DQuotes(err.full_name));
return new Pair<>(out, err);
}
}