LyoKICogQ29weXJpZ2h0IChjKSAyMDA4IEJvcmxhbmQgU29mdHdhcmUgQ29ycG9yYXRpb24KICogCiAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuIFRoaXMgcHJvZ3JhbSBhbmQgdGhlIGFjY29tcGFueWluZyBtYXRlcmlhbHMKICogYXJlIG1hZGUgYXZhaWxhYmxlIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgRWNsaXBzZSBQdWJsaWMgTGljZW5zZSB2MS4wCiAqIHdoaWNoIGFjY29tcGFuaWVzIHRoaXMgZGlzdHJpYnV0aW9uLCBhbmQgaXMgYXZhaWxhYmxlIGF0CiAqIGh0dHA6Ly93d3cuZWNsaXBzZS5vcmcvbGVnYWwvZXBsLXYxMC5odG1sCiAqCiAqIENvbnRyaWJ1dG9yczoKICogICAgQXJ0ZW0gVGlraG9taXJvdiAoQm9ybGFuZCkgLSBpbml0aWFsIEFQSSBhbmQgaW1wbGVtZW50YXRpb24KICovCgqrSU1QT1JUICJodHRwOi8vd3d3LmVjbGlwc2Uub3JnL2dtZi8yMDA4L0dlbk1vZGVsIrsKq0lNUE9SVCAiaHR0cDovL3d3dy5lY2xpcHNlLm9yZy9lbWYvMjAwMi9FY29yZSK7CqtJTVBPUlQgImh0dHA6Ly93d3cuZWNsaXBzZS5vcmcvZW1mLzIwMDIvR2VuTW9kZWwiuwoKq0VYVEVOU0lPTiBGYWNpbGl0ebsKCqtERUZJTkUgTWFpbiBGT1IgRHluYW1pY01vZGVsQWNjZXNzLbsKcGFja2FnZSCrcGFja2FnZU5hbWW7OwoKcHVibGljIGNsYXNzIKtjbGFzc05hbWW7IHsKCgmrRVhQQU5EIGZpZWxkKHRoaXMpIEZPUkVBQ0ggZWRpdG9yR2VuLmdldEFsbERvbWFpbkdlblBhY2thZ2VzKGZhbHNlKS27CgoJq0VYUEFORCB4cHQ6OkNvbW1vbjo6Z2VuZXJhdGVkTWVtYmVyQ29tbWVudLsKCXByaXZhdGUgZmluYWwgb3JnLmVjbGlwc2UuZW1mLmVjb3JlLkVQYWNrYWdlIGVQYWNrYWdlOwoKCatFWFBBTkQgeHB0OjpDb21tb246OmdlbmVyYXRlZE1lbWJlckNvbW1lbnS7Cglwcml2YXRlIKtjbGFzc05hbWW7KG9yZy5lY2xpcHNlLmVtZi5lY29yZS5FUGFja2FnZSBlUGFja2FnZSkgewoJCXRoaXMuZVBhY2thZ2UgPSBlUGFja2FnZTsKCX0KCgmrRVhQQU5EIGdldE1ldGhvZCh0aGlzKSBGT1JFQUNIIGVkaXRvckdlbi5nZXRBbGxEb21haW5HZW5QYWNrYWdlcyhmYWxzZSktuwoKCatFWFBBTkQgZ2V0UmVnaXN0cnlNZXRob2S7CgoJq0VYUEFORCB4cHQ6OkNvbW1vbjo6Z2VuZXJhdGVkTWVtYmVyQ29tbWVudLsKCXB1YmxpYyBib29sZWFuIGlzSW5zdGFuY2UoT2JqZWN0IG9iaiwgU3RyaW5nIG1ldGFDbGFzc05hbWUpIHsKCQlvcmcuZWNsaXBzZS5lbWYuZWNvcmUuRUNsYXNzIG1ldGFDbGFzcyA9IGdldEVDbGFzcyhtZXRhQ2xhc3NOYW1lKTsKCQlyZXR1cm4gb2JqIGluc3RhbmNlb2Ygb3JnLmVjbGlwc2UuZW1mLmVjb3JlLkVPYmplY3QgJiYgbWV0YUNsYXNzLmlzU3VwZXJUeXBlT2YoKChvcmcuZWNsaXBzZS5lbWYuZWNvcmUuRU9iamVjdCkgb2JqKS5lQ2xhc3MoKSk7Cgl9CgoJq0VYUEFORCB4cHQ6OkNvbW1vbjo6Z2VuZXJhdGVkTWVtYmVyQ29tbWVudLsKCXB1YmxpYyBvcmcuZWNsaXBzZS5lbWYuZWNvcmUuRU9iamVjdCBuZXdJbnN0YW5jZShTdHJpbmcgbWV0YUNsYXNzTmFtZSkgewoJCXJldHVybiB0aGlzLmVQYWNrYWdlLmdldEVGYWN0b3J5SW5zdGFuY2UoKS5jcmVhdGUoZ2V0RUNsYXNzKG1ldGFDbGFzc05hbWUpKTsKCX0KCgmrRVhQQU5EIHhwdDo6Q29tbW9uOjpnZW5lcmF0ZWRNZW1iZXJDb21tZW50uwoJcHVibGljIG9yZy5lY2xpcHNlLmVtZi5lY29yZS5FQ2xhc3MgZ2V0RUNsYXNzKFN0cmluZyBtZXRhQ2xhc3NOYW1lKSB7CgkJYXNzZXJ0IG1ldGFDbGFzc05hbWUgIT0gbnVsbDsKCQlvcmcuZWNsaXBzZS5lbWYuZWNvcmUuRUNsYXNzIG1ldGFDbGFzcyA9IGZpbmRNZXRhQ2xhc3MobWV0YUNsYXNzTmFtZSk7CgkJYXNzZXJ0TWV0YUNsYXNzKG1ldGFDbGFzcywgbWV0YUNsYXNzTmFtZSk7CgkJcmV0dXJuIG1ldGFDbGFzczsKCX0KCgmrRVhQQU5EIHhwdDo6Q29tbW9uOjpnZW5lcmF0ZWRNZW1iZXJDb21tZW50uwoJcHVibGljIG9yZy5lY2xpcHNlLmVtZi5lY29yZS5FU3RydWN0dXJhbEZlYXR1cmUgZ2V0RUZlYXR1cmUoU3RyaW5nIG1ldGFDbGFzc05hbWUsIFN0cmluZyBtZXRhRmVhdHVyZU5hbWUpIHsKCQlhc3NlcnQgbWV0YUZlYXR1cmVOYW1lICE9IG51bGw7CgkJb3JnLmVjbGlwc2UuZW1mLmVjb3JlLkVDbGFzcyBtZXRhQ2xhc3MgPSBnZXRFQ2xhc3MobWV0YUNsYXNzTmFtZSk7CgkJb3JnLmVjbGlwc2UuZW1mLmVjb3JlLkVTdHJ1Y3R1cmFsRmVhdHVyZSBmID0gbWV0YUNsYXNzLmdldEVTdHJ1Y3R1cmFsRmVhdHVyZShtZXRhRmVhdHVyZU5hbWUpOwoJCWFzc2VydE1ldGFGZWF0dXJlKGYsIG1ldGFDbGFzcywgbWV0YUZlYXR1cmVOYW1lKTsKCQlyZXR1cm4gZjsKCX0KCgmrRVhQQU5EIHhwdDo6Q29tbW9uOjpnZW5lcmF0ZWRNZW1iZXJDb21tZW50uwoJcHVibGljIG9yZy5lY2xpcHNlLmVtZi5lY29yZS5FQXR0cmlidXRlIGdldEVBdHRyaWJ1dGUoU3RyaW5nIG1ldGFDbGFzc05hbWUsIFN0cmluZyBtZXRhRmVhdHVyZU5hbWUpIHsKCQlyZXR1cm4gKG9yZy5lY2xpcHNlLmVtZi5lY29yZS5FQXR0cmlidXRlKSBnZXRFRmVhdHVyZShtZXRhQ2xhc3NOYW1lLCBtZXRhRmVhdHVyZU5hbWUpOwoJfQoKCatFWFBBTkQgeHB0OjpDb21tb246OmdlbmVyYXRlZE1lbWJlckNvbW1lbnS7CglwdWJsaWMgb3JnLmVjbGlwc2UuZW1mLmVjb3JlLkVSZWZlcmVuY2UgZ2V0RVJlZmVyZW5jZShTdHJpbmcgbWV0YUNsYXNzTmFtZSwgU3RyaW5nIG1ldGFGZWF0dXJlTmFtZSkgewoJCXJldHVybiAob3JnLmVjbGlwc2UuZW1mLmVjb3JlLkVSZWZlcmVuY2UpIGdldEVGZWF0dXJlKG1ldGFDbGFzc05hbWUsIG1ldGFGZWF0dXJlTmFtZSk7Cgl9CgoJq0VYUEFORCB4cHQ6OkNvbW1vbjo6Z2VuZXJhdGVkTWVtYmVyQ29tbWVudLsKCXB1YmxpYyBvcmcuZWNsaXBzZS5lbWYuZWNvcmUuRURhdGFUeXBlIGdldEVEYXRhVHlwZShTdHJpbmcgbWV0YUNsYXNzTmFtZSkgewoJCWFzc2VydCBtZXRhQ2xhc3NOYW1lICE9IG51bGw7CgkJb3JnLmVjbGlwc2UuZW1mLmVjb3JlLkVDbGFzc2lmaWVyIGMgPSB0aGlzLmVQYWNrYWdlLmdldEVDbGFzc2lmaWVyKG1ldGFDbGFzc05hbWUpOwoJCWlmIChmYWxzZSA9PSBjIGluc3RhbmNlb2Ygb3JnLmVjbGlwc2UuZW1mLmVjb3JlLkVEYXRhVHlwZSkgewoJCQlyZXR1cm4gbnVsbDsKCQl9CgkJcmV0dXJuIChvcmcuZWNsaXBzZS5lbWYuZWNvcmUuRURhdGFUeXBlKSBjOwoJfQoKCatFWFBBTkQgeHB0OjpDb21tb246OmdlbmVyYXRlZE1lbWJlckNvbW1lbnS7CglwdWJsaWMgb3JnLmVjbGlwc2UuZW1mLmVjb3JlLkVFbnVtIGdldEVFbnVtKFN0cmluZyBtZXRhQ2xhc3NOYW1lKSB7CgkJYXNzZXJ0IG1ldGFDbGFzc05hbWUgIT0gbnVsbDsKCQlvcmcuZWNsaXBzZS5lbWYuZWNvcmUuRUNsYXNzaWZpZXIgYyA9IHRoaXMuZVBhY2thZ2UuZ2V0RUNsYXNzaWZpZXIobWV0YUNsYXNzTmFtZSk7CgkJaWYgKGZhbHNlID09IGMgaW5zdGFuY2VvZiBvcmcuZWNsaXBzZS5lbWYuZWNvcmUuRUVudW0pIHsKCQkJcmV0dXJuIG51bGw7CgkJfQoJCXJldHVybiAob3JnLmVjbGlwc2UuZW1mLmVjb3JlLkVFbnVtKSBjOwoJfQoKCatFWFBBTkQgeHB0OjpDb21tb246OmdlbmVyYXRlZE1lbWJlckNvbW1lbnS7Cglwcml2YXRlIG9yZy5lY2xpcHNlLmVtZi5lY29yZS5FQ2xhc3MgZmluZE1ldGFDbGFzcyhTdHJpbmcgbmFtZSkgewoJCW9yZy5lY2xpcHNlLmVtZi5lY29yZS5FQ2xhc3NpZmllciBjID0gdGhpcy5lUGFja2FnZS5nZXRFQ2xhc3NpZmllcihuYW1lKTsKCQlpZiAoZmFsc2UgPT0gYyBpbnN0YW5jZW9mIG9yZy5lY2xpcHNlLmVtZi5lY29yZS5FQ2xhc3MpIHsKCQkJcmV0dXJuIG51bGw7CgkJfQoJCXJldHVybiAob3JnLmVjbGlwc2UuZW1mLmVjb3JlLkVDbGFzcykgYzsKCX0KCgmrRVhQQU5EIHhwdDo6Q29tbW9uOjpnZW5lcmF0ZWRNZW1iZXJDb21tZW50KCJEZWZhdWx0IGltcGxlbWVudGF0aW9uIHRocm93cyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24gaWYgbWV0YWNsYXNzIGlzIG51bGwiKbsKCXByaXZhdGUgdm9pZCBhc3NlcnRNZXRhQ2xhc3Mob3JnLmVjbGlwc2UuZW1mLmVjb3JlLkVDbGFzcyBtZXRhQ2xhc3MsIFN0cmluZyBtZXRhQ2xhc3NOYW1lKSB7CgkJaWYgKG1ldGFDbGFzcyA9PSBudWxsKSB7CgkJCXRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oamF2YS50ZXh0Lk1lc3NhZ2VGb3JtYXQuZm9ybWF0KCJDYW4ndCBmaW5kIGNsYXNzIHswfSBpbiB0aGUgcGFja2FnZSB7MX0iLCBuZXcgT2JqZWN0W10ge21ldGFDbGFzc05hbWUsIHRoaXMuZVBhY2thZ2UuZ2V0TmFtZSgpfSkpOwoJCX0KCX0KCgmrRVhQQU5EIHhwdDo6Q29tbW9uOjpnZW5lcmF0ZWRNZW1iZXJDb21tZW50KCJEZWZhdWx0IGltcGxlbWVudGF0aW9uIHRocm93cyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24gaWYgbWV0YS1mZWF0dXJlIGlzIG51bGwiKbsKCXByaXZhdGUgdm9pZCBhc3NlcnRNZXRhRmVhdHVyZShvcmcuZWNsaXBzZS5lbWYuZWNvcmUuRVN0cnVjdHVyYWxGZWF0dXJlIG1ldGFGZWF0dXJlLCBvcmcuZWNsaXBzZS5lbWYuZWNvcmUuRUNsYXNzIG1ldGFDbGFzcywgU3RyaW5nIGZlYXR1cmVOYW1lKSB7CgkJaWYgKG1ldGFGZWF0dXJlID09IG51bGwpIHsKCQkJdGhyb3cgbmV3IElsbGVnYWxTdGF0ZUV4Y2VwdGlvbihqYXZhLnRleHQuTWVzc2FnZUZvcm1hdC5mb3JtYXQoIkNhbid0IGZpbmQgZmVhdHVyZSB7MH0gb2YgY2xhc3MgezF9IGluIHRoZSBwYWNrYWdlIHsyfSIsIG5ldyBPYmplY3RbXSB7ZmVhdHVyZU5hbWUsIG1ldGFDbGFzcy5nZXROYW1lKCksIHRoaXMuZVBhY2thZ2UuZ2V0TmFtZSgpfSkpOwoJCX0KCX0KCgmrRVhQQU5EIGluaXRNZXRob2QgRk9SRUFDSCBlZGl0b3JHZW4uZ2V0QWxsRG9tYWluR2VuUGFja2FnZXMoZmFsc2UpLbsKq0VYUEFORCBhZGRpdGlvbnMtuwp9CqtFTkRERUZJTkW7CgqrREVGSU5FIGFkZGl0aW9ucyBGT1IgRHluYW1pY01vZGVsQWNjZXNzu6tFTkRERUZJTkW7CgqrREVGSU5FIGZpZWxkKER5bmFtaWNNb2RlbEFjY2VzcyBkbWEpIEZPUiBHZW5QYWNrYWdlLbsKq0VYUEFORCB4cHQ6OkNvbW1vbjo6Z2VuZXJhdGVkTWVtYmVyQ29tbWVudLsKcHJpdmF0ZSBzdGF0aWMgq2RtYS5jbGFzc05hbWW7IKtmaWVsZE5hbWUoKbs7CqtFTkRERUZJTkW7CgqrREVGSU5FIGdldE1ldGhvZChEeW5hbWljTW9kZWxBY2Nlc3MgZG1hKSBGT1IgR2VuUGFja2FnZS27CgmrRVhQQU5EIHhwdDo6Q29tbW9uOjpnZW5lcmF0ZWRNZW1iZXJDb21tZW50KCJAdGhyb3dzIElsbGVnYWxTdGF0ZUV4Y2VwdGlvbiBpZiBubyBFUGFja2FnZSB3aXRoIGdpdmVuIFVSSSBpcyByZWdpc3RlcmVkLiIpuwoJcHVibGljIHN0YXRpYyCrZG1hLmNsYXNzTmFtZbsgZ2V0q2dldE5hbWVUb2tlbigpuygpIHsKCQlpZiAoq2ZpZWxkTmFtZSgpuyA9PSBudWxsKSB7CgkJCW9yZy5lY2xpcHNlLmVtZi5lY29yZS5FUGFja2FnZSBwa2cgPSBnZXRSZWdpc3RyeSgpLmdldEVQYWNrYWdlKCKrZWNvcmVQYWNrYWdlLm5zVVJJuyIpOwoJCQlpZiAocGtnID09IG51bGwpIHsKCQkJCXRocm93IG5ldyBJbGxlZ2FsU3RhdGVFeGNlcHRpb24oIlBhY2thZ2Ugq2Vjb3JlUGFja2FnZS5uYW1luyirZWNvcmVQYWNrYWdlLm5zVVJJuykgbm90IGZvdW5kIik7CgkJCX0KCQkJq2ZpZWxkTmFtZSgpuyA9IG5ldyCrZG1hLmNsYXNzTmFtZbsocGtnKTsKCQkJq2ZpZWxkTmFtZSgpuy5pbml0q2dldE5hbWVUb2tlbigpuygpOwoJCX0KCQlyZXR1cm4gq2ZpZWxkTmFtZSgpuzsKCX0Kq0VORERFRklORbsKCqtERUZJTkUgaW5pdE1ldGhvZCBGT1IgR2VuUGFja2FnZS27CgmrRVhQQU5EIHhwdDo6Q29tbW9uOjpnZW5lcmF0ZWRNZW1iZXJDb21tZW50uwoJcHJpdmF0ZSB2b2lkIGluaXSrZ2V0TmFtZVRva2VuKCm7KCkgewoJfQqrRU5EREVGSU5FuwoKq0RFRklORSBnZXRSZWdpc3RyeU1ldGhvZCBGT1IgRHluYW1pY01vZGVsQWNjZXNzuwoJq0VYUEFORCB4cHQ6OkNvbW1vbjo6Z2VuZXJhdGVkTWVtYmVyQ29tbWVudCgiRGVmYXVsdCBpbXBsZW1lbnRhdGlvbiByZXR1cm5zIGdsb2JhbCByZWdpc3RyeSwgY2xpZW50cyB0aGF0IG5lZWQgYW5vdGhlciBtYXkgcmVkZWZpbmUuIim7Cglwcml2YXRlIHN0YXRpYyBvcmcuZWNsaXBzZS5lbWYuZWNvcmUuRVBhY2thZ2UuUmVnaXN0cnkgZ2V0UmVnaXN0cnkoKSB7CgkJcmV0dXJuIG9yZy5lY2xpcHNlLmVtZi5lY29yZS5FUGFja2FnZS5SZWdpc3RyeS5JTlNUQU5DRTsKCX0Kq0VORERFRklORbs=