package Ġcom . lo lo of 6 4 . che sso ex scanner Ċ Ċ import Ġkotlinx . coroutines .* Ċ import Ġkotlinx . coroutines . sync . Mutex Ċ import Ġkotlinx . coroutines . sync . with Lock Ċ import Ġjava . io .* Ċ import Ġjava . util .* Ċ import Ġjava . util . concurrent . atomic . Atomic Boolean Ċ import Ġkotlin . NoSuch ElementException Ċ Ċ sealed Ġclass ĠError Ċ object ĠEngine Not Started Ġ: ĠError () Ċ data Ġclass ĠCannot Start Engine ( val Ġmsg : ĠString ) Ġ: ĠError () Ċ data Ġclass ĠCannot Com municate With Engine ( val Ġmsg : ĠString ) Ġ: ĠError () Ċ data Ġclass ĠMisc Error ( val Ġmsg : ĠString ) Ġ: ĠError () Ċ Ċ class ĠChe ss Engine Runner ( ĊĠĠĠ Ġprivate Ġval Ġengine File : ĠFile , ĊĠĠĠ Ġval Ġerror Callback : Ġ( Error ) Ġ-> ĠUnit Ċ ) Ġ{ ĊĠĠĠ Ġprivate Ġval Ġmutex Ġ= ĠMutex () ĊĠĠĠ Ġvar Ġis Running Ġ= ĠAtomic Boolean ( false ) ĊĠĠĠ Ġvar Ġis U CI Ġ= Ġfalse ĊĠĠĠ Ġvar Ġstarted Ok Ġ= ĠAtomic Boolean ( false ) ĊĠĠĠ Ġvar Ġmain Job : ĠJob ? Ġ= Ġnull ĊĠĠĠ Ġvar Ġprocess : ĠProcess ? Ġ= Ġnull ĊĠĠĠ Ġvar Ġoutput Queue Ġ= ĠLinkedList < String >() ĊĠĠĠ Ġvar Ġprocess BufferedReader : ĠBufferedReader ? Ġ= Ġnull ĊĠĠĠ Ġvar Ġprocess OutputStream : ĠOutputStream ? Ġ= Ġnull ĊĊĠĠĠ Ġfun Ġrun () Ġ= Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠ Ġoutput Queue . clear () ĊĠĠĠĠĠĠĠ Ġ// Ġstarter Ġcoroutine ĊĠĠĠĠĠĠĠ Ġcoroutine Scope Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlaunch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdelay ( 1 0 0 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( started Ok . get () Ġ&& Ġis Running . get () Ġ&& Ġ! is U CI ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġerror Callback ( Engine Not Started ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġrunning Ġengine Ġcoroutine ĊĠĠĠĠĠĠĠ Ġmain Job Ġ= ĠGlobal Scope . launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġengine AbsolutePath Ġ= Ġengine File . absolute Path ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmutex . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Ġ= ĠProcess Builder ( engine AbsolutePath ). start () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( process Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġerror Callback ( Cannot Com municate With Engine ("")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ launch ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( isActive ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠinputStream Ġ= Ġprocess !!. inputStream ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġinput Steam Reader Ġ= ĠInputStreamReader ( inputStream ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess BufferedReader Ġ= ĠBufferedReader ( input Steam Reader , Ġ 8 1 9 2 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess OutputStream Ġ= Ġprocess !!. output Stream ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCor outine Scope ( Dispatch ers . IO ). launch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrun Catch ing Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġfirst Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġline : ĠString ? Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmutex . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġline Ġ= Ġprocess BufferedReader ?. readLine () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( line Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoutput Queue . add ( line !! ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( first ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstarted Ok . set ( true ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Running . set ( true ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfirst Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmutex . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġline Ġ= Ġprocess BufferedReader ?. readLine () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ignore : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ex : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġerror Callback ( Misc Error ( ex . message Ġ?: Ġ"")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ex : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( ex ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠSecurity Exception Ġ-> Ġerror Callback ( Cannot Start Engine ( ex . message Ġ?: Ġ"")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠIOException Ġ-> Ġerror Callback ( Cannot Com municate With Engine ( ex . message Ġ?: Ġ"")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġerror Callback ( Misc Error ( ex . message Ġ?: Ġ"")) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsend Command ( command : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcar riage Return Terminated Cmd Ġ= Ġ"$ command \ n " ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmutex . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( process Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess OutputStream ?. write ( car riage Return Terminated Cmd . toByteArray ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess OutputStream ?. flush () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ignore : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġread Pending Outputs (): ĠArray < String > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresults Ġ= Ġmutable ListOf < String >() ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmutex . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnext Ġ= Ġoutput Queue . remove () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresults . add ( next ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ex : ĠNoSuch ElementException ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġresults . to Typed Array () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġstop () Ġ{ ĊĠĠĠĠĠĠĠ Ġmain Job ?. cancel () ĊĠĠĠĠĠĠĠ Ġprocess BufferedReader ?. close () ĊĠĠĠĠĠĠĠ Ġprocess OutputStream ?. close () ĊĠĠĠ Ġ} Ċ }