LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDAzLCAyMDA0IElCTSBDb3Jwb3JhdGlvbiBhbmQgb3RoZXJzLgogKiBBbGwgcmlnaHRzIHJlc2VydmVkLiBUaGlzIHByb2dyYW0gYW5kIHRoZSBhY2NvbXBhbnlpbmcgbWF0ZXJpYWxzCiAqIGFyZSBtYWRlIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIENvbW1vbiBQdWJsaWMgTGljZW5zZSB2MS4wCiAqIHdoaWNoIGFjY29tcGFuaWVzIHRoaXMgZGlzdHJpYnV0aW9uLCBhbmQgaXMgYXZhaWxhYmxlIGF0CiAqIGh0dHA6Ly93d3cuZWNsaXBzZS5vcmcvbGVnYWwvY3BsLXYxMC5odG1sCqAqCiAqIENvbnRyaWJ1dG9yczoKICogICAgSUJNIC0gSW5pdGlhbCBBUEkgYW5kIGltcGxlbWVudGF0aW9uCiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy5lY2xpcHNlLndzdC5zZXJ2ZXIudWkuaW50ZXJuYWw7CgppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMuSVByb2plY3Q7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JUHJvamVjdERlc2NyaXB0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZXMuSVdvcmtzcGFjZTsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2VzLlJlc291cmNlc1BsdWdpbjsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5Db3JlRXhjZXB0aW9uOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLklQYXRoOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLklQcm9ncmVzc01vbml0b3I7CmltcG9ydCBvcmcuZWNsaXBzZS5jb3JlLnJ1bnRpbWUuSVN0YXR1czsKaW1wb3J0IG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5OdWxsUHJvZ3Jlc3NNb25pdG9yOwppbXBvcnQgb3JnLmVjbGlwc2UuY29yZS5ydW50aW1lLlN0YXR1czsKaW1wb3J0IG9yZy5lY2xpcHNlLmRlYnVnLmNvcmUuSUxhdW5jaDsKaW1wb3J0IG9yZy5lY2xpcHNlLmRlYnVnLmludGVybmFsLnVpLkRlYnVnVUlQbHVnaW47CmltcG9ydCBvcmcuZWNsaXBzZS5qZmFjZS5kaWFsb2dzLkVycm9yRGlhbG9nOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UuZGlhbG9ncy5NZXNzYWdlRGlhbG9nOwppbXBvcnQgb3JnLmVjbGlwc2UuamZhY2UucmVzb3VyY2UuSW1hZ2VEZXNjcmlwdG9yOwppbXBvcnQgb3JnLmVjbGlwc2Uuc3d0LndpZGdldHMuRGlzcGxheTsKaW1wb3J0IG9yZy5lY2xpcHNlLnN3dC53aWRnZXRzLlNoZWxsOwppbXBvcnQgb3JnLmVjbGlwc2UudWkubW9kZWwuSVdvcmtiZW5jaEFkYXB0ZXI7CgppbXBvcnQgb3JnLmVjbGlwc2Uud3N0LnNlcnZlci5jb3JlLklTZXJ2ZXI7CmltcG9ydCBvcmcuZWNsaXBzZS53c3Quc2VydmVyLmNvcmUuU2VydmVyQ29yZTsKLyoqCiAqIEVjbGlwc2UgdXRpbGl0eSBtZXRob2RzLgogKi8KcHVibGljIGNsYXNzIEVjbGlwc2VVdGlsIHsKCS8qKgoJICogRWNsaXBzZVV0aWwgY29uc3RydWN0b3IgY29tbWVudC4KCSAqLwoJcHJpdmF0ZSBFY2xpcHNlVXRpbCgpIHsKCQlzdXBlcigpOwoJfQoJCgkvKioKCSAqIENyZWF0ZXMgYSBuZXcgc2VydmVyIHByb2plY3Qgd2l0aCB0aGUgZ2l2ZW4gbmFtZS4gSWYgcGF0aCBpcwoJICogbnVsbCwgaXQgd2lsbCBiZSBjcmVhdGVkIGluIHRoZSBkZWZhdWx0IGxvY2F0aW9uLgoJICoKCSAqIEBwYXJhbSBuYW1lIGphdmEubGFuZy5TdHJpbmcKCSAqIEBwYXJhbSBwYXRoIG9yZy5lY2xpcHNlLmNvcmUucmVzb3VyY2UuSVBhdGgKCSAqIEBwYXJhbSBtb25pdG9yCgkgKiBAcmV0dXJuIG9yZy5lY2xpcHNlLmNvcmUucnVudGltZS5JU3RhdHVzCgkgKi8KCXByaXZhdGUgc3RhdGljIElTdGF0dXMgY3JlYXRlU2VydmVyUHJvamVjdChTdHJpbmcgbmFtZSwgSVBhdGggcGF0aCwgSVByb2dyZXNzTW9uaXRvciBtb25pdG9yKSB7CgkJLy9tb25pdG9yID0gUHJvZ3Jlc3NVdGlsLmdldE1vbml0b3JGb3IobW9uaXRvcik7CgkJLy9tb25pdG9yLmJlZ2luVGFzayhTZXJ2ZXJQbHVnaW4uZ2V0UmVzb3VyY2UoIiVjcmVhdGVTZXJ2ZXJQcm9qZWN0VGFzayIpLCAzMDAwKTsKCgkJdHJ5IHsKCQkJSVdvcmtzcGFjZSB3b3Jrc3BhY2UgPSBSZXNvdXJjZXNQbHVnaW4uZ2V0V29ya3NwYWNlKCk7CgkJCUlQcm9qZWN0IHByb2plY3QgPSB3b3Jrc3BhY2UuZ2V0Um9vdCgpLmdldFByb2plY3QobmFtZSk7CgkKCQkJLy8gZ2V0IGEgcHJvamVjdCBkZXNjcmlwdG9yCgkJCUlQcm9qZWN0RGVzY3JpcHRpb24gZGVzY3JpcHRpb24gPSB3b3Jrc3BhY2UubmV3UHJvamVjdERlc2NyaXB0aW9uKG5hbWUpOwoJCQlkZXNjcmlwdGlvbi5zZXRMb2NhdGlvbihwYXRoKTsKCQoJCQlwcm9qZWN0LmNyZWF0ZShkZXNjcmlwdGlvbiwgUHJvZ3Jlc3NVdGlsLmdldFN1Yk1vbml0b3JGb3IobW9uaXRvciwgMTAwMCkpOwoJCQlpZiAobW9uaXRvci5pc0NhbmNlbGVkKCkpCgkJCQlyZXR1cm4gbnVsbDsKCQkJcHJvamVjdC5vcGVuKFByb2dyZXNzVXRpbC5nZXRTdWJNb25pdG9yRm9yKG1vbml0b3IsIDEwMDApKTsKCQkJaWYgKG1vbml0b3IuaXNDYW5jZWxlZCgpKQoJCQkJcmV0dXJuIG51bGw7CgoJCQkvLyBhZGQgdGhlIHNlcnZlciBwcm9qZWN0IG5hdHVyZQoJCQlTZXJ2ZXJDb3JlLmdldFByb2plY3RQcm9wZXJ0aWVzKHByb2plY3QpLnNldFNlcnZlclByb2plY3QodHJ1ZSwgbW9uaXRvcik7CgkKCQkJaWYgKG1vbml0b3IuaXNDYW5jZWxlZCgpKQoJCQkJcmV0dXJuIG51bGw7CgkKCQkJcmV0dXJuIG5ldyBTdGF0dXMoSVN0YXR1cy5PSywgU2VydmVyVUlQbHVnaW4uUExVR0lOX0lELCAwLCBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJXNlcnZlclByb2plY3RDcmVhdGVkIiksIG51bGwpOwoJCX0gY2F0Y2ggKENvcmVFeGNlcHRpb24gY2UpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiQ291bGQgbm90IGNyZWF0ZSBzZXJ2ZXIgcHJvamVjdCBuYW1lZCAiICsgbmFtZSwgY2UpOwoJCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJVSVBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclVJUGx1Z2luLmdldFJlc291cmNlKCIlZXJyb3JDb3VsZE5vdENyZWF0ZVNlcnZlclByb2plY3RTdGF0dXMiLCBjZS5nZXRNZXNzYWdlKCkpLCBjZSk7CgkJfSBjYXRjaCAoRXhjZXB0aW9uIGUpIHsKCQkJVHJhY2UudHJhY2UoVHJhY2UuU0VWRVJFLCAiQ291bGQgbm90IGNyZWF0ZSBzZXJ2ZXIgcHJvamVjdCAoMikgbmFtZWQgIiArIG5hbWUsIGUpOwoJCQlyZXR1cm4gbmV3IFN0YXR1cyhJU3RhdHVzLkVSUk9SLCBTZXJ2ZXJVSVBsdWdpbi5QTFVHSU5fSUQsIDAsIFNlcnZlclVJUGx1Z2luLmdldFJlc291cmNlKCIlZXJyb3JDb3VsZE5vdENyZWF0ZVNlcnZlclByb2plY3QiKSwgZSk7CgkJfSBmaW5hbGx5IHsKCQkJbW9uaXRvci5kb25lKCk7CgkJfQoJfQoKCS8qKgoJICogQ3JlYXRlcyBhIG5ldyBzZXJ2ZXIgcHJvamVjdCB3aXRoIHRoZSBnaXZlbiBuYW1lLiBJZiBwYXRoIGlzCgkgKiBudWxsLCBpdCB3aWxsIGJlIGNyZWF0ZWQgaW4gdGhlIGRlZmF1bHQgbG9jYXRpb24uCgkgKgoJICogQHBhcmFtIG5hbWUgamF2YS5sYW5nLlN0cmluZwoJICogQHBhcmFtIHBhdGggb3JnLmVjbGlwc2UuY29yZS5yZXNvdXJjZS5JUGF0aAoJICogQHJldHVybiBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JUHJvamVjdAoJICovCglwdWJsaWMgc3RhdGljIElTdGF0dXMgY3JlYXRlTmV3U2VydmVyUHJvamVjdChmaW5hbCBTaGVsbCBzaGVsbCwgU3RyaW5nIG5hbWUsIElQYXRoIHBhdGgsIElQcm9ncmVzc01vbml0b3IgbW9uaXRvcikgewoJCWZpbmFsIElTdGF0dXMgc3RhdHVzID0gY3JlYXRlU2VydmVyUHJvamVjdChuYW1lLCBwYXRoLCBtb25pdG9yKTsKCQlpZiAoIXN0YXR1cy5pc09LKCkpIHsKCQkJRGlzcGxheS5nZXREZWZhdWx0KCkuYXN5bmNFeGVjKG5ldyBSdW5uYWJsZSgpIHsKCQkJCXB1YmxpYyB2b2lkIHJ1bigpIHsKCQkJCQlTaGVsbCBzaGVsbDIgPSBzaGVsbDsKCQkJCQlpZiAoc2hlbGwgPT0gbnVsbCkKCQkJCQkJc2hlbGwyID0gZ2V0U2hlbGwoKTsKCQkJCQlvcGVuRXJyb3Ioc2hlbGwyLCBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yQ291bGROb3RDcmVhdGVTZXJ2ZXJQcm9qZWN0IiksIHN0YXR1cyk7CgkJCQl9CgkJCX0pOwoJCX0KCQlyZXR1cm4gc3RhdHVzOwoJfQoKCS8qKgoJICogUmV0dXJucyB0aGUgaW1hZ2UgZm9yIGEgcHJvamVjdC4KCSAqCgkgKiBAcGFyYW0gcHJvamVjdCBvcmcuZWNsaXBzZS5jb3JlLnJlc291cmNlcy5JUHJvamVjdAoJICogQHJldHVybiBvcmcuZWNsaXBzZS5qZmFjZS5yZXNvdXJjZS5JbWFnZURlc2NyaXB0b3IKCSAqLwoJcHVibGljIHN0YXRpYyBJbWFnZURlc2NyaXB0b3IgZ2V0UHJvamVjdEltYWdlRGVzY3JpcHRvcihJUHJvamVjdCBwcm9qZWN0KSB7CgkJaWYgKHByb2plY3QgPT0gbnVsbCkKCQkJcmV0dXJuIG51bGw7CgkKCQlJV29ya2JlbmNoQWRhcHRlciBhZGFwdGVyID0gKElXb3JrYmVuY2hBZGFwdGVyKSBwcm9qZWN0LmdldEFkYXB0ZXIoSVdvcmtiZW5jaEFkYXB0ZXIuY2xhc3MpOwoJCgkJaWYgKGFkYXB0ZXIgIT0gbnVsbCkKCQkJcmV0dXJuIGFkYXB0ZXIuZ2V0SW1hZ2VEZXNjcmlwdG9yKHByb2plY3QpOwoJCQoJCXJldHVybiBudWxsOwoJfQoKCS8qKgoJICogUmV0dXJuIGEgc2hlbGwgZm9yIHRoZSB3b3JrYmVuY2guCgkgKgoJICogQHJldHVybiBvcmcuZWNsaXBzZS5zd3Qud2lkZ2V0cy5TaGVsbAoJICovCglwdWJsaWMgc3RhdGljIFNoZWxsIGdldFNoZWxsKCkgewoJCXJldHVybiBnZXRTdGFuZGFyZERpc3BsYXkoKS5nZXRBY3RpdmVTaGVsbCgpOwoJfQoJCgkvKioKCSAqIFJldHVybnMgdGhlIHN0YW5kYXJkIGRpc3BsYXkgdG8gYmUgdXNlZC4gVGhlIG1ldGhvZCBmaXJzdCBjaGVja3MsIGlmCgkgKiB0aGUgdGhyZWFkIGNhbGxpbmcgdGhpcyBtZXRob2QgaGFzIGFuIGFzc29jaWF0ZWQgZGlzcGxheS4gSWYgc28sIHRoaXMKCSAqIGRpc3BsYXkgaXMgcmV0dXJuZWQuIE90aGVyd2lzZSB0aGUgbWV0aG9kIHJldHVybnMgdGhlIGRlZmF1bHQgZGlzcGxheS4KCSAqLwoJcHVibGljIHN0YXRpYyBEaXNwbGF5IGdldFN0YW5kYXJkRGlzcGxheSgpIHsKCQlEaXNwbGF5IGRpc3BsYXkgPSBEaXNwbGF5LmdldEN1cnJlbnQoKTsKCQlpZiAoZGlzcGxheSA9PSBudWxsKQoJCQlkaXNwbGF5ID0gRGlzcGxheS5nZXREZWZhdWx0KCk7CgoJCXJldHVybiBkaXNwbGF5OwkJCgl9CQoJCgkvKioKCSAqIE9wZW4gYSBkaWFsb2cgd2luZG93LgoJICoKCSAqIEBwYXJhbSB0aXRsZSBqYXZhLmxhbmcuU3RyaW5nCgkgKiBAcGFyYW0gbWVzc2FnZSBqYXZhLmxhbmcuU3RyaW5nCgkgKi8KCXB1YmxpYyBzdGF0aWMgdm9pZCBvcGVuRXJyb3IoZmluYWwgU3RyaW5nIG1lc3NhZ2UpIHsKCQlEaXNwbGF5LmdldERlZmF1bHQoKS5hc3luY0V4ZWMobmV3IFJ1bm5hYmxlKCkgewoJCQlwdWJsaWMgdm9pZCBydW4oKSB7CgkJCQlTaGVsbCBzaGVsbCA9IGdldFNoZWxsKCk7CgkJCQlNZXNzYWdlRGlhbG9nLm9wZW5FcnJvcihzaGVsbCwgU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiVlcnJvckRpYWxvZ1RpdGxlIiksIG1lc3NhZ2UpOwoJCQl9CgkJfSk7Cgl9CgoJLyoqCgkgKiBPcGVuIGEgZGlhbG9nIHdpbmRvdy4KCSAqCgkgKiBAcGFyYW0gbWVzc2FnZSBqYXZhLmxhbmcuU3RyaW5nCgkgKiBAcGFyYW0gc3RhdHVzIElTdGF0dXMKCSAqLwoJcHVibGljIHN0YXRpYyB2b2lkIG9wZW5FcnJvcihmaW5hbCBTdHJpbmcgbWVzc2FnZSwgZmluYWwgSVN0YXR1cyBzdGF0dXMpIHsKCQlEaXNwbGF5LmdldERlZmF1bHQoKS5hc3luY0V4ZWMobmV3IFJ1bm5hYmxlKCkgewoJCQlwdWJsaWMgdm9pZCBydW4oKSB7CgkJCQlTaGVsbCBzaGVsbCA9IGdldFNoZWxsKCk7CgkJCQlFcnJvckRpYWxvZy5vcGVuRXJyb3Ioc2hlbGwsIFNlcnZlclVJUGx1Z2luLmdldFJlc291cmNlKCIlZXJyb3JEaWFsb2dUaXRsZSIpLCBtZXNzYWdlLCBzdGF0dXMpOwoJCQl9CgkJfSk7Cgl9CgoJLyoqCgkgKiBPcGVuIGEgZGlhbG9nIHdpbmRvdy4KCSAqCgkgKiBAcGFyYW0gdGl0bGUgamF2YS5sYW5nLlN0cmluZwoJICogQHBhcmFtIG1lc3NhZ2UgamF2YS5sYW5nLlN0cmluZwoJICovCglwdWJsaWMgc3RhdGljIHZvaWQgb3BlbkVycm9yKFNoZWxsIHNoZWxsLCBTdHJpbmcgbWVzc2FnZSkgewoJCU1lc3NhZ2VEaWFsb2cub3BlbkVycm9yKHNoZWxsLCBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yRGlhbG9nVGl0bGUiKSwgbWVzc2FnZSk7Cgl9CgoJLyoqCgkgKiBPcGVuIGEgZGlhbG9nIHdpbmRvdy4KCSAqCgkgKiBAcGFyYW0gbWVzc2FnZSBqYXZhLmxhbmcuU3RyaW5nCgkgKiBAcGFyYW0gc3RhdHVzIElTdGF0dXMKCSAqLwoJcHVibGljIHN0YXRpYyB2b2lkIG9wZW5FcnJvcihTaGVsbCBzaGVsbCwgU3RyaW5nIG1lc3NhZ2UsIElTdGF0dXMgc3RhdHVzKSB7CgkJRXJyb3JEaWFsb2cub3BlbkVycm9yKHNoZWxsLCBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yRGlhbG9nVGl0bGUiKSwgbWVzc2FnZSwgc3RhdHVzKTsKCX0KCQoJLyoqCgkgKiBTdGFydCBhIHNlcnZlciBhbmQgZGlzcGxheSBhIGRpYWxvZyBpZiBpdCBmYWlscy4KCSAqLwoJcHVibGljIHN0YXRpYyBJTGF1bmNoIHN0YXJ0U2VydmVyKGZpbmFsIFNoZWxsIHNoZWxsLCBmaW5hbCBJU2VydmVyIHNlcnZlciwgZmluYWwgU3RyaW5nIG1vZGUsIGZpbmFsIFNlcnZlclN0YXJ0dXBMaXN0ZW5lciBsaXN0ZW5lcikgdGhyb3dzIENvcmVFeGNlcHRpb24gewoJCS8vIEVjbGlwc2UgdjIgd29ya2Fyb3VuZCB0byBtYWtlIHN1cmUgdGhhdCB0aGUgZGVidWcgVUkgbGlzdGVuZXJzIGFyZSBzZXR1cAoJCURlYnVnVUlQbHVnaW4uZ2V0RGVmYXVsdCgpOwoKCQl0cnkgewoJCQlyZXR1cm4gc2VydmVyLnN0YXJ0KG1vZGUsIG5ldyBOdWxsUHJvZ3Jlc3NNb25pdG9yKCkpOwoJCX0gY2F0Y2ggKGZpbmFsIENvcmVFeGNlcHRpb24gZSkgewoJCQlUcmFjZS50cmFjZShUcmFjZS5TRVZFUkUsICJFcnJvciBzdGFydGluZyBzZXJ2ZXIiLCBlKTsKCQkJRGlzcGxheS5nZXREZWZhdWx0KCkuc3luY0V4ZWMobmV3IFJ1bm5hYmxlKCkgewoJCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJCUVjbGlwc2VVdGlsLm9wZW5FcnJvcihzaGVsbCwgU2VydmVyVUlQbHVnaW4uZ2V0UmVzb3VyY2UoIiVzZXJ2ZXJTdGFydEVycm9yIiksIGUuZ2V0U3RhdHVzKCkpOwoJCQkJCWxpc3RlbmVyLnNldEVuYWJsZWQoZmFsc2UpOwoJCQkJfQoJCQl9KTsKCQkJdGhyb3cgZTsKCQl9Cgl9CgoJLyoqCgkgKiBEbyBhIHZhbGlkYXRlRWRpdCgpIG9uIHRoZSBnaXZlbiBzZXJ2ZXIuCgkgKi8KCXB1YmxpYyBzdGF0aWMgYm9vbGVhbiB2YWxpZGF0ZUVkaXQoU2hlbGwgc2hlbGwsIElTZXJ2ZXIgc2VydmVyKSB7CgkJSVN0YXR1cyBzdGF0dXMgPSBzZXJ2ZXIudmFsaWRhdGVFZGl0KHNoZWxsKTsKCQlyZXR1cm4gdmFsaWRhdGVFZGl0KHNoZWxsLCBzdGF0dXMpOwoJfQoJCQoJcHJvdGVjdGVkIHN0YXRpYyBib29sZWFuIHZhbGlkYXRlRWRpdChTaGVsbCBzaGVsbCwgSVN0YXR1cyBzdGF0dXMpIHsKCQlpZiAoc3RhdHVzICE9IG51bGwgJiYgc3RhdHVzLmdldFNldmVyaXR5KCkgPT0gSVN0YXR1cy5FUlJPUikgewoJCQkvLyBpbmZvcm0gdXNlcgoJCQlTdHJpbmcgbWVzc2FnZSA9IFNlcnZlclVJUGx1Z2luLmdldFJlc291cmNlKCIlZWRpdG9yVmFsaWRhdGVFZGl0RmFpbHVyZU1lc3NhZ2UiKTsKCQkJRXJyb3JEaWFsb2cub3BlbkVycm9yKHNoZWxsLCBTZXJ2ZXJVSVBsdWdpbi5nZXRSZXNvdXJjZSgiJWVycm9yRGlhbG9nVGl0bGUiKSwgbWVzc2FnZSwgc3RhdHVzKTsKCgkJCS8vIGRvIG5vdCBleGVjdXRlIGNvbW1hbmQKCQkJcmV0dXJuIGZhbHNlOwoJCX0KCQlyZXR1cm4gdHJ1ZTsKCX0KfQ==