LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDA1LCAyMDEwIEFuZHJlYSBCaXR0YXUsIFVuaXZlcnNpdHkgQ29sbGVnZSBMb25kb24sIGFuZCBvdGhlcnMKICogQWxsIHJpZ2h0cyByZXNlcnZlZC4gVGhpcyBwcm9ncmFtIGFuZCB0aGUgYWNjb21wYW55aW5nIG1hdGVyaWFscwogKiBhcmUgbWFkZSBhdmFpbGFibGUgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBFY2xpcHNlIFB1YmxpYyBMaWNlbnNlIHYxLjAKICogd2hpY2ggYWNjb21wYW5pZXMgdGhpcyBkaXN0cmlidXRpb24sIGFuZCBpcyBhdmFpbGFibGUgYXQKICogaHR0cDovL3d3dy5lY2xpcHNlLm9yZy9sZWdhbC9lcGwtdjEwLmh0bWwKICoKICogQ29udHJpYnV0b3JzOgogKiAgICAgQW5kcmVhIEJpdHRhdSAtIGluaXRpYWwgQVBJIGFuZCBpbXBsZW1lbnRhdGlvbiBmcm9tIHRoZSBQc3ljaG9QYXRoIFhQYXRoIDIuMAogKiAgICAgTXVrdWwgR2FuZGhpIC0gYnVnIDI3NjEzNCAtIGltcHJvdmVtZW50cyB0byBzY2hlbWEgYXdhcmUgcHJpbWl0aXZlIHR5cGUgc3VwcG9ydAogKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciBhdHRyaWJ1dGUvZWxlbWVudCBub2RlcyAKICogICAgIERhdmlkIENhcnZlciAtIGJ1ZyAyNjI3NjUgLSBmaXhlZCBjb21wYXJpc29uIG9uIHNlcXVlbmNlIHJhbmdlIHZhbHVlcy4KICogICAgIEplc3BlciBTIE1vbGxlciAtIGJ1ZyAyODMyMTQgLSBmaXggZXEgZm9yIHVudHlwZWQgYXRvbWljIHZhbHVlcwogKiAgICAgSmVzcGVyIFN0ZWVuIE1vZWxsZXIgLSBidWcgMjg1MTQ1IC0gaW1wbGVtZW50IGZ1bGwgYXJpdHkgY2hlY2tpbmcKICogICAgIEplc3BlciBTdGVlbiBNb2VsbGVyIC0gYnVnIDI4MDU1NSAtIEFkZCBwbHVnZ2FibGUgY29sbGF0aW9uIHN1cHBvcnQKICogICAgIE11a3VsIEdhbmRoaSAtIGJ1ZyAyODA3OTggLSBQc3ljaG9QYXRoIHN1cHBvcnQgZm9yIEpESyAxLjQKICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCgpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC54bWwueHBhdGgyLnByb2Nlc3Nvci5pbnRlcm5hbC5mdW5jdGlvbjsKCmltcG9ydCBvcmcuZWNsaXBzZS53c3QueG1sLnhwYXRoMi5wcm9jZXNzb3IuRHluYW1pY0NvbnRleHQ7CmltcG9ydCBvcmcuZWNsaXBzZS53c3QueG1sLnhwYXRoMi5wcm9jZXNzb3IuRHluYW1pY0Vycm9yOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnhtbC54cGF0aDIucHJvY2Vzc29yLlJlc3VsdFNlcXVlbmNlOwppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnhtbC54cGF0aDIucHJvY2Vzc29yLlJlc3VsdFNlcXVlbmNlRmFjdG9yeTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC54bWwueHBhdGgyLnByb2Nlc3Nvci5pbnRlcm5hbC5UeXBlRXJyb3I7CmltcG9ydCBvcmcuZWNsaXBzZS53c3QueG1sLnhwYXRoMi5wcm9jZXNzb3IuaW50ZXJuYWwudHlwZXMuQW55VHlwZTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC54bWwueHBhdGgyLnByb2Nlc3Nvci5pbnRlcm5hbC50eXBlcy5OdW1lcmljVHlwZTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC54bWwueHBhdGgyLnByb2Nlc3Nvci5pbnRlcm5hbC50eXBlcy5RTmFtZTsKaW1wb3J0IG9yZy5lY2xpcHNlLndzdC54bWwueHBhdGgyLnByb2Nlc3Nvci5pbnRlcm5hbC50eXBlcy5YU0Jvb2xlYW47CmltcG9ydCBvcmcuZWNsaXBzZS53c3QueG1sLnhwYXRoMi5wcm9jZXNzb3IuaW50ZXJuYWwudHlwZXMuWFNEb3VibGU7CmltcG9ydCBvcmcuZWNsaXBzZS53c3QueG1sLnhwYXRoMi5wcm9jZXNzb3IuaW50ZXJuYWwudHlwZXMuWFNTdHJpbmc7CmltcG9ydCBvcmcuZWNsaXBzZS53c3QueG1sLnhwYXRoMi5wcm9jZXNzb3IuaW50ZXJuYWwudHlwZXMuWFNVbnR5cGVkQXRvbWljOwoKaW1wb3J0IGphdmEubGFuZy5yZWZsZWN0Lkludm9jYXRpb25UYXJnZXRFeGNlcHRpb247CmltcG9ydCBqYXZhLmxhbmcucmVmbGVjdC5NZXRob2Q7CmltcG9ydCBqYXZhLnV0aWwuQXJyYXlMaXN0OwppbXBvcnQgamF2YS51dGlsLkNvbGxlY3Rpb247CmltcG9ydCBqYXZhLnV0aWwuSXRlcmF0b3I7CgovKioKICogQ2xhc3MgZm9yIHRoZSBFcXVhbGl0eSBmdW5jdGlvbi4KICovCnB1YmxpYyBjbGFzcyBGc0VxIGV4dGVuZHMgRnVuY3Rpb24gewoJLyoqCgkgKiBDb25zdHJ1Y3RvciBmb3IgRnNFcS4KCSAqLwoJcHVibGljIEZzRXEoKSB7CgkJc3VwZXIobmV3IFFOYW1lKCJlcSIpLCAyKTsKCX0KCgkvKioKCSAqIEV2YWx1YXRlIGFyZ3VtZW50cy4KCSAqIAoJICogQHBhcmFtIGFyZ3MKCSAqICAgICAgICAgICAgYXJndW1lbnQgZXhwcmVzc2lvbnMuCgkgKiBAdGhyb3dzIER5bmFtaWNFcnJvcgoJICogICAgICAgICAgICAgRHluYW1pYyBlcnJvci4KCSAqIEByZXR1cm4gUmVzdWx0IG9mIGV2YWx1YXRpb24uCgkgKi8KCXB1YmxpYyBSZXN1bHRTZXF1ZW5jZSBldmFsdWF0ZShDb2xsZWN0aW9uIGFyZ3MpIHRocm93cyBEeW5hbWljRXJyb3IgewoJCWFzc2VydCBhcmdzLnNpemUoKSA+PSBtaW5fYXJpdHkoKSAmJiBhcmdzLnNpemUoKSA8PSBtYXhfYXJpdHkoKTsKCgkJcmV0dXJuIGZzX2VxX3ZhbHVlKGFyZ3MsIGR5bmFtaWNfY29udGV4dCgpKTsKCX0KCgkvKioKCSAqIENvbnZlcnRzIGFyZ3VtZW50cyB0byB2YWx1ZXMuCgkgKiAKCSAqIEBwYXJhbSBhcmdzCgkgKiAgICAgICAgICAgIFJlc3VsdCBmcm9tIGV4cHJlc3Npb25zIGV2YWx1YXRpb24uCgkgKiBAdGhyb3dzIER5bmFtaWNFcnJvcgoJICogICAgICAgICAgICAgRHluYW1pYyBlcnJvci4KCSAqIEByZXR1cm4gUmVzdWx0IG9mIGNvbnZlcnNpb24uCgkgKi8KCXByaXZhdGUgc3RhdGljIENvbGxlY3Rpb24gdmFsdWVfY29udmVydF9hcmdzKENvbGxlY3Rpb24gYXJncykKCQkJdGhyb3dzIER5bmFtaWNFcnJvciB7CgkJQ29sbGVjdGlvbiByZXN1bHQgPSBuZXcgQXJyYXlMaXN0KGFyZ3Muc2l6ZSgpKTsKCgkJLy8gYXRvbWl6ZSBhcmd1bWVudHMKCQlmb3IgKEl0ZXJhdG9yIGkgPSBhcmdzLml0ZXJhdG9yKCk7IGkuaGFzTmV4dCgpOykgewoJCQlSZXN1bHRTZXF1ZW5jZSBycyA9IChSZXN1bHRTZXF1ZW5jZSkgaS5uZXh0KCk7CgoJCQkvL0ZuRGF0YS5mYXN0X2F0b21pemUocnMpOwoJCQlycyA9IEZuRGF0YS5hdG9taXplKHJzKTsKCgkJCWlmIChycy5lbXB0eSgpKQoJCQkJcmV0dXJuIG5ldyBBcnJheUxpc3QoKTsKCgkJCWlmIChycy5zaXplKCkgPiAxKQoJCQkJdGhyb3cgbmV3IER5bmFtaWNFcnJvcihUeXBlRXJyb3IuaW52YWxpZF90eXBlKG51bGwpKTsKCgkJCUFueVR5cGUgYXJnID0gcnMuZmlyc3QoKTsKCgkJCWlmIChhcmcgaW5zdGFuY2VvZiBYU1VudHlwZWRBdG9taWMpCgkJCQlhcmcgPSBuZXcgWFNTdHJpbmcoYXJnLnN0cmluZ192YWx1ZSgpKTsKCgkJCXJzID0gUmVzdWx0U2VxdWVuY2VGYWN0b3J5LmNyZWF0ZV9uZXcoKTsKCQkJcnMuYWRkKGFyZyk7CgkJCXJlc3VsdC5hZGQocnMpOwoJCX0KCgkJcmV0dXJuIHJlc3VsdDsKCX0KCgkvKioKCSAqIENvbnZlcnNpb24gb3BlcmF0aW9uIGZvciB0aGUgdmFsdWVzIG9mIHRoZSBhcmd1bWVudHMuCgkgKiAKCSAqIEBwYXJhbSBhcmdzCgkgKiAgICAgICAgICAgIFJlc3VsdCBmcm9tIGNvbnZlcnQgdmFsdWUgb3BlcmF0aW9uLgoJICogQHRocm93cyBEeW5hbWljRXJyb3IKCSAqICAgICAgICAgICAgIER5bmFtaWMgZXJyb3IuCgkgKiBAcmV0dXJuIFJlc3VsdCBvZiBjb252ZXJzaW9uLgoJICovCglwdWJsaWMgc3RhdGljIFJlc3VsdFNlcXVlbmNlIGZzX2VxX3ZhbHVlKENvbGxlY3Rpb24gYXJncywgRHluYW1pY0NvbnRleHQgZHluYW1pY0NvbnRleHQpCgkJCXRocm93cyBEeW5hbWljRXJyb3IgewoJCXJldHVybiBkb19jbXBfdmFsdWVfb3AoYXJncywgQ21wRXEuY2xhc3MsICJlcSIsIGR5bmFtaWNDb250ZXh0KTsKCX0KCgkvKioKCSAqIEEgZmFzdCBFcXVhbGl0eSBvcGVyYXRpb24sIG5vIGNvbnZlcnNpb24gZm9yIHRoZSBpbnB1dHMgcGVyZm9ybWVkLgoJICogCgkgKiBAcGFyYW0gb25lCgkgKiAgICAgICAgICAgIGlucHV0MSBvZiBhbnkgdHlwZS4KCSAqIEBwYXJhbSB0d28KCSAqICAgICAgICAgICAgaW5wdXQyIG9mIGFueSB0eXBlLgoJICogQHRocm93cyBEeW5hbWljRXJyb3IKCSAqICAgICAgICAgICAgIER5bmFtaWMgZXJyb3IuCgkgKiBAcmV0dXJuIFJlc3VsdCBvZiBFcXVhbGl0eSBvcGVyYXRpb24uCgkgKi8KCXB1YmxpYyBzdGF0aWMgYm9vbGVhbiBmc19lcV9mYXN0KEFueVR5cGUgb25lLCBBbnlUeXBlIHR3bywgRHluYW1pY0NvbnRleHQgZHluYW1pY0NvbnRleHQpCgkJCXRocm93cyBEeW5hbWljRXJyb3IgewoKCQlvbmUgPSBGbkRhdGEuYXRvbWl6ZShvbmUpOwoJCXR3byA9IEZuRGF0YS5hdG9taXplKHR3byk7CgoJCWlmIChvbmUgaW5zdGFuY2VvZiBYU1VudHlwZWRBdG9taWMpCgkJCW9uZSA9IG5ldyBYU1N0cmluZyhvbmUuc3RyaW5nX3ZhbHVlKCkpOwoKCQlpZiAodHdvIGluc3RhbmNlb2YgWFNVbnR5cGVkQXRvbWljKQoJCQl0d28gPSBuZXcgWFNTdHJpbmcodHdvLnN0cmluZ192YWx1ZSgpKTsKCgkJaWYgKCEob25lIGluc3RhbmNlb2YgQ21wRXEpKQoJCQlEeW5hbWljRXJyb3IudGhyb3dfdHlwZV9lcnJvcigpOwoKCQlDbXBFcSBjbXBvbmUgPSAoQ21wRXEpIG9uZTsKCgkJcmV0dXJuIGNtcG9uZS5lcSh0d28sIGR5bmFtaWNDb250ZXh0KTsKCX0KCgkvKioKCSAqIE1ha2luZyBzdXJlIHRoYXQgdGhlIHR5cGVzIGFyZSB0aGUgc2FtZSBiZWZvcmUgY29tcGFyaW5nIHRoZSBpbnB1dHMuCgkgKiAKCSAqIEBwYXJhbSBhCgkgKiAgICAgICAgICAgIGlucHV0MSBvZiBhbnkgdHlwZS4KCSAqIEBwYXJhbSBiCgkgKiAgICAgICAgICAgIGlucHV0MiBvZiBhbnkgdHlwZS4KCSAqIEBwYXJhbSBkYwoJICogICAgICAgICAgICAgIER5bmFtaWMgQ29udGV4dAoJICogQHRocm93cyBEeW5hbWljRXJyb3IKCSAqICAgICAgICAgICAgIER5bmFtaWMgZXJyb3IuCgkgKiBAcmV0dXJuIFJlc3VsdCBvZiBFcXVhbGl0eSBvcGVyYXRpb24uCgkgKi8KCXByaXZhdGUgc3RhdGljIGJvb2xlYW4gZG9fZ2VuZXJhbF9wYWlyKEFueVR5cGUgYSwgQW55VHlwZSBiLAoJCQlNZXRob2QgY29tcGFyYXRvciwgRHluYW1pY0NvbnRleHQgZGMpIHRocm93cyBEeW5hbWljRXJyb3IgewoKCQkvLyBzZWN0aW9uIDMuNS4yCgoJCS8vIHJ1bGUgYQoJCS8vIGlmIG9uZSBpcyB1bnR5cGVkIGFuZCBvdGhlciBpcyBudW1lcmljLCBjYXN0IHVudHlwZWQgdG8KCQkvLyBkb3VibGUKCQlpZiAoKGEgaW5zdGFuY2VvZiBYU1VudHlwZWRBdG9taWMgJiYgYiBpbnN0YW5jZW9mIE51bWVyaWNUeXBlKQoJCQkJfHwgKGIgaW5zdGFuY2VvZiBYU1VudHlwZWRBdG9taWMgJiYgYSBpbnN0YW5jZW9mIE51bWVyaWNUeXBlKSkgewoJCQlpZiAoYSBpbnN0YW5jZW9mIFhTVW50eXBlZEF0b21pYykKCQkJCWEgPSBuZXcgWFNEb3VibGUoYS5zdHJpbmdfdmFsdWUoKSk7CgkJCWVsc2UKCQkJCWIgPSBuZXcgWFNEb3VibGUoYi5zdHJpbmdfdmFsdWUoKSk7CgoJCX0KCgkJLy8gcnVsZSBiCgkJLy8gaWYgb25lIGlzIHVudHlwZWQgYW5kIG90aGVyIGlzIHN0cmluZyBvciB1bnR5cGVkLCB0aGVuIGNhc3QKCQkvLyB1bnR5cGVkIHRvIHN0cmluZwoJCWVsc2UgaWYgKChhIGluc3RhbmNlb2YgWFNVbnR5cGVkQXRvbWljCgkJCQkmJiAoYiBpbnN0YW5jZW9mIFhTU3RyaW5nIHx8IGIgaW5zdGFuY2VvZiBYU1VudHlwZWRBdG9taWMpIHx8IChiIGluc3RhbmNlb2YgWFNVbnR5cGVkQXRvbWljICYmIChhIGluc3RhbmNlb2YgWFNTdHJpbmcgfHwgYSBpbnN0YW5jZW9mIFhTVW50eXBlZEF0b21pYykpKSkgewoKCQkJaWYgKGEgaW5zdGFuY2VvZiBYU1VudHlwZWRBdG9taWMpCgkJCQlhID0gbmV3IFhTU3RyaW5nKGEuc3RyaW5nX3ZhbHVlKCkpOwoJCQlpZiAoYiBpbnN0YW5jZW9mIFhTVW50eXBlZEF0b21pYykKCQkJCWIgPSBuZXcgWFNTdHJpbmcoYi5zdHJpbmdfdmFsdWUoKSk7CgkJfQoKCQkvLyBydWxlIGMKCQkvLyBpZiBvbmUgaXMgdW50eXBlZCBhbmQgb3RoZXIgaXMgbm90IHN0cmluZyx1bnR5cGVkLG51bWVyaWMKCQkvLyBjYXN0IHVudHlwZWQgdG8gZHluYW1pYyB0eXBlIG9mIG90aGVyCgoJCS8vIFhYWD8KCQllbHNlIGlmIChhIGluc3RhbmNlb2YgWFNVbnR5cGVkQXRvbWljKSB7CgkJCVJlc3VsdFNlcXVlbmNlIGNvbnZlcnRlZCA9IFJlc3VsdFNlcXVlbmNlRmFjdG9yeS5jcmVhdGVfbmV3KGEpOwoJCQlhc3NlcnQgY29udmVydGVkLnNpemUoKSA9PSAxOwoJCQlhID0gY29udmVydGVkLmZpcnN0KCk7CgkJfSBlbHNlIGlmIChiIGluc3RhbmNlb2YgWFNVbnR5cGVkQXRvbWljKSB7CgkJCVJlc3VsdFNlcXVlbmNlIGNvbnZlcnRlZCA9IFJlc3VsdFNlcXVlbmNlRmFjdG9yeS5jcmVhdGVfbmV3KGIpOwoJCQlhc3NlcnQgY29udmVydGVkLnNpemUoKSA9PSAxOwoJCQliID0gY29udmVydGVkLmZpcnN0KCk7CgkJfQoKCQkvLyBydWxlIGQKCQkvLyBpZiB2YWx1ZSBjb21wYXJpc29uIGlzIHRydWUsIHJldHVybiB0cnVlLgoKCQlSZXN1bHRTZXF1ZW5jZSBvbmUgPSBSZXN1bHRTZXF1ZW5jZUZhY3RvcnkuY3JlYXRlX25ldyhhKTsKCQlSZXN1bHRTZXF1ZW5jZSB0d28gPSBSZXN1bHRTZXF1ZW5jZUZhY3RvcnkuY3JlYXRlX25ldyhiKTsKCgkJQ29sbGVjdGlvbiBhcmdzID0gbmV3IEFycmF5TGlzdCgpOwoJCWFyZ3MuYWRkKG9uZSk7CgkJYXJncy5hZGQodHdvKTsKCgkJT2JqZWN0IG1hcmdzW10gPSB7IGFyZ3MsIGRjIH07CgoJCVJlc3VsdFNlcXVlbmNlIHJlc3VsdCA9IG51bGw7CgkJdHJ5IHsKCQkJcmVzdWx0ID0gKFJlc3VsdFNlcXVlbmNlKSBjb21wYXJhdG9yLmludm9rZShudWxsLCBtYXJncyk7CgkJfSBjYXRjaCAoSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbiBlcnIpIHsKCQkJYXNzZXJ0IGZhbHNlOwoJCX0gY2F0Y2ggKEludm9jYXRpb25UYXJnZXRFeGNlcHRpb24gZXJyKSB7CgkJCVRocm93YWJsZSBleCA9IGVyci5nZXRUYXJnZXRFeGNlcHRpb24oKTsKCgkJCWlmIChleCBpbnN0YW5jZW9mIER5bmFtaWNFcnJvcikKCQkJCXRocm93IChEeW5hbWljRXJyb3IpIGV4OwoKCQkJZXgucHJpbnRTdGFja1RyYWNlKCk7CgkJCVN5c3RlbS5leGl0KDEpOwoJCX0KCgkJaWYgKCgoWFNCb29sZWFuKSByZXN1bHQuZmlyc3QoKSkudmFsdWUoKSkKCQkJcmV0dXJuIHRydWU7CgoJCXJldHVybiBmYWxzZTsKCX0KCgkvKioKCSAqIEEgZ2VuZXJhbCBlcXVhbGl0eSBmdW5jdGlvbi4KCSAqIAoJICogQHBhcmFtIGFyZ3MKCSAqICAgICAgICAgICAgaW5wdXQgYXJndW1lbnRzLgoJICogQHBhcmFtIGRjCgkgKiAgICAgICAgIER5bmFtaWMgY29udGV4dCAKCSAqIEB0aHJvd3MgRHluYW1pY0Vycm9yCgkgKiAgICAgICAgICAgICBEeW5hbWljIGVycm9yLgoJICogQHJldHVybiBSZXN1bHQgb2YgZ2VuZXJhbCBlcXVhbGl0eSBvcGVyYXRpb24uCgkgKi8KCXB1YmxpYyBzdGF0aWMgUmVzdWx0U2VxdWVuY2UgZnNfZXFfZ2VuZXJhbChDb2xsZWN0aW9uIGFyZ3MsIER5bmFtaWNDb250ZXh0IGRjKQoJCQl0aHJvd3MgRHluYW1pY0Vycm9yIHsKCQlyZXR1cm4gZG9fY21wX2dlbmVyYWxfb3AoYXJncywgRnNFcS5jbGFzcywgImZzX2VxX3ZhbHVlIiwgZGMpOwoJfQoKCS8vIHZvb2RvbyAzCgkvKioKCSAqIEFjdHVhbCBlcXVhbGl0eSBvcGVyYXRpb24gZm9yIGZzX2VxX2dlbmVyYWwuCgkgKiAKCSAqIEBwYXJhbSBhcmdzCgkgKiAgICAgICAgICAgIGlucHV0IGFyZ3VtZW50cy4KCSAqIEBwYXJhbSB0eXBlCgkgKiAgICAgICAgICAgIHR5cGUgb2YgdGhlIGFyZ3VtZW50cy4KCSAqIEBwYXJhbSBtbmFtZQoJICogICAgICAgICAgICBNZXRob2QgbmFtZSBmb3IgdGVtcGxhdGUgc2ltdWxhdGlvbi4KCSAqIEB0aHJvd3MgRHluYW1pY0Vycm9yCgkgKiAgICAgICAgICAgICBEeW5hbWljIGVycm9yLgoJICogQHJldHVybiBSZXN1bHQgb2YgdGhlIG9wZXJhdGlvbi4KCSAqLwoJcHVibGljIHN0YXRpYyBSZXN1bHRTZXF1ZW5jZSBkb19jbXBfZ2VuZXJhbF9vcChDb2xsZWN0aW9uIGFyZ3MsIENsYXNzIHR5cGUsCgkJCVN0cmluZyBtbmFtZSwgRHluYW1pY0NvbnRleHQgZGMpIHRocm93cyBEeW5hbWljRXJyb3IgewoKCQkvLyBkbyB0aGUgdm9vZG9vCgkJTWV0aG9kIGNvbXBhcmF0b3IgPSBudWxsOwoKCQl0cnkgewoJCQlDbGFzcyBtYXJnc2RlZltdID0geyBDb2xsZWN0aW9uLmNsYXNzLCBEeW5hbWljQ29udGV4dC5jbGFzcyB9OwoKCQkJY29tcGFyYXRvciA9IHR5cGUuZ2V0TWV0aG9kKG1uYW1lLCBtYXJnc2RlZik7CgoJCX0gY2F0Y2ggKE5vU3VjaE1ldGhvZEV4Y2VwdGlvbiBlcnIpIHsKCQkJdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oIkNhbr8ndCBmaW5kIG1ldGhvZCA6ICIgKyBtbmFtZSwgZXJyKTsKCQl9CgoJCS8vIHNhbml0eSBjaGVjayBhcmdzIGFuZCBnZXQgdGhlbQoJCWlmIChhcmdzLnNpemUoKSAhPSAyKQoJCQlEeW5hbWljRXJyb3IudGhyb3dfdHlwZV9lcnJvcigpOwoKCQlJdGVyYXRvciBhcmdpdGVyID0gYXJncy5pdGVyYXRvcigpOwoKCQlSZXN1bHRTZXF1ZW5jZSBvbmUgPSAoUmVzdWx0U2VxdWVuY2UpIGFyZ2l0ZXIubmV4dCgpOwoJCVJlc3VsdFNlcXVlbmNlIHR3byA9IChSZXN1bHRTZXF1ZW5jZSkgYXJnaXRlci5uZXh0KCk7CgoJCS8vIFhYWCA/CgkJaWYgKG9uZS5lbXB0eSgpIHx8IHR3by5lbXB0eSgpKQoJCQlyZXR1cm4gUmVzdWx0U2VxdWVuY2VGYWN0b3J5LmNyZWF0ZV9uZXcobmV3IFhTQm9vbGVhbihmYWxzZSkpOwoKCQkvLyBhdG9taXplCgkJb25lID0gRm5EYXRhLmF0b21pemUob25lKTsKCQl0d28gPSBGbkRhdGEuYXRvbWl6ZSh0d28pOwoKCQkvLyB3ZSBnb3R0YSBmaW5kIGEgcGFpciB0aGF0IHNhdGlzZmllZCB0aGUgY29uZGl0aW9uCgkJZm9yIChJdGVyYXRvciBpID0gb25lLml0ZXJhdG9yKCk7IGkuaGFzTmV4dCgpOykgewoJCQlBbnlUeXBlIGEgPSAoQW55VHlwZSkgaS5uZXh0KCk7CgkJCWZvciAoSXRlcmF0b3IgaiA9IHR3by5pdGVyYXRvcigpOyBqLmhhc05leHQoKTspIHsKCQkJCUFueVR5cGUgYiA9IChBbnlUeXBlKSBqLm5leHQoKTsKCgkJCQlpZiAoZG9fZ2VuZXJhbF9wYWlyKGEsIGIsIGNvbXBhcmF0b3IsIGRjKSkKCQkJCQlyZXR1cm4gUmVzdWx0U2VxdWVuY2VGYWN0b3J5CgkJCQkJCQkuY3JlYXRlX25ldyhuZXcgWFNCb29sZWFuKHRydWUpKTsKCQkJfQoJCX0KCgkJcmV0dXJuIFJlc3VsdFNlcXVlbmNlRmFjdG9yeS5jcmVhdGVfbmV3KG5ldyBYU0Jvb2xlYW4oZmFsc2UpKTsKCX0KCgkvLyB2b29kb28gMgoJLyoqCgkgKiBBY3R1YWwgZXF1YWxpdHkgb3BlcmF0aW9uIGZvciBmc19lcV92YWx1ZS4KCSAqIAoJICogQHBhcmFtIGFyZ3MKCSAqICAgICAgICAgICAgaW5wdXQgYXJndW1lbnRzLgoJICogQHBhcmFtIHR5cGUKCSAqICAgICAgICAgICAgdHlwZSBvZiB0aGUgYXJndW1lbnRzLgoJICogQHBhcmFtIG1uYW1lCgkgKiAgICAgICAgICAgIE1ldGhvZCBuYW1lIGZvciB0ZW1wbGF0ZSBzaW11bGF0aW9uLgoJICogQHBhcmFtIGR5bmFtaWNDb250ZXh0IAoJICogICAgICAgICAgICAgRHluYW1pYyBlcnJvci4KCSAqIEB0aHJvd3MgRHluYW1pY0Vycm9yCgkgKiAgICAgICAgICAgICBEeW5hbWljIGVycm9yLgoJICogQHJldHVybiBSZXN1bHQgb2YgdGhlIG9wZXJhdGlvbi4KCSAqLwoJcHVibGljIHN0YXRpYyBSZXN1bHRTZXF1ZW5jZSBkb19jbXBfdmFsdWVfb3AoQ29sbGVjdGlvbiBhcmdzLCBDbGFzcyB0eXBlLAoJCQlTdHJpbmcgbW5hbWUsIER5bmFtaWNDb250ZXh0IGR5bmFtaWNDb250ZXh0KSB0aHJvd3MgRHluYW1pY0Vycm9yIHsKCgkJLy8gc2FuaXR5IGNoZWNrIGFyZ3MgKyBjb252ZXJ0IGVtCgkJaWYgKGFyZ3Muc2l6ZSgpICE9IDIpCgkJCUR5bmFtaWNFcnJvci50aHJvd190eXBlX2Vycm9yKCk7CgoJCUNvbGxlY3Rpb24gY2FyZ3MgPSB2YWx1ZV9jb252ZXJ0X2FyZ3MoYXJncyk7CgoJCVJlc3VsdFNlcXVlbmNlIHJlc3VsdCA9IFJlc3VsdFNlcXVlbmNlRmFjdG9yeS5jcmVhdGVfbmV3KCk7CgoJCWlmIChjYXJncy5zaXplKCkgPT0gMCkKCQkJcmV0dXJuIHJlc3VsdDsKCgkJLy8gbWFrZSBzdXJlIGFydWdtZW50cyBhcmUgY29tcGFyYWJsZSBieSBlcXVhbGl0eQoJCUl0ZXJhdG9yIGFyZ2kgPSBjYXJncy5pdGVyYXRvcigpOwoJCUFueVR5cGUgYXJnID0gKChSZXN1bHRTZXF1ZW5jZSkgYXJnaS5uZXh0KCkpLmZpcnN0KCk7CgkJUmVzdWx0U2VxdWVuY2UgYXJnMiA9IChSZXN1bHRTZXF1ZW5jZSkgYXJnaS5uZXh0KCk7CgoJCWlmIChhcmcyLnNpemUoKSAhPSAxKQoJCQlEeW5hbWljRXJyb3IudGhyb3dfdHlwZV9lcnJvcigpOwoKCQlpZiAoISh0eXBlLmlzSW5zdGFuY2UoYXJnKSkpCgkJCUR5bmFtaWNFcnJvci50aHJvd190eXBlX2Vycm9yKCk7CgoJCXRyeSB7CgkJCUNsYXNzIG1hcmdzZGVmW10gPSB7IEFueVR5cGUuY2xhc3MsIER5bmFtaWNDb250ZXh0LmNsYXNzIH07CgkJCU1ldGhvZCBtZXRob2QgPSBudWxsOwoKCQkJbWV0aG9kID0gdHlwZS5nZXRNZXRob2QobW5hbWUsIG1hcmdzZGVmKTsKCgkJCU9iamVjdCBtYXJnc1tdID0geyBhcmcyLmZpcnN0KCksIGR5bmFtaWNDb250ZXh0IH07CgkJCUJvb2xlYW4gY21wcmVzID0gKEJvb2xlYW4pIG1ldGhvZC5pbnZva2UoYXJnLCBtYXJncyk7CgoJCQlyZXR1cm4gUmVzdWx0U2VxdWVuY2VGYWN0b3J5LmNyZWF0ZV9uZXcobmV3IFhTQm9vbGVhbihjbXByZXMKCQkJCQkuYm9vbGVhblZhbHVlKCkpKTsKCQl9IGNhdGNoIChOb1N1Y2hNZXRob2RFeGNlcHRpb24gZXJyKSB7CgkJCWFzc2VydCBmYWxzZTsKCQkJdGhyb3cgbmV3IFJ1bnRpbWVFeGNlcHRpb24oImNhbm5vdCBjb21wYXJlIHVzaW5nIG1ldGhvZCAiICsgbW5hbWUsIGVycik7CgkJfSBjYXRjaCAoSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbiBlcnIpIHsKCQkJYXNzZXJ0IGZhbHNlOwoJCQl0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigiY2Fubm90IGNvbXBhcmUgdXNpbmcgbWV0aG9kICIgKyBtbmFtZSwgZXJyKTsKCQl9IGNhdGNoIChJbnZvY2F0aW9uVGFyZ2V0RXhjZXB0aW9uIGVycikgewoJCQlUaHJvd2FibGUgZXggPSBlcnIuZ2V0VGFyZ2V0RXhjZXB0aW9uKCk7CgoJCQlpZiAoZXggaW5zdGFuY2VvZiBEeW5hbWljRXJyb3IpCgkJCQl0aHJvdyAoRHluYW1pY0Vycm9yKSBleDsKCgkJCXRocm93IG5ldyBSdW50aW1lRXhjZXB0aW9uKCJjYW5ub3QgY29tcGFyZSB1c2luZyBtZXRob2QgIiArIG1uYW1lLCBleCk7CgkJfQoJfQp9Cg==