package Ġme . alex . pet . apps . zh ish i . data . common Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroidx . sqlite . db . Support SQLite Database Ċ import Ġandroidx . sqlite . db . Support SQLite Open Helper Ċ import Ġandroidx . sqlite . db . framework . Framework SQLite Open Helper Factory Ċ import Ġtim ber . log . Tim ber Ċ import Ġjava . io . File Ċ import Ġjava . io . FileInputStream Ċ import Ġjava . io . File OutputStream Ċ import Ġjava . io . IOException Ċ import Ġjava . nio . ByteBuffer Ċ import Ġjava . util . concurrent . locks . Re entrant Lock ĊĊ Ċ class ĠCopy Open Helper ( ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġcontext : ĠContext , ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġassets Path : ĠString , ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġdatabase Version : ĠInt , ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġdelegate : ĠSupport SQLite Open Helper Ċ ) Ġ: ĠSupport SQLite Open Helper Ġ{ ĊĊĠĠĠ Ġclass ĠDatabase Copy Exception ( message : ĠString , Ġcause : ĠThrowable ? Ġ= Ġnull ) Ġ: ĠRuntimeException ( message , Ġcause ) ĊĊĠĠĠ Ġoverride Ġfun Ġget Database Name (): ĠString ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġdelegate . database Name ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġset Write A head Logging Enabled ( enabled : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ Ġdelegate . set Write A head Logging Enabled ( enabled ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġget Writable Database (): ĠSupport SQLite Database Ġ{ ĊĠĠĠĠĠĠĠ Ġverify Database ( true ) ĊĠĠĠĠĠĠĠ Ġreturn Ġdelegate . writable Database ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġget Readable Database (): ĠSupport SQLite Database Ġ{ ĊĠĠĠĠĠĠĠ Ġverify Database ( false ) ĊĠĠĠĠĠĠĠ Ġreturn Ġdelegate . readable Database ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġverify Database ( writable : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ ĠTim ber . i (" Verify ing Ġdatabase Ġfile ...") ĊĠĠĠĠĠĠĠ Ġval Ġdb File : ĠFile Ġ= Ġcontext . get Database Path ( database Name ) ĊĠĠĠĠĠĠĠ Ġval Ġcopy Lock Ġ= ĠRe entrant Lock () ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcopy Lock . lock () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! db File . exists ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" No Ġdatabase Ġfile Ġfound Ġat Ġ${ db File . absolute Path }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Copy Database File From Assets ( db File , Ġwritable ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" Found Ġdatabase Ġfile Ġ${ db File . absolute Path }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverify Database Version ( db File , Ġwritable ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcopy Lock . unlock () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġverify Database Version ( db File : ĠFile , Ġwritable : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ ĠTim ber . i (" Verify ing Ġexisting Ġdatabase Ġversion ...") ĊĠĠĠĠĠĠĠ Ġval Ġcurrent Version Ġ= Ġtry Read Database Version ( db File ) ĊĠĠĠĠĠĠĠ Ġif Ġ( current Version Ġ!= Ġdatabase Version ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" Database Ġversion Ġis Ġnot Ġup Ġto Ġdate Ġ( current Ġversion Ġ= Ġ$ current Version , Ġrequired Ġversion Ġ= Ġ$ database Version )") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreplace Existing Database ( db File , Ġwritable ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" Database Ġversion Ġis Ġup Ġto Ġdate Ġ( current Ġversion Ġ= Ġ$ current Version )") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġreplace Existing Database ( db File : ĠFile , Ġwritable : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ ĠTim ber . i (" Trying Ġto Ġreplace Ġexisting Ġdatabase ...") ĊĠĠĠĠĠĠĠ Ġif Ġ( context . delete Database ( database Name )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Copy Database File From Assets ( db File , Ġwritable ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠDatabase Copy Exception (" Failed Ġto Ġdelete Ġold Ġversion Ġof Ġthe Ġdatabase Ġfile Ġ$ database Name ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġtry Copy Database File From Assets ( db File : ĠFile , Ġwritable : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcopy Database File From Assets ( db File , Ġwritable ) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠDatabase Copy Exception (" Unable Ġto Ġcopy Ġdatabase Ġfile Ġfrom Ġassets ", Ġe ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcopy Database File From Assets ( destination File : ĠFile , Ġwritable : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ ĠTim ber . i (" At tempting Ġto Ġcopy Ġthe Ġdatabase Ġfrom Ġthe Ġassets ...") ĊĊĠĠĠĠĠĠĠ Ġval Ġtemp File Ġ= ĠFile . create TempFile ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" database ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ". tmp ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontext . cacheDir ĊĠĠĠĠĠĠĠ Ġ). also Ġ{ Ġit . delete On Exit () Ġ} ĊĊĠĠĠĠĠĠĠ Ġcontext . assets . open ( assets Path ). use Ġ{ ĠinputStream Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ ĠFileOutputStream ( temp File ). use Ġ{ ĠoutputStream Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbyte Count Ġ= ĠinputStream . copy To ( output Stream ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTim ber . i (" Copied Ġ$ byte Count ĠB Ġfrom Ġassets Ġto Ġtemp Ġfile ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġparent Ġ= Ġdestination File . parent File ĊĠĠĠĠĠĠĠ Ġif Ġ( parent Ġ!= Ġnull Ġ&& Ġ! parent . exists () Ġ&& Ġ! parent . mkdir s ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Failed Ġto Ġcreate Ġparent Ġdirectories Ġfor Ġ${ destination File . absolute Path }") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġtry Open Database ( temp File , Ġwritable ) ĊĊĠĠĠĠĠĠĠ Ġval Ġassets Db Version Ġ= Ġread Database Version ( temp File ) ĊĠĠĠĠĠĠĠ Ġif Ġ( assets Db Version Ġ!= Ġdatabase Version ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Assets Ġcontain ĠDB Ġwith Ġunexpected Ġversion Ġ( expected Ġ= Ġ$ database Version , Ġactual Ġ= Ġ$ assets Db Version )") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ(! temp File . rename To ( destination File )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Failed Ġto Ġmove Ġtemp Ġfile Ġ${ temp File . absolute Path } Ġto Ġ${ destination File . absolute Path }") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠTim ber . i (" Database Ġhas Ġbeen Ġsuccessfully Ġcopied Ġfrom Ġassets ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġtry Read Database Version ( db File : ĠFile ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġread Database Version ( db File ) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠDatabase Copy Exception (" Unable Ġto Ġread Ġdatabase Ġversion ", Ġe ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġread Database Version ( db File : ĠFile ): ĠInt Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠFileInputStream ( db File ). channel . use Ġ{ Ġinput Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinput . try Lock ( 6 0 , Ġ 4 , Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinput . position ( 6 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbuffer Ġ= ĠByteBuffer . allocate ( 4 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠnumOf Read Bytes Ġ= Ġinput . read ( buffer ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( num Of Read Bytes Ġ!= Ġ 4 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Bad Ġdatabase Ġheader , Ġunable Ġto Ġread Ġ 4 Ġbytes Ġat Ġoffset Ġ 6 0 ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuffer . rewind () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuffer . int ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġtry Open Database ( database File : ĠFile , Ġwritable : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ Ġcreate Framework Open Helper ( database File ). use Ġ{ Ġhelper Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( writable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhelper . writable Database ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhelper . readable Database ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcreate Framework Open Helper ( database File : ĠFile ): ĠSupport SQLite Open Helper Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġdatabase Name Ġ= Ġdatabase File . name ĊĠĠĠĠĠĠĠ Ġval Ġversion Ġ= Ġtry Read Database Version ( database File ) ĊĠĠĠĠĠĠĠ Ġval Ġfactory Ġ= ĠFramework SQLite Open Helper Factory () ĊĠĠĠĠĠĠĠ Ġval Ġconfiguration Ġ= ĠSupport SQLite Open Helper . Configuration . builder ( context ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. name ( database Name ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. callback ( object Ġ: ĠSupport SQLite Open Helper . Callback ( version ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun ĠonCreate ( db : ĠSupport SQLite Database ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠDo Ġnothing ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Upgrade ( db : ĠSupport SQLite Database , Ġold Version : ĠInt , Ġnew Version : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠDo Ġnothing ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠ Ġreturn Ġfactory . create ( configuration ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġclose () Ġ{ ĊĠĠĠĠĠĠĠ Ġdelegate . close () ĊĠĠĠ Ġ} Ċ }