package Ġorg . hu keh rs . k jsonrpc . server Ċ Ċ import Ġcom . fasterxml . jackson . core . Json Generator Ċ import Ġcom . fasterxml . jackson . core . Json Processing Exception Ċ import Ġcom . fasterxml . jackson . module . kotlin . jackson ObjectMapper Ċ import Ġio . ktor . application . Application Call Ċ import Ġio . ktor . http . HttpStatusCode Ċ import Ġio . ktor . request . authorization Ċ import Ġio . ktor . request . receive Ċ import Ġio . ktor . response . respond Ċ import Ġorg . hu keh rs . k jsonrpc . authentication . Authentication Checker Ċ import Ġorg . hu keh rs . k jsonrpc . authentication . I UserService Ċ import Ġorg . hu keh rs . k jsonrpc . jsonrpc . Json Rpc Exception Ċ import Ġorg . hu keh rs . k jsonrpc . jsonrpc . Method Error Ċ import Ġorg . hu keh rs . k jsonrpc . server . context . Call Context Holder Ċ import Ġorg . slf 4 j . LoggerFactory Ċ Ċ class ĠHttp Json Rpc Server ( private Ġval Ġservices : ĠArray < Any >, Ġprivate Ġval ĠuserService : ĠI UserService ) Ġ{ ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġlog Ġ= ĠLoggerFactory . getLogger ( Http Json Rpc Server :: class . java ) ĊĊĠĠĠĠĠĠĠ Ġval Ġmapper Ġ= Ġj ack son ObjectMapper (). configure ( Json Generator . Feature . IGNORE _ UNKNOWN , Ġtrue ) ĊĊĠĠĠĠĠĠĠ Ġconst Ġval ĠJson Rpc Authorization TokenType Ġ= Ġ" Json Rpc Token " ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġauthentication Checker Ġ= ĠAuthentication Checker () ĊĊĠĠĠ Ġprivate Ġfun Ġcall Method ( authorization Header : ĠString ?, Ġcall : ĠIncoming MethodCall ): ĠOut going MethodResult ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmethod Ġ= ĠMethod Identifier . createFrom FullName ( call . method ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġimpl Ġ= Ġfind And Verify Implementation ( method ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġjson Rpc Token Ġ= Ġvalidate Token And Strip Type ( authorization Header ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġuser Ġ= Ġif ( json Rpc Token Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠuserService . find User By Token OrNull ( json Rpc Token ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif (! authentication Checker . test Authentication ( user , Ġimpl . method , Ġimpl . iface )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠJson Rpc Exception (" authentication Ġfailed ", ĠJson Rpc Exception . error Authentication Failed ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif ( call . params . size Ġ!= Ġimpl . method . parameter Count ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġcreate Invalid Params Error ( call . id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" given Ġparameter Ġcount Ġ(${ call . params . size } Ġ!= Ġrequired Ġ(${ impl . method . parameter Count }") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠCall Context Holder . store Call Context ( null , Ġcall ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . trace (" starting Ġinvoke Ġon Ġproxy ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġimpl . method . invoke ( impl . impl , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ* impl . method . parameter Types . map Indexed Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġindex , Ġcls Ġ-> Ġmapper . tree To Value ( call . params [ index ], Ġcls ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}. to Typed Array ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . trace (" proxy Ġinvoke Ġsuccess ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠOut going MethodResult ( call . id , Ġresult , Ġnull ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġcatch Ġ( throwable : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġwhen ( throwable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠJson Rpc Exception Ġ-> ĠOut going MethodResult ( call . id , Ġnull , ĠMethod Error ( throwable . code , Ġthrowable . message !! , Ġnull )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠIllegalArgumentException Ġ-> Ġcreate Invalid Params Error ( call . id , Ġthrowable . message !! ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠJson Processing Exception Ġ-> Ġcreate Invalid Params Error ( call . id , Ġthrowable . message !! ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> ĠOut going MethodResult ( call . id , Ġnull , ĠMethod Error ( Json Rpc Exception . error Server , Ġthrowable . message ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġ" internal Ġserver Ġerror ", Ġnull )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġvalidate Token And Strip Type ( authorization Header : ĠString ?): ĠString ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġif ( authorization Header Ġ== Ġnull ) ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġif (! authorization Header . startsWith ( Json Rpc Authorization TokenType )) ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġauthorization Header . substring ( Json Rpc Authorization TokenType . length + 1 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcreate Invalid Params Error ( id : ĠInt , Ġmessage : ĠString ): ĠOut going MethodResult Ġ= ĠOut going MethodResult ( id , Ġnull , ĠMethod Error ( Json Rpc Exception . error Invalid Params , Ġmessage , Ġnull )) ĊĊĠĠĠ Ġprivate Ġfun Ġfind And Verify Implementation ( method : ĠMethod Identifier ): ĠCallable Method Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġimpl Ġ= Ġservices ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġservice Ġ-> Ġservice . java Class . interfaces . any Ġ{ Ġit . simple Name Ġ== Ġmethod . iface Ġ} Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġservice . java Class . methods . any Ġ{ Ġit . name Ġ== Ġmethod . methodName Ġ}} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġservice Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCallable Method ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġservice . java Class . methods . first Ġ{ Ġit . name Ġ== Ġmethod . methodName Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġservice , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġservice . java Class . interfaces . first Ġ{ Ġit . simple Name Ġ== Ġmethod . iface Ġ}. kotlin ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. first OrNull () ĊĊĠĠĠĠĠĠĠ Ġif ( impl Ġ!= Ġnull ) ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . debug (" found Ġimplementation Ġfor Ġ$ method : Ġ${ impl . impl } Ġ- Ġ${ impl . method }") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġimpl ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠJson Rpc Exception (" no Ġimplementation Ġfound Ġfor Ġ$ method ", ĠJson Rpc Exception . error Method NotFound ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsuspend Ġfun Ġhandle ( call : ĠApplication Call ) ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmethod Call Ġ= Ġcall . receive < Incoming MethodCall >() ĊĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġcall Method ( call . request . authorization (), Ġmethod Call ) ĊĊĠĠĠĠĠĠĠ Ġval Ġstatus Ġ= Ġif ( result . has Error () Ġ&& Ġis Internal Error ( result . error !!. code )) ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠHttpStatusCode . BadRequest ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġif ( result . has Error ()) ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠHttpStatusCode . BadRequest ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠHttpStatusCode . OK ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcall . respond ( status , Ġresult ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġis Internal Error ( code : ĠInt ) Ġ= Ġcode Ġ< Ġ 0 Ċ }