package TestingSystem.DVM; import Common.CommonConstants; import Common.Utils.CommonUtils; import Common_old.Constants; import Common_old.Utils.Utils; import GlobalData.Machine.Machine; import GlobalData.RemoteFile.RemoteFile; import GlobalData.User.User; import ProjectData.Project.db_project_info; 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 { //http://www.jcraft.com/jsch/ public int iterations = 0; //для тестирования //-- public ChannelSftp sftpChannel = null; public ChannelShell shellChannel = null; public ChannelExec execChannel = null; //-- JSch jsch = null; Session session = null; //--- PipedInputStream in = null; PipedOutputStream out = null; //--- PipedOutputStream pin = null; PipedInputStream pout = null; InputStreamReader fromServer = null; //--- Machine machine = null; User user = null; //--- public UserConnection(Machine machine_in, User user_in) throws Exception { machine = machine_in; user = user_in; //-- 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(); //--> //создать канал для команд } public void Disconnect() { if (in != null) { try { in.close(); } catch (Exception exception) { CommonUtils.MainLog.PrintException(exception); } } if (out != null) { try { out.close(); } catch (Exception exception) { CommonUtils.MainLog.PrintException(exception); } } if (pin != null) { try { pin.close(); } catch (Exception exception) { CommonUtils.MainLog.PrintException(exception); } } if (pout != null) { try { pout.close(); } catch (Exception exception) { CommonUtils.MainLog.PrintException(exception); } } if (fromServer != null) { try { fromServer.close(); } catch (Exception exception) { CommonUtils.MainLog.PrintException(exception); } } if (sftpChannel != null) sftpChannel.disconnect(); if (shellChannel != null) shellChannel.disconnect(); if (execChannel != null) execChannel.disconnect(); if (session != null) { session.disconnect(); } //---------------------- sftpChannel = null; shellChannel = null; execChannel = null; session = null; //--- in = null; out = null; //--- pin = null; pout = null; fromServer = null; jsch = null; System.gc(); } 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" + CommonUtils.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("*")) { Command("rm -rf " + CommonUtils.DQuotes(dir)); } else throw new PassException("Недопустимый путь для удаления папки " + CommonUtils.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 remote_subdirs = new LinkedHashMap<>(); LinkedHashMap remote_files = new LinkedHashMap<>(); Vector 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 Busy(String file_full_name) throws Exception { try { sftpChannel.lstat(file_full_name); return true; } catch (SftpException e) { if (e.id == ChannelSftp.SSH_FX_PERMISSION_DENIED) { // file busy return false; } else { // something else went wrong throw e; } } } public boolean Busy(RemoteFile file) throws Exception { return Busy(file.full_name); } public boolean Exists(RemoteFile file) throws Exception { return Exists(file.full_name); } //-- public Pair 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 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 " + CommonUtils.DQuotes(directory.full_name) + "\n" + String.join("\n", commands), script_file); //-- Command(CommonUtils.DQuotes(script_file.full_name) + " 1>" + CommonUtils.DQuotes(out.full_name) + " 2>" + CommonUtils.DQuotes(err.full_name)); return new Pair<>(out, err); } public void putResource(RemoteFile dstDirectory, String resource_name) throws Exception { File src = Utils.CreateTempResourceFile(resource_name); RemoteFile dst = new RemoteFile(dstDirectory, resource_name); putSingleFile(src, dst); } boolean compileModule(RemoteFile modulesDirectory, String module_name) throws Exception { String flags = module_name.equals("planner") ? getAvailibleCPPStandard(modulesDirectory) : ""; String command = "g++ -O3 " + flags + " " + CommonUtils.DQuotes(module_name + ".cpp") + " -o " + CommonUtils.DQuotes(module_name); RemoteFile binary = new RemoteFile(modulesDirectory, module_name); //-- if (Exists(binary)) sftpChannel.rm(binary.full_name); //-- performScript(modulesDirectory, command); //-- if (Exists(binary)) { sftpChannel.chmod(0777, binary.full_name); return true; } return false; } String getAvailibleCPPStandard(RemoteFile scriptDirectory) throws Exception { String res = ""; String command = "g++ -v --help 2> /dev/null | sed -n '/^ *-std=\\([^<][^ ]\\+\\).*/ {s//\\1/p}' | grep c++"; Pair oe = performScript(scriptDirectory, command); RemoteFile outFile = oe.getKey(); String out = readFromFile(outFile); //-- RemoteFile cppVersionsInfo = new RemoteFile(scriptDirectory, "cpp_versions.txt"); sftpChannel.rename(outFile.full_name, cppVersionsInfo.full_name); //-- String[] data = out.split("\n"); boolean cpp_17 = false; boolean cpp_11 = false; //определить какие есть версии. for (String version : data) { switch (version) { case "c++17": cpp_17 = true; break; case "c++11": cpp_11 = true; break; } } if (cpp_17) res = "-std=c++17"; else if (cpp_11) res = "-std=c++11"; RemoteFile cppFlag = new RemoteFile(scriptDirectory, "current_ccp_version"); writeToFile(res, cppFlag); return res; } public String compileModules(RemoteFile modulesDirectory) throws Exception { if (!compileModule(modulesDirectory, "launcher")) { return "Не удалось собрать модуль [launcher]"; } if (!compileModule(modulesDirectory, "starter")) { return "Не удалось собрать модуль [starter]"; } if (!compileModule(modulesDirectory, "planner")) { return "Не удалось собрать модуль [planner]"; } return ""; } //-- public void tryRM(RemoteFile file) throws Exception { if (Exists(file)) sftpChannel.rm(file.full_name); } //с проверкой. public boolean tryGetSingleFileWithMaxSize(RemoteFile src, File dst, int maxSize) throws Exception { if (Exists(src)) { if ((maxSize == 0) || (getFileKBSize(src.full_name) <= maxSize)) { getSingleFile(src.full_name, dst.getAbsolutePath()); return true; } else { Utils.WriteToFile(dst, "Размер файла превышает " + maxSize + " KB.\n" + "Файл не загружен. Его можно просмотреть на машине по адресу\n" + CommonUtils.Brackets(src.full_name)); } } return false; } //-- public void SynchronizeProjectSubDirsR(db_project_info project, File local_dir, RemoteFile remote_dir, boolean data) throws Exception { // ShowMessage2("синхронизация: " + local_dir.getName()); Vector local_subdirs = project.getSubdirectoriesSimple(local_dir); Vector local_files = project.getActiveFilesForSynchronization(local_dir, data); //------------------------------------------------------------------------ LinkedHashMap remote_subdirs = new LinkedHashMap<>(); LinkedHashMap remote_files = new LinkedHashMap<>(); Vector 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); } } for (File lsd : local_subdirs) { 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()); SynchronizeProjectSubDirsR(project, lsd, rsd, data); } for (File lf : local_files) { RemoteFile rf = null; if (!remote_files.containsKey(lf.getName())) { rf = new RemoteFile(remote_dir.full_name, lf.getName()); // ShowMessage2(lf.getName()); putSingleFile(lf, rf); } else { rf = remote_files.get(lf.getName()); if (lf.lastModified() > rf.updateTime) { // ShowMessage2(lf.getName()); putSingleFile(lf, rf); } } } } //-- public Vector getFilesByExtensions(RemoteFile dir, String... extensions) throws Exception { Vector res = new Vector<>(); Vector files = sftpChannel.ls(dir.full_name); for (ChannelSftp.LsEntry file : files) { String[] data = file.getFilename().split("\\."); if (data.length > 1) { String file_extension = data[data.length - 1]; for (String extension : extensions) { if (file_extension.equalsIgnoreCase(extension)) res.add(new RemoteFile(dir.full_name, file.getFilename())); } } } return res; } public void deleteFilesByExtensions(RemoteFile dir, String... extensions) throws Exception { Vector to_delete = getFilesByExtensions(dir, extensions); for (RemoteFile file : to_delete) sftpChannel.rm(file.full_name); } public void Command(String... commands) throws Exception { if (commands.length > 0) { String command = String.join("\n", commands); execChannel = (ChannelExec) session.openChannel("exec"); execChannel.setErrStream(System.err); execChannel.setCommand(command); execChannel.connect(); BufferedReader in = new BufferedReader(new InputStreamReader(execChannel.getInputStream())); String line = null; while ((line = in.readLine()) != null) { System.out.println(CommonUtils.Brackets(line)); } } execChannel.disconnect(); } public void CommandNoWait(String... commands) throws Exception { if (commands.length > 0) { String command = String.join("\n", commands); execChannel = (ChannelExec) session.openChannel("exec"); execChannel.setErrStream(System.err); execChannel.setCommand(command); execChannel.connect(); execChannel.disconnect(); } } //----- public void ShellConnect() throws Exception { 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 ShellDisconnect() throws Exception { if (in != null) { try { in.close(); } catch (Exception exception) { CommonUtils.MainLog.PrintException(exception); } } if (out != null) { try { out.close(); } catch (Exception exception) { CommonUtils.MainLog.PrintException(exception); } } if (pin != null) { try { pin.close(); } catch (Exception exception) { CommonUtils.MainLog.PrintException(exception); } } if (pout != null) { try { pout.close(); } catch (Exception exception) { CommonUtils.MainLog.PrintException(exception); } } if (fromServer != null) { try { fromServer.close(); } catch (Exception exception) { CommonUtils.MainLog.PrintException(exception); } } if (shellChannel != null) shellChannel.disconnect(); //-- in = null; out = null; pin = null; pout = null; fromServer = null; shellChannel = null; System.gc(); } public void waitForFileCreation(RemoteFile file) throws Exception { while (!Exists(file)) { System.out.println(file.full_name + " NOT FOUND"); Utils.sleep(1000); } } public void waitForFileFree(RemoteFile file) throws Exception { while (!Busy(file)) { System.out.println(file.full_name + " PERMISSION DENIED"); Utils.sleep(1000); } } public String startShellProcess(RemoteFile directory, String outFileName, String... commands) throws Exception { Vector commands_ = new Vector<>(); commands_.add("cd " + CommonUtils.DQuotes(directory.full_name)); for (int i = 0; i < commands.length; ++i) { if (i == commands.length - 1) { commands_.add(commands[i] + " 1>" + CommonUtils.DQuotes(outFileName)); } else { commands_.add(commands[i]); } } RemoteFile script_file = new RemoteFile(directory, Constants.script); if (Exists(script_file)) sftpChannel.rm(script_file.full_name); writeToFile(String.join("\n", commands_), script_file); String start_command = CommonUtils.DQuotes(script_file.full_name); //-- RemoteFile outFile = new RemoteFile(directory, outFileName); if (Exists(outFile)) sftpChannel.rm(outFile.full_name); ShellConnect(); pin.write(("nohup " + start_command + " &\r\n").getBytes()); waitForFileCreation(outFile); waitForFileFree(outFile); ShellDisconnect(); return readFromFile(outFile).replace("\n", "").replace("\r", ""); } //-- проверка существования рабочего пространства. public void CheckUserInitialization(String email) throws Exception { RemoteFile userWorkspace = new RemoteFile(user.workspace, true); if (!Exists(userWorkspace)) { sftpChannel.mkdir(userWorkspace.full_name); //-- RemoteFile modulesDirectory = new RemoteFile(userWorkspace, "modules"); RemoteFile projectsDirectory = new RemoteFile(userWorkspace, "projects"); RemoteFile testsDirectory = new RemoteFile(userWorkspace, "tests"); //-- Vector subdirectories = new Vector<>(); subdirectories.add(modulesDirectory); subdirectories.add(projectsDirectory); subdirectories.add(testsDirectory); for (RemoteFile remoteFile : subdirectories) sftpChannel.mkdir(remoteFile.full_name); //-- for (String resource_name : Constants.resourses_names) { putResource(modulesDirectory, resource_name); } //- String modules_log = compileModules(modulesDirectory); if (!modules_log.isEmpty()) throw new PassException(modules_log); //-- RemoteFile info = new RemoteFile(userWorkspace, email); user.connection.writeToFile("", info); } } //-- public String CheckModulesVersion() throws Exception { RemoteFile modulesDirectory = new RemoteFile(user.workspace, "modules"); RemoteFile version = new RemoteFile(modulesDirectory, "version.h"); int current_version = CommonConstants.Nan; int actual_version = Constants.planner_version; if (Exists(version)) { try { current_version = Integer.parseInt(readFromFile(version)); } catch (Exception ex) { ex.printStackTrace(); } } if (current_version < actual_version) { for (String resource_name : Constants.resourses_names) { putResource(modulesDirectory, resource_name); } //-- return compileModules(modulesDirectory); } return ""; } }