/* Ċ Ġ* ĠCopyright Ġ 2 0 1 8 ĠRealm ĠInc . Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ package Ġio . realm . build transformer . asm Ċ Ċ import Ġio . realm . build transformer . Byte Code MethodName Ċ import Ġio . realm . build transformer . Byte Code TypeDescriptor Ċ import Ġio . realm . build transformer . FieldName Ċ import Ġio . realm . build transformer . QualifiedName Ċ import Ġio . realm . build transformer . asm . visitor s . Annotated Code Strip Visitor Ċ import Ġio . realm . build transformer . asm . visitor s . Annotation Visitor Ċ import Ġio . realm . build transformer . ext . shouldBe Deleted Ċ import Ġorg . object web . asm . Class Reader Ċ import Ġorg . object web . asm . Class Writer Ċ import Ġjava . io . File Ċ Ċ /** Ċ Ġ* ĠTransformer Ġthat Ġwill Ġtransform Ġa Ġpool Ġof Ġclasses Ġby Ġremoving Ġall Ġclasses , Ġmethods Ġand Ġfields Ġannotated Ġwith Ċ Ġ* Ġa Ġgiven Ġannotation . Ċ Ġ* Ċ Ġ* ĠIt Ġdoes Ġso Ġin Ġ 2 Ġpasses Ġusing Ġthe ĠAS M ĠVisitor ĠAPI . ĠThe Ġfirst Ġpass Ġwill Ġgather Ġmetadata Ġabout Ġthe Ġclass Ġhierarchy , Ċ Ġ* Ġthe Ġ 2 nd Ġpass Ġwill Ġdo Ġthe Ġactual Ġtransform . ĠThe ĠAS M ĠTree ĠAPI Ġwas Ġconsidered Ġas Ġwell , Ġbut Ġit Ġdoes Ġnot Ġprovide Ċ Ġ* Ġaccess Ġto Ġreferenced Ġclasses Ġeasily , Ġso Ġtwo Ġpasses Ġwould Ġbe Ġrequired Ġhere Ġas Ġwell Ġand Ġthe ĠVisitor ĠAPI Ġis Ġfaster Ġand Ċ Ġ* Ġrequires Ġless Ġmemory . Ċ Ġ*/ Ċ class ĠClass Pool Transformer ( annotation QualifiedName : ĠQual ified Name , Ġprivate Ġval Ġinput Classes : ĠSet < File >) Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġannotation Descriptor : ĠString Ġ= Ġcreate Descriptor ( annotation QualifiedName ) ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠTransform Ġfiles ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return ĠAll Ġinput Ġfiles , Ġboth Ġthose Ġthat Ġhave Ġbeen Ġmodified Ġand Ġthose Ġthat Ġhave Ġnot . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġtransform (): ĠSet < File > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġ( marked Classes , Ġmarked Methods , Ġmarked Fields ) Ġ= Ġpass 1 () ĊĠĠĠĠĠĠĠ Ġreturn Ġpass 2 ( marked Classes , Ġmarked Methods , Ġmarked Fields ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠPass Ġ 1 : ĠCollect Ġall Ġclasses , Ġinterfaces Ġand Ġenums Ġthat Ġcontain Ġthe Ġgiven Ġannotation . ĠThis Ġinclude Ġboth Ġtop - level ĊĠĠĠĠ Ġ* Ġand Ġinner Ġtypes . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġpass 1 (): ĠTrip le < Set < String >, ĠMap < Byte Code TypeDescriptor , ĠSet < Byte Code MethodName >>, ĠMap < Byte Code TypeDescriptor , ĠSet < FieldName >>> Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmetadata Collector Ġ= ĠAnnotation Visitor ( annotation Descriptor ) ĊĠĠĠĠĠĠĠ Ġinput Classes . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . inputStream (). use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclass Reader Ġ= ĠClass Reader ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclass Reader . accept ( metadata Collector , Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ex : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠRuntimeException (" Failed Ġto Ġcollect Ġdata Ġin : Ġ${ it . absolute Path }", Ġex ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn ĠTrip le ( metadata Collector . annotated Classes , Ġmetadata Collector . annotated Methods , Ġmetadata Collector . annotated Fields ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠPass Ġ 2 : ĠRemove Ġmethods Ġand Ġfields Ġmarked Ġwith Ġthe Ġannotation . ĠClasses Ġthat Ġare Ġremoved ĊĠĠĠĠ Ġ* Ġare Ġinstead Ġmarked Ġfor Ġdeletion Ġas Ġdeleting Ġthe ĠFile Ġis Ġthe Ġresponsibility Ġof Ġthe ĊĠĠĠĠ Ġ* Ġtransform ĠAPI . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġpass 2 ( marked Classes : ĠSet < String >, Ġmarked Methods : ĠMap < Byte Code TypeDescriptor , ĠSet < Byte Code MethodName >>, Ġmarked Fields : ĠMap < Byte Code TypeDescriptor , ĠSet < FieldName >> ): ĠSet < File > Ġ{ ĊĠĠĠĠĠĠĠ Ġinput Classes . forEach Ġ{ Ġclass File Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġresult Ġ= ĠByteArray ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! class File . shouldBe Deleted ) Ġ{ Ġ// ĠRes pect Ġpreviously Ġset Ġdelete Ġflag , Ġso Ġavoid Ġdoing Ġany Ġwork ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclass File . inputStream (). use Ġ{ ĠinputStream Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġwriter Ġ= ĠClass Writer ( 0 ) Ġ// ĠWe Ġdon 't Ġmodify Ġmethods Ġso Ġno Ġreason Ġto Ġre - calculate Ġmethod Ġframes ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclass Rem over Ġ= ĠAnnot ated Code Strip Visitor ( annotation Descriptor , Ġmarked Classes , Ġmarked Methods , Ġmarked Fields , Ġwriter ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġreader Ġ= ĠClass Reader ( inputStream ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreader . accept ( class Rem over , Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult Ġ= Ġif Ġ( class Rem over . delete Class ) ĠByteArray ( 0 ) Ġelse Ġwriter . toByteArray () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclass File . output Stream (). use Ġ{ ĠoutputStream Ġ-> ĠoutputStream . write ( result ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclass File . shouldBe Deleted Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ex : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠRuntimeException ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Failed Ġto Ġremove Ġclass , Ġfield Ġor Ġmethod Ġin : Ġ${ class File . absolute Path }", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġex ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġinput Classes ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCreates Ġthe Ġdescriptor Ġused Ġby ĠAS M Ġto Ġidentify Ġtypes . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġcreate Descriptor ( qualified Name : ĠString ): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġ" L ${ qualified Name . replace (".", Ġ"/") }; " ĊĠĠĠ Ġ} Ċ } Ċ