cGFja2FnZSBqdW5pdC5mcmFtZXdvcms7CgppbXBvcnQgamF2YS51dGlsLlZlY3RvcjsKaW1wb3J0IGphdmEudXRpbC5FbnVtZXJhdGlvbjsKaW1wb3J0IGphdmEuaW8uUHJpbnRXcml0ZXI7CmltcG9ydCBqYXZhLmlvLlN0cmluZ1dyaXRlcjsKaW1wb3J0IGphdmEubGFuZy5yZWZsZWN0Lio7CgovKioKICogQSA8Y29kZT5UZXN0U3VpdGU8L2NvZGU+IGlzIGEgPGNvZGU+Q29tcG9zaXRlPC9jb2RlPiBvZiBUZXN0cy4KICogSXQgcnVucyBhIGNvbGxlY3Rpb24gb2YgdGVzdCBjYXNlcy4gSGVyZSBpcyBhbiBleGFtcGxlIHVzaW5nCiAqIHRoZSBkeW5hbWljIHRlc3QgZGVmaW5pdGlvbi4KICogPHByZT4KICogVGVzdFN1aXRlIHN1aXRlPSBuZXcgVGVzdFN1aXRlKCk7CiAqIHN1aXRlLmFkZFRlc3QobmV3IE1hdGhUZXN0KCJ0ZXN0QWRkIikpOwogKiBzdWl0ZS5hZGRUZXN0KG5ldyBNYXRoVGVzdCgidGVzdERpdmlkZUJ5WmVybyIpKTsKICogPC9wcmU+CiAqIEFsdGVybmF0aXZlbHksIGEgVGVzdFN1aXRlIGNhbiBleHRyYWN0IHRoZSB0ZXN0cyB0byBiZSBydW4gYXV0b21hdGljYWxseS4KICogVG8gZG8gc28geW91IHBhc3MgdGhlIGNsYXNzIG9mIHlvdXIgVGVzdENhc2UgY2xhc3MgdG8gdGhlCiAqIFRlc3RTdWl0ZSBjb25zdHJ1Y3Rvci4KICogPHByZT4KICogVGVzdFN1aXRlIHN1aXRlPSBuZXcgVGVzdFN1aXRlKE1hdGhUZXN0LmNsYXNzKTsKICogPC9wcmU+CiAqIFRoaXMgY29uc3RydWN0b3IgY3JlYXRlcyBhIHN1aXRlIHdpdGggYWxsIHRoZSBtZXRob2RzCiAqIHN0YXJ0aW5nIHdpdGggInRlc3QiIHRoYXQgdGFrZSBubyBhcmd1bWVudHMuCiAqCiAqIEBzZWUgVGVzdAogKi8KcHVibGljIGNsYXNzIFRlc3RTdWl0ZSBpbXBsZW1lbnRzIFRlc3QgewoKCXByaXZhdGUgVmVjdG9yIGZUZXN0cz0gbmV3IFZlY3RvcigxMCk7Cglwcml2YXRlIFN0cmluZyBmTmFtZTsKCiAgIC8qKgoJICogQ29uc3RydWN0cyBhbiBlbXB0eSBUZXN0U3VpdGUuCgkgKi8KCXB1YmxpYyBUZXN0U3VpdGUoKSB7Cgl9CgkvKioKCSAqIENvbnN0cnVjdHMgYSBUZXN0U3VpdGUgZnJvbSB0aGUgZ2l2ZW4gY2xhc3MuIEFkZHMgYWxsIHRoZSBtZXRob2RzCgkgKiBzdGFydGluZyB3aXRoICJ0ZXN0IiBhcyB0ZXN0IGNhc2VzIHRvIHRoZSBzdWl0ZS4KCSAqIFBhcnRzIG9mIHRoaXMgbWV0aG9kIHdhcyB3cml0dGVuIGF0IDIzMzcgbWV0ZXJzIGluIHRoZSBI/GZmaWj8dHRlLAoJICogS2FudG9uIFVyaQoJICovCgoJIHB1YmxpYyBUZXN0U3VpdGUoZmluYWwgQ2xhc3MgdGhlQ2xhc3MpIHsKCQlmTmFtZT0gdGhlQ2xhc3MuZ2V0TmFtZSgpOwoJCUNvbnN0cnVjdG9yIGNvbnN0cnVjdG9yPSBudWxsOwoJCXRyeSB7CQoJCQljb25zdHJ1Y3Rvcj0gZ2V0Q29uc3RydWN0b3IodGhlQ2xhc3MpOwoJCX0gY2F0Y2ggKE5vU3VjaE1ldGhvZEV4Y2VwdGlvbiBlKSB7CgkJCWFkZFRlc3Qod2FybmluZygiQ2xhc3MgIit0aGVDbGFzcy5nZXROYW1lKCkrIiBoYXMgbm8gcHVibGljIGNvbnN0cnVjdG9yIFRlc3RDYXNlKFN0cmluZyBuYW1lKSIpKTsKCQkJcmV0dXJuOwoJCX0KCgkJaWYgKCFNb2RpZmllci5pc1B1YmxpYyh0aGVDbGFzcy5nZXRNb2RpZmllcnMoKSkpIHsKCQkJYWRkVGVzdCh3YXJuaW5nKCJDbGFzcyAiK3RoZUNsYXNzLmdldE5hbWUoKSsiIGlzIG5vdCBwdWJsaWMiKSk7CgkJCXJldHVybjsKCQl9CgoJCUNsYXNzIHN1cGVyQ2xhc3M9IHRoZUNsYXNzOwoJCVZlY3RvciBuYW1lcz0gbmV3IFZlY3RvcigpOwoJCXdoaWxlIChUZXN0LmNsYXNzLmlzQXNzaWduYWJsZUZyb20oc3VwZXJDbGFzcykpIHsKCQkJTWV0aG9kW10gbWV0aG9kcz0gc3VwZXJDbGFzcy5nZXREZWNsYXJlZE1ldGhvZHMoKTsKCQkJZm9yIChpbnQgaT0gMDsgaSA8IG1ldGhvZHMubGVuZ3RoOyBpKyspIHsKCQkJCWFkZFRlc3RNZXRob2QobWV0aG9kc1tpXSwgbmFtZXMsIGNvbnN0cnVjdG9yKTsKCQkJfQoJCQlzdXBlckNsYXNzPSBzdXBlckNsYXNzLmdldFN1cGVyY2xhc3MoKTsKCQl9CgkJaWYgKGZUZXN0cy5zaXplKCkgPT0gMCkKCQkJYWRkVGVzdCh3YXJuaW5nKCJObyB0ZXN0cyBmb3VuZCBpbiAiK3RoZUNsYXNzLmdldE5hbWUoKSkpOwoJfQogICAJLyoqCgkgKiBDb25zdHJ1Y3RzIGFuIGVtcHR5IFRlc3RTdWl0ZS4KCSAqLwoJcHVibGljIFRlc3RTdWl0ZShTdHJpbmcgbmFtZSkgewoJCWZOYW1lPSBuYW1lOwoJfQoJLyoqCgkgKiBBZGRzIGEgdGVzdCB0byB0aGUgc3VpdGUuCgkgKi8KCXB1YmxpYyB2b2lkIGFkZFRlc3QoVGVzdCB0ZXN0KSB7CgkJZlRlc3RzLmFkZEVsZW1lbnQodGVzdCk7Cgl9CgkKCS8qKgoJICogQWRkcyB0aGUgdGVzdHMgZnJvbSB0aGUgZ2l2ZW4gY2xhc3MgdG8gdGhlIHN1aXRlCgkgKi8KCXB1YmxpYyB2b2lkIGFkZFRlc3RTdWl0ZShDbGFzcyB0ZXN0Q2xhc3MpIHsKCQlhZGRUZXN0KG5ldyBUZXN0U3VpdGUodGVzdENsYXNzKSk7Cgl9CgoJcHJpdmF0ZSB2b2lkIGFkZFRlc3RNZXRob2QoTWV0aG9kIG0sIFZlY3RvciBuYW1lcywgQ29uc3RydWN0b3IgY29uc3RydWN0b3IpIHsKCQlTdHJpbmcgbmFtZT0gbS5nZXROYW1lKCk7CgkJaWYgKG5hbWVzLmNvbnRhaW5zKG5hbWUpKSAKCQkJcmV0dXJuOwoJCWlmIChpc1B1YmxpY1Rlc3RNZXRob2QobSkpIHsKCQkJbmFtZXMuYWRkRWxlbWVudChuYW1lKTsKCgkJCU9iamVjdFtdIGFyZ3M9IG5ldyBPYmplY3RbXXtuYW1lfTsKCQkJdHJ5IHsKCQkJCWFkZFRlc3QoKFRlc3QpY29uc3RydWN0b3IubmV3SW5zdGFuY2UoYXJncykpOwoJCQl9IGNhdGNoIChJbnN0YW50aWF0aW9uRXhjZXB0aW9uIGUpIHsKCQkJCWFkZFRlc3Qod2FybmluZygiQ2Fubm90IGluc3RhbnRpYXRlIHRlc3QgY2FzZTogIituYW1lKyIgKCIrZXhjZXB0aW9uVG9TdHJpbmcoZSkrIikiKSk7CgkJCX0gY2F0Y2ggKEludm9jYXRpb25UYXJnZXRFeGNlcHRpb24gZSkgewoJCQkJYWRkVGVzdCh3YXJuaW5nKCJFeGNlcHRpb24gaW4gY29uc3RydWN0b3I6ICIrbmFtZSsiICgiK2V4Y2VwdGlvblRvU3RyaW5nKGUuZ2V0VGFyZ2V0RXhjZXB0aW9uKCkpKyIpIikpOwoJCQl9IGNhdGNoIChJbGxlZ2FsQWNjZXNzRXhjZXB0aW9uIGUpIHsKCQkJCWFkZFRlc3Qod2FybmluZygiQ2Fubm90IGFjY2VzcyB0ZXN0IGNhc2U6ICIrbmFtZSsiICgiK2V4Y2VwdGlvblRvU3RyaW5nKGUpKyIpIikpOwoJCQl9CgoJCX0gZWxzZSB7IC8vIGFsbW9zdCBhIHRlc3QgbWV0aG9kCgkJCWlmIChpc1Rlc3RNZXRob2QobSkpIAoJCQkJYWRkVGVzdCh3YXJuaW5nKCJUZXN0IG1ldGhvZCBpc24ndCBwdWJsaWM6ICIrbS5nZXROYW1lKCkpKTsKCQl9Cgl9CgkKCS8qKgoJICogQ29udmVydHMgdGhlIHN0YWNrIHRyYWNlIGludG8gYSBzdHJpbmcKCSAqLwoJcHJpdmF0ZSBTdHJpbmcgZXhjZXB0aW9uVG9TdHJpbmcoVGhyb3dhYmxlIHQpIHsKCQlTdHJpbmdXcml0ZXIgc3RyaW5nV3JpdGVyPSBuZXcgU3RyaW5nV3JpdGVyKCk7CgkJUHJpbnRXcml0ZXIgd3JpdGVyPSBuZXcgUHJpbnRXcml0ZXIoc3RyaW5nV3JpdGVyKTsKCQl0LnByaW50U3RhY2tUcmFjZSh3cml0ZXIpOwoJCXJldHVybiBzdHJpbmdXcml0ZXIudG9TdHJpbmcoKTsKCQkKCX0KCS8qKgoJICogQ291bnRzIHRoZSBudW1iZXIgb2YgdGVzdCBjYXNlcyB0aGF0IHdpbGwgYmUgcnVuIGJ5IHRoaXMgdGVzdC4KCSAqLwoJcHVibGljIGludCBjb3VudFRlc3RDYXNlcygpIHsKCQlpbnQgY291bnQ9IDA7CgkJZm9yIChFbnVtZXJhdGlvbiBlPSB0ZXN0cygpOyBlLmhhc01vcmVFbGVtZW50cygpOyApIHsKCQkJVGVzdCB0ZXN0PSAoVGVzdCllLm5leHRFbGVtZW50KCk7CgkJCWNvdW50PSBjb3VudCArIHRlc3QuY291bnRUZXN0Q2FzZXMoKTsKCQl9CgkJcmV0dXJuIGNvdW50OwoJfQoJLyoqCgkgKiBHZXRzIGEgY29uc3RydWN0b3Igd2hpY2ggdGFrZXMgYSBzaW5nbGUgU3RyaW5nIGFzCgkgKiBpdHMgYXJndW1lbnQuCgkgKi8KCXByaXZhdGUgQ29uc3RydWN0b3IgZ2V0Q29uc3RydWN0b3IoQ2xhc3MgdGhlQ2xhc3MpIHRocm93cyBOb1N1Y2hNZXRob2RFeGNlcHRpb24gewoJCUNsYXNzW10gYXJncz0geyBTdHJpbmcuY2xhc3MgfTsKCQlyZXR1cm4gdGhlQ2xhc3MuZ2V0Q29uc3RydWN0b3IoYXJncyk7Cgl9CgkKCS8qKgoJICovCglwcml2YXRlIGJvb2xlYW4gaXNQdWJsaWNUZXN0TWV0aG9kKE1ldGhvZCBtKSB7CgkJcmV0dXJuIGlzVGVzdE1ldGhvZChtKSAmJiBNb2RpZmllci5pc1B1YmxpYyhtLmdldE1vZGlmaWVycygpKTsKCSB9CgkvKioKCSAqLwoJcHJpdmF0ZSBib29sZWFuIGlzVGVzdE1ldGhvZChNZXRob2QgbSkgewoJCVN0cmluZyBuYW1lPSBtLmdldE5hbWUoKTsKCQlDbGFzc1tdIHBhcmFtZXRlcnM9IG0uZ2V0UGFyYW1ldGVyVHlwZXMoKTsKCQlDbGFzcyByZXR1cm5UeXBlPSBtLmdldFJldHVyblR5cGUoKTsKCQlyZXR1cm4gcGFyYW1ldGVycy5sZW5ndGggPT0gMCAmJiBuYW1lLnN0YXJ0c1dpdGgoInRlc3QiKSAmJiByZXR1cm5UeXBlLmVxdWFscyhWb2lkLlRZUEUpOwoJIH0KCS8qKgoJICogUnVucyB0aGUgdGVzdHMgYW5kIGNvbGxlY3RzIHRoZWlyIHJlc3VsdCBpbiBhIFRlc3RSZXN1bHQuCgkgKi8KCXB1YmxpYyB2b2lkIHJ1bihUZXN0UmVzdWx0IHJlc3VsdCkgewoJCWZvciAoRW51bWVyYXRpb24gZT0gdGVzdHMoKTsgZS5oYXNNb3JlRWxlbWVudHMoKTsgKSB7CgkgIAkJaWYgKHJlc3VsdC5zaG91bGRTdG9wKCkgKQoJICAJCQlicmVhazsKCQkJVGVzdCB0ZXN0PSAoVGVzdCllLm5leHRFbGVtZW50KCk7CgkJCXJ1blRlc3QodGVzdCwgcmVzdWx0KTsKCQl9Cgl9CgkKCXB1YmxpYyB2b2lkIHJ1blRlc3QoVGVzdCB0ZXN0LCBUZXN0UmVzdWx0IHJlc3VsdCkgewoJCXRlc3QucnVuKHJlc3VsdCk7Cgl9CgkKCS8qKgoJICogUmV0dXJucyB0aGUgdGVzdCBhdCB0aGUgZ2l2ZW4gaW5kZXggCgkgKi8KCXB1YmxpYyBUZXN0IHRlc3RBdChpbnQgaW5kZXgpIHsKCQlyZXR1cm4gKFRlc3QpZlRlc3RzLmVsZW1lbnRBdChpbmRleCk7Cgl9CgkvKioKCSAqIFJldHVybnMgdGhlIG51bWJlciBvZiB0ZXN0cyBpbiB0aGlzIHN1aXRlIAoJICovCglwdWJsaWMgaW50IHRlc3RDb3VudCgpIHsKCQlyZXR1cm4gZlRlc3RzLnNpemUoKTsKCX0KCS8qKgoJICogUmV0dXJucyB0aGUgdGVzdHMgYXMgYW4gZW51bWVyYXRpb24KCSAqLwoJcHVibGljIEVudW1lcmF0aW9uIHRlc3RzKCkgewoJCXJldHVybiBmVGVzdHMuZWxlbWVudHMoKTsKCX0KCS8qKgoJICovCglwdWJsaWMgU3RyaW5nIHRvU3RyaW5nKCkgewoJCWlmIChnZXROYW1lKCkgIT0gbnVsbCkKCQkJcmV0dXJuIGdldE5hbWUoKTsKCQlyZXR1cm4gc3VwZXIudG9TdHJpbmcoKTsKCSB9CgkJIAoJLyoqCgkgKiBTZXRzIHRoZSBuYW1lIG9mIHRoZSBzdWl0ZS4KCSAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIHRvIHNldAoJICovCglwdWJsaWMgdm9pZCBzZXROYW1lKFN0cmluZyBuYW1lKSB7CgkJZk5hbWU9IG5hbWU7Cgl9CgoJLyoqCgkgKiBSZXR1cm5zIHRoZSBuYW1lIG9mIHRoZSBzdWl0ZS4gTm90IGFsbAoJICogdGVzdCBzdWl0ZXMgaGF2ZSBhIG5hbWUgYW5kIHRoaXMgbWV0aG9kCgkgKiBjYW4gcmV0dXJuIG51bGwuCgkgKi8KCXB1YmxpYyBTdHJpbmcgZ2V0TmFtZSgpIHsKCQlyZXR1cm4gZk5hbWU7Cgl9CgkgCgkvKioKCSAqIFJldHVybnMgYSB0ZXN0IHdoaWNoIHdpbGwgZmFpbCBhbmQgbG9nIGEgd2FybmluZyBtZXNzYWdlLgoJICovCgkgcHJpdmF0ZSBUZXN0IHdhcm5pbmcoZmluYWwgU3RyaW5nIG1lc3NhZ2UpIHsKCQlyZXR1cm4gbmV3IFRlc3RDYXNlKCJ3YXJuaW5nIikgewoJCQlwcm90ZWN0ZWQgdm9pZCBydW5UZXN0KCkgewoJCQkJZmFpbChtZXNzYWdlKTsKCQkJfQoJCX07CQkKCX0KfQ==