LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA0IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIENvbW1vbiBQdWJsaWMgTGljZW5zZSB2MS4wCiAqIHdoaWNoIGFjY29tcGFuaWVzIHRoaXMgZGlzdHJpYnV0aW9uLCBhbmQgaXMgYXZhaWxhYmxlIGF0CiAqIGh0dHA6Ly93d3cuZWNsaXBzZS5vcmcvbGVnYWwvY3BsLXYxMC5odG1sCqAqCiAqIENvbnRyaWJ1dG9yczoKICogICAgSUJNIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5pbnRlcm5ldC5tb25pdG9yLmNvcmUuaW50ZXJuYWwuaHR0cDsKCmltcG9ydCBqYXZhLmlvLio7CmltcG9ydCBvcmcuZWNsaXBzZS53c3QuaW50ZXJuZXQubW9uaXRvci5jb3JlLklSZXF1ZXN0OwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LmludGVybmV0Lm1vbml0b3IuY29yZS5pbnRlcm5hbC5Db25uZWN0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LmludGVybmV0Lm1vbml0b3IuY29yZS5pbnRlcm5hbC5UcmFjZTsKLyoqCiAqIE1vbml0b3Igc2VydmVyIEkvTyB0aHJlYWQuCiAqLwpwdWJsaWMgY2xhc3MgSFRUUFRocmVhZCBleHRlbmRzIFRocmVhZCB7Cglwcml2YXRlIHN0YXRpYyBmaW5hbCBpbnQgQlVGRkVSID0gMjA0ODsKCXByaXZhdGUgc3RhdGljIGZpbmFsIGJ5dGUgQ1IgPSAoYnl0ZSkgJ1xyJzsKCXByaXZhdGUgc3RhdGljIGZpbmFsIGJ5dGUgTEYgPSAoYnl0ZSkgJ1xuJzsKCXByb3RlY3RlZCBzdGF0aWMgaW50IHRocmVhZENvdW50ID0gMDsKCglwcml2YXRlIGJ5dGVbXSByZWFkQnVmZmVyID0gbmV3IGJ5dGVbQlVGRkVSXTsKCgkvLyBidWZmZXIgYW5kIGluZGV4Cglwcm90ZWN0ZWQgYnl0ZVtdIGJ1ZmZlciA9IG5ldyBieXRlWzBdOwoJcHJvdGVjdGVkIGludCBidWZmZXJJbmRleCA9IDA7CgoJcHJvdGVjdGVkIElucHV0U3RyZWFtIGluOwoJcHJvdGVjdGVkIE91dHB1dFN0cmVhbSBvdXQ7Cglwcm90ZWN0ZWQgSFRUUENvbm5lY3Rpb24gY29ubjsKCXByb3RlY3RlZCBib29sZWFuIGlzUmVxdWVzdDsKCXByb3RlY3RlZCBDb25uZWN0aW9uIGNvbm4yOwoJCglwcm90ZWN0ZWQgSFRUUFRocmVhZCByZXF1ZXN0OwoJcHJvdGVjdGVkIGJvb2xlYW4gaXNXYWl0aW5nOwoJCgkvLyB1c2VyIHRvIHRyYW5zbGF0ZSB0aGUgSG9zdDogaGVhZGVyCglwcm90ZWN0ZWQgU3RyaW5nIGhvc3Q7Cglwcm90ZWN0ZWQgaW50IHBvcnQ7CgoJcHJvdGVjdGVkIGludCBjb250ZW50TGVuZ3RoID0gLTE7Cglwcm90ZWN0ZWQgYnl0ZSB0cmFuc2ZlckVuY29kaW5nID0gLTE7Cglwcm90ZWN0ZWQgU3RyaW5nIHJlc3BvbnNlVHlwZSA9IG51bGw7Cglwcm90ZWN0ZWQgYm9vbGVhbiBrZWVwQWxpdmUgPSBmYWxzZTsKCglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIFN0cmluZ1tdIEVOQ09ESU5HX1NUUklORyA9IG5ldyBTdHJpbmdbXSB7CgkJImNodW5rZWQiLCAiaWRlbnRpdHkiLCAiZ3ppcCIsICJjb21wcmVzc2VkIiwgImRlZmxhdGUifTsKCglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIGJ5dGUgRU5DT0RJTkdfQ0hVTktFRCA9IDA7Cglwcm90ZWN0ZWQgc3RhdGljIGZpbmFsIGJ5dGUgRU5DT0RJTkdfSURFTlRJVFkgPSAxOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBieXRlIEVOQ09ESU5HX0daSVAgPSAyOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBieXRlIEVOQ09ESU5HX0NPTVBSRVNTRUQgPSAzOwoJcHJvdGVjdGVkIHN0YXRpYyBmaW5hbCBieXRlIEVOQ09ESU5HX0RFRkxBVEUgPSA0OwoKLyogY2hhbmdlOgpSZWZlcmVyOiBodHRwOi8vbG9jYWxob3N0OjgwODEvaW5kZXguaHRtbApIb3N0OiBsb2NhbGhvc3Q6ODA4MQoqLwovKiBUaGUgQ29ubmVjdGlvbiBoZWFkZXIgaGFzIHRoZSBmb2xsb3dpbmcgZ3JhbW1hcjoKCgkgICBDb25uZWN0aW9uID0gIkNvbm5lY3Rpb24iICI6IiAxIyhjb25uZWN0aW9uLXRva2VuKQoJICAgY29ubmVjdGlvbi10b2tlbiAgPSB0b2tlbgoKICAgSFRUUC8xLjEgcHJveGllcyBNVVNUIHBhcnNlIHRoZSBDb25uZWN0aW9uIGhlYWRlciBmaWVsZCBiZWZvcmUgYQogICBtZXNzYWdlIGlzIGZvcndhcmRlZCBhbmQsIGZvciBlYWNoIGNvbm5lY3Rpb24tdG9rZW4gaW4gdGhpcyBmaWVsZCwKICAgcmVtb3ZlIGFueSBoZWFkZXIgZmllbGQocykgZnJvbSB0aGUgbWVzc2FnZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgdGhlCiAgIGNvbm5lY3Rpb24tdG9rZW4uICovCgoJLyoqCgkgKiBNb25pdG9yVGhyZWFkIGNvbnN0cnVjdG9yIGNvbW1lbnQuCgkgKi8KCXB1YmxpYyBIVFRQVGhyZWFkKENvbm5lY3Rpb24gY29ubjIsIElucHV0U3RyZWFtIGluLCBPdXRwdXRTdHJlYW0gb3V0LCBIVFRQQ29ubmVjdGlvbiBjb25uLCBib29sZWFuIGlzUmVxdWVzdCwgU3RyaW5nIGhvc3QsIGludCBwb3J0KSB7CgkJc3VwZXIoKTsKCQl0aGlzLmNvbm4yID0gY29ubjI7CgkJdGhpcy5pbiA9IGluOwoJCXRoaXMub3V0ID0gb3V0OwoJCXRoaXMuY29ubiA9IGNvbm47CgkJdGhpcy5pc1JlcXVlc3QgPSBpc1JlcXVlc3Q7CgkJdGhpcy5ob3N0ID0gaG9zdDsKCQl0aGlzLnBvcnQgPSBwb3J0OwoJCgkJc2V0TmFtZSgiSFRUUCAoIiArIGhvc3QgKyAiOiIgKyBwb3J0ICsgIikgIiArIChpc1JlcXVlc3QgPyAiUkVRVUVTVCIgOiAiUkVTUE9OU0UiKSArICIgIiArICh0aHJlYWRDb3VudCsrKSk7CgkJc2V0UHJpb3JpdHkoVGhyZWFkLk5PUk1fUFJJT1JJVFkgKyAxKTsKCQlzZXREYWVtb24odHJ1ZSk7CgkJCgkJVHJhY2UudHJhY2UoVHJhY2UuUEFSU0lORywgIlN0YXJ0ZWQ6ICIgKyB0aGlzKTsKCX0KCQoJLyoqCgkgKiBNb25pdG9yVGhyZWFkIGNvbnN0cnVjdG9yIGNvbW1lbnQuCgkgKi8KCXB1YmxpYyBIVFRQVGhyZWFkKENvbm5lY3Rpb24gY29ubjIsIElucHV0U3RyZWFtIGluLCBPdXRwdXRTdHJlYW0gb3V0LCBIVFRQQ29ubmVjdGlvbiBjb25uLCBib29sZWFuIGlzUmVxdWVzdCwgU3RyaW5nIGhvc3QsIGludCBwb3J0LCBIVFRQVGhyZWFkIHJlcXVlc3QpIHsKCQl0aGlzKGNvbm4yLCBpbiwgb3V0LCBjb25uLCBpc1JlcXVlc3QsIGhvc3QsIHBvcnQpOwoJCQoJCXRoaXMucmVxdWVzdCA9IHJlcXVlc3Q7Cgl9CgoJLyoqCgkgKiBBZGQgYSBsaW5lIGZlZWQgdG8gdGhlIGVuZCBvZiB0aGUgYnl0ZSBhcnJheS4KCSAqIEByZXR1cm4gYnl0ZVtdCgkgKiBAcGFyYW0gYiBieXRlW10KCSAqLwoJcHJvdGVjdGVkIHN0YXRpYyBieXRlW10gY29udmVydChieXRlW10gYikgewoJCWlmIChiID09IG51bGwgfHwgYi5sZW5ndGggPT0gMCkKCQkJcmV0dXJuIGI7CgkKCQlpbnQgc2l6ZSA9IGIubGVuZ3RoOwoJCWJ5dGVbXSB4ID0gbmV3IGJ5dGVbc2l6ZSArIDJdOwoJCVN5c3RlbS5hcnJheWNvcHkoYiwgMCwgeCwgMCwgc2l6ZSk7CgkJeFtzaXplXSA9IChieXRlKSAnXHInOyAgICAgLy8gQ1IKCQl4W3NpemUgKyAxXSA9IChieXRlKSAnXG4nOyAvLyBMRgoJCXJldHVybiB4OwoJfQoKCS8qKgoJICogUmVhZCBtb3JlIGRhdGEgaW50byB0aGUgYnVmZmVyLgoJICoKCSAqIEByZXR1cm4gYnl0ZVtdCgkgKi8KCXByb3RlY3RlZCB2b2lkIGZpbGxCdWZmZXIoKSB0aHJvd3MgSU9FeGNlcHRpb24gewoJCWludCBuID0gaW4ucmVhZChyZWFkQnVmZmVyKTsKCQoJCWlmIChuIDw9IDApCgkJCXRocm93IG5ldyBJT0V4Y2VwdGlvbigiRW5kIG9mIGlucHV0Iik7CgkKCQkvLyBhZGQgdG8gZnVsbCBidWZmZXIKCQlpbnQgbGVuID0gYnVmZmVyLmxlbmd0aCAtIGJ1ZmZlckluZGV4OwoJCWlmIChsZW4gPCAwKQoJCQlsZW4gPSAwOwoJCWJ5dGVbXSB4ID0gbmV3IGJ5dGVbbiArIGxlbl07CgkJU3lzdGVtLmFycmF5Y29weShidWZmZXIsIGJ1ZmZlckluZGV4LCB4LCAwLCBsZW4pOwoJCVN5c3RlbS5hcnJheWNvcHkocmVhZEJ1ZmZlciwgMCwgeCwgbGVuLCBuKTsKCQlidWZmZXJJbmRleCA9IDA7CgkJYnVmZmVyID0geDsKCX0KCgkvKioKCSAqIFJldHVybnMgdGhlIGZpcnN0IGxvY2F0aW9uIG9mIGEgQ1JMRi4KCSAqCgkgKiBAcmV0dXJuIGludAoJICovCglwcm90ZWN0ZWQgaW50IGdldEZpcnN0Q1JMRigpIHsKCQlpbnQgc2l6ZSA9IGJ1ZmZlci5sZW5ndGg7CgkJaW50IGkgPSBidWZmZXJJbmRleCArIDE7CgkJd2hpbGUgKGkgPCBzaXplKSB7CgkJCWlmIChidWZmZXJbaSAtIDFdID09IENSICYmIGJ1ZmZlcltpXSA9PSBMRikKCQkJCXJldHVybiBpOwoJCQlpKys7CgkJfQoJCXJldHVybiAtMTsKCX0KCgkvKioKCSAqIE91dHB1dCB0aGUgZ2l2ZW4gYnl0ZXMuCgkgKiBAcGFyYW0gYiBieXRlW10KCSAqLwoJcHJvdGVjdGVkIHZvaWQgb3V0cHV0Qnl0ZXMoYnl0ZVtdIGIsIGJvb2xlYW4gaXNOZXcpIHRocm93cyBJT0V4Y2VwdGlvbiB7CgkJb3V0LndyaXRlKGIpOwoJCWlmIChpc1JlcXVlc3QpCgkJCWNvbm4uYWRkUmVxdWVzdChiLCBpc05ldyk7CgkJZWxzZQoJCQljb25uLmFkZFJlc3BvbnNlKGIsIGlzTmV3KTsKCX0KCgkvKioKCSAqIFBhcnNlIHRoZSBIVFRQIGJvZHkuCgkgKi8KCXB1YmxpYyB2b2lkIHBhcnNlQm9keSgpIHRocm93cyBJT0V4Y2VwdGlvbiB7CgkJVHJhY2UudHJhY2UoVHJhY2UuUEFSU0lORywgIlBhcnNpbmcgYm9keSBmb3I6ICIgKyB0aGlzKTsKCQkKCQlpZiAoaXNSZXF1ZXN0KSB7CgkJCWlmIChjb250ZW50TGVuZ3RoICE9IC0xKSB7CgkJCQlieXRlW10gYiA9IHJlYWRCeXRlcyhjb250ZW50TGVuZ3RoKTsKCQkJCW91dC53cml0ZShiKTsKCQkJCWNvbm4uYWRkUmVxdWVzdChiLCBmYWxzZSk7CgkJCQlzZXRIVFRQQm9keShiKTsKCQkJfSBlbHNlIGlmICh0cmFuc2ZlckVuY29kaW5nICE9IC0xICYmIHRyYW5zZmVyRW5jb2RpbmcgIT0gRU5DT0RJTkdfSURFTlRJVFkpIHsKCQkJCXBhcnNlQ2h1bmsoKTsKCQkJfQoJCQkKCQkJVHJhY2UudHJhY2UoVHJhY2UuUEFSU0lORywgIkRvbmUgcGFyc2luZyByZXF1ZXN0IGJvZHkgZm9yOiAiICsgdGhpcyk7CgkJCXJldHVybjsKCQl9CgkKCQkvLyBqdXN0IHJldHVybiBib2R5IGZvciBIVFRQIDEuMCByZXNwb25zZXMKCQlpZiAoIWlzUmVxdWVzdCAmJiAha2VlcEFsaXZlICYmIGNvbnRlbnRMZW5ndGggPT0gLTEgJiYgdHJhbnNmZXJFbmNvZGluZyA9PSAtMSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5QQVJTSU5HLCAiQXNzdW1pbmcgSFRUUCAxLjAgZm9yOiAiICsgdGhpcyk7CgkJCWludCBuID0gYnVmZmVyLmxlbmd0aCAtIGJ1ZmZlckluZGV4OwoJCQlieXRlW10gYiA9IHJlYWRCeXRlcyhuKTsKCQkJYnl0ZVtdIGJvZHkgPSBuZXcgYnl0ZVswXTsKCQkJd2hpbGUgKG4gPj0gMCkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuUEFSU0lORywgIkJ5dGVzIHJlYWQ6ICIgKyBuICsgIiAiICsgdGhpcyk7CgkJCQlpZiAoYiAhPSBudWxsICYmIG4gPiAwKSB7CgkJCQkJYnl0ZVtdIHggPSBudWxsOwoJCQkJCWlmIChuID09IGIubGVuZ3RoKQoJCQkJCQl4ID0gYjsKCQkJCQllbHNlIHsKCQkJCQkJeCA9IG5ldyBieXRlW25dOwoJCQkJCQlTeXN0ZW0uYXJyYXljb3B5KGIsIDAsIHgsIDAsIG4pOwoJCQkJCX0KCQkJCQlvdXRwdXRCeXRlcyh4LCBmYWxzZSk7CgkJCQkJCgkJCQkJLy8gY29weSB0byBIVFRQIGJvZHkKCQkJCQlieXRlW10gdGVtcCA9IG5ldyBieXRlW2JvZHkubGVuZ3RoICsgeC5sZW5ndGhdOwoJCQkJCVN5c3RlbS5hcnJheWNvcHkoYm9keSwgMCwgdGVtcCwgMCwgYm9keS5sZW5ndGgpOwoJCQkJCVN5c3RlbS5hcnJheWNvcHkoeCwgMCwgdGVtcCwgYm9keS5sZW5ndGgsIHgubGVuZ3RoKTsKCQkJCQlib2R5ID0gdGVtcDsKCQkJCX0KCQkJCWlmIChiLmxlbmd0aCA8IEJVRkZFUikKCQkJCQliID0gbmV3IGJ5dGVbQlVGRkVSXTsKCQkJCW4gPSBpbi5yZWFkKGIpOwoJCQkJVGhyZWFkLnlpZWxkKCk7CgkJCX0KCQkJb3V0LmZsdXNoKCk7CgkJCXNldEhUVFBCb2R5KGJvZHkpOwoJCQlyZXR1cm47CgkJfQoJCgkJLy8gc3BlYyA0LjQuMQoJCWlmIChyZXNwb25zZVR5cGUgIT0gbnVsbCAmJgkocmVzcG9uc2VUeXBlLnN0YXJ0c1dpdGgoIjEiKSB8fCAiMjA0Ii5lcXVhbHMocmVzcG9uc2VUeXBlKSB8fCAiMzA0Ii5lcXVhbHMocmVzcG9uc2VUeXBlKSkpIHsKCQkJc2V0SFRUUEJvZHkobmV3IGJ5dGVbMF0pOwoJCQlyZXR1cm47CgkJfQoJCgkJLy8gc3BlYyA0LjQuMgoJCWlmICh0cmFuc2ZlckVuY29kaW5nICE9IC0xICYmIHRyYW5zZmVyRW5jb2RpbmcgIT0gRU5DT0RJTkdfSURFTlRJVFkpIHsKCQkJcGFyc2VDaHVuaygpOwoJCQlyZXR1cm47CgkJfQoJCgkJLy8gc3BlYyA0LjQuMwoJCWlmIChjb250ZW50TGVuZ3RoICE9IC0xKSB7CgkJCWJ5dGVbXSBiID0gcmVhZEJ5dGVzKGNvbnRlbnRMZW5ndGgpOwoJCQlvdXQud3JpdGUoYik7CgkJCWlmIChpc1JlcXVlc3QpCgkJCQljb25uLmFkZFJlcXVlc3QoYiwgZmFsc2UpOwoJCQllbHNlCgkJCQljb25uLmFkZFJlc3BvbnNlKGIsIGZhbHNlKTsKCQkJc2V0SFRUUEJvZHkoYik7CgkJCXJldHVybjsKCQl9CgkJCgkJLy8gc3BlYyA0LjQuNCAoPykKCQkKCQlUcmFjZS50cmFjZShUcmFjZS5QQVJTSU5HLCAiVW5rbm93biBib2R5IGZvcjogIiArIHRoaXMpOwoJfQoKCS8qKgoJICogUGFyc2UgYW4gSFRUUCBjaHVuay4KCSAqLwoJcHVibGljIHZvaWQgcGFyc2VDaHVuaygpIHRocm93cyBJT0V4Y2VwdGlvbiB7CgkJVHJhY2UudHJhY2UoVHJhY2UuUEFSU0lORywgIlBhcnNpbmcgY2h1bmsgZm9yOiAiICsgdGhpcyk7CgkJYm9vbGVhbiBkb25lID0gZmFsc2U7CgkJYnl0ZVtdIGJvZHkgPSBuZXcgYnl0ZVswXTsKCQoJCXdoaWxlICghZG9uZSkgewoJCQkvLyByZWFkIGNodW5rIHNpemUKCQkJYnl0ZVtdIGIgPSByZWFkTGluZSgpOwoJCgkJCVN0cmluZyBzID0gbmV3IFN0cmluZyhiKTsKCQkJaW50IGluZGV4ID0gcy5pbmRleE9mKCIgIik7CgkJCWludCBsZW5ndGggPSAtMTsKCQkJdHJ5IHsKCQkJCWlmIChpbmRleCA+IDApCgkJCQkJcyA9IHMuc3Vic3RyaW5nKDAsIGluZGV4KTsKCQkJCWxlbmd0aCA9IEludGVnZXIucGFyc2VJbnQocy50cmltKCksIDE2KTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJFcnJvciBjaHVuayBmb3I6ICIgKyB0aGlzLCBlKTsKCQkJfQoJCgkJCS8vIG91dHB1dCBieXRlcwoJCQlvdXRwdXRCeXRlcyhiLCBmYWxzZSk7CgkKCQkJaWYgKGxlbmd0aCA8PSAwKQoJCQkJZG9uZSA9IHRydWU7CgkJCWVsc2UgewoJCQkJLy8gcmVhZCBhbmQgb3V0cHV0IGNodW5rIGRhdGEgcGx1cyBDUkxGCgkJCQliID0gcmVhZEJ5dGVzKGxlbmd0aCArIDIpOwoJCQkJb3V0cHV0Qnl0ZXMoYiwgZmFsc2UpOwoJCQkJCgkJCQkvLyBjb3B5IHRvIEhUVFAgYm9keQoJCQkJYnl0ZVtdIHRlbXAgPSBuZXcgYnl0ZVtib2R5Lmxlbmd0aCArIGIubGVuZ3RoIC0gMl07CgkJCQlTeXN0ZW0uYXJyYXljb3B5KGJvZHksIDAsIHRlbXAsIDAsIGJvZHkubGVuZ3RoKTsKCQkJCVN5c3RlbS5hcnJheWNvcHkoYiwgMCwgdGVtcCwgYm9keS5sZW5ndGgsIGIubGVuZ3RoIC0gMik7CgkJCQlib2R5ID0gdGVtcDsKCQkJfQoJCX0KCQoJCS8vIHJlYWQgdHJhaWxlcgoJCWJ5dGVbXSBiID0gcmVhZExpbmUoKTsKCQl3aGlsZSAoYi5sZW5ndGggPiAyKSB7CgkJCW91dHB1dEJ5dGVzKGIsIGZhbHNlKTsKCQkJYiA9IHJlYWRMaW5lKCk7CgkJfQoJCgkJb3V0cHV0Qnl0ZXMoYiwgZmFsc2UpOwoJCXNldEhUVFBCb2R5KGJvZHkpOwoJfQoKCS8qKgoJICogUGFyc2UgYW4gSFRUUCBoZWFkZXIuCgkgKi8KCXB1YmxpYyB2b2lkIHBhcnNlSGVhZGVyKCkgdGhyb3dzIElPRXhjZXB0aW9uIHsKCQlUcmFjZS50cmFjZShUcmFjZS5QQVJTSU5HLCAiUGFyc2luZyBoZWFkZXIgZm9yOiAiICsgdGhpcyk7CgkKCQkvLyByZWFkIHVudGlsIGZpcnN0IGJsYW5rIGxpbmUKCQlib29sZWFuIGlzRmlyc3RMaW5lID0gdHJ1ZTsKCQlib29sZWFuIGlzTmV3ID0gdHJ1ZTsKCQoJCWJ5dGVbXSBiID0gcmVhZExpbmUoKTsKCQl3aGlsZSAoYi5sZW5ndGggPiA1KSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJQYXJzaW5nIGhlYWRlciBsaW5lOiAnIiArIG5ldyBTdHJpbmcoYikgKyAiJyIpOwoJCQkKCQkJaWYgKGlzRmlyc3RMaW5lKSB7CgkJCQlTdHJpbmcgcyA9IG5ldyBTdHJpbmcoYik7CgkJCQlpZiAoaXNSZXF1ZXN0KSB7CgkJCQkJc2V0TGFiZWwocyk7CgkJCQkJaXNOZXcgPSBmYWxzZTsKCQkJCX0KCQoJCQkJaWYgKCFpc1JlcXVlc3QpIHsKCQkJCQlpbnQgaW5kZXgxID0gcy5pbmRleE9mKCcgJyk7CgkJCQkJaW50IGluZGV4MiA9IHMuaW5kZXhPZignICcsIGluZGV4MSArIDEpOwoJCgkJCQkJdHJ5IHsKCQkJCQkJcmVzcG9uc2VUeXBlID0gcy5zdWJzdHJpbmcoaW5kZXgxICsgMSwgaW5kZXgyKS50cmltKCk7CgkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJSZXNwb25zZSBUeXBlOiAiICsgdGhpcyArICIgIiArIHJlc3BvbnNlVHlwZSk7CgkJCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCQkJVHJhY2UudHJhY2UoVHJhY2UuUEFSU0lORywgIkVycm9yIHBhcnNpbmcgcmVzcG9uc2UgdHlwZSBmb3I6ICIgKyB0aGlzLCBlKTsKCQkJCQl9CgkJCQkJaWYgKHJlc3BvbnNlVHlwZSAhPSBudWxsICYmIHJlc3BvbnNlVHlwZS5lcXVhbHMoIjEwMCIpKSB7CgkJCQkJCW91dHB1dEJ5dGVzKGIsIGlzTmV3KTsKCQkJCQkJaXNOZXcgPSBmYWxzZTsKCgkJCQkJCWIgPSByZWFkTGluZSgpOwoJCQkJCQlvdXRwdXRCeXRlcyhiLCBmYWxzZSk7CgoJCQkJCQliID0gcmVhZExpbmUoKTsKCgkJCQkJCWluZGV4MSA9IHMuaW5kZXhPZignICcpOwoJCQkJCQlpbmRleDIgPSBzLmluZGV4T2YoJyAnLCBpbmRleDEgKyAxKTsKCgkJCQkJCXRyeSB7CgkJCQkJCQlyZXNwb25zZVR5cGUgPSBzLnN1YnN0cmluZyhpbmRleDEgKyAxLCBpbmRleDIpLnRyaW0oKTsKCQkJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJSZXNwb25zZSBUeXBlOiAiICsgdGhpcyArICIgIiArIHJlc3BvbnNlVHlwZSk7CgkJCQkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkJCQlUcmFjZS50cmFjZShUcmFjZS5QQVJTSU5HLCAiRXJyb3IgcGFyc2luZyByZXNwb25zZSB0eXBlIGZvcjogIiArIHRoaXMsIGUpOwoJCQkJCQl9CgkJCQkJfQoJCQkJfQoJCQkJaXNGaXJzdExpbmUgPSBmYWxzZTsKCQkJfQoJCgkJCS8vIHRyYW5zbGF0ZQoJCQliID0gdHJhbnNsYXRlSGVhZGVyTGluZShiKTsKCQkJCgkJCW91dHB1dEJ5dGVzKGIsIGlzTmV3KTsKCQkJaXNOZXcgPSBmYWxzZTsKCQoJCQliID0gcmVhZExpbmUoKTsKCQl9CgoJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJQYXJzaW5nIGZpbmFsIGhlYWRlciBsaW5lOiAnIiArIG5ldyBTdHJpbmcoYikgKyAiJyIpOwoKCQlvdXRwdXRCeXRlcyhiLCBmYWxzZSk7CgoJCUlSZXF1ZXN0IHJyID0gY29ubi5nZXRSZXF1ZXN0UmVzcG9uc2UoaXNSZXF1ZXN0KTsKCQlUcmFjZS50cmFjZShUcmFjZS5QQVJTSU5HLCAiU2V0dGluZyBoZWFkZXIgbGVuZ3RoOiAiICsgcnIuZ2V0UmVxdWVzdChJUmVxdWVzdC5BTEwpLmxlbmd0aCk7CgkJCgkJc2V0SFRUUEhlYWRlcihycik7Cgl9CgoJLyoqCgkgKiBSZWFkIGJ5dGVzIGZyb20gdGhlIHN0cmVhbS4KCSAqIEByZXR1cm4gYnl0ZVtdCgkgKi8KCXByb3RlY3RlZCBieXRlW10gcmVhZEJ5dGVzKGludCBuKSB0aHJvd3MgSU9FeGNlcHRpb24gewoJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJyZWFkQnl0ZXMoKSAiICsgbiArICIgZm9yOiAiICsgdGhpcyk7CgkJd2hpbGUgKGJ1ZmZlci5sZW5ndGggLSBidWZmZXJJbmRleCA8IG4pCgkJCWZpbGxCdWZmZXIoKTsKCQoJCXJldHVybiByZW1vdmVGcm9tQnVmZmVyKGJ1ZmZlckluZGV4ICsgbik7Cgl9CgoJLyoqCgkgKiBSZWFkIGFuZCByZXR1cm4gdGhlIG5leHQgZnVsbCBsaW5lLgoJICoKCSAqIEByZXR1cm4gYnl0ZVtdCgkgKi8KCXByb3RlY3RlZCBieXRlW10gcmVhZExpbmUoKSB0aHJvd3MgSU9FeGNlcHRpb24gewoJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJyZWFkTGluZSgpIGZvcjogIiArIHRoaXMpOwoJCgkJaW50IG4gPSBnZXRGaXJzdENSTEYoKTsKCQl3aGlsZSAobiA8IDApIHsKCQkJZmlsbEJ1ZmZlcigpOwoJCQluID0gZ2V0Rmlyc3RDUkxGKCk7CgkJfQoJCXJldHVybiByZW1vdmVGcm9tQnVmZmVyKG4gKyAxKTsKCX0KCgkvKioKCSAqIFJlbW92ZSBkYXRhIGZyb20gdGhlIGJ1ZmZlciB1cCB0byB0aGUgYWJzb2x1dGUgaW5kZXggbi4KCSAqIFJldHVybiB0aGUgZGF0YSBmcm9tIGJldHdlZW4gYnVmZmVySW5kZXggYW5kIG4uCgkgKgoJICogQHJldHVybiBieXRlW10KCSAqIEBwYXJhbSBpbmRleCBpbnQKCSAqLwoJcHJvdGVjdGVkIGJ5dGVbXSByZW1vdmVGcm9tQnVmZmVyKGludCBuKSB7CgkJLy8gY29weSBsaW5lIG91dCBvZiBidWZmZXIKCQlieXRlW10gYiA9IG5ldyBieXRlW24gLSBidWZmZXJJbmRleF07CgkJU3lzdGVtLmFycmF5Y29weShidWZmZXIsIGJ1ZmZlckluZGV4LCBiLCAwLCBuIC0gYnVmZmVySW5kZXgpOwoJCgkJaWYgKGJ1ZmZlci5sZW5ndGggPiBCVUZGRVIgKiAyIHx8IGJ1ZmZlckluZGV4ID4gQlVGRkVSKSB7CgkJCS8vIHJlbW92ZSBsaW5lIGZyb20gYnVmZmVyCgkJCWludCBzaXplID0gYnVmZmVyLmxlbmd0aDsKCQkJYnl0ZVtdIHggPSBuZXcgYnl0ZVtzaXplIC0gbl07CgkJCVN5c3RlbS5hcnJheWNvcHkoYnVmZmVyLCBuLCB4LCAwLCBzaXplIC0gbik7CgkJCWJ1ZmZlciA9IHg7CgkJCWJ1ZmZlckluZGV4ID0gMDsKCQl9IGVsc2UKCQkJYnVmZmVySW5kZXggPSBuOwoJCgkJcmV0dXJuIGI7Cgl9CgoJLyoqCgkgKiBMaXN0ZW4gZm9yIGlucHV0LCBzYXZlIGl0LCBhbmQgcGFzcyB0byB0aGUgb3V0cHV0IHN0cmVhbS4KCSAqIFBoaWxvc29waHk6IFJlYWQgYSBzaW5nbGUgbGluZSBzZXBhcmF0ZWx5IGFuZCB0cmFuc2xhdGUuCgkgKiBXaGVuIGJsYW5rIGxpbmUgaXMgcmVhY2hlZCwganVzdCBwYXNzIGFsbCBvdGhlciBkYXRhIHRocm91Z2guCgkgKi8KCXB1YmxpYyB2b2lkIHJ1bigpIHsKCQl0cnkgewoJCQl0cnkgewoJCQkJd2hpbGUgKHRydWUpIHsKCQkJCQljb250ZW50TGVuZ3RoID0gLTE7CgkJCQkJdHJhbnNmZXJFbmNvZGluZyA9IC0xOwoJCQkJCWtlZXBBbGl2ZSA9IGZhbHNlOwoKCQkJCQlwYXJzZUhlYWRlcigpOwoJCQkJCXBhcnNlQm9keSgpOwoJCQkJCQoJCQkJCWlmIChpc1JlcXVlc3QgJiYga2VlcEFsaXZlKQoJCQkJCQl3YWl0Rm9yUmVzcG9uc2UoKTsKCQkJCQkKCQkJCQlJUmVxdWVzdCByID0gY29ubi5nZXRSZXF1ZXN0UmVzcG9uc2UodHJ1ZSk7CgkJCQkJci5maXJlQ2hhbmdlZEV2ZW50KCk7CgoJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJEb25lIEhUVFAgcmVxdWVzdCBmb3IgIiArIHRoaXMgKyAiICIgKyBrZWVwQWxpdmUpOwoJCQkJCWlmICghaXNSZXF1ZXN0ICYmICFyZXF1ZXN0LmtlZXBBbGl2ZSkgewoJCQkJCQljb25uMi5jbG9zZSgpOwoJCQkJCQlicmVhazsKCQkJCQl9CgkJCQkJCgkJCQkJaWYgKCFpc1JlcXVlc3QpCgkJCQkJCW5vdGlmeVJlcXVlc3QoKTsKCQkJCQkKCQkJCQlUaHJlYWQueWllbGQoKTsKCQkJCX0KCQkJfSBjYXRjaCAoSU9FeGNlcHRpb24gZSkgewoJCQkJLy8gcmVhY2hlZCBlbmQgb2YgaW5wdXQKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJFbmQgb2YgYnVmZmVyIGZvcjogIiArIHRoaXMgKyAiICIgKyBlLmdldE1lc3NhZ2UoKSk7CgkJCX0KCgkJCS8vIHNlbmQgcmVzdCBvZiBidWZmZXIKCQkJb3V0LndyaXRlKGJ1ZmZlciwgYnVmZmVySW5kZXgsIGJ1ZmZlci5sZW5ndGggLSBidWZmZXJJbmRleCk7CgkJCW91dC5mbHVzaCgpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJFcnJvciBpbjogIiArIHRoaXMsIGUpOwoJCX0KCQkvL2lmICghaXNSZXF1ZXN0KQoJCS8vCWNvbm4yLmNsb3NlKCk7CgoJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJDbG9zaW5nIHRocmVhZCAiICsgdGhpcyk7Cgl9CgoJLyoqCgkgKiBTZXRzIHRoZSB0aXRsZSBvZiB0aGUgY2FsbC4KCSAqCgkgKiBAcGFyYW0gcyBqYXZhLmxhbmcuU3RyaW5nCgkgKi8KCXByb3RlY3RlZCB2b2lkIHNldExhYmVsKFN0cmluZyBzKSB7CgkJdHJ5IHsKCQkJaW50IGluZGV4MSA9IHMuaW5kZXhPZignICcpOwoJCQlpZiAoaW5kZXgxIDwgMCB8fCBpbmRleDEgPiAxNSkKCQkJCXJldHVybjsKCQkJaW50IGluZGV4MiA9IHMuaW5kZXhPZignICcsIGluZGV4MSArIDEpOwoJCQlpZiAoaW5kZXgyIDwgMCkKCQkJCXJldHVybjsKCQoJCQljb25uLnNldExhYmVsKHMuc3Vic3RyaW5nKGluZGV4MSArIDEsIGluZGV4MiksIHRydWUpOwoJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCS8vIGlnbm9yZQoJCX0KCX0KCgkvKioKCSAqIFRyYW5zbGF0ZSB0aGUgaGVhZGVyIGxpbmUuCgkgKiAKCSAqIEByZXR1cm4gYnl0ZVtdCgkgKiBAcGFyYW0gYiBieXRlW10KCSAqLwoJcHJvdGVjdGVkIGJ5dGVbXSB0cmFuc2xhdGVIZWFkZXJMaW5lKGJ5dGVbXSBiKSB7CgkJU3RyaW5nIHMgPSBuZXcgU3RyaW5nKGIpOwoJCgkJaWYgKGlzUmVxdWVzdCAmJiBzLnN0YXJ0c1dpdGgoIkhvc3Q6ICIpKSB7CgkJCVN0cmluZyB0ID0gIkhvc3Q6ICIgKyBob3N0OwoJCQlpZiAocG9ydCAhPSA4MCkKCQkJCXQgKz0gIjoiICsgcG9ydDsKCQkJcmV0dXJuIGNvbnZlcnQodC5nZXRCeXRlcygpKTsKCQl9IGVsc2UgaWYgKHMuc3RhcnRzV2l0aCgiQ29udGVudC1MZW5ndGg6ICIpKSB7CgkJCXRyeSB7CgkJCQljb250ZW50TGVuZ3RoID0gSW50ZWdlci5wYXJzZUludChzLnN1YnN0cmluZygxNikudHJpbSgpKTsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJDb250ZW50IGxlbmd0aDogIiArIHRoaXMgKyAiICIgKyBjb250ZW50TGVuZ3RoKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJDb250ZW50IGxlbmd0aCBlcnJvciIsIGUpOwoJCQl9CgkJfSBlbHNlIGlmIChzLnN0YXJ0c1dpdGgoIkNvbm5lY3Rpb246ICIpKSB7CgkJCXRyeSB7CgkJCQlTdHJpbmcgdCA9IHMuc3Vic3RyaW5nKDExKS50cmltKCk7CgkJCQlpZiAodC5lcXVhbHNJZ25vcmVDYXNlKCJLZWVwLUFsaXZlIikpCgkJCQkJa2VlcEFsaXZlID0gdHJ1ZTsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJLZWVwIGFsaXZlOiAiICsga2VlcEFsaXZlKTsKCQkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJFcnJvciBnZXR0aW5nIENvbm5lY3Rpb246IGZyb20gaGVhZGVyIiwgZSk7CgkJCX0KCQl9IGVsc2UgaWYgKHMuc3RhcnRzV2l0aCgiVHJhbnNmZXItRW5jb2Rpbmc6ICIpKSB7CgkJCVN0cmluZyB0ID0gcy5zdWJzdHJpbmcoMTkpLnRyaW0oKTsKCQkJaW50IHNpemUgPSBFTkNPRElOR19TVFJJTkcubGVuZ3RoOwoJCQlmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewoJCQkJaWYgKEVOQ09ESU5HX1NUUklOR1tpXS5lcXVhbHNJZ25vcmVDYXNlKHQpKSB7CgkJCQkJdHJhbnNmZXJFbmNvZGluZyA9IChieXRlKSBpOwoJCQkJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJUcmFuc2ZlciBlbmNvZGluZzogIiArIEVOQ09ESU5HX1NUUklOR1tpXSk7CgkJCQl9CgkJCX0KCQl9CgkKCQlyZXR1cm4gYjsKCX0KCQoJcHJvdGVjdGVkIHZvaWQgY2xvc2UoKSB7CgkJdHJ5IHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuUEFSU0lORywgIkNsb3Npbmc6ICIgKyB0aGlzKTsKCQkJb3V0LmNsb3NlKCk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuUEFSU0lORywgIkVycm9yIGNsb3NpbmcgY29ubmVjdGlvbiAiICsgdGhpcyArICIgIiArIGUuZ2V0TWVzc2FnZSgpKTsKCQl9Cgl9CgoJcHJvdGVjdGVkIHZvaWQgd2FpdEZvclJlc3BvbnNlKCkgewoJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJXYWl0aW5nIGZvciByZXNwb25zZSAiICsgdGhpcyk7CgkJc3luY2hyb25pemVkICh0aGlzKSB7CgkJCXRyeSB7CgkJCQlpc1dhaXRpbmcgPSB0cnVlOwoJCQkJd2FpdCgpOwoJCQl9IGNhdGNoIChFeGNlcHRpb24gZSkgewoJCQkJVHJhY2UudHJhY2UoVHJhY2UuUEFSU0lORywgIkVycm9yIGluIHdhaXRGb3JSZXNwb25zZSgpICIgKyB0aGlzICsgIiAiICsgZS5nZXRNZXNzYWdlKCkpOwoJCQl9CgkJCWlzV2FpdGluZyA9IGZhbHNlOwoJCX0KCQlUcmFjZS50cmFjZShUcmFjZS5QQVJTSU5HLCAiRG9uZSB3YWl0aW5nIGZvciByZXNwb25zZSAiICsgdGhpcyk7Cgl9CgoJcHJvdGVjdGVkIHZvaWQgbm90aWZ5UmVxdWVzdCgpIHsKCQlUcmFjZS50cmFjZShUcmFjZS5QQVJTSU5HLCAiTm90aWZ5aW5nIHJlcXVlc3QgIiArIHRoaXMpOwoJCXdoaWxlIChyZXF1ZXN0LmtlZXBBbGl2ZSAmJiAhcmVxdWVzdC5pc1dhaXRpbmcpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuUEFSU0lORywgIldhaXRpbmcgZm9yIHJlcXVlc3QgIiArIHRoaXMpOwoJCQl0cnkgewoJCQkJVGhyZWFkLnNsZWVwKDEwMCk7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQkvLyBpZ25vcmUKCQkJfQoJCX0KCQlzeW5jaHJvbml6ZWQgKHJlcXVlc3QpIHsKCQkJdHJ5IHsKCQkJCXJlcXVlc3Qubm90aWZ5KCk7CgkJCX0gY2F0Y2ggKEV4Y2VwdGlvbiBlKSB7CgkJCQlUcmFjZS50cmFjZShUcmFjZS5QQVJTSU5HLCAiRXJyb3IgaW4gbm90aWZ5UmVxdWVzdCgpICIgKyB0aGlzICsgIiAiICsgZS5nZXRNZXNzYWdlKCkpOwoJCQl9CgkJfQoJCVRyYWNlLnRyYWNlKFRyYWNlLlBBUlNJTkcsICJEb25lIG5vdGlmeWluZyByZXF1ZXN0ICIgKyB0aGlzKTsKCX0KCQoJcHJvdGVjdGVkIHZvaWQgc2V0SFRUUEhlYWRlcihJUmVxdWVzdCBycikgewoJCWlmIChpc1JlcXVlc3QpIHsKCQkJYnl0ZVtdIGIgPSByci5nZXRSZXF1ZXN0KElSZXF1ZXN0LkFMTCk7CgkJCWJ5dGVbXSBoID0gbmV3IGJ5dGVbYi5sZW5ndGhdOwoJCQlTeXN0ZW0uYXJyYXljb3B5KGIsIDAsIGgsIDAsIGIubGVuZ3RoKTsKCQkJcnIuYWRkUHJvcGVydHkoSFRUUFJlcXVlc3QuSFRUUF9SRVFVRVNUX0hFQURFUiwgaCk7CgkJfSBlbHNlIHsKCQkJYnl0ZVtdIGIgPSByci5nZXRSZXNwb25zZShJUmVxdWVzdC5BTEwpOwoJCQlieXRlW10gaCA9IG5ldyBieXRlW2IubGVuZ3RoXTsKCQkJU3lzdGVtLmFycmF5Y29weShiLCAwLCBoLCAwLCBiLmxlbmd0aCk7CgkJCXJyLmFkZFByb3BlcnR5KEhUVFBSZXF1ZXN0LkhUVFBfUkVTUE9OU0VfSEVBREVSLCBoKTsKCQl9Cgl9CgkKCXByb3RlY3RlZCB2b2lkIHNldEhUVFBCb2R5KGJ5dGVbXSBiKSB7CgkJSVJlcXVlc3QgcnIgPSBjb25uLmdldFJlcXVlc3RSZXNwb25zZShpc1JlcXVlc3QpOwoJCWlmIChpc1JlcXVlc3QpCgkJCXJyLmFkZFByb3BlcnR5KEhUVFBSZXF1ZXN0LkhUVFBfUkVRVUVTVF9CT0RZLCBiKTsKCQllbHNlCgkJCXJyLmFkZFByb3BlcnR5KEhUVFBSZXF1ZXN0LkhUVFBfUkVTUE9OU0VfQk9EWSwgYik7Cgl9Cn0=