2023-11-19 02:12:44 +03:00
package TestingSystem.DVM ;
2023-10-06 22:51:09 +03:00
import Common.Constants ;
2023-09-17 22:13:42 +03:00
import Common.Global ;
import Common.Utils.Utils ;
import Common.Utils.Validators.ShellParser ;
import GlobalData.Machine.Machine ;
import GlobalData.RemoteFile.RemoteFile ;
import GlobalData.User.User ;
2024-01-08 20:37:16 +03:00
import ProjectData.Project.db_project_info ;
2023-11-19 02:12:44 +03:00
import Visual_DVM_2021.Passes.PassException ;
2023-12-04 14:42:36 +03:00
import com.jcraft.jsch.* ;
2023-12-04 20:40:44 +03:00
import javafx.util.Pair ;
2023-09-17 22:13:42 +03:00
import java.io.* ;
import java.nio.charset.StandardCharsets ;
import java.util.LinkedHashMap ;
import java.util.Vector ;
public class UserConnection {
2023-12-15 16:44:14 +03:00
public int iterations = 0 ; //для тестирования
//--
2023-09-17 22:13:42 +03:00
public ChannelSftp sftpChannel = null ;
public ChannelShell shellChannel = null ;
2024-01-08 20:37:16 +03:00
public ChannelExec execChannel = null ;
2023-09-17 22:13:42 +03:00
//--
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 ( ) ;
2024-01-08 20:37:16 +03:00
if ( execChannel ! = null ) execChannel . disconnect ( ) ;
2023-09-17 22:13:42 +03:00
if ( session ! = null ) session . disconnect ( ) ;
//----------------------
sftpChannel = null ;
shellChannel = null ;
2024-01-08 20:37:16 +03:00
execChannel = null ;
2023-09-17 22:13:42 +03:00
jsch = null ;
session = null ;
//---
in = null ;
out = null ;
//---
pin = null ;
pout = null ;
fromServer = null ;
System . gc ( ) ;
}
//--
2023-12-04 14:42:36 +03:00
//todo из за мусора результатом пользоваться в общем случае невозможно.
//следует перенаправлять вывод в какой нибудь временный файл на сервере.
2023-09-17 22:13:42 +03:00
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 ) ;
}
2023-12-04 14:42:36 +03:00
public long getFileKBSize ( String path ) throws Exception {
2023-09-17 22:13:42 +03:00
long size = sftpChannel . lstat ( path ) . getSize ( ) ;
2023-12-04 14:42:36 +03:00
return size / 1024 ;
2023-09-17 22:13:42 +03:00
}
2023-12-04 14:42:36 +03:00
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 ) ) ;
2023-09-17 22:13:42 +03:00
}
}
public void putSingleFile ( File src , RemoteFile dst ) throws Exception {
sftpChannel . put ( src . getAbsolutePath ( ) , dst . full_name ) ;
}
//-
public void MKDIR ( RemoteFile dir ) throws Exception {
2023-12-04 14:42:36 +03:00
if ( ! Exists ( dir ) ) sftpChannel . mkdir ( dir . full_name ) ;
2023-09-17 22:13:42 +03:00
}
//-
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 ) {
2023-10-06 22:51:09 +03:00
if ( ! lsd . getName ( ) . equals ( Constants . data ) ) {
2023-09-17 22:13:42 +03:00
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 ( ) ) ;
}
2023-12-04 14:42:36 +03:00
//--
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 ) ;
}
2023-12-04 20:40:44 +03:00
//--
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 ) ;
}
//--
2023-12-24 01:36:52 +03:00
writeToFile ( " cd " + Utils . DQuotes ( directory . full_name ) + " \ n " + String . join ( " \ n " , commands ) , script_file ) ;
2023-12-04 20:40:44 +03:00
//--
ShellCommand ( script_file . full_name + " 1> " + Utils . DQuotes ( out . full_name ) + " 2> " + Utils . DQuotes ( err . full_name ) ) ;
return new Pair < > ( out , err ) ;
}
2023-12-24 01:36:52 +03:00
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 + " " + Utils . DQuotes ( module_name + " .cpp " ) + " -o " + Utils . 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++ " ;
System . out . println ( command ) ;
Pair < RemoteFile , RemoteFile > oe = performScript ( scriptDirectory , command ) ;
RemoteFile outFile = oe . getKey ( ) ;
String out = readFromFile ( outFile ) ;
String [ ] data = out . split ( " \ n " ) ;
for ( String version : data ) {
System . out . println ( Utils . Brackets ( version ) ) ;
if ( version . equals ( " c++17 " ) ) {
res = " -std=c++17 " ;
break ;
} else if ( version . equals ( " c++11 " ) ) {
res = " -std=c++11 " ;
break ;
}
}
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 " " ;
}
2024-01-08 20:37:16 +03:00
//--
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 " + Utils . 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 < File > local_subdirs = project . getSubdirectoriesSimple ( local_dir ) ;
Vector < File > local_files = project . getActiveFilesForSynchronization ( local_dir , data ) ;
//------------------------------------------------------------------------
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 ) ;
}
}
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 < RemoteFile > getFilesByExtensions ( RemoteFile dir , String . . . extensions ) throws Exception {
Vector < RemoteFile > res = new Vector < > ( ) ;
Vector < ChannelSftp . LsEntry > 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 < RemoteFile > 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 ) ;
// UI.Print(DebugPrintLevel.Session, command);
// UI.Print(DebugPrintLevel.Session, "Creating Exec Channel.");
execChannel = ( ChannelExec ) session . openChannel ( " exec " ) ;
execChannel . setErrStream ( System . err ) ;
execChannel . setCommand ( command ) ;
execChannel . connect ( ) ;
BufferedReader in = new BufferedReader ( new InputStreamReader ( execChannel . getInputStream ( ) ) ) ;
while ( in . readLine ( ) ! = null ) ;
execChannel . disconnect ( ) ;
}
}
public String CommandWithAnswer ( char end , String . . . commands ) throws Exception {
String output = " " ;
if ( commands . length > 0 ) {
String command = String . join ( " \ n " , commands ) ;
// UI.Print(DebugPrintLevel.Session, command);
// UI.Print(DebugPrintLevel.Session, "Creating Exec Channel.");
// System.out.println(Utils.Brackets(command));
execChannel = ( ChannelExec ) session . openChannel ( " exec " ) ;
execChannel . setErrStream ( System . err ) ;
InputStreamReader reader = new InputStreamReader ( execChannel . getInputStream ( ) ) ;
execChannel . setCommand ( command ) ;
execChannel . connect ( ) ;
char [ ] chars = new char [ 1 ] ;
while ( reader . read ( chars ) > = 0 ) if ( chars [ 0 ] = = end ) break ;
else output + = chars [ 0 ] ;
execChannel . disconnect ( ) ;
}
// System.out.println(Utils.Brackets(output));
return output ;
}
public void copy ( RemoteFile src , RemoteFile dst ) throws Exception {
ShellCommand ( " cp " + Utils . DQuotes ( src . full_name ) + " " + Utils . DQuotes ( dst . full_name ) ) ;
}
2023-09-17 22:13:42 +03:00
}