LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDA2LCAyMDA4IE9yYWNsZS4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KICogVGhpcyBwcm9ncmFtIGFuZCB0aGUgYWNjb21wYW55aW5nIG1hdGVyaWFscyBhcmUgbWFkZSBhdmFpbGFibGUgdW5kZXIgdGhlCiAqIHRlcm1zIG9mIHRoZSBFY2xpcHNlIFB1YmxpYyBMaWNlbnNlIHYxLjAsIHdoaWNoIGFjY29tcGFuaWVzIHRoaXMgZGlzdHJpYnV0aW9uCiAqIGFuZCBpcyBhdmFpbGFibGUgYXQgaHR0cDovL3d3dy5lY2xpcHNlLm9yZy9sZWdhbC9lcGwtdjEwLmh0bWwuCiAqIAogKiBDb250cmlidXRvcnM6CiAqICAgICBPcmFjbGUgLSBpbml0aWFsIEFQSSBhbmQgaW1wbGVtZW50YXRpb24KICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KcGFja2FnZSBvcmcuZWNsaXBzZS5qcHQuZGIuaW50ZXJuYWw7CgppbXBvcnQgamF2YS50ZXh0LkNvbGxhdG9yOwppbXBvcnQgamF2YS51dGlsLkhhc2hNYXA7CmltcG9ydCBqYXZhLnV0aWwuSXRlcmF0b3I7CmltcG9ydCBqYXZhLnV0aWwuTGlzdDsKCmltcG9ydCBvcmcuZWNsaXBzZS5kYXRhdG9vbHMuY29ubmVjdGl2aXR5LnNxbS5jb3JlLmRlZmluaXRpb24uRGF0YWJhc2VEZWZpbml0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuZGF0YXRvb2xzLmNvbm5lY3Rpdml0eS5zcW0uaW50ZXJuYWwuY29yZS5SREJDb3JlUGx1Z2luOwppbXBvcnQgb3JnLmVjbGlwc2UuanB0LmRiLkNhdGFsb2c7CmltcG9ydCBvcmcuZWNsaXBzZS5qcHQuZGIuRGF0YWJhc2U7CmltcG9ydCBvcmcuZWNsaXBzZS5qcHQuZGIuRGF0YWJhc2VPYmplY3Q7CmltcG9ydCBvcmcuZWNsaXBzZS5qcHQudXRpbGl0eS5pbnRlcm5hbC5Db2xsZWN0aW9uVG9vbHM7CmltcG9ydCBvcmcuZWNsaXBzZS5qcHQudXRpbGl0eS5pbnRlcm5hbC5TdHJpbmdUb29sczsKaW1wb3J0IG9yZy5lY2xpcHNlLmpwdC51dGlsaXR5LmludGVybmFsLml0ZXJhdG9ycy5BcnJheUl0ZXJhdG9yOwppbXBvcnQgb3JnLmVjbGlwc2UuanB0LnV0aWxpdHkuaW50ZXJuYWwuaXRlcmF0b3JzLlRyYW5zZm9ybWF0aW9uSXRlcmF0b3I7CgovKioKICogV3JhcCBhIERUUCBEYXRhYmFzZS4KICogCiAqIFNvbWV0aW1lcyB0aGUgZGF0YWJhc2Ugd2lsbCBkaXJlY3RseSBob2xkIHNjaGVtYXRhOyBidXQgaWYgdGhlIGRhdGFiYXNlCiAqIHN1cHBvcnRzIGNhdGFsb2dzLCBpdCB3aWxsIG5vdCBob2xkIHRoZSBzY2hlbWF0YSBkaXJlY3RseSwgYnV0IHdpbGwgZGVsZWdhdGUKICogdG8gdGhlICJkZWZhdWx0IiBjYXRhbG9nLgogKiAKICogTm90ZToKICogV2UgdXNlICJuYW1lIiB3aGVuIGRlYWxpbmcgd2l0aCB0aGUgdW5tb2RpZmllZCBuYW1lIG9mIGEgZGF0YWJhc2Ugb2JqZWN0CiAqIGFzIHN1cHBsaWVkIGJ5IHRoZSBkYXRhYmFzZSBpdHNlbGYgKGkuZS4gaXQgaXMgbm90IGRlbGltaXRlZCBhbmQgaXQgaXMgYWx3YXlzCiAqIGNhc2Utc2Vuc2l0aXZlKS4KICogV2UgdXNlICJpZGVudGlmaWVyIiB3aGVuIGRlYWxpbmcgd2l0aCBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIGRhdGFiYXNlCiAqIG9iamVjdCBuYW1lIChpLmUuIGl0IG1heSBiZSBkZWxpbWl0ZWQgYW5kLCBkZXBlbmRpbmcgb24gdGhlIHZlbmRvciwgaXQgbWF5CiAqIGJlIGNhc2UtaW5zZW5zaXRpdmUpLgogKi8KZmluYWwgY2xhc3MgRFRQRGF0YWJhc2VXcmFwcGVyCglleHRlbmRzIERUUFNjaGVtYUNvbnRhaW5lcldyYXBwZXIKCWltcGxlbWVudHMgRGF0YWJhc2UKewoJLy8gdGhlIHdyYXBwZWQgRFRQIGRhdGFiYXNlCglwcml2YXRlIGZpbmFsIG9yZy5lY2xpcHNlLmRhdGF0b29scy5tb2RlbGJhc2Uuc3FsLnNjaGVtYS5EYXRhYmFzZSBkdHBEYXRhYmFzZTsKCgkvLyBsYXp5LWluaXRpYWxpemVkLCBzb3J0ZWQKCXByaXZhdGUgRFRQQ2F0YWxvZ1dyYXBwZXJbXSBjYXRhbG9nczsKCgkvLyBsYXp5LWluaXRpYWxpemVkIC0gYnV0IGl0IGNhbiBiZSAnbnVsbCcgc28gd2UgdXNlIGEgZmxhZwoJcHJpdmF0ZSBEVFBDYXRhbG9nV3JhcHBlciBkZWZhdWx0Q2F0YWxvZzsKCXByaXZhdGUgYm9vbGVhbiBkZWZhdWx0Q2F0YWxvZ0NhbGN1bGF0ZWQgPSBmYWxzZTsKCgoJcHJpdmF0ZSBzdGF0aWMgZmluYWwgRFRQQ2F0YWxvZ1dyYXBwZXJbXSBFTVBUWV9DQVRBTE9HUyA9IG5ldyBEVFBDYXRhbG9nV3JhcHBlclswXTsKCgoJLy8gKioqKioqKioqKiBjb25zdHJ1Y3RvciAqKioqKioqKioqCgoJRFRQRGF0YWJhc2VXcmFwcGVyKERUUENvbm5lY3Rpb25Qcm9maWxlV3JhcHBlciBjb25uZWN0aW9uUHJvZmlsZSwgb3JnLmVjbGlwc2UuZGF0YXRvb2xzLm1vZGVsYmFzZS5zcWwuc2NoZW1hLkRhdGFiYXNlIGR0cERhdGFiYXNlKSB7CgkJc3VwZXIoY29ubmVjdGlvblByb2ZpbGUsIGR0cERhdGFiYXNlKTsKCQl0aGlzLmR0cERhdGFiYXNlID0gZHRwRGF0YWJhc2U7Cgl9CgoKCS8vICoqKioqKioqKiogRFRQV3JhcHBlciBpbXBsZW1lbnRhdGlvbiAqKioqKioqKioqCgoJQE92ZXJyaWRlCglzeW5jaHJvbml6ZWQgdm9pZCBjYXRhbG9nT2JqZWN0Q2hhbmdlZCgpIHsKCQlzdXBlci5jYXRhbG9nT2JqZWN0Q2hhbmdlZCgpOwoJCXRoaXMuZ2V0Q29ubmVjdGlvblByb2ZpbGUoKS5kYXRhYmFzZUNoYW5nZWQodGhpcyk7Cgl9CgoJQE92ZXJyaWRlCglwdWJsaWMgRFRQRGF0YWJhc2VXcmFwcGVyIGdldERhdGFiYXNlKCkgewoJCXJldHVybiB0aGlzOwoJfQoKCgkvLyAqKioqKioqKioqIERUUFNjaGVtYUNvbnRhaW5lcldyYXBwZXIgaW1wbGVtZW50YXRpb24gKioqKioqKioqKgoKCUBPdmVycmlkZQoJQFN1cHByZXNzV2FybmluZ3MoInVuY2hlY2tlZCIpCglMaXN0PG9yZy5lY2xpcHNlLmRhdGF0b29scy5tb2RlbGJhc2Uuc3FsLnNjaGVtYS5TY2hlbWE+IGdldERUUFNjaGVtYXRhKCkgewoJCXJldHVybiB0aGlzLmR0cERhdGFiYXNlLmdldFNjaGVtYXMoKTsKCX0KCglAT3ZlcnJpZGUKCURUUFNjaGVtYVdyYXBwZXIgZ2V0U2NoZW1hKG9yZy5lY2xpcHNlLmRhdGF0b29scy5tb2RlbGJhc2Uuc3FsLnNjaGVtYS5TY2hlbWEgZHRwU2NoZW1hKSB7CgkJcmV0dXJuIHRoaXMuZ2V0U2NoZW1hXyhkdHBTY2hlbWEpOwoJfQoKCUBPdmVycmlkZQoJRFRQVGFibGVXcmFwcGVyIGdldFRhYmxlKG9yZy5lY2xpcHNlLmRhdGF0b29scy5tb2RlbGJhc2Uuc3FsLnRhYmxlcy5UYWJsZSBkdHBUYWJsZSkgewoJCXJldHVybiB0aGlzLmdldFRhYmxlXyhkdHBUYWJsZSk7Cgl9CgoJQE92ZXJyaWRlCglEVFBDb2x1bW5XcmFwcGVyIGdldENvbHVtbihvcmcuZWNsaXBzZS5kYXRhdG9vbHMubW9kZWxiYXNlLnNxbC50YWJsZXMuQ29sdW1uIGR0cENvbHVtbikgewoJCXJldHVybiB0aGlzLmdldENvbHVtbl8oZHRwQ29sdW1uKTsKCX0KCgoJLy8gKioqKioqKioqKiBEYXRhYmFzZU9iamVjdCBpbXBsZW1lbnRhdGlvbiAqKioqKioqKioqCgoJcHVibGljIFN0cmluZyBnZXROYW1lKCkgewoJCXJldHVybiB0aGlzLmR0cERhdGFiYXNlLmdldE5hbWUoKTsKCX0KCgoJLy8gKioqKioqKioqKiBEYXRhYmFzZSBpbXBsZW1lbnRhdGlvbiAqKioqKioqKioqCgoJcHVibGljIFN0cmluZyBnZXRWZW5kb3JOYW1lKCkgewoJCXJldHVybiB0aGlzLmR0cERhdGFiYXNlLmdldFZlbmRvcigpOwoJfQoKCXB1YmxpYyBTdHJpbmcgZ2V0VmVyc2lvbigpIHsKCQlyZXR1cm4gdGhpcy5kdHBEYXRhYmFzZS5nZXRWZXJzaW9uKCk7Cgl9CgoJLy8gb3ZlcnJpZGUgdG8gbWFrZSBtZXRob2QgcHVibGljIHNpbmNlIGl0J3MgaW4gdGhlIERhdGFiYXNlIGludGVyZmFjZQoJQE92ZXJyaWRlCglwdWJsaWMgPFQgZXh0ZW5kcyBEYXRhYmFzZU9iamVjdD4gVCBzZWxlY3REYXRhYmFzZU9iamVjdEZvcklkZW50aWZpZXIoVFtdIGRhdGFiYXNlT2JqZWN0cywgU3RyaW5nIGlkZW50aWZpZXIpIHsKCQlyZXR1cm4gc3VwZXIuc2VsZWN0RGF0YWJhc2VPYmplY3RGb3JJZGVudGlmaWVyKGRhdGFiYXNlT2JqZWN0cywgaWRlbnRpZmllcik7Cgl9CgoJLy8gKioqKiogY2F0YWxvZ3MKCglwdWJsaWMgYm9vbGVhbiBzdXBwb3J0c0NhdGFsb2dzKCkgewoJCS8vIGlmIHRoZSBEVFAgZGF0YWJhc2UgZG9lcyBub3QgaGF2ZSBhbnkgc2NoZW1hdGEsIGl0IG11c3QgaGF2ZSBjYXRhbG9ncy4uLgoJCUxpc3Q8b3JnLmVjbGlwc2UuZGF0YXRvb2xzLm1vZGVsYmFzZS5zcWwuc2NoZW1hLlNjaGVtYT4gZHRwU2NoZW1hdGEgPSB0aGlzLmdldERUUFNjaGVtYXRhKCk7CgkJcmV0dXJuIChkdHBTY2hlbWF0YSA9PSBudWxsKSB8fCBkdHBTY2hlbWF0YS5pc0VtcHR5KCk7Cgl9CgoJcHVibGljIEl0ZXJhdG9yPENhdGFsb2c+IGNhdGFsb2dzKCkgewoJCXJldHVybiBuZXcgQXJyYXlJdGVyYXRvcjxDYXRhbG9nPih0aGlzLmdldENhdGFsb2dzKCkpOwoJfQoKCXByaXZhdGUgSXRlcmF0b3I8RFRQQ2F0YWxvZ1dyYXBwZXI+IGNhdGFsb2dXcmFwcGVycygpIHsKCQlyZXR1cm4gbmV3IEFycmF5SXRlcmF0b3I8RFRQQ2F0YWxvZ1dyYXBwZXI+KHRoaXMuZ2V0Q2F0YWxvZ3MoKSk7Cgl9CgoJcHJpdmF0ZSBzeW5jaHJvbml6ZWQgRFRQQ2F0YWxvZ1dyYXBwZXJbXSBnZXRDYXRhbG9ncygpIHsKCQlpZiAodGhpcy5jYXRhbG9ncyA9PSBudWxsKSB7CgkJCXRoaXMuY2F0YWxvZ3MgPSB0aGlzLmJ1aWxkQ2F0YWxvZ3MoKTsKCQl9CgkJcmV0dXJuIHRoaXMuY2F0YWxvZ3M7Cgl9CgoJcHJpdmF0ZSBEVFBDYXRhbG9nV3JhcHBlcltdIGJ1aWxkQ2F0YWxvZ3MoKSB7CgkJTGlzdDxvcmcuZWNsaXBzZS5kYXRhdG9vbHMubW9kZWxiYXNlLnNxbC5zY2hlbWEuQ2F0YWxvZz4gZHRwQ2F0YWxvZ3MgPSB0aGlzLmdldERUUENhdGFsb2dzKCk7CgkJaWYgKChkdHBDYXRhbG9ncyA9PSBudWxsKSB8fCBkdHBDYXRhbG9ncy5pc0VtcHR5KCkpIHsKCQkJcmV0dXJuIEVNUFRZX0NBVEFMT0dTOwoJCX0KCQlEVFBDYXRhbG9nV3JhcHBlcltdIHJlc3VsdCA9IG5ldyBEVFBDYXRhbG9nV3JhcHBlcltkdHBDYXRhbG9ncy5zaXplKCldOwoJCWZvciAoaW50IGkgPSByZXN1bHQubGVuZ3RoOyBpLS0gPiAwOykgewoJCQlyZXN1bHRbaV0gPSBuZXcgRFRQQ2F0YWxvZ1dyYXBwZXIodGhpcywgZHRwQ2F0YWxvZ3MuZ2V0KGkpKTsKCQl9CgkJcmV0dXJuIENvbGxlY3Rpb25Ub29scy5zb3J0KHJlc3VsdCk7Cgl9CgoJLy8gbWluaW1pemUgc2NvcGUgb2Ygc3VwcHJlc3NlZCB3YXJuaW5ncwoJQFN1cHByZXNzV2FybmluZ3MoInVuY2hlY2tlZCIpCglwcml2YXRlIExpc3Q8b3JnLmVjbGlwc2UuZGF0YXRvb2xzLm1vZGVsYmFzZS5zcWwuc2NoZW1hLkNhdGFsb2c+IGdldERUUENhdGFsb2dzKCkgewoJCXJldHVybiB0aGlzLmR0cERhdGFiYXNlLmdldENhdGFsb2dzKCk7Cgl9CgoJcHVibGljIGludCBjYXRhbG9nc1NpemUoKSB7CgkJcmV0dXJuIHRoaXMuZ2V0Q2F0YWxvZ3MoKS5sZW5ndGg7Cgl9CgoJLyoqCgkgKiByZXR1cm4gdGhlIGNhdGFsb2cgZm9yIHRoZSBzcGVjaWZpZWQgRFRQIGNhdGFsb2cKCSAqLwoJRFRQQ2F0YWxvZ1dyYXBwZXIgZ2V0Q2F0YWxvZyhvcmcuZWNsaXBzZS5kYXRhdG9vbHMubW9kZWxiYXNlLnNxbC5zY2hlbWEuQ2F0YWxvZyBkdHBDYXRhbG9nKSB7CgkJZm9yIChEVFBDYXRhbG9nV3JhcHBlciBjYXRhbG9nIDogdGhpcy5nZXRDYXRhbG9ncygpKSB7CgkJCWlmIChjYXRhbG9nLndyYXBzKGR0cENhdGFsb2cpKSB7CgkJCQlyZXR1cm4gY2F0YWxvZzsKCQkJfQoJCX0KCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJpbnZhbGlkIERUUCBjYXRhbG9nOiAiICsgZHRwQ2F0YWxvZyk7ICAvLyROT04tTkxTLTEkCgl9CgoJcHVibGljIERUUENhdGFsb2dXcmFwcGVyIGdldENhdGFsb2dOYW1lZChTdHJpbmcgbmFtZSkgewoJCXJldHVybiB0aGlzLnNlbGVjdERhdGFiYXNlT2JqZWN0TmFtZWQodGhpcy5nZXRDYXRhbG9ncygpLCBuYW1lKTsKCX0KCglwdWJsaWMgSXRlcmF0b3I8U3RyaW5nPiBzb3J0ZWRDYXRhbG9nSWRlbnRpZmllcnMoKSB7CgkJLy8gdGhlIGNhdGFsb2dzIGFyZSBhbHJlYWR5IHNvcnRlZAoJCXJldHVybiBuZXcgVHJhbnNmb3JtYXRpb25JdGVyYXRvcjxEVFBDYXRhbG9nV3JhcHBlciwgU3RyaW5nPih0aGlzLmNhdGFsb2dXcmFwcGVycygpKSB7CgkJCUBPdmVycmlkZQoJCQlwcm90ZWN0ZWQgU3RyaW5nIHRyYW5zZm9ybShEVFBDYXRhbG9nV3JhcHBlciBuZXh0KSB7CgkJCQkgcmV0dXJuIG5leHQuZ2V0SWRlbnRpZmllcigpOwoJCQl9CgkJfTsKCX0KCglwdWJsaWMgRFRQQ2F0YWxvZ1dyYXBwZXIgZ2V0Q2F0YWxvZ0ZvcklkZW50aWZpZXIoU3RyaW5nIGlkZW50aWZpZXIpIHsKCQlyZXR1cm4gdGhpcy5zZWxlY3REYXRhYmFzZU9iamVjdEZvcklkZW50aWZpZXIodGhpcy5nZXRDYXRhbG9ncygpLCBpZGVudGlmaWVyKTsKCX0KCglwdWJsaWMgc3luY2hyb25pemVkIERUUENhdGFsb2dXcmFwcGVyIGdldERlZmF1bHRDYXRhbG9nKCkgewoJCWlmICggISB0aGlzLmRlZmF1bHRDYXRhbG9nQ2FsY3VsYXRlZCkgewoJCQl0aGlzLmRlZmF1bHRDYXRhbG9nQ2FsY3VsYXRlZCA9IHRydWU7CgkJCXRoaXMuZGVmYXVsdENhdGFsb2cgPSB0aGlzLmJ1aWxkRGVmYXVsdENhdGFsb2coKTsKCQl9CgkJcmV0dXJuIHRoaXMuZGVmYXVsdENhdGFsb2c7Cgl9CgoJcHJpdmF0ZSBEVFBDYXRhbG9nV3JhcHBlciBidWlsZERlZmF1bHRDYXRhbG9nKCkgewoJCXJldHVybiB0aGlzLnN1cHBvcnRzQ2F0YWxvZ3MoKSA/IHRoaXMuZ2V0VmVuZG9yKCkuZ2V0RGVmYXVsdENhdGFsb2codGhpcykgOiBudWxsOwoJfQoKCS8vICoqKioqIHNjaGVtYXRhCgoJQE92ZXJyaWRlCglzeW5jaHJvbml6ZWQgRFRQU2NoZW1hV3JhcHBlcltdIGdldFNjaGVtYXRhKCkgewoJCURUUENhdGFsb2dXcmFwcGVyIGNhdCA9IHRoaXMuZ2V0RGVmYXVsdENhdGFsb2coKTsKCQlyZXR1cm4gKGNhdCA9PSBudWxsKSA/IHN1cGVyLmdldFNjaGVtYXRhKCkgOiBjYXQuZ2V0U2NoZW1hdGEoKTsKCX0KCglEVFBTY2hlbWFXcmFwcGVyIGdldERlZmF1bHRTY2hlbWEoRFRQU2NoZW1hQ29udGFpbmVyV3JhcHBlciBzY2hlbWFDb250YWluZXIpIHsKCQlyZXR1cm4gdGhpcy5nZXRWZW5kb3IoKS5nZXREZWZhdWx0U2NoZW1hKHNjaGVtYUNvbnRhaW5lcik7Cgl9CgoKCS8vICoqKioqKioqKiogbmFtZXMgdnMuIGlkZW50aWZpZXJzICoqKioqKioqKioKCgkvKioKCSAqIENvbnZlcnQgdGhlIHNwZWNpZmllZCBuYW1lIHRvIGFuIGlkZW50aWZpZXIuIFJldHVybiBudWxsIGlmIHRoZSByZXN1bHRpbmcKCSAqIGlkZW50aWZpZXIgbWF0Y2hlcyB0aGUgc3BlY2lmaWVkIGRlZmF1bHQgbmFtZS4KCSAqLwoJU3RyaW5nIGNvbnZlcnROYW1lVG9JZGVudGlmaWVyKFN0cmluZyBuYW1lLCBTdHJpbmcgZGVmYXVsdE5hbWUpIHsKCQlyZXR1cm4gdGhpcy5nZXRWZW5kb3IoKS5jb252ZXJ0TmFtZVRvSWRlbnRpZmllcihuYW1lLCBkZWZhdWx0TmFtZSk7Cgl9CgoJLyoqCgkgKiBDb252ZXJ0IHRoZSBzcGVjaWZpZWQgbmFtZSB0byBhbiBpZGVudGlmaWVyLgoJICovCglwdWJsaWMgU3RyaW5nIGNvbnZlcnROYW1lVG9JZGVudGlmaWVyKFN0cmluZyBuYW1lKSB7CgkJcmV0dXJuIHRoaXMuZ2V0VmVuZG9yKCkuY29udmVydE5hbWVUb0lkZW50aWZpZXIobmFtZSk7Cgl9CgoJLyoqCgkgKiBSZXR1cm4gdGhlIGRhdGFiYXNlIG9iamVjdCBpZGVudGlmaWVkIGJ5IHRoZSBzcGVjaWZpZWQgaWRlbnRpZmllci4gSWYKCSAqIHRoZSBpZGVudGlmaWVyIGlzICJkZWxpbWl0ZWQiICh0eXBpY2FsbHkgd2l0aCBkb3VibGUtcXVvdGVzKSwgaXQgd2lsbCBiZQoJICogdXNlZCB3aXRob3V0IGFueSBmb2xkaW5nLiBJZiB0aGUgbmFtZSBpcyAibm9ybWFsIiAoaS5lLiBub3QgZGVsaW1pdGVkKSwKCSAqIGl0IHdpbGwgYmUgZm9sZGVkIHRvIHRoZSBhcHByb3ByaWF0ZSBjYXNlICh0eXBpY2FsbHkgdXBwZXJjYXNlKS4KCSAqIAoJICogU2luY2UgdGhlIGRhdGFiYXNlIGhhcyB0aGUgYXBwcm9wcmlhdGUgc3RhdGUgdG8gY29tcGFyZSBpZGVudGlmaWVycyBhbmQKCSAqIG5hbWVzLCB0aGUgY29ubmVjdGlvbiBwcm9maWxlIGRlbGVnYXRlcyB0byBoZXJlIHdoZW4gdXNpbmcgdGhlIGRlZmF1bHQKCSAqICJkYXRhYmFzZSBmaW5kZXIiLgoJICovCgk8VCBleHRlbmRzIERhdGFiYXNlT2JqZWN0PiBUIHNlbGVjdERhdGFiYXNlT2JqZWN0Rm9ySWRlbnRpZmllcl8oVFtdIGRhdGFiYXNlT2JqZWN0cywgU3RyaW5nIGlkZW50aWZpZXIpIHsKCQlyZXR1cm4gdGhpcy5zZWxlY3REYXRhYmFzZU9iamVjdE5hbWVkKGRhdGFiYXNlT2JqZWN0cywgdGhpcy5jb252ZXJ0SWRlbnRpZmllclRvTmFtZShpZGVudGlmaWVyKSk7Cgl9CgoJLyoqCgkgKiBDb252ZXJ0IHRoZSBzcGVjaWZpZWQgaWRlbnRpZmllciB0byBhIG5hbWUuCgkgKi8KCVN0cmluZyBjb252ZXJ0SWRlbnRpZmllclRvTmFtZShTdHJpbmcgaWRlbnRpZmllcikgewoJCXJldHVybiB0aGlzLmdldFZlbmRvcigpLmNvbnZlcnRJZGVudGlmaWVyVG9OYW1lKGlkZW50aWZpZXIpOwoJfQoKCgkvLyAqKioqKioqKioqIENvbXBhcmFibGUgaW1wbGVtZW50YXRpb24gKioqKioqKioqKgoKCXB1YmxpYyBpbnQgY29tcGFyZVRvKERhdGFiYXNlIGRhdGFiYXNlKSB7CgkJcmV0dXJuIENvbGxhdG9yLmdldEluc3RhbmNlKCkuY29tcGFyZSh0aGlzLmdldE5hbWUoKSwgZGF0YWJhc2UuZ2V0TmFtZSgpKTsKCX0KCgoJLy8gKioqKioqKioqKiBpbnRlcm5hbCBtZXRob2RzICoqKioqKioqKioKCglEYXRhYmFzZURlZmluaXRpb24gZ2V0RFRQRGVmaW5pdGlvbigpIHsKCQlyZXR1cm4gUkRCQ29yZVBsdWdpbi5nZXREZWZhdWx0KCkuZ2V0RGF0YWJhc2VEZWZpbml0aW9uUmVnaXN0cnkoKS5nZXREZWZpbml0aW9uKHRoaXMuZHRwRGF0YWJhc2UpOwoJfQoKCXByaXZhdGUgVmVuZG9yIGdldFZlbmRvcigpIHsKCQlyZXR1cm4gZ2V0VmVuZG9yKHRoaXMuZ2V0VmVuZG9yTmFtZSgpKTsKCX0KCgoJLy8gKioqKioqKioqKiBsaXN0ZW5pbmcgKioqKioqKioqKgoKCUBPdmVycmlkZQoJc3luY2hyb25pemVkIHZvaWQgc3RhcnRMaXN0ZW5pbmcoKSB7CgkJaWYgKHRoaXMuY2F0YWxvZ3MgIT0gbnVsbCkgewoJCQl0aGlzLnN0YXJ0Q2F0YWxvZ3MoKTsKCQl9CgkJc3VwZXIuc3RhcnRMaXN0ZW5pbmcoKTsKCX0KCglwcml2YXRlIHZvaWQgc3RhcnRDYXRhbG9ncygpIHsKCQlmb3IgKERUUENhdGFsb2dXcmFwcGVyIGNhdGFsb2cgOiB0aGlzLmNhdGFsb2dzKSB7CgkJCWNhdGFsb2cuc3RhcnRMaXN0ZW5pbmcoKTsKCQl9Cgl9CgoJQE92ZXJyaWRlCglzeW5jaHJvbml6ZWQgdm9pZCBzdG9wTGlzdGVuaW5nKCkgewoJCWlmICh0aGlzLmNhdGFsb2dzICE9IG51bGwpIHsKCQkJdGhpcy5zdG9wQ2F0YWxvZ3MoKTsKCQl9CgkJc3VwZXIuc3RvcExpc3RlbmluZygpOwoJfQoKCXByaXZhdGUgdm9pZCBzdG9wQ2F0YWxvZ3MoKSB7CgkJZm9yIChEVFBDYXRhbG9nV3JhcHBlciBjYXRhbG9nIDogdGhpcy5jYXRhbG9ncykgewoJCQljYXRhbG9nLnN0b3BMaXN0ZW5pbmcoKTsKCQl9Cgl9CgoKCS8vICoqKioqKioqKiogY2xlYXIgKioqKioqKioqKgoKCUBPdmVycmlkZQoJdm9pZCBjbGVhcigpIHsKCQl0aGlzLmRlZmF1bHRDYXRhbG9nQ2FsY3VsYXRlZCA9IGZhbHNlOwoJCXRoaXMuZGVmYXVsdENhdGFsb2cgPSBudWxsOwoJCWlmICh0aGlzLmNhdGFsb2dzICE9IG51bGwpIHsKCQkJdGhpcy5jbGVhckNhdGFsb2dzKCk7CgkJfQoJCXN1cGVyLmNsZWFyKCk7Cgl9CgoJcHJpdmF0ZSB2b2lkIGNsZWFyQ2F0YWxvZ3MoKSB7CgkJdGhpcy5zdG9wQ2F0YWxvZ3MoKTsKCQlmb3IgKERUUENhdGFsb2dXcmFwcGVyIGNhdGFsb2cgOiB0aGlzLmNhdGFsb2dzKSB7CgkJCWNhdGFsb2cuY2xlYXIoKTsKCQl9CgkJdGhpcy5jYXRhbG9ncyA9IG51bGw7Cgl9CgoKCS8vICoqKioqKioqKiogdmVuZG9ycyAqKioqKioqKioqCgoJcHJpdmF0ZSBzdGF0aWMgVmVuZG9yIGdldFZlbmRvcihTdHJpbmcgbmFtZSkgewoJCVZlbmRvciB2ZW5kb3IgPSBnZXRWZW5kb3JzKCkuZ2V0KG5hbWUpOwoJCXJldHVybiAodmVuZG9yICE9IG51bGwpID8gdmVuZG9yIDogRGVmYXVsdC5JTlNUQU5DRTsKCX0KCgkvKioKCSAqIGtleWVkIGJ5IHZlbmRvciBuYW1lCgkgKi8KCXByaXZhdGUgc3RhdGljIEhhc2hNYXA8U3RyaW5nLCBWZW5kb3I+IFZlbmRvcnM7CgoJcHJpdmF0ZSBzdGF0aWMgc3luY2hyb25pemVkIEhhc2hNYXA8U3RyaW5nLCBWZW5kb3I+IGdldFZlbmRvcnMoKSB7CgkJaWYgKFZlbmRvcnMgPT0gbnVsbCkgewoJCQlWZW5kb3JzID0gYnVpbGRWZW5kb3JzKCk7CgkJfQoJCXJldHVybiBWZW5kb3JzOwoJfQoKCXByaXZhdGUgc3RhdGljIEhhc2hNYXA8U3RyaW5nLCBWZW5kb3I+IGJ1aWxkVmVuZG9ycygpIHsKCQlIYXNoTWFwPFN0cmluZywgVmVuZG9yPiBtYXAgPSBuZXcgSGFzaE1hcDxTdHJpbmcsIFZlbmRvcj4oMjApOwoJCXB1dFZlbmRvcihtYXAsIERlcmJ5LklOU1RBTkNFKTsKCQlwdXRWZW5kb3IobWFwLCBIU1FMREIuSU5TVEFOQ0UpOwoJCXB1dFZlbmRvcihtYXAsIERCMi5VREIpOwoJCXB1dFZlbmRvcihtYXAsIERCMi5VREJfSV9TRVJJRVMpOwoJCXB1dFZlbmRvcihtYXAsIERCMi5VREJfWl9TRVJJRVMpOwoJCXB1dFZlbmRvcihtYXAsIEluZm9ybWl4LklOU1RBTkNFKTsKCQlwdXRWZW5kb3IobWFwLCBTUUxTZXJ2ZXIuSU5TVEFOQ0UpOwoJCXB1dFZlbmRvcihtYXAsIE15U1FMLklOU1RBTkNFKTsKCQlwdXRWZW5kb3IobWFwLCBPcmFjbGUuSU5TVEFOQ0UpOwoJCXB1dFZlbmRvcihtYXAsIFBvc3RncmVzLklOU1RBTkNFKTsKCQlwdXRWZW5kb3IobWFwLCBNYXhEQi5JTlNUQU5DRSk7CgkJcHV0VmVuZG9yKG1hcCwgU3liYXNlLkFTQSk7CgkJcHV0VmVuZG9yKG1hcCwgU3liYXNlLkFTRSk7CgkJcmV0dXJuIG1hcDsKCX0KCglwcml2YXRlIHN0YXRpYyB2b2lkIHB1dFZlbmRvcihIYXNoTWFwPFN0cmluZywgVmVuZG9yPiBtYXAsIFZlbmRvciB2ZW5kb3IpIHsKCQlTdHJpbmcgbmFtZSA9IHZlbmRvci5nZXROYW1lKCk7CgkJaWYgKG1hcC5wdXQobmFtZSwgdmVuZG9yKSAhPSBudWxsKSB7CgkJCXRocm93IG5ldyBJbGxlZ2FsQXJndW1lbnRFeGNlcHRpb24oIkR1cGxpY2F0ZSB2ZW5kb3I6ICIgKyBuYW1lKTsgLy8kTk9OLU5MUy0xJAoJCX0KCX0KCgoJLy8gKioqKioqKioqKiB2ZW5kb3IgY2xhc3NlcyAqKioqKioqKioqCgoJLyoqCgkgKiBEZWxlZ2F0ZSB2ZW5kb3Itc3BlY2lmaWMgYmVoYXZpb3IgdG8gaW1wbGVtZW50YXRpb25zIG9mIHRoaXMgY2xhc3MiCgkgKiAgIC0gZGVmYXVsdCBjYXRhbG9nIGFuZCBzY2hlbWEKCSAqICAgLSBjb252ZXJ0aW5nIG5hbWVzIHRvIGlkZW50aWZpZXJzIGFuZCB2aWNlLXZlcnNhCgkgKiAKCSAqIE5vdGU6CgkgKiBXZSB1c2UgIm5hbWUiIHdoZW4gZGVhbGluZyB3aXRoIHRoZSB1bm1vZGlmaWVkIG5hbWUgb2YgYSBkYXRhYmFzZSBvYmplY3QKCSAqIGFzIHN1cHBsaWVkIGJ5IHRoZSBkYXRhYmFzZSBpdHNlbGYgKGkuZS4gaXQgaXMgbm90IGRlbGltaXRlZCBhbmQgaXQgaXMgYWx3YXlzCgkgKiBjYXNlLXNlbnNpdGl2ZSkuCgkgKiBXZSB1c2UgImlkZW50aWZpZXIiIHdoZW4gZGVhbGluZyB3aXRoIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgZGF0YWJhc2UKCSAqIG9iamVjdCBuYW1lIChpLmUuIGl0IG1heSBiZSBkZWxpbWl0ZWQgYW5kLCBkZXBlbmRpbmcgb24gdGhlIHZlbmRvciwgaXQgbWF5CgkgKiBiZSBjYXNlLWluc2Vuc2l0aXZlKS4KCSAqLwoJcHJpdmF0ZSBhYnN0cmFjdCBzdGF0aWMgY2xhc3MgVmVuZG9yIHsKCgkJVmVuZG9yKCkgewoJCQlzdXBlcigpOwoJCX0KCgkJLyoqCgkJICogUmV0dXJuIHRoZSB2ZW5kb3IncyBuYW1lLiBUaGlzIG11c3QgbWF0Y2ggdGhlIG5hbWUgc3BlY2lmaWVkIGJ5IHRoZQoJCSAqIERUUCBjb25uZWN0aW9uIHByb2ZpbGUuCgkJICovCgkJYWJzdHJhY3QgU3RyaW5nIGdldE5hbWUoKTsKCgkJLyoqCgkJICogVGhlIFNRTCBzcGVjIHNheXMgYSAibm9ybWFsIiAobm9uLWRlbGltaXRlZCkgaWRlbnRpZmllciBzaG91bGQgYmUKCQkgKiBmb2xkZWQgdG8gdXBwZXJjYXNlOyBidXQgc29tZSBkYXRhYmFzZXMgZG8gb3RoZXJ3aXNlIChlLmcuIFN5YmFzZSkuCgkJICovCgkJRm9sZGVyIGdldEZvbGRlcigpIHsKCQkJcmV0dXJuIEZvbGRlci5VUFBFUjsKCQl9CgoKCQkvLyAqKioqKioqKioqIGRlZmF1bHQgY2F0YWxvZyBhbmQgc2NoZW1hICoqKioqKioqKioKCgkJRFRQQ2F0YWxvZ1dyYXBwZXIgZ2V0RGVmYXVsdENhdGFsb2coRFRQRGF0YWJhc2VXcmFwcGVyIGRhdGFiYXNlKSB7CgkJCXJldHVybiBkYXRhYmFzZS5nZXRDYXRhbG9nRm9ySWRlbnRpZmllcih0aGlzLmdldERlZmF1bHRDYXRhbG9nSWRlbnRpZmllcihkYXRhYmFzZSkpOwoJCX0KCgkJLyoqCgkJICogVHlwaWNhbGx5LCB0aGUgbmFtZSBvZiB0aGUgZGVmYXVsdCBjYXRhbG9nIGlzIHRoZSB1c2VyIG5hbWUuCgkJICovCgkJU3RyaW5nIGdldERlZmF1bHRDYXRhbG9nSWRlbnRpZmllcihEVFBEYXRhYmFzZVdyYXBwZXIgZGF0YWJhc2UpIHsKCQkJcmV0dXJuIGRhdGFiYXNlLmdldENvbm5lY3Rpb25Qcm9maWxlKCkuZ2V0VXNlck5hbWUoKTsKCQl9CgoJCURUUFNjaGVtYVdyYXBwZXIgZ2V0RGVmYXVsdFNjaGVtYShEVFBTY2hlbWFDb250YWluZXJXcmFwcGVyIHNjKSB7CgkJCXJldHVybiBzYy5nZXRTY2hlbWFGb3JJZGVudGlmaWVyKHRoaXMuZ2V0RGVmYXVsdFNjaGVtYUlkZW50aWZpZXIoc2MpKTsKCQl9CgoJCS8qKgoJCSAqIFR5cGljYWxseSwgdGhlIG5hbWUgb2YgdGhlIGRlZmF1bHQgc2NoZW1hIGlzIHRoZSB1c2VyIG5hbWUuCgkJICovCgkJU3RyaW5nIGdldERlZmF1bHRTY2hlbWFJZGVudGlmaWVyKERUUFNjaGVtYUNvbnRhaW5lcldyYXBwZXIgc2MpIHsKCQkJcmV0dXJuIHNjLmdldERhdGFiYXNlKCkuZ2V0Q29ubmVjdGlvblByb2ZpbGUoKS5nZXRVc2VyTmFtZSgpOwoJCX0KCgoJCS8vICoqKioqKioqKiogbmFtZSAtPiBpZGVudGlmaWVyICoqKioqKioqKioKCgkJLyoqCgkJICogQHNlZSBEVFBEYXRhYmFzZVdyYXBwZXIjY29udmVydE5hbWVUb0lkZW50aWZpZXIoU3RyaW5nLCBTdHJpbmcpCgkJICovCgkJZmluYWwgU3RyaW5nIGNvbnZlcnROYW1lVG9JZGVudGlmaWVyKFN0cmluZyBuYW1lLCBTdHJpbmcgZGVmYXVsdE5hbWUpIHsKCQkJcmV0dXJuIHRoaXMubmFtZVJlcXVpcmVzRGVsaW1pdGVycyhuYW1lKSA/IHRoaXMuZGVsaW1pdE5hbWUobmFtZSkKCQkJCQkJCTogdGhpcy5ub3JtYWxOYW1lc01hdGNoKG5hbWUsIGRlZmF1bHROYW1lKSA/IG51bGwgOiBuYW1lOwoJCX0KCgkJLyoqCgkJICogQHNlZSBEVFBEYXRhYmFzZVdyYXBwZXIjY29udmVydE5hbWVUb0lkZW50aWZpZXIoU3RyaW5nKQoJCSAqLwoJCWZpbmFsIFN0cmluZyBjb252ZXJ0TmFtZVRvSWRlbnRpZmllcihTdHJpbmcgbmFtZSkgewoJCQlyZXR1cm4gdGhpcy5uYW1lUmVxdWlyZXNEZWxpbWl0ZXJzKG5hbWUpID8gdGhpcy5kZWxpbWl0TmFtZShuYW1lKSA6IG5hbWU7CgkJfQoKCQkvKioKCQkgKiBSZXR1cm4gd2hldGhlciB0aGUgc3BlY2lmaWVkIGRhdGFiYXNlIG9iamVjdCBuYW1lIG11c3QgYmUgZGVsaW1pdGVkCgkJICogd2hlbiB1c2VkIGluIGFuIFNRTCBzdGF0ZW1lbnQuCgkJICogSWYgdGhlIG5hbWUgaGFzIGFueSAic3BlY2lhbCIgY2hhcmFjdGVycyAoYXMgb3Bwb3NlZCB0byBsZXR0ZXJzLAoJCSAqIGRpZ2l0cywgYW5kIG90aGVyIGFsbG93ZWQgY2hhcmFjdGVycyBbZS5nLiB1bmRlcnNjb3Jlc10pLCBpdCByZXF1aXJlcwoJCSAqIGRlbGltaXRlcnMuCgkJICogSWYgdGhlIG5hbWUgaXMgbWl4ZWQgY2FzZSBhbmQgdGhlIGRhdGFiYXNlIGZvbGRzIHVuZGVsaW1pdGVkIG5hbWVzCgkJICogKHRvIGVpdGhlciB1cHBlcmNhc2Ugb3IgbG93ZXJjYXNlKSwgaXQgcmVxdWlyZXMgZGVsaW1pdGVycy4KCQkgKi8KCQlmaW5hbCBib29sZWFuIG5hbWVSZXF1aXJlc0RlbGltaXRlcnMoU3RyaW5nIG5hbWUpIHsKCQkJcmV0dXJuIChuYW1lLmxlbmd0aCgpID09IDApICAvLyAgYW4gZW1wdHkgc3RyaW5nIG11c3QgYmUgZGVsaW1pdGVkKD8pCgkJCQkJCXx8IHRoaXMubmFtZUNvbnRhaW5zQW55U3BlY2lhbENoYXJhY3RlcnMobmFtZSkKCQkJCQkJfHwgdGhpcy5uYW1lSXNOb3RGb2xkZWQobmFtZSk7CgkJfQoKCQkvKioKCQkgKiBSZXR1cm4gd2hldGhlciB0aGUgc3BlY2lmaWVkIG5hbWUgY29udGFpbnMgYW55ICJzcGVjaWFsIiBjaGFyYWN0ZXJzCgkJICogdGhhdCByZXF1aXJlIHRoZSBuYW1lIHRvIGJlIGRlbGltaXRlZC4KCQkgKiBQcmUtY29uZGl0aW9uOiB0aGUgc3BlY2lmaWVkIG5hbWUgaXMgbm90IGVtcHR5CgkJICovCgkJZmluYWwgYm9vbGVhbiBuYW1lQ29udGFpbnNBbnlTcGVjaWFsQ2hhcmFjdGVycyhTdHJpbmcgbmFtZSkgewoJCQljaGFyW10gc3RyaW5nID0gbmFtZS50b0NoYXJBcnJheSgpOwoJCQlpZiAodGhpcy5jaGFyYWN0ZXJJc1NwZWNpYWxOYW1lU3RhcnQoc3RyaW5nWzBdKSkgewoJCQkJcmV0dXJuIHRydWU7CgkJCX0KCQkJZm9yIChpbnQgaSA9IHN0cmluZy5sZW5ndGg7IGktLSA+IDE7ICkgeyAgLy8gbm90ZTogc3RvcCBhdCAxCgkJCQlpZiAodGhpcy5jaGFyYWN0ZXJJc1NwZWNpYWxOYW1lUGFydChzdHJpbmdbaV0pKSB7CgkJCQkJcmV0dXJuIHRydWU7CgkJCQl9CgkJCX0KCQkJcmV0dXJuIGZhbHNlOwoJCX0KCgkJLyoqCgkJICogUmV0dXJuIHdoZXRoZXIgdGhlIHNwZWNpZmllZCBjaGFyYWN0ZXIgaXMgInNwZWNpYWwiIGZvciB0aGUgZmlyc3QKCQkgKiBjaGFyYWN0ZXIgb2YgYSBuYW1lLgoJCSAqIFR5cGljYWxseSwgZGF0YWJhc2VzIGFyZSBtb3JlIHJlc3RyaWN0aXZlIGFib3V0IHdoYXQgY2hhcmFjdGVycyBjYW4KCQkgKiBiZSB1c2VkIHRvICpzdGFydCogYW4gaWRlbnRpZmllciAoYXMgb3Bwb3NlZCB0byB0aGUgY2hhcmFjdGVycwoJCSAqIGFsbG93ZWQgZm9yIHRoZSByZW1haW5kZXIgb2YgdGhlIGlkZW50aWZpZXIpLgoJCSAqLwoJCWZpbmFsIGJvb2xlYW4gY2hhcmFjdGVySXNTcGVjaWFsTmFtZVN0YXJ0KGNoYXIgYykgewoJCQlyZXR1cm4gISB0aGlzLmNoYXJhY3RlcklzTm9ybWFsTmFtZVN0YXJ0KGMpOwoJCX0KCgkJLyoqCgkJICogUmV0dXJuIHdoZXRoZXIgdGhlIHNwZWNpZmllZCBjaGFyYWN0ZXIgaXMgIm5vcm1hbCIgZm9yIHRoZSBmaXJzdAoJCSAqIGNoYXJhY3RlciBvZiBhIG5hbWUuCgkJICogVGhlIGZpcnN0IGNoYXJhY3RlciBvZiBhbiBpZGVudGlmaWVyIGNhbiBiZToKCQkgKiAgIC0gYSBsZXR0ZXIKCQkgKiAgIC0gYW55IG9mIHRoZSBvdGhlciwgdmVuZG9yLXNwZWNpZmljLCAibm9ybWFsIiBzdGFydCBjaGFyYWN0ZXJzCgkJICovCgkJYm9vbGVhbiBjaGFyYWN0ZXJJc05vcm1hbE5hbWVTdGFydChjaGFyIGMpIHsKCQkJLy8gYWxsIHZlbmRvcnMgYWxsb3cgYSBsZXR0ZXIKCQkJcmV0dXJuIENoYXJhY3Rlci5pc0xldHRlcihjKQoJCQkJCXx8IHRoaXMuY2hhcmFjdGVySXNOb3JtYWxOYW1lU3RhcnRfKGMpOwoJCX0KCgkJcHJpdmF0ZSBib29sZWFuIGNoYXJhY3RlcklzTm9ybWFsTmFtZVN0YXJ0XyhjaGFyIGMpIHsKCQkJcmV0dXJuIGFycmF5Q29udGFpbnModGhpcy5nZXROb3JtYWxOYW1lU3RhcnRDaGFyYWN0ZXJzKCksIGMpOwoJCX0KCgkJLyoqCgkJICogUmV0dXJuIHRoZSAibm9ybWFsIiBjaGFyYWN0ZXJzLCBiZXlvbmQgbGV0dGVycywgZm9yIHRoZQoJCSAqIGZpcnN0IGNoYXJhY3RlciBvZiBhIG5hbWUuCgkJICogUmV0dXJuIG51bGwgaWYgdGhlcmUgYXJlIG5vIGFkZGl0aW9uYWwgY2hhcmFjdGVycy4KCQkgKi8KCQljaGFyW10gZ2V0Tm9ybWFsTmFtZVN0YXJ0Q2hhcmFjdGVycygpIHsKCQkJcmV0dXJuIG51bGw7CgkJfQoKCQkvKioKCQkgKiBSZXR1cm4gd2hldGhlciB0aGUgc3BlY2lmaWVkIGNoYXJhY3RlciBpcyAic3BlY2lhbCIgZm9yIHRoZSBzZWNvbmQgYW5kCgkJICogc3Vic2VxdWVudCBjaGFyYWN0ZXJzIG9mIGEgbmFtZS4KCQkgKi8KCQlmaW5hbCBib29sZWFuIGNoYXJhY3RlcklzU3BlY2lhbE5hbWVQYXJ0KGNoYXIgYykgewoJCQlyZXR1cm4gISB0aGlzLmNoYXJhY3RlcklzTm9ybWFsTmFtZVBhcnQoYyk7CgkJfQoKCQkvKioKCQkgKiBSZXR1cm4gd2hldGhlciB0aGUgc3BlY2lmaWVkIGNoYXJhY3RlciBpcyAibm9ybWFsIiBmb3IgdGhlIHNlY29uZCBhbmQKCQkgKiBzdWJzZXF1ZW50IGNoYXJhY3RlcnMgb2YgYSBuYW1lLgoJCSAqIFRoZSBzZWNvbmQgYW5kIHN1YnNlcXVlbnQgY2hhcmFjdGVycyBvZiBhICJub3JtYWwiIG5hbWUgY2FuIGJlOgoJCSAqICAgLSBhIGxldHRlcgoJCSAqICAgLSBhIGRpZ2l0CgkJICogICAtIGFueSBvZiB0aGUgb3RoZXIsIHZlbmRvci1zcGVjaWZpYywgIm5vcm1hbCIgc3RhcnQgY2hhcmFjdGVycwoJCSAqICAgLSBhbnkgb2YgdGhlIG90aGVyLCB2ZW5kb3Itc3BlY2lmaWMsICJub3JtYWwiIHBhcnQgY2hhcmFjdGVycwoJCSAqLwoJCWJvb2xlYW4gY2hhcmFjdGVySXNOb3JtYWxOYW1lUGFydChjaGFyIGMpIHsKCQkJLy8gYWxsIHZlbmRvcnMgYWxsb3cgYSBsZXR0ZXIgb3IgZGlnaXQKCQkJcmV0dXJuIENoYXJhY3Rlci5pc0xldHRlck9yRGlnaXQoYykKCQkJCQl8fCB0aGlzLmNoYXJhY3RlcklzTm9ybWFsTmFtZVN0YXJ0XyhjKQoJCQkJCXx8IHRoaXMuY2hhcmFjdGVySXNOb3JtYWxOYW1lUGFydF8oYyk7CgkJfQoKCQlwcml2YXRlIGJvb2xlYW4gY2hhcmFjdGVySXNOb3JtYWxOYW1lUGFydF8oY2hhciBjKSB7CgkJCXJldHVybiBhcnJheUNvbnRhaW5zKHRoaXMuZ2V0Tm9ybWFsTmFtZVBhcnRDaGFyYWN0ZXJzKCksIGMpOwoJCX0KCgkJLyoqCgkJICogUmV0dXJuIHRoZSAibm9ybWFsIiBjaGFyYWN0ZXJzLCBiZXlvbmQgbGV0dGVycyBhbmQgZGlnaXRzIGFuZCB0aGUKCQkgKiAibm9ybWFsIiBmaXJzdCBjaGFyYWN0ZXJzLCBmb3IgdGhlIHNlY29uZCBhbmQgc3Vic2VxdWVudCBjaGFyYWN0ZXJzCgkJICogb2YgYW4gaWRlbnRpZmllci4gUmV0dXJuIG51bGwgaWYgdGhlcmUgYXJlIG5vIGFkZGl0aW9uYWwgY2hhcmFjdGVycy4KCQkgKi8KCQljaGFyW10gZ2V0Tm9ybWFsTmFtZVBhcnRDaGFyYWN0ZXJzKCkgewoJCQlyZXR1cm4gbnVsbDsKCQl9CgoJCS8qKgoJCSAqIFJldHVybiB3aGV0aGVyIHRoZSBzcGVjaWZpZWQgbmFtZSBpcyBub3QgZm9sZGVkIHRvIHRoZSBkYXRhYmFzZSdzCgkJICogY2FzZSwgcmVxdWlyaW5nIGl0IHRvIGJlIGRlbGltaXRlZC4KCQkgKi8KCQlmaW5hbCBib29sZWFuIG5hbWVJc05vdEZvbGRlZChTdHJpbmcgbmFtZSkgewoJCQlyZXR1cm4gISB0aGlzLmdldEZvbGRlcigpLnN0cmluZ0lzRm9sZGVkKG5hbWUpOwoJCX0KCgkJLyoqCgkJICogUmV0dXJuIHdoZXRoZXIgdGhlIHNwZWNpZmllZCAibm9ybWFsIiBuYW1lcyBtYXRjaC4KCQkgKi8KCQlmaW5hbCBib29sZWFuIG5vcm1hbE5hbWVzTWF0Y2goU3RyaW5nIG5hbWUxLCBTdHJpbmcgbmFtZTIpIHsKCQkJcmV0dXJuIHRoaXMubm9ybWFsSWRlbnRpZmllcnNBcmVDYXNlU2Vuc2l0aXZlKCkgPwoJCQkJCQkJbmFtZTEuZXF1YWxzKG5hbWUyKQoJCQkJCQk6CgkJCQkJCQluYW1lMS5lcXVhbHNJZ25vcmVDYXNlKG5hbWUyKTsKCQl9CgoJCS8qKgoJCSAqIFR5cGljYWxseSwgIm5vcm1hbCIgaWRlbnRpZmllcnMgYXJlIGNhc2UtaW5zZW5zaXRpdmUuCgkJICovCgkJZmluYWwgYm9vbGVhbiBub3JtYWxJZGVudGlmaWVyc0FyZUNhc2VTZW5zaXRpdmUoKSB7CgkJCXJldHVybiB0aGlzLmdldEZvbGRlcigpLmlzQ2FzZVNlbnNpdGl2ZSgpOwoJCX0KCgkJLyoqCgkJICogV3JhcCB0aGUgc3BlY2lmaWVkIG5hbWUgaW4gZGVsaW1pdGVycyAodHlwaWNhbGx5IGRvdWJsZS1xdW90ZXMpLAoJCSAqIGNvbnZlcnRpbmcgaXQgdG8gYW4gaWRlbnRpZmllci4KCQkgKi8KCQlTdHJpbmcgZGVsaW1pdE5hbWUoU3RyaW5nIG5hbWUpIHsKCQkJcmV0dXJuIFN0cmluZ1Rvb2xzLnF1b3RlKG5hbWUpOwoJCX0KCgoJCS8vICoqKioqKioqKiogaWRlbnRpZmllciAtPiBuYW1lICoqKioqKioqKioKCgkJLyoqCgkJICogQHNlZSBEVFBEYXRhYmFzZVdyYXBwZXIjc2VsZWN0RGF0YWJhc2VPYmplY3RGb3JJZGVudGlmaWVyXyhEYXRhYmFzZU9iamVjdFtdLCBTdHJpbmcpCgkJICovCgkJLy8gbm90IHN1cmUgaG93IHRvIGhhbmRsZSBhbiBlbXB0eSBzdHJpbmc6CgkJLy8gYm90aCAiIiBhbmQgIlwiXCIiIGFyZSBjb252ZXJ0ZWQgdG8gIiIgLi4uCgkJLy8gY29udmVydCAiIiB0byAnbnVsbCcgc2luY2UgZW1wdHkgc3RyaW5ncyBtdXN0IGJlIGRlbGltaXRlZD8KCQlmaW5hbCBTdHJpbmcgY29udmVydElkZW50aWZpZXJUb05hbWUoU3RyaW5nIGlkZW50aWZpZXIpIHsKCQkJcmV0dXJuIChpZGVudGlmaWVyID09IG51bGwpID8gbnVsbCA6CgkJCQkJCXRoaXMuaWRlbnRpZmllcklzRGVsaW1pdGVkKGlkZW50aWZpZXIpID8KCQkJCQkJCVN0cmluZ1Rvb2xzLnVuZGVsaW1pdChpZGVudGlmaWVyKQoJCQkJCQk6CgkJCQkJCQl0aGlzLmdldEZvbGRlcigpLmZvbGQoaWRlbnRpZmllcik7CgkJfQoKCQkvKioKCQkgKiBSZXR1cm4gd2hldGhlciB0aGUgc3BlY2lmaWVkIGlkZW50aWZpZXIgaXMgImRlbGltaXRlZCIuCgkJICogVGhlIFNRTC05MiBzcGVjIHNheXMgaWRlbnRpZmllcnMgc2hvdWxkIGJlIGRlbGltaXRlZCBieQoJCSAqIGRvdWJsZS1xdW90ZXM7IGJ1dCBzb21lIGRhdGFiYXNlcyBhbGxvdyBvdGhlcndpc2UgKGUuZy4gU3liYXNlKS4KCQkgKi8KCQlib29sZWFuIGlkZW50aWZpZXJJc0RlbGltaXRlZChTdHJpbmcgaWRlbnRpZmllcikgewoJCQlyZXR1cm4gU3RyaW5nVG9vbHMuc3RyaW5nSXNRdW90ZWQoaWRlbnRpZmllcik7CgkJfQoKCgkJLy8gKioqKioqKioqKiBtaXNjICoqKioqKioqKioKCgkJQE92ZXJyaWRlCgkJcHVibGljIFN0cmluZyB0b1N0cmluZygpIHsKCQkJcmV0dXJuIHRoaXMuZ2V0TmFtZSgpOwoJCX0KCgkJLyoqCgkJICogc3RhdGljIGNvbnZlbmllbmNlIG1ldGhvZCAtIGFycmF5IG51bGwgY2hlY2sKCQkgKi8KCQlzdGF0aWMgYm9vbGVhbiBhcnJheUNvbnRhaW5zKGNoYXJbXSBhcnJheSwgY2hhciBjKSB7CgkJCXJldHVybiAoYXJyYXkgIT0gbnVsbCkgJiYgQ29sbGVjdGlvblRvb2xzLmNvbnRhaW5zKGFycmF5LCBjKTsKCQl9CgoJCS8qKgoJCSAqIEhhbmRsZSBkYXRhYmFzZS1zcGVjaWZpYyBjYXNlLWZvbGRpbmcgaXNzdWVzLgoJCSAqLwoJCWVudW0gRm9sZGVyIHsKCQkJVVBQRVIgewoJCQkJQE92ZXJyaWRlIFN0cmluZyBmb2xkKFN0cmluZyBzdHJpbmcpIHsgcmV0dXJuIHN0cmluZy50b1VwcGVyQ2FzZSgpOyB9CgkJCQlAT3ZlcnJpZGUgYm9vbGVhbiBzdHJpbmdJc0ZvbGRlZChTdHJpbmcgc3RyaW5nKSB7IHJldHVybiBTdHJpbmdUb29scy5zdHJpbmdJc1VwcGVyY2FzZShzdHJpbmcpOyB9CgkJCQlAT3ZlcnJpZGUgYm9vbGVhbiBpc0Nhc2VTZW5zaXRpdmUoKSB7IHJldHVybiBmYWxzZTsgfQoJCQl9LAoJCQlMT1dFUiB7CgkJCQlAT3ZlcnJpZGUgU3RyaW5nIGZvbGQoU3RyaW5nIHN0cmluZykgeyByZXR1cm4gc3RyaW5nLnRvTG93ZXJDYXNlKCk7IH0KCQkJCUBPdmVycmlkZSBib29sZWFuIHN0cmluZ0lzRm9sZGVkKFN0cmluZyBzdHJpbmcpIHsgcmV0dXJuIFN0cmluZ1Rvb2xzLnN0cmluZ0lzTG93ZXJjYXNlKHN0cmluZyk7IH0KCQkJCUBPdmVycmlkZSBib29sZWFuIGlzQ2FzZVNlbnNpdGl2ZSgpIHsgcmV0dXJuIGZhbHNlOyB9CgkJCX0sCgkJCU5PTkUgewoJCQkJQE92ZXJyaWRlIFN0cmluZyBmb2xkKFN0cmluZyBzdHJpbmcpIHsgcmV0dXJuIHN0cmluZzsgfQoJCQkJQE92ZXJyaWRlIGJvb2xlYW4gc3RyaW5nSXNGb2xkZWQoU3RyaW5nIHN0cmluZykgeyByZXR1cm4gdHJ1ZTsgfQoJCQkJQE92ZXJyaWRlIGJvb2xlYW4gaXNDYXNlU2Vuc2l0aXZlKCkgeyByZXR1cm4gdHJ1ZTsgfQoJCQl9OwoJCQlhYnN0cmFjdCBTdHJpbmcgZm9sZChTdHJpbmcgc3RyaW5nKTsKCQkJYWJzdHJhY3QgYm9vbGVhbiBzdHJpbmdJc0ZvbGRlZChTdHJpbmcgc3RyaW5nKTsKCQkJYWJzdHJhY3QgYm9vbGVhbiBpc0Nhc2VTZW5zaXRpdmUoKTsKCQl9CgoJfQoKCXByaXZhdGUgc3RhdGljIGNsYXNzIERlZmF1bHQgZXh0ZW5kcyBWZW5kb3IgewoJCXN0YXRpYyBmaW5hbCBWZW5kb3IgSU5TVEFOQ0UgPSBuZXcgRGVmYXVsdCgpOwoKCQlwcml2YXRlIERlZmF1bHQoKSB7CgkJCXN1cGVyKCk7CgkJfQoKCQlAT3ZlcnJpZGUKCQlTdHJpbmcgZ2V0TmFtZSgpIHsKCQkJcmV0dXJuICJEZWZhdWx0IFZlbmRvciI7IC8vJE5PTi1OTFMtMSQKCQl9CgoJfQoKCXByaXZhdGUgc3RhdGljIGNsYXNzIERlcmJ5IGV4dGVuZHMgVmVuZG9yIHsKCQlzdGF0aWMgZmluYWwgVmVuZG9yIElOU1RBTkNFID0gbmV3IERlcmJ5KCk7CgoJCXByaXZhdGUgRGVyYnkoKSB7CgkJCXN1cGVyKCk7CgkJfQoKCQlAT3ZlcnJpZGUKCQlTdHJpbmcgZ2V0TmFtZSgpIHsKCQkJcmV0dXJuICJEZXJieSI7IC8vJE5PTi1OTFMtMSQKCQl9CgoJCS8qKgoJCSAqIERlcmJ5IGhhcyBhIHNpbmdsZSwgdW5uYW1lZCBjYXRhbG9nIHRoYXQgY29udGFpbnMgYWxsIHRoZSBzY2hlbWF0YS4KCQkgKi8KCQlAT3ZlcnJpZGUKCQlTdHJpbmcgZ2V0RGVmYXVsdENhdGFsb2dJZGVudGlmaWVyKERUUERhdGFiYXNlV3JhcHBlciBkYXRhYmFzZSkgewoJCQlyZXR1cm4gIiI7IC8vJE5PTi1OTFMtMSQKCQl9CgoJCS8qKgoJCSAqIFRoZSBkZWZhdWx0IHVzZXIgbmFtZSBvbiBEZXJieSBpcyAiQVBQIi4KCQkgKi8KCQlAT3ZlcnJpZGUKCQlTdHJpbmcgZ2V0RGVmYXVsdFNjaGVtYUlkZW50aWZpZXIoRFRQU2NoZW1hQ29udGFpbmVyV3JhcHBlciBzYykgewoJCQlTdHJpbmcgdXNlciA9IHN1cGVyLmdldERlZmF1bHRTY2hlbWFJZGVudGlmaWVyKHNjKTsKCQkJcmV0dXJuICgodXNlciA9PSBudWxsKSB8fCAodXNlci5sZW5ndGgoKSA9PSAwKSkgPwoJCQkJCQkJREVGQVVMVF9VU0VSX05BTUUKCQkJCQkJOgoJCQkJCQkJdXNlcjsKCQl9CgkJcHJpdmF0ZSBzdGF0aWMgZmluYWwgU3RyaW5nIERFRkFVTFRfVVNFUl9OQU1FID0gIkFQUCI7ICAvLyROT04tTkxTLTEkCgoJCUBPdmVycmlkZQoJCWNoYXJbXSBnZXROb3JtYWxOYW1lUGFydENoYXJhY3RlcnMoKSB7CgkJCXJldHVybiBOT1JNQUxfTkFNRV9QQVJUX0NIQVJBQ1RFUlM7CgkJfQoJCXByaXZhdGUgc3RhdGljIGZpbmFsIGNoYXJbXSBOT1JNQUxfTkFNRV9QQVJUX0NIQVJBQ1RFUlMgPSBuZXcgY2hhcltdIHsgJ18nIH07CgoJfQoKCXByaXZhdGUgc3RhdGljIGNsYXNzIEhTUUxEQiBleHRlbmRzIFZlbmRvciB7CgkJc3RhdGljIGZpbmFsIFZlbmRvciBJTlNUQU5DRSA9IG5ldyBIU1FMREIoKTsKCgkJcHJpdmF0ZSBIU1FMREIoKSB7CgkJCXN1cGVyKCk7CgkJfQoKCQlAT3ZlcnJpZGUKCQlTdHJpbmcgZ2V0TmFtZSgpIHsKCQkJcmV0dXJuICJIU1FMREIiOyAvLyROT04tTkxTLTEkCgkJfQoKCX0KCglwcml2YXRlIHN0YXRpYyBjbGFzcyBEQjIgZXh0ZW5kcyBWZW5kb3IgewoJCXN0YXRpYyBmaW5hbCBWZW5kb3IgVURCX0lfU0VSSUVTID0gbmV3IERCMigiREIyIFVEQiBpU2VyaWVzIik7IC8vJE5PTi1OTFMtMSQKCQlzdGF0aWMgZmluYWwgVmVuZG9yIFVEQiA9IG5ldyBEQjIoIkRCMiBVREIiKTsgLy8kTk9OLU5MUy0xJAoJCXN0YXRpYyBmaW5hbCBWZW5kb3IgVURCX1pfU0VSSUVTID0gbmV3IERCMigiREIyIFVEQiB6U2VyaWVzIik7IC8vJE5PTi1OTFMtMSQKCgkJcHJpdmF0ZSBmaW5hbCBTdHJpbmcgbmFtZTsKCgkJcHJpdmF0ZSBEQjIoU3RyaW5nIG5hbWUpIHsKCQkJc3VwZXIoKTsKCQkJdGhpcy5uYW1lID0gbmFtZTsKCQl9CgoJCUBPdmVycmlkZQoJCVN0cmluZyBnZXROYW1lKCkgewoJCQlyZXR1cm4gdGhpcy5uYW1lOwoJCX0KCgkJQE92ZXJyaWRlCgkJY2hhcltdIGdldE5vcm1hbE5hbWVQYXJ0Q2hhcmFjdGVycygpIHsKCQkJcmV0dXJuIE5PUk1BTF9OQU1FX1BBUlRfQ0hBUkFDVEVSUzsKCQl9CgkJcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2hhcltdIE5PUk1BTF9OQU1FX1BBUlRfQ0hBUkFDVEVSUyA9IG5ldyBjaGFyW10geyAnXycgfTsKCgl9CgoJcHJpdmF0ZSBzdGF0aWMgY2xhc3MgSW5mb3JtaXggZXh0ZW5kcyBWZW5kb3IgewoJCXN0YXRpYyBmaW5hbCBWZW5kb3IgSU5TVEFOQ0UgPSBuZXcgSW5mb3JtaXgoKTsKCgkJcHJpdmF0ZSBJbmZvcm1peCgpIHsKCQkJc3VwZXIoKTsKCQl9CgoJCUBPdmVycmlkZQoJCVN0cmluZyBnZXROYW1lKCkgewoJCQlyZXR1cm4gIkluZm9ybWl4IjsgLy8kTk9OLU5MUy0xJAoJCX0KCgkJQE92ZXJyaWRlCgkJRm9sZGVyIGdldEZvbGRlcigpIHsKCQkJcmV0dXJuIEZvbGRlci5MT1dFUjsKCQl9CgoJCUBPdmVycmlkZQoJCWNoYXJbXSBnZXROb3JtYWxOYW1lU3RhcnRDaGFyYWN0ZXJzKCkgewoJCQlyZXR1cm4gTk9STUFMX05BTUVfU1RBUlRfQ0hBUkFDVEVSUzsKCQl9CgkJcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2hhcltdIE5PUk1BTF9OQU1FX1NUQVJUX0NIQVJBQ1RFUlMgPSBuZXcgY2hhcltdIHsgJ18nIH07CgoJCUBPdmVycmlkZQoJCWNoYXJbXSBnZXROb3JtYWxOYW1lUGFydENoYXJhY3RlcnMoKSB7CgkJCXJldHVybiBOT1JNQUxfTkFNRV9QQVJUX0NIQVJBQ1RFUlM7CgkJfQoJCXByaXZhdGUgc3RhdGljIGZpbmFsIGNoYXJbXSBOT1JNQUxfTkFNRV9QQVJUX0NIQVJBQ1RFUlMgPSBuZXcgY2hhcltdIHsgJyQnIH07CgoJfQoKCXByaXZhdGUgc3RhdGljIGNsYXNzIFNRTFNlcnZlciBleHRlbmRzIFZlbmRvciB7CgkJc3RhdGljIGZpbmFsIFZlbmRvciBJTlNUQU5DRSA9IG5ldyBTUUxTZXJ2ZXIoKTsKCgkJcHJpdmF0ZSBTUUxTZXJ2ZXIoKSB7CgkJCXN1cGVyKCk7CgkJfQoKCQlAT3ZlcnJpZGUKCQlTdHJpbmcgZ2V0TmFtZSgpIHsKCQkJcmV0dXJuICJTUUwgU2VydmVyIjsgLy8kTk9OLU5MUy0xJAoJCX0KCgkJLyoqCgkJICogVGhlIGRlZmF1bHQgc2NoZW1hIG9uIFNRTCBTZXJ2ZXIgZm9yIGFueSBkYXRhYmFzZSAoY2F0YWxvZykgaXMgJ2RibycuCgkJICovCgkJQE92ZXJyaWRlCgkJU3RyaW5nIGdldERlZmF1bHRTY2hlbWFJZGVudGlmaWVyKERUUFNjaGVtYUNvbnRhaW5lcldyYXBwZXIgc2MpIHsKCQkJcmV0dXJuIERFRkFVTFRfU0NIRU1BX05BTUU7CgkJfQoJCXByaXZhdGUgc3RhdGljIGZpbmFsIFN0cmluZyBERUZBVUxUX1NDSEVNQV9OQU1FID0gImRibyI7ICAvLyROT04tTkxTLTEkCgoJCS8qKgoJCSAqIEJ5IGRlZmF1bHQsIFNRTCBTZXJ2ZXIgaWRlbnRpZmllcnMgYXJlIGNhc2Utc2Vuc2l0aXZlLCBldmVuIHdpdGhvdXQKCQkgKiBkZWxpbWl0ZXJzLiBUaGlzIGNhbiBkZXBlbmQgb24gdGhlIGNvbGxhdGlvbiBzZXR0aW5nLi4uLgoJCSAqLwoJCUBPdmVycmlkZQoJCUZvbGRlciBnZXRGb2xkZXIoKSB7CgkJCXJldHVybiBGb2xkZXIuTk9ORTsKCQl9CgoJCUBPdmVycmlkZQoJCWNoYXJbXSBnZXROb3JtYWxOYW1lU3RhcnRDaGFyYWN0ZXJzKCkgewoJCQlyZXR1cm4gTk9STUFMX05BTUVfU1RBUlRfQ0hBUkFDVEVSUzsKCQl9CgkJcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2hhcltdIE5PUk1BTF9OQU1FX1NUQVJUX0NIQVJBQ1RFUlMgPSBuZXcgY2hhcltdIHsgJ18nLCAnQCcsICcjJyB9OwoKCQlAT3ZlcnJpZGUKCQljaGFyW10gZ2V0Tm9ybWFsTmFtZVBhcnRDaGFyYWN0ZXJzKCkgewoJCQlyZXR1cm4gTk9STUFMX05BTUVfUEFSVF9DSEFSQUNURVJTOwoJCX0KCQlwcml2YXRlIHN0YXRpYyBmaW5hbCBjaGFyW10gTk9STUFMX05BTUVfUEFSVF9DSEFSQUNURVJTID0gbmV3IGNoYXJbXSB7ICckJyB9OwoKCQkvKioKCQkgKiBCeSBkZWZhdWx0LCBTUUwgU2VydmVyIGRlbGltaXRzIGlkZW50aWZpZXJzIHdpdGggYnJhY2tldHMgKFtdKTsgYnV0IGl0CgkJICogY2FuIGFsc28gYmUgY29uZmlndXJlZCB0byB1c2UgZG91YmxlLXF1b3Rlcy4KCQkgKi8KCQlAT3ZlcnJpZGUKCQlib29sZWFuIGlkZW50aWZpZXJJc0RlbGltaXRlZChTdHJpbmcgaWRlbnRpZmllcikgewoJCQlyZXR1cm4gU3RyaW5nVG9vbHMuc3RyaW5nSXNCcmFja2V0ZWQoaWRlbnRpZmllcikKCQkJCQkJfHwgc3VwZXIuaWRlbnRpZmllcklzRGVsaW1pdGVkKGlkZW50aWZpZXIpOwoJCX0KCgl9CgoJcHJpdmF0ZSBzdGF0aWMgY2xhc3MgTXlTUUwgZXh0ZW5kcyBWZW5kb3IgewoJCXN0YXRpYyBmaW5hbCBWZW5kb3IgSU5TVEFOQ0UgPSBuZXcgTXlTUUwoKTsKCgkJcHJpdmF0ZSBNeVNRTCgpIHsKCQkJc3VwZXIoKTsKCQl9CgoJCUBPdmVycmlkZQoJCVN0cmluZyBnZXROYW1lKCkgewoJCQlyZXR1cm4gIk15U3FsIjsgLy8kTk9OLU5MUy0xJAoJCX0KCgkJLyoqCgkJICogTXlTUUwgaXMgYSBiaXQgdW51c3VhbCwgc28gd2UgZm9yY2UgZXhhY3QgbWF0Y2hlcy4KCQkgKiAoZS5nLiBNeVNRTCBmb2xkcyBkYXRhYmFzZSBhbmQgdGFibGUgbmFtZXMgdG8gbG93ZXJjYXNlIG9uIFdpbmRvd3MKCQkgKiBieSBkZWZhdWx0OyBidXQgdGhhdCBkZWZhdWx0IGNhbiBiZSBjaGFuZ2VkIGJ5IHRoZQoJCSAqICdsb3dlcl9jYXNlX3RhYmxlX25hbWVzJyBzeXN0ZW0gdmFyaWFibGUuIFRoaXMgaXMgYmVjYXVzZSBkYXRhYmFzZXMgYXJlCgkJICogc3RvcmVkIGFzIGRpcmVjdG9yaWVzIGFuZCB0YWJsZXMgYXJlIHN0b3JlZCBhcyBmaWxlcyBpbiB0aGUgdW5kZXJseWluZwoJCSAqIE8vUzsgYW5kIHRoZSBjYXNlLXNlbnNpdGl2aXR5IG9mIHRoZSBuYW1lcyBpcyBkZXRlcm1pbmVkIGJ5IHRoZSBiZWhhdmlvcgoJCSAqIG9mIGZpbGVuYW1lcyBvbiB0aGUgTy9TLiBUaGVuLCB0byBjb21wbGljYXRlIHRoaW5ncywKCQkgKiBub25lIG9mIHRoZSBvdGhlciBpZGVudGlmaWVycywgbGlrZSB0YWJsZSBhbmQgY29sdW1uIG5hbWVzLCBhcmUgZm9sZGVkOwoJCSAqIGJ1dCB0aGV5IGFyZSBjYXNlLWluc2Vuc2l0aXZlLCB1bmxlc3MgZGVsaW1pdGVkLiBTZWUKCQkgKiBodHRwOi8vZGV2Lm15c3FsLmNvbS9kb2MvcmVmbWFuLzYuMC9lbi9pZGVudGlmaWVyLWNhc2Utc2Vuc2l0aXZpdHkuaHRtbC4pCgkJICovCgkJQE92ZXJyaWRlCgkJRm9sZGVyIGdldEZvbGRlcigpIHsKCQkJcmV0dXJuIEZvbGRlci5OT05FOwoJCX0KCgkJLyoqCgkJICogTXlTUUwgaGFzIGEgc2luZ2xlIHNjaGVtYSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgdGhlIGRhdGFiYXNlLgoJCSAqLwoJCUBPdmVycmlkZQoJCVN0cmluZyBnZXREZWZhdWx0U2NoZW1hSWRlbnRpZmllcihEVFBTY2hlbWFDb250YWluZXJXcmFwcGVyIHNjKSB7CgkJCXJldHVybiBzYy5nZXREYXRhYmFzZSgpLmdldE5hbWUoKTsKCQl9CgoJCS8qKgoJCSAqIE15U1FMIGlzIHRoZSBvbmx5IHZlbmRvciB0aGF0IGFsbG93cyBhIGRpZ2l0LgoJCSAqIEFsdGhvdWdoLCB0aGUgbmFtZSBjYW5ubm90IGJlICphbGwqIGRpZ2l0cy4KCQkgKi8KCQlAT3ZlcnJpZGUKCQlib29sZWFuIGNoYXJhY3RlcklzTm9ybWFsTmFtZVN0YXJ0KGNoYXIgYykgewoJCQlyZXR1cm4gQ2hhcmFjdGVyLmlzRGlnaXQoYykgfHwgc3VwZXIuY2hhcmFjdGVySXNOb3JtYWxOYW1lU3RhcnQoYyk7CgkJfQoKCQlAT3ZlcnJpZGUKCQljaGFyW10gZ2V0Tm9ybWFsTmFtZVN0YXJ0Q2hhcmFjdGVycygpIHsKCQkJcmV0dXJuIE5PUk1BTF9OQU1FX1NUQVJUX0NIQVJBQ1RFUlM7CgkJfQoJCXByaXZhdGUgc3RhdGljIGZpbmFsIGNoYXJbXSBOT1JNQUxfTkFNRV9TVEFSVF9DSEFSQUNURVJTID0gbmV3IGNoYXJbXSB7ICdfJywgJyQnIH07CgoJCS8qKgoJCSAqIEJ5IGRlZmF1bHQsIE15U1FMIGRlbGltaXRzIGlkZW50aWZpZXJzIHdpdGggYmFja3RpY2tzIChgKTsgYnV0IGl0CgkJICogY2FuIGFsc28gYmUgY29uZmlndXJlZCB0byB1c2UgZG91YmxlLXF1b3Rlcy4KCQkgKi8KCQlAT3ZlcnJpZGUKCQlib29sZWFuIGlkZW50aWZpZXJJc0RlbGltaXRlZChTdHJpbmcgaWRlbnRpZmllcikgewoJCQlyZXR1cm4gU3RyaW5nVG9vbHMuc3RyaW5nSXNEZWxpbWl0ZWQoaWRlbnRpZmllciwgQkFDS1RJQ0spCgkJCQkJCXx8IHN1cGVyLmlkZW50aWZpZXJJc0RlbGltaXRlZChpZGVudGlmaWVyKTsKCQl9CgkJcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2hhciBCQUNLVElDSyA9ICdgJzsKCgl9CgoJcHJpdmF0ZSBzdGF0aWMgY2xhc3MgT3JhY2xlIGV4dGVuZHMgVmVuZG9yIHsKCQlzdGF0aWMgZmluYWwgVmVuZG9yIElOU1RBTkNFID0gbmV3IE9yYWNsZSgpOwoKCQlwcml2YXRlIE9yYWNsZSgpIHsKCQkJc3VwZXIoKTsKCQl9CgoJCUBPdmVycmlkZQoJCVN0cmluZyBnZXROYW1lKCkgewoJCQlyZXR1cm4gIk9yYWNsZSI7IC8vJE5PTi1OTFMtMSQKCQl9CgoJCS8qKgoJCSAqIE9yYWNsZSBoYXMgYSBzaW5nbGUsIHVubmFtZWQgY2F0YWxvZyB0aGF0IGNvbnRhaW5zIGFsbCB0aGUgc2NoZW1hdGEuCgkJICovCgkJQE92ZXJyaWRlCgkJU3RyaW5nIGdldERlZmF1bHRDYXRhbG9nSWRlbnRpZmllcihEVFBEYXRhYmFzZVdyYXBwZXIgZGF0YWJhc2UpIHsKCQkJcmV0dXJuICIiOyAvLyROT04tTkxTLTEkCgkJfQoKCQlAT3ZlcnJpZGUKCQljaGFyW10gZ2V0Tm9ybWFsTmFtZVBhcnRDaGFyYWN0ZXJzKCkgewoJCQlyZXR1cm4gTk9STUFMX05BTUVfUEFSVF9DSEFSQUNURVJTOwoJCX0KCQlwcml2YXRlIHN0YXRpYyBmaW5hbCBjaGFyW10gTk9STUFMX05BTUVfUEFSVF9DSEFSQUNURVJTID0gbmV3IGNoYXJbXSB7ICdfJywgJyQnLCAnIycgfTsKCgl9CgoJcHJpdmF0ZSBzdGF0aWMgY2xhc3MgUG9zdGdyZXMgZXh0ZW5kcyBWZW5kb3IgewoJCXN0YXRpYyBmaW5hbCBWZW5kb3IgSU5TVEFOQ0UgPSBuZXcgUG9zdGdyZXMoKTsKCgkJcHJpdmF0ZSBQb3N0Z3JlcygpIHsKCQkJc3VwZXIoKTsKCQl9CgoJCUBPdmVycmlkZQoJCVN0cmluZyBnZXROYW1lKCkgewoJCQlyZXR1cm4gInBvc3RncmVzIjsgLy8kTk9OLU5MUy0xJAoJCX0KCgkJQE92ZXJyaWRlCgkJRm9sZGVyIGdldEZvbGRlcigpIHsKCQkJcmV0dXJuIEZvbGRlci5MT1dFUjsKCQl9CgoJCS8qKgoJCSAqIFBvc3RncmVTUUwgaGFzIGEgc2luZ2xlLCB1bm5hbWVkIGNhdGFsb2cgdGhhdCBjb250YWlucyBhbGwgdGhlIHNjaGVtYXRhLgoJCSAqLwoJCUBPdmVycmlkZQoJCVN0cmluZyBnZXREZWZhdWx0Q2F0YWxvZ0lkZW50aWZpZXIoRFRQRGF0YWJhc2VXcmFwcGVyIGRhdGFiYXNlKSB7CgkJCXJldHVybiAiIjsgLy8kTk9OLU5MUy0xJAoJCX0KCgkJLyoqCgkJICogUG9zdGdyZVNRTCBoYXMgYSAic2NoZW1hIHNlYXJjaCBwYXRoIi4gVGhlIGRlZmF1bHQgaXM6CgkJICogICAgICIkdXNlciIscHVibGljCgkJICogSWYgIiR1c2VyIiBpcyBub3QgZm91bmQsIHJldHVybiAicHVibGljIi4KCQkgKi8KCQlAT3ZlcnJpZGUKCQlEVFBTY2hlbWFXcmFwcGVyIGdldERlZmF1bHRTY2hlbWEoRFRQU2NoZW1hQ29udGFpbmVyV3JhcHBlciBzYykgewoJCQlEVFBTY2hlbWFXcmFwcGVyIHNjaGVtYSA9IHN1cGVyLmdldERlZmF1bHRTY2hlbWEoc2MpOwoJCQlyZXR1cm4gKHNjaGVtYSAhPSBudWxsKSA/IHNjaGVtYSA6IHNjLmdldFNjaGVtYU5hbWVkKFBVQkxJQ19TQ0hFTUFfTkFNRSk7CgkJfQoJCXByaXZhdGUgc3RhdGljIGZpbmFsIFN0cmluZyBQVUJMSUNfU0NIRU1BX05BTUUgPSAicHVibGljIjsgIC8vJE5PTi1OTFMtMSQKCgkJQE92ZXJyaWRlCgkJY2hhcltdIGdldE5vcm1hbE5hbWVTdGFydENoYXJhY3RlcnMoKSB7CgkJCXJldHVybiBOT1JNQUxfTkFNRV9TVEFSVF9DSEFSQUNURVJTOwoJCX0KCQlwcml2YXRlIHN0YXRpYyBmaW5hbCBjaGFyW10gTk9STUFMX05BTUVfU1RBUlRfQ0hBUkFDVEVSUyA9IG5ldyBjaGFyW10geyAnXycgfTsKCgkJQE92ZXJyaWRlCgkJY2hhcltdIGdldE5vcm1hbE5hbWVQYXJ0Q2hhcmFjdGVycygpIHsKCQkJcmV0dXJuIE5PUk1BTF9OQU1FX1BBUlRfQ0hBUkFDVEVSUzsKCQl9CgkJcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2hhcltdIE5PUk1BTF9OQU1FX1BBUlRfQ0hBUkFDVEVSUyA9IG5ldyBjaGFyW10geyAnJCcgfTsKCgl9CgoJcHJpdmF0ZSBzdGF0aWMgY2xhc3MgTWF4REIgZXh0ZW5kcyBWZW5kb3IgewoJCXN0YXRpYyBmaW5hbCBWZW5kb3IgSU5TVEFOQ0UgPSBuZXcgTWF4REIoKTsKCgkJcHJpdmF0ZSBNYXhEQigpIHsKCQkJc3VwZXIoKTsKCQl9CgoJCUBPdmVycmlkZQoJCVN0cmluZyBnZXROYW1lKCkgewoJCQlyZXR1cm4gIk1heERCIjsgLy8kTk9OLU5MUy0xJAoJCX0KCgkJQE92ZXJyaWRlCgkJY2hhcltdIGdldE5vcm1hbE5hbWVTdGFydENoYXJhY3RlcnMoKSB7CgkJCXJldHVybiBOT1JNQUxfTkFNRV9TVEFSVF9DSEFSQUNURVJTOwoJCX0KCQlwcml2YXRlIHN0YXRpYyBmaW5hbCBjaGFyW10gTk9STUFMX05BTUVfU1RBUlRfQ0hBUkFDVEVSUyA9IG5ldyBjaGFyW10geyAnIycsICdAJywgJyQnIH07CgoJCUBPdmVycmlkZQoJCWNoYXJbXSBnZXROb3JtYWxOYW1lUGFydENoYXJhY3RlcnMoKSB7CgkJCXJldHVybiBOT1JNQUxfTkFNRV9QQVJUX0NIQVJBQ1RFUlM7CgkJfQoJCXByaXZhdGUgc3RhdGljIGZpbmFsIGNoYXJbXSBOT1JNQUxfTkFNRV9QQVJUX0NIQVJBQ1RFUlMgPSBuZXcgY2hhcltdIHsgJ18nIH07CgoJfQoKCXByaXZhdGUgc3RhdGljIGNsYXNzIFN5YmFzZSBleHRlbmRzIFZlbmRvciB7CgkJc3RhdGljIGZpbmFsIFZlbmRvciBBU0EgPSBuZXcgU3liYXNlKCJTeWJhc2VfQVNBIik7IC8vJE5PTi1OTFMtMSQKCQlzdGF0aWMgZmluYWwgVmVuZG9yIEFTRSA9IG5ldyBTeWJhc2UoIlN5YmFzZV9BU0UiKTsgLy8kTk9OLU5MUy0xJAoKCQlwcml2YXRlIGZpbmFsIFN0cmluZyBuYW1lOwoKCQlwcml2YXRlIFN5YmFzZShTdHJpbmcgbmFtZSkgewoJCQlzdXBlcigpOwoJCQl0aGlzLm5hbWUgPSBuYW1lOwoJCX0KCgkJQE92ZXJyaWRlCgkJU3RyaW5nIGdldE5hbWUoKSB7CgkJCXJldHVybiB0aGlzLm5hbWU7CgkJfQoKCQkvKioKCQkgKiBUaGUgZGVmYXVsdCBzY2hlbWEgb24gU3liYXNlIGZvciBhbnkgZGF0YWJhc2UgKGNhdGFsb2cpIGlzICdkYm8nLgoJCSAqLwoJCUBPdmVycmlkZQoJCVN0cmluZyBnZXREZWZhdWx0U2NoZW1hSWRlbnRpZmllcihEVFBTY2hlbWFDb250YWluZXJXcmFwcGVyIHNjKSB7CgkJCXJldHVybiBERUZBVUxUX1NDSEVNQV9OQU1FOwoJCX0KCQlwcml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgREVGQVVMVF9TQ0hFTUFfTkFNRSA9ICJkYm8iOyAgLy8kTk9OLU5MUy0xJAoKCQkvKioKCQkgKiBCeSBkZWZhdWx0LCBTeWJhc2UgaWRlbnRpZmllcnMgYXJlIGNhc2Utc2Vuc2l0aXZlLCBldmVuIHdpdGhvdXQKCQkgKiBkZWxpbWl0ZXJzLiBUaGlzIGNhbiBkZXBlbmQgb24gdGhlIGNvbGxhdGlvbiBzZXR0aW5nLi4uLgoJCSAqLwoJCUBPdmVycmlkZQoJCUZvbGRlciBnZXRGb2xkZXIoKSB7CgkJCXJldHVybiBGb2xkZXIuTk9ORTsKCQl9CgoJCUBPdmVycmlkZQoJCWNoYXJbXSBnZXROb3JtYWxOYW1lU3RhcnRDaGFyYWN0ZXJzKCkgewoJCQlyZXR1cm4gTk9STUFMX05BTUVfU1RBUlRfQ0hBUkFDVEVSUzsKCQl9CgkJcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2hhcltdIE5PUk1BTF9OQU1FX1NUQVJUX0NIQVJBQ1RFUlMgPSBuZXcgY2hhcltdIHsgJ18nLCAnQCcgfTsKCgkJQE92ZXJyaWRlCgkJY2hhcltdIGdldE5vcm1hbE5hbWVQYXJ0Q2hhcmFjdGVycygpIHsKCQkJcmV0dXJuIE5PUk1BTF9OQU1FX1BBUlRfQ0hBUkFDVEVSUzsKCQl9CgkJcHJpdmF0ZSBzdGF0aWMgZmluYWwgY2hhcltdIE5PUk1BTF9OQU1FX1BBUlRfQ0hBUkFDVEVSUyA9IG5ldyBjaGFyW10geyAnJCcsICelJywgJ6MnLCAnIycgfTsKCgkJLyoqCgkJICogQnkgZGVmYXVsdCwgU3liYXNlIGRlbGltaXRzIGlkZW50aWZpZXJzIHdpdGggYnJhY2tldHMgKFtdKTsgYnV0IGl0CgkJICogY2FuIGFsc28gYmUgY29uZmlndXJlZCB0byB1c2UgZG91YmxlLXF1b3Rlcy4KCQkgKi8KCQlAT3ZlcnJpZGUKCQlib29sZWFuIGlkZW50aWZpZXJJc0RlbGltaXRlZChTdHJpbmcgaWRlbnRpZmllcikgewoJCQlyZXR1cm4gU3RyaW5nVG9vbHMuc3RyaW5nSXNCcmFja2V0ZWQoaWRlbnRpZmllcikKCQkJCQkJfHwgc3VwZXIuaWRlbnRpZmllcklzRGVsaW1pdGVkKGlkZW50aWZpZXIpOwoJCX0KCgl9Cgp9Cg==