// ĠCopyright Ġ 2 0 1 9 ĠAmazon . com , ĠInc . Ġor Ġits Ġaffiliates . ĠAll ĠRights ĠReserved . Ċ // ĠSPDX - License - Identifier : ĠApache - 2 . 0 Ċ Ċ package Ġsoftware . aws . tool k its . jetbrains . utils Ċ Ċ import Ġcom . intellij . openapi . application . Application Manager Ċ import Ġcom . intellij . openapi . progress . Process Canceled Exception Ċ import Ġorg . jetbrains . annotations . Test Only Ċ import Ġorg . jetbrains . concurrency . Async Promise Ċ import Ġorg . jetbrains . concurrency . Promise Ċ import Ġorg . jetbrains . concurrency . is Pending Ċ import Ġorg . slf 4 j . Logger Ċ import Ġorg . slf 4 j . LoggerFactory Ċ import Ġsoftware . aws . tool k its . core . utils . info Ċ import Ġsoftware . aws . tool k its . resources . message Ċ import Ġjava . nio . file . Files Ċ import Ġjava . nio . file . NoSuch File Exception Ċ import Ġjava . nio . file . Paths Ċ import Ġjava . time . Instant Ċ import Ġjava . util . concurrent . TimeUnit Ċ Ċ /** Ċ Ġ* ĠStores Ġdata Ġrelated Ġto Ġa Ġfile Ġpath . ĠCache Ġis Ġinvalid ated Ġwhen Ġthe Ġcache Ġentry Ġis Ġdetected Ġas Ġstale . Ġ ĠErrors Ġare Ċ Ġ* Ġcached Ġuntil Ġthe Ġunderlying Ġpath Ġis Ġdetected Ġas Ġstale . ĠSt ale Ġis Ġdefined Ġas Ġthe Ġcache Ġentries Ġ( file Ġmodification Ġtime )[ Files . getLast Modified Time ] Ċ Ġ* Ġis Ġolder Ġthan Ġthe Ġpath 's Ġcurrent Ġmodification Ġtime . Ċ Ġ*/ Ċ abstract Ġclass ĠFileInfo Cache < T > Ġ{ ĊĠĠĠ Ġprivate Ġval Ġlogger : ĠLogger Ġ= ĠLoggerFactory . getLogger ( this :: class . java ) ĊĠĠĠ Ġprivate Ġval Ġinfo Cache Ġ= Ġhash Map Of < String , ĠInfo Result < T >>() ĊĠĠĠ Ġprivate Ġval Ġlock Ġ= ĠObject () ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* Ġ@ return ĠA Ġpromise Ġfor Ġthe Ġrequested Ġfile Ġinfo . ĠPromise Ġwill Ġbe Ġresolved Ġwhen Ġthe Ġinfo Ġis Ġready . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġevaluate ( path : ĠString ): ĠPromise < T > Ġ{ ĊĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" Evalu ating Ġ$ path " Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġasync Promise Ġ= ĠAsync Promise < T >() ĊĠĠĠĠĠĠĠ Ġasync Promise ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. on Success Ġ{ Ġresult Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" File Ġinfo Ġevaluation Ġis Ġcompleted : Ġ'$ result '" Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. onError Ġ{ Ġerror Ġ-> Ġ// ĠNeed Ġto Ġset Ġan Ġerror Ġhandler Ġearly , Ġelse Ġthe ĠsetError Ġcall Ġwill Ġthrow ĠAssertionError ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( error Ġ! is ĠProcess Canceled Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info ( error ) Ġ{ Ġ" Failed Ġto Ġevaluate Ġ$ path " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġinfo Result Ġ= Ġsynchronized ( lock ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget Cache Entry ( path , Ġasync Promise ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( info Result . result Ġ== Ġasync Promise Ġ&& Ġasync Promise . is Pending ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠApplication Manager . getApplication (). execute On P ooled Thread Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġget FileInfo ( path ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġasync Promise . set Result ( result ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( t : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġasync Promise . setError ( t ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġinfo Result . result ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġget Cache Entry ( path : ĠString , Ġasync Promise : ĠAsync Promise < T >): ĠInfo Result < T > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcache Entry Ġ= Ġinfo Cache [ path ] ĊĊĠĠĠĠĠĠĠ Ġval Ġcurrent Last Modification Date Ġ= Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFiles . getLast Modified Time ( Paths . get ( path )). to Instant () ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠNoSuch File Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIf Ġunable Ġto Ġget Ġthe Ġcurrent Ġtime , Ġoverride Ġthe Ġcache Ġentry Ġthat Ġthe Ġfile Ġcan 't Ġbe Ġfound ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġasync Promise . setError ( IllegalStateException ( message (" general . file _ not _ found ", Ġpath ))) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Result Ġ= ĠInfo Result ( async Promise , ĠInstant . MIN ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinfo Cache [ path ] Ġ= Ġnew Result ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnew Result ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠIf Ġthe Ġpromise Ġis Ġful filled , Ġand Ġthe Ġpath Ġhas Ġbeen Ġmodified Ġsince Ġlast Ġchecking , Ġwe Ġneed Ġto Ġcheck Ġagain ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( cache Entry Ġ== Ġnull Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ(! cache Entry . result . is Pending Ġ&& Ġcurrent Last Modification Date . is After ( cache Entry . timestamp )) ĊĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" Info Result Ġfor Ġ$ path Ġis Ġeither Ġmissing , Ġor Ġstale . ĠChecking Ġagain " Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Result Ġ= ĠInfo Result ( async Promise , Ġcurrent Last Modification Date ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinfo Cache [ path ] Ġ= Ġnew Result ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnew Result ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcache Entry ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Suppress (" UN CHECK ED _ CAST ") ĊĠĠĠ Ġfun Ġevaluate Blocking ( path : ĠString , Ġblocking Time : ĠInt Ġ= Ġ 5 0 0 , Ġblocking Unit : ĠTimeUnit Ġ= ĠTimeUnit . MILLISECONDS ): ĠT Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġpromise Ġ= Ġevaluate ( path ) ĊĠĠĠĠĠĠĠ Ġreturn Ġpromise . blocking Get ( blocking Time , Ġblocking Unit ). also Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! promise . is Succeeded ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException (" Promise Ġdid Ġnot Ġsucceed Ġsuccessfully ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġas ĠT ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Test Only ĊĠĠĠ Ġfun Ġtest Only GetRequest Cache () Ġ= Ġinfo Cache ĊĊĠĠĠ Ġprotected Ġabstract Ġfun Ġget FileInfo ( path : ĠString ): ĠT ĊĊĠĠĠ Ġdata Ġclass ĠInfo Result < T >( val Ġresult : ĠPromise < T >, Ġinternal Ġval Ġtimestamp : ĠInstant ) Ċ }