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 ;
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 ;
//--
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 ( ) ;
}
//--
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 " " ;
}
2023-09-17 22:13:42 +03:00
}