-
Notifications
You must be signed in to change notification settings - Fork 16
Open
Labels
Description
Description
Dear Team,
I have faced the below annoymous error when run copy command and found that
force option is missed in SVNANT component due to which it thorws the waring in
the log. I have added new logic to avoid the issues.
Scnario is : Trying to copying the file from one reposiroty to another
repository which is already exist in Target URL.
[svn] svn: Path 'https://serverName/Repository/Project/Version/x.xml' already
exists
[svn] svn:
Path ''https://serverName/Repository/Project/Version/x.xml'already exists
[svn] <Copy> failed.
[svn] the execution failed for some reason. cause: Can't copy
at org.tigris.subversion.svnant.commands.SvnCommand.ex(Unknown Source)
Metadata Imported from Tigris (Issue 1495)
- Creation Date: 2013-03-26 00:01:57
- Reporter: sendhilsubramani
- Subcomponent: svnClientAdapter
- Version: 0.9.x
- Milestone: not determined
- Keywords:
- Cc:
Comments
2013-03-26 00:21:44 by sendhilsubramani
Created an attachment (id=402)
Force Option included for copy command.
2013-03-26 00:23:03 by sendhilsubramani
Created an attachment (id=403)
New Abstartct method is created fopr Copy with Force option.
2013-03-26 00:24:39 by sendhilsubramani
Created an attachment (id=404)
Implemented Abstarct method of Copy with force option
2013-03-26 00:25:13 by sendhilsubramani
Created an attachment (id=405)
Included Force option into actual svncopy command
Attachments
Copy.java - Force Option included for copy command.
Posted 2013-03-26 00:21:44 by sendhilsubramani
LyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT0KICogVGhlIEFwYWNoZSBTb2Z0d2FyZSBMaWNlbnNlLCBWZXJzaW9uIDEu
MQogKgogKiBDb3B5cmlnaHQgKGMpIDIwMDAgVGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9u
LiAgQWxsIHJpZ2h0cwogKiByZXNlcnZlZC4KICoKICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBp
biBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0CiAqIG1vZGlmaWNhdGlv
biwgYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucwog
KiBhcmUgbWV0OgogKgogKiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCBy
ZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodAogKiAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25k
aXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuCiAqCiAqIDIuIFJlZGlzdHJpYnV0
aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0CiAq
ICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlz
Y2xhaW1lciBpbgogKiAgICB0aGUgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxz
IHByb3ZpZGVkIHdpdGggdGhlCiAqICAgIGRpc3RyaWJ1dGlvbi4KICoKICogMy4gVGhlIGVuZC11
c2VyIGRvY3VtZW50YXRpb24gaW5jbHVkZWQgd2l0aCB0aGUgcmVkaXN0cmlidXRpb24sCiAqICAg
IGlmIGFueSwgbXVzdCBpbmNsdWRlIHRoZSBmb2xsb3dpbmcgYWNrbm93bGVkZ21lbnQ6CiAqICAg
ICAgICJUaGlzIHByb2R1Y3QgaW5jbHVkZXMgc29mdHdhcmUgZGV2ZWxvcGVkIGJ5IHRoZQogKiAg
ICAgICAgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24gKGh0dHA6Ly93d3cuYXBhY2hlLm9yZy8p
LiIKICogICAgQWx0ZXJuYXRlbHksIHRoaXMgYWNrbm93bGVkZ21lbnQgbWF5IGFwcGVhciBpbiB0
aGUgc29mdHdhcmUgaXRzZWxmLAogKiAgICBpZiBhbmQgd2hlcmV2ZXIgc3VjaCB0aGlyZC1wYXJ0
eSBhY2tub3dsZWRnbWVudHMgbm9ybWFsbHkgYXBwZWFyLgogKgogKiA0LiBUaGUgbmFtZXMgIkFw
YWNoZSIgYW5kICJBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbiIgbXVzdAogKiAgICBub3QgYmUg
dXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMKICog
ICAgc29mdHdhcmUgd2l0aG91dCBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24uIEZvciB3cml0dGVu
CiAqICAgIHBlcm1pc3Npb24sIHBsZWFzZSBjb250YWN0IGFwYWNoZUBhcGFjaGUub3JnLgogKgog
KiA1LiBQcm9kdWN0cyBkZXJpdmVkIGZyb20gdGhpcyBzb2Z0d2FyZSBtYXkgbm90IGJlIGNhbGxl
ZCAiQXBhY2hlIiwKICogICAgbm9yIG1heSAiQXBhY2hlIiBhcHBlYXIgaW4gdGhlaXIgbmFtZSwg
d2l0aG91dCBwcmlvciB3cml0dGVuCiAqICAgIHBlcm1pc3Npb24gb2YgdGhlIEFwYWNoZSBTb2Z0
d2FyZSBGb3VuZGF0aW9uLgogKgogKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIGBgQVMgSVMn
JyBBTkQgQU5ZIEVYUFJFU1NFRCBPUiBJTVBMSUVECiAqIFdBUlJBTlRJRVMsIElOQ0xVRElORywg
QlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTCiAqIE9GIE1FUkNIQU5U
QUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFCiAqIERJU0NM
QUlNRUQuICBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVBBQ0hFIFNPRlRXQVJFIEZPVU5EQVRJT04g
T1IKICogSVRTIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNU
LCBJTkNJREVOVEFMLAogKiBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFN
QUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UCiAqIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNV
QlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YKICogVVNFLCBEQVRBLCBPUiBQUk9G
SVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORAogKiBPTiBB
TlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJ
TElUWSwKICogT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklT
SU5HIElOIEFOWSBXQVkgT1VUCiAqIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJ
RiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRgogKiBTVUNIIERBTUFHRS4KICogPT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT0KICoKICogVGhpcyBzb2Z0d2FyZSBjb25zaXN0cyBvZiB2b2x1bnRhcnkgY29udHJpYnV0
aW9ucyBtYWRlIGJ5IG1hbnkKICogaW5kaXZpZHVhbHMgb24gYmVoYWxmIG9mIHRoZSBBcGFjaGUg
U29mdHdhcmUgRm91bmRhdGlvbi4gIEZvciBtb3JlCiAqIGluZm9ybWF0aW9uIG9uIHRoZSBBcGFj
aGUgU29mdHdhcmUgRm91bmRhdGlvbiwgcGxlYXNlIHNlZQogKiA8aHR0cDovL3d3dy5hcGFjaGUu
b3JnLz4uCiAqCiAqLwpwYWNrYWdlIG9yZy50aWdyaXMuc3VidmVyc2lvbi5zdm5hbnQuY29tbWFu
ZHM7CgppbXBvcnQgb3JnLnRpZ3Jpcy5zdWJ2ZXJzaW9uLnN2bmNsaWVudGFkYXB0ZXIuU1ZOQ2xp
ZW50RXhjZXB0aW9uOwppbXBvcnQgb3JnLnRpZ3Jpcy5zdWJ2ZXJzaW9uLnN2bmNsaWVudGFkYXB0
ZXIuU1ZOUmV2aXNpb247CmltcG9ydCBvcmcudGlncmlzLnN1YnZlcnNpb24uc3ZuY2xpZW50YWRh
cHRlci5TVk5Vcmw7CgppbXBvcnQgb3JnLnRpZ3Jpcy5zdWJ2ZXJzaW9uLnN2bmFudC5Tdm5BbnRV
dGlsaXRpZXM7CgppbXBvcnQgamF2YS5pby5GaWxlOwoKLyoqCiAqIHN2biBDb3B5LiBEdXBsaWNh
dGUgc29tZXRoaW5nIGluIHdvcmtpbmcgY29weSBvciByZXBvcywgcmVtZW1iZXJpbmcgaGlzdG9y
eS4KICogCiAqIEBhdXRob3IgQ+lkcmljIENoYWJhbm9pcyAoY2NoYWJhbm9pc0BpZnJhbmNlLmNv
bSkKICogQGF1dGhvciBEYW5pZWwgS2FzbWVyb2dsdSAoRGFuaWVsLkthc21lcm9nbHVAa2FzaXNv
ZnQubmV0KQogKi8KcHVibGljIGNsYXNzIENvcHkgZXh0ZW5kcyBTdm5Db21tYW5kIHsKCiAgICBw
cml2YXRlIHN0YXRpYyBmaW5hbCBTdHJpbmcgTVNHX0NBTlRfQ09QWSA9ICJDYW4ndCBjb3B5IjsK
ICAgIHByaXZhdGUgRmlsZSAgICAgICAgc3JjUGF0aCAgICAgPSBudWxsOwogICAgcHJpdmF0ZSBG
aWxlICAgICAgICBkZXN0UGF0aCAgICA9IG51bGw7CiAgICBwcml2YXRlIFNWTlVybCAgICAgIHNy
Y1VybCAgICAgID0gbnVsbDsKICAgIHByaXZhdGUgU1ZOVXJsICAgICAgZGVzdFVybCAgICAgPSBu
dWxsOwogICAgcHJpdmF0ZSBib29sZWFuICAgICBtYWtlcGFyZW50cyA9IGZhbHNlOwogICAgcHJp
dmF0ZSBib29sZWFuIAlmb3JjZQk9CWZhbHNlOwoKICAgIC8qKiByZXZpc2lvbiB0byBjb3B5IGZy
b20gKGhlYWQgYnkgZGVmYXVsdCkgKi8KICAgIHByaXZhdGUgU1ZOUmV2aXNpb24gcmV2aXNpb24g
ICAgPSBTVk5SZXZpc2lvbi5IRUFEOwoKICAgIC8qKiBtZXNzYWdlIGZvciBjb21taXQgKG9ubHkg
d2hlbiB0YXJnZXQgaXMgYW4gdXJsKSAqLwogICAgcHJpdmF0ZSBTdHJpbmcgICAgICBtZXNzYWdl
ICAgICA9IG51bGw7CgogICAgLyoqCiAgICAgKiB7QGluaGVyaXREb2N9CiAgICAgKi8KICAgIHB1
YmxpYyB2b2lkIGV4ZWN1dGUoKSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgICAgaWYoIHNyY1Bh
dGggIT0gbnVsbCApIHsKICAgICAgICAgICAgCQogICAgICAgICAgICAgICAgaWYoIGRlc3RQYXRo
ICE9IG51bGwgKSB7CiAgICAgICAgICAgICAgICAgICAgZ2V0Q2xpZW50KCkuY29weSggc3JjUGF0
aCwgZGVzdFBhdGgpOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAg
ICBnZXRDbGllbnQoKS5jb3B5KCBzcmNQYXRoLCBkZXN0VXJsLCBtZXNzYWdlICk7CiAgICAgICAg
ICAgICAgICB9CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAg
ICAgICAgIGlmKCBkZXN0UGF0aCAhPSBudWxsICkgewogICAgICAgICAgICAgICAgICAgIGdldENs
aWVudCgpLmNvcHkoIHNyY1VybCwgZGVzdFBhdGgsIHJldmlzaW9uKTsKICAgICAgICAgICAgICAg
IH0gZWxzZSB7CiAgICAgICAgICAgICAgICAJaWYgKGZvcmNlKQogICAgICAgICAgICAgICAgCXsK
ICAgICAgICAgICAgICAgIAkJLy8gSW5jbHVkZSBmb3JjZSBjb21tYW5kIHRvIGF2b2lkIEFub255
bW91cyBlcnJvciBkdXJpbmcgZmlsZSBjb3B5IHVybDEgdG8gdXJsMi4KICAgICAgICAgICAgICAg
IAkJZ2V0Q2xpZW50KCkuY29weSggc3JjVXJsLCBkZXN0VXJsLCBtZXNzYWdlLCByZXZpc2lvbiwg
bWFrZXBhcmVudHMsIGZvcmNlKTsKICAgICAgICAgICAgICAgIAl9ZWxzZQogICAgICAgICAgICAg
ICAgCXsKICAgICAgICAgICAgICAgIAkgICAgZ2V0Q2xpZW50KCkuY29weSggc3JjVXJsLCBkZXN0
VXJsLCBtZXNzYWdlLCByZXZpc2lvbiwgbWFrZXBhcmVudHMpOwogICAgICAgICAgICAgICAgCX0K
ICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0gY2F0Y2goIFNWTkNsaWVu
dEV4Y2VwdGlvbiBleCApIHsKICAgICAgICAgICAgdGhyb3cgZXgoIGV4LCBNU0dfQ0FOVF9DT1BZ
ICk7CiAgICAgICAgfQogICAgfQoKICAgIC8qKgogICAgICoge0Bpbmhlcml0RG9jfQogICAgICov
CiAgICBwcm90ZWN0ZWQgdm9pZCB2YWxpZGF0ZUF0dHJpYnV0ZXMoKSB7CiAgICAgICAgU3ZuQW50
VXRpbGl0aWVzLmF0dHJzTm90U2V0KCAic3JjUGF0aCwgc3JjVXJsIiwgdHJ1ZSwgc3JjUGF0aCwg
c3JjVXJsICk7CiAgICAgICAgU3ZuQW50VXRpbGl0aWVzLmF0dHJzTm90U2V0KCAiZGVzdFBhdGgs
IGRlc3RVcmwiLCB0cnVlLCBkZXN0UGF0aCwgZGVzdFVybCApOwogICAgICAgIFN2bkFudFV0aWxp
dGllcy5hdHRyTm90TnVsbCggInJldmlzaW9uIiwgcmV2aXNpb24gKTsKICAgICAgICBpZiggZGVz
dFVybCAhPSBudWxsICkgewogICAgICAgICAgICBTdm5BbnRVdGlsaXRpZXMuYXR0ck5vdEVtcHR5
KCAibWVzc2FnZSIsIG1lc3NhZ2UgKTsKICAgICAgICB9CiAgICB9CgogICAgLyoqCiAgICAgKiBz
ZXQgdGhlIHBhdGggdG8gY29weSBmcm9tCiAgICAgKiBAcGFyYW0gc3JjUGF0aAogICAgICovCiAg
ICBwdWJsaWMgdm9pZCBzZXRTcmNQYXRoKCBGaWxlIHNyY1BhdGggKSB7CiAgICAgICAgdGhpcy5z
cmNQYXRoID0gc3JjUGF0aDsKICAgIH0KCiAgICAvKioKICAgICAqIHNldCB0aGUgcGF0aCB0byBj
b3B5IHRvCiAgICAgKiBAcGFyYW0gZGVzdFBhdGgKICAgICAqLwogICAgcHVibGljIHZvaWQgc2V0
RGVzdFBhdGgoIEZpbGUgZGVzdFBhdGggKSB7CiAgICAgICAgdGhpcy5kZXN0UGF0aCA9IGRlc3RQ
YXRoOwogICAgfQoKICAgIC8qKgogICAgICogc2V0IHRoZSB1cmwgdG8gY29weSBmcm9tCiAgICAg
KiBAcGFyYW0gc3JjVXJsCiAgICAgKi8KICAgIHB1YmxpYyB2b2lkIHNldFNyY1VybCggU1ZOVXJs
IHNyY1VybCApIHsKICAgICAgICB0aGlzLnNyY1VybCA9IHNyY1VybDsKICAgIH0KCiAgICAvKioK
ICAgICAqIHNldCB0aGUgdXJsIHRvIGNvcHkgdG8KICAgICAqIEBwYXJhbSBkZXN0VXJsCiAgICAg
Ki8KICAgIHB1YmxpYyB2b2lkIHNldERlc3RVcmwoIFNWTlVybCBkZXN0VXJsICkgewogICAgICAg
IHRoaXMuZGVzdFVybCA9IGRlc3RVcmw7CiAgICB9CgogICAgLyoqCiAgICAgKiBzZXQgdGhlIG1l
c3NhZ2UgZm9yIHRoZSBjb21taXQgKG9ubHkgd2hlbiBjb3B5aW5nIGRpcmVjdGx5IHRvIHJlcG9z
aXRvcnkgdXNpbmcgYW4gdXJsKQogICAgICogCiAgICAgKiBAcGFyYW0gbWVzc2FnZQogICAgICov
CiAgICBwdWJsaWMgdm9pZCBzZXRNZXNzYWdlKCBTdHJpbmcgbWVzc2FnZSApIHsKICAgICAgICB0
aGlzLm1lc3NhZ2UgPSBtZXNzYWdlOwogICAgfQoKICAgIC8qKgogICAgICogU2V0cyB0aGUgcmV2
aXNpb24KICAgICAqIAogICAgICogQHBhcmFtIHJldmlzaW9uCiAgICAgKi8KICAgIHB1YmxpYyB2
b2lkIHNldFJldmlzaW9uKCBTdHJpbmcgcmV2aXNpb24gKSB7CiAgICAgICAgdGhpcy5yZXZpc2lv
biA9IGdldFJldmlzaW9uRnJvbSggcmV2aXNpb24gKTsKICAgIH0KCiAgICAvKioKICAgICAqIEZv
cmNlcyB0aGUgY3JlYXRpb24gb2YgdGhlIHBhcmVudHMgZmlyc3QgaWYgYSBjb3B5IGhhcyB0byBi
ZSBkb25lIGZyb20gYSA8Y29kZT5zcmNVcmw8L2NvZGU+CiAgICAgKiB0byBhIDxjb2RlPmRlc3RV
cmw8L2NvZGU+LgogICAgICogCiAgICAgKiBAcGFyYW0gbmV3bWFrZXBhcmVudHMgICA8Y29kZT50
cnVlPC9jb2RlPiA8PT4gQ3JlYXRlIHBhcmVudHMgZmlyc3QuCiAgICAgKi8KICAgIHB1YmxpYyB2
b2lkIHNldE1ha2VQYXJlbnRzKCBib29sZWFuIG5ld21ha2VwYXJlbnRzICkgewogICAgICAgIHRo
aXMubWFrZXBhcmVudHMgPSBuZXdtYWtlcGFyZW50czsKICAgIH0KICAgIC8qKgogICAgICogQHBh
cmFtIGZvcmNlIHRoZSBmb3JjZSB0byBzZXQKICAgICAqLwogICAgcHVibGljIHZvaWQgc2V0Rm9y
Y2UoIGJvb2xlYW4gZm9yY2UgKSB7CiAgICAgICAgdGhpcy5mb3JjZSA9IGZvcmNlOwogICAgfQoK
fQo=
encoding=base64
ISVNClientAdapter.java - New Abstartct method is created fopr Copy with Force option.
Posted 2013-03-26 00:23:03 by sendhilsubramani
/*******************************************************************************
* Copyright (c) 2003, 2006 svnClientAdapter project and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* svnClientAdapter project committers - initial API and implementation
******************************************************************************/
package org.tigris.subversion.svnclientadapter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* High level API for Subversion
*
*/
public interface ISVNClientAdapter {
/** constant identifying the "bdb" repository type */
public final static String REPOSITORY_FSTYPE_BDB = "bdb";
/** constant identifying the "fsfs" repository type */
public final static String REPOSITORY_FSTYPE_FSFS = "fsfs";
public final static String[] DEFAULT_LOG_PROPERTIES = new String[] {"svn:author", "svn:date", "svn:log"};
/**
* Returns whether the client adapter implementation is threadsafe
*/
public abstract boolean isThreadsafe();
/**
* Add a notification listener
* @param listener
*/
public abstract void addNotifyListener(ISVNNotifyListener listener);
/**
* Remove a notification listener
* @param listener
*/
public abstract void removeNotifyListener(ISVNNotifyListener listener);
/**
* @return the notification handler
*/
public abstract SVNNotificationHandler getNotificationHandler();
/**
* Sets the username.
* @param username
*/
public abstract void setUsername(String username);
/**
* Sets the password.
* @param password
*/
public abstract void setPassword(String password);
/**
* Add a callback for prompting for username, password SSL etc...
* @param callback
*/
public abstract void addPasswordCallback(ISVNPromptUserPassword callback);
/**
* Add a callback for resolving conflicts during up/sw/merge
* @param callback
*/
public abstract void addConflictResolutionCallback(ISVNConflictResolver callback);
/**
* Set a progress listener
* @param progressListener
*/
public abstract void setProgressListener(ISVNProgressListener progressListener);
/**
* Adds a file (or directory) to the repository.
* @param file
* @throws SVNClientException
*/
public abstract void addFile(File file) throws SVNClientException;
/**
* Adds a directory to the repository.
* @param dir
* @param recurse
* @throws SVNClientException
*/
public abstract void addDirectory(File dir, boolean recurse)
throws SVNClientException;
/**
* Adds a directory to the repository.
* @param dir
* @param recurse
* @param force
* @throws SVNClientException
*/
public abstract void addDirectory(File dir, boolean recurse, boolean force)
throws SVNClientException;
/**
* Executes a revision checkout.
* @param moduleName name of the module to checkout.
* @param destPath destination directory for checkout.
* @param revision the revision number to checkout. If the number is -1
* then it will checkout the latest revision.
* @param recurse whether you want it to checkout files recursively.
* @exception SVNClientException
*/
public abstract void checkout(
SVNUrl moduleName,
File destPath,
SVNRevision revision,
boolean recurse)
throws SVNClientException;
/**
* Executes a revision checkout.
* @param moduleName name of the module to checkout.
* @param destPath destination directory for checkout.
* @param revision the revision number to checkout. If the number is -1
* then it will checkout the latest revision.
* @param depth how deep to checkout files recursively.
* @param ignoreExternals if externals are ignored during checkout.
* @param force allow unversioned paths that obstruct adds.
* @exception SVNClientException
*/
public abstract void checkout(
SVNUrl moduleName,
File destPath,
SVNRevision revision,
int depth,
boolean ignoreExternals,
boolean force)
throws SVNClientException;
/**
* Commits changes to the repository. This usually requires
* authentication, see Auth.
* @return Returns a long representing the revision. It returns a
* -1 if the revision number is invalid.
* @param paths files to commit.
* @param message log message.
* @param recurse whether the operation should be done recursively.
* @exception SVNClientException
*/
public abstract long commit(File[] paths, String message, boolean recurse)
throws SVNClientException;
/**
* Commits changes to the repository. This usually requires
* authentication, see Auth.
* @return Returns a long representing the revision. It returns a
* -1 if the revision number is invalid.
* @param paths files to commit.
* @param message log message.
* @param recurse whether the operation should be done recursively.
* @param keepLocks
* @exception SVNClientException
*/
public abstract long commit(File[] paths, String message, boolean recurse, boolean keepLocks)
throws SVNClientException;
/**
* Commits changes to the repository. This usually requires
* authentication, see Auth.
*
* This differs from the normal commit method in that it can accept paths from
* more than one working copy.
*
* @return Returns an array of longs representing the revisions. It returns a
* -1 if the revision number is invalid.
* @param paths files to commit.
* @param message log message.
* @param recurse whether the operation should be done recursively.
* @param keepLocks whether to keep locks on files that are committed.
* @param atomic whether to attempt to perform the commit from multiple
* working copies atomically. Files from the same repository will be
* processed with one commit operation. If files span multiple repositories
* they will be processed in multiple commits.
* When atomic is false, you will get one commit per WC.
* @exception SVNClientException
*/
public abstract long[] commitAcrossWC(File[] paths, String message, boolean recurse, boolean keepLocks, boolean atomic)
throws SVNClientException;
public String getPostCommitError();
/**
* List directory entries of a URL
* @param url
* @param revision
* @param recurse
* @return an array of ISVNDirEntries
* @throws SVNClientException
*/
public abstract ISVNDirEntry[] getList(
SVNUrl url,
SVNRevision revision,
boolean recurse)
throws SVNClientException;
/**
* List directory entries of a URL
* @param url
* @param revision
* @param pegRevision
* @param recurse
* @return an array of ISVNDirEntries
* @throws SVNClientException
*/
public abstract ISVNDirEntry[] getList(
SVNUrl url,
SVNRevision revision,
SVNRevision pegRevision,
boolean recurse)
throws SVNClientException;
/**
* List directory entries of a URL with lock information
* @param url
* @param revision
* @param pegRevision
* @param recurse
* @return an array of ISVNDirEntries
* @throws SVNClientException
*/
public abstract ISVNDirEntryWithLock[] getListWithLocks(
SVNUrl url,
SVNRevision revision,
SVNRevision pegRevision,
boolean recurse)
throws SVNClientException;
/**
* List directory entries of a directory
* @param path
* @param revision
* @param recurse
* @return an array of ISVNDirEntries
* @throws SVNClientException
*/
public ISVNDirEntry[] getList(File path, SVNRevision revision, boolean recurse)
throws SVNClientException;
/**
* List directory entries of a directory
* @param path
* @param revision
* @param pegRevision
* @param recurse
* @return an array of ISVNDirEntries
* @throws SVNClientException
*/
public ISVNDirEntry[] getList(File path, SVNRevision revision, SVNRevision pegRevision, boolean recurse)
throws SVNClientException;
/**
* get the dirEntry for the given url
* @param url
* @param revision
* @return an ISVNDirEntry
* @throws SVNClientException
*/
public ISVNDirEntry getDirEntry(SVNUrl url, SVNRevision revision)
throws SVNClientException;
/**
* get the dirEntry for the given directory
* @param path
* @param revision
* @return an ISVNDirEntry
* @throws SVNClientException
*/
public ISVNDirEntry getDirEntry(File path, SVNRevision revision)
throws SVNClientException;
/**
* Returns the status of a single file in the path.
*
* @param path File to gather status.
* @return a Status
* @throws SVNClientException
*/
public abstract ISVNStatus getSingleStatus(File path)
throws SVNClientException;
/**
* Returns the status of given resources
* @param path
* @return the status of given resources
* @throws SVNClientException
*/
public abstract ISVNStatus[] getStatus(File[] path)
throws SVNClientException;
/**
* Returns the status of path and its children.
* If descend is true, recurse fully, else do only immediate children.
* If getAll is set, retrieve all entries; otherwise, retrieve only
* "interesting" entries (local mods and/or out-of-date).
*
* @param path File to gather status.
* @param descend get recursive status information
* @param getAll get status information for all files
* @return a Status
* @throws SVNClientException
*/
public abstract ISVNStatus[] getStatus(File path, boolean descend, boolean getAll)
throws SVNClientException;
/**
* Returns the status of path and its children.
* If descend is true, recurse fully, else do only immediate children.
* If getAll is set, retrieve all entries; otherwise, retrieve only
* "interesting" entries (local mods and/or out-of-date). Use the
* contactServer option to get server change information.
*
* @param path File to gather status.
* @param descend get recursive status information
* @param getAll get status information for all files
* @param contactServer contact server to get remote changes
* @return a Status
* @throws SVNClientException
*/
public abstract ISVNStatus[] getStatus(File path, boolean descend, boolean getAll, boolean contactServer)
throws SVNClientException;
/**
* Returns the status of path and its children.
* If descend is true, recurse fully, else do only immediate children.
* If getAll is set, retrieve all entries; otherwise, retrieve only
* "interesting" entries (local mods and/or out-of-date). Use the
* contactServer option to get server change information.
*
* @param path File to gather status.
* @param descend get recursive status information
* @param getAll get status information for all files
* @param contactServer contact server to get remote changes
* @param ignoreExternals if externals are ignored during status
* @return a Status
* @throws SVNClientException
*/
public abstract ISVNStatus[] getStatus(File path, boolean descend, boolean getAll, boolean contactServer, boolean ignoreExternals)
throws SVNClientException;
/**
* Returns the status of path and its children.
* If descend is true, recurse fully, else do only immediate children.
* If getAll is set, retrieve all entries; otherwise, retrieve only
* "interesting" entries (local mods and/or out-of-date). Use the
* contactServer option to get server change information.
*
* @param path File to gather status.
* @param descend get recursive status information
* @param getAll get status information for all files
* @param contactServer contact server to get remote changes
* @param ignoreExternals if externals are ignored during status
* @param callback callback to collect statuses
* @return a Status
* @throws SVNClientException
*/
public abstract ISVNStatus[] getStatus(File path, boolean descend, boolean getAll, boolean contactServer, boolean ignoreExternals, ISVNStatusCallback callback)
throws SVNClientException;
/**
* copy and schedule for addition (with history)
* @param srcPath
* @param destPath
* @throws SVNClientException
*/
public abstract void copy(File srcPath, File destPath)
throws SVNClientException;
/**
* immediately commit a copy of WC to URL
* @param srcPath
* @param destUrl
* @param message
* @throws SVNClientException
*/
public abstract void copy(File srcPath, SVNUrl destUrl, String message)
throws SVNClientException;
/**
* immediately commit a copy of WC to URL
* @param srcPaths
* @param destUrl
* @param message
* @param copyAsChild
* @param makeParents
* @throws SVNClientException
*/
public abstract void copy(File[] srcPaths, SVNUrl destUrl, String message, boolean copyAsChild, boolean makeParents)
throws SVNClientException;
/**
* check out URL into WC, schedule for addition
* @param srcUrl
* @param destPath
* @param revision
* @throws SVNClientException
*/
public abstract void copy(SVNUrl srcUrl, File destPath, SVNRevision revision)
throws SVNClientException;
/**
* check out URL into WC, schedule for addition
* @param srcUrl
* @param destPath
* @param revision
* @param boolean
* @param boolean
* @throws SVNClientException
*/
public abstract void copy(SVNUrl srcUrl, File destPath, SVNRevision revision, boolean copyAsChild, boolean makeParents)
throws SVNClientException;
/**
* check out URL into WC, schedule for addition
* @param srcUrl
* @param destPath
* @param revision
* @param pegRevision
* @param boolean
* @param boolean
* @throws SVNClientException
*/
public abstract void copy(SVNUrl srcUrl, File destPath, SVNRevision revision, SVNRevision pegRevision, boolean copyAsChild, boolean makeParents)
throws SVNClientException;
/**
* complete server-side copy; used to branch & tag
* @param srcUrl
* @param destUrl
* @param message
* @param revision
* @throws SVNClientException
*/
public abstract void copy(
SVNUrl srcUrl,
SVNUrl destUrl,
String message,
SVNRevision revision)
throws SVNClientException;
/**
* complete server-side copy with option to create intermediate folders; used to branch & tag
* @param srcUrl
* @param destUrl
* @param message
* @param revision
* @param make parents
* @throws SVNClientException
*/
public abstract void copy(
SVNUrl srcUrl,
SVNUrl destUrl,
String message,
SVNRevision revision,
boolean makeParents)
throws SVNClientException;
/**
* complete server-side copy with option to create intermediate folders; used to branch & tag
* @param srcUrl
* @param destUrl
* @param message
* @param revision
* @param copyAsChild
* @param make parents
* @throws SVNClientException
*/
public abstract void copy(
SVNUrl[] srcUrls,
SVNUrl destUrl,
String message,
SVNRevision revision,
boolean copyAsChild,
boolean makeParents)
throws SVNClientException;
/**
* complete server-side copy with option to create intermediate folders; used to branch & tag
* @param srcUrl
* @param destUrl
* @param message
* @param revision
* @param copyAsChild
* @param make parents
* @param force
* @throws SVNClientException
*/
public abstract void copy(
SVNUrl srcUrl,
SVNUrl destUrl,
String message,
SVNRevision revision,
boolean makeParents,
boolean force)
throws SVNClientException;
/**
* item is deleted from the repository via an immediate commit.
* @param url
* @param message
* @throws SVNClientException
*/
public abstract void remove(SVNUrl url[], String message)
throws SVNClientException;
/**
* the item is scheduled for deletion upon the next commit.
* Files, and directories that have not been committed, are immediately
* removed from the working copy. The command will not remove TARGETs
* that are, or contain, unversioned or modified items;
* use the force option to override this behaviour.
* @param file
* @param force
* @throws SVNClientException
*/
public abstract void remove(File file[], boolean force)
throws SVNClientException;
/**
* Exports a clean directory tree from the repository specified by
* srcUrl, at revision revision
* @param srcUrl
* @param destPath
* @param revision
* @param force
* @throws SVNClientException
*/
public abstract void doExport(
SVNUrl srcUrl,
File destPath,
SVNRevision revision,
boolean force)
throws SVNClientException;
/**
* Exports a clean directory tree from the working copy specified by
* PATH1 into PATH2. all local changes will be preserved, but files
* not under revision control will not be copied.
* @param srcPath
* @param destPath
* @param force
* @throws SVNClientException
*/
public abstract void doExport(File srcPath, File destPath, boolean force)
throws SVNClientException;
/**
* Import file or directory PATH into repository directory URL at head
* @param path
* @param url
* @param message
* @param recurse
* @throws SVNClientException
*/
public abstract void doImport(
File path,
SVNUrl url,
String message,
boolean recurse)
throws SVNClientException;
/**
* Creates a directory directly in a repository
* @param url
* @param message
* @throws SVNClientException
*/
public abstract void mkdir(SVNUrl url, String message)
throws SVNClientException;
/**
* Creates a directory directly in a repository
* @param url
* @param makeParents
* @param message
* @throws SVNClientException
*/
public abstract void mkdir(SVNUrl url, boolean makeParents, String message)
throws SVNClientException;
/**
* creates a directory on disk and schedules it for addition.
* @param file
* @throws SVNClientException
*/
public abstract void mkdir(File file) throws SVNClientException;
/**
* Moves or renames a file.
* @param srcPath
* @param destPath
* @param force
* @throws SVNClientException
*/
public abstract void move(File srcPath, File destPath, boolean force)
throws SVNClientException;
/**
* Moves or renames a file.
* @param srcUrl
* @param destUrl
* @param message
* @param revision
* @throws SVNClientException
*/
public abstract void move(
SVNUrl srcUrl,
SVNUrl destUrl,
String message,
SVNRevision revision)
throws SVNClientException;
/**
* Update a file or a directory
* @param path
* @param revision
* @param recurse
* @return Returns a long representing the revision. It returns a
* -1 if the revision number is invalid.
* @throws SVNClientException
*/
public abstract long update(File path, SVNRevision revision, boolean recurse)
throws SVNClientException;
/**
* Update a file or a directory
* @param path
* @param revision
* @param depth
* @param setDepth
* @param ignoreExternals
* @param force
* @return Returns a long representing the revision. It returns a
* -1 if the revision number is invalid.
* @throws SVNClientException
*/
public abstract long update(File path, SVNRevision revision, int depth, boolean setDepth, boolean ignoreExternals, boolean force)
throws SVNClientException;
/**
* Updates the directories or files from repository
* @param path array of target files.
* @param revision the revision number to update.
* @param recurse recursively update.
* @param ignoreExternals if externals are ignored during update
* @return Returns an array of longs representing the revision. It returns a
* -1 if the revision number is invalid.
* @throws SVNClientException
* @since 1.2
*/
public abstract long[] update(
File[] path,
SVNRevision revision,
boolean recurse,
boolean ignoreExternals)
throws SVNClientException;
/**
* Updates the directories or files from repository
* @param path array of target files.
* @param revision the revision number to update.
* @param depth the depth to recursively update.
* @param setDepth change working copy to specified depth
* @param ignoreExternals if externals are ignored during update.
* @param force allow unversioned paths that obstruct adds.
* @return Returns an array of longs representing the revision. It returns a
* -1 if the revision number is invalid.
* @throws SVNClientException
*/
public abstract long[] update(
File[] path,
SVNRevision revision,
int depth,
boolean setDepth,
boolean ignoreExternals,
boolean force)
throws SVNClientException;
/**
* Restore pristine working copy file (undo all local edits)
* @param path
* @param recurse
* @throws SVNClientException
*/
public abstract void revert(File path, boolean recurse)
throws SVNClientException;
/**
* Get the log messages for a set of revision(s)
* @param url
* @param revisionStart
* @param revisionEnd
* @return The list of log messages.
* @throws SVNClientException
*/
public abstract ISVNLogMessage[] getLogMessages(
SVNUrl url,
SVNRevision revisionStart,
SVNRevision revisionEnd)
throws SVNClientException;
/**
* Get the log messages for a set of revision(s)
* @param url
* @param revisionStart
* @param revisionEnd
* @param fetchChangePath Whether or not to interogate the
* repository for the verbose log information containing the list
* of paths touched by the delta specified by
* <code>revisionStart</code> and <code>revisionEnd</code>.
* Setting this to <code>false</code> results in a more performant
* and memory efficient operation.
* @return The list of log messages.
* @throws SVNClientException
*/
public abstract ISVNLogMessage[] getLogMessages(
SVNUrl url,
SVNRevision revisionStart,
SVNRevision revisionEnd,
boolean fetchChangePath)
throws SVNClientException;
/**
* Get the log messages for a set paths and revision(s)
* @param url
* @param paths
* @param revStart
* @param revEnd
* @param stopOnCopy
* @param fetchChangePath
* @return The list of log messages.
* @throws SVNClientException
*/
public ISVNLogMessage[] getLogMessages(final SVNUrl url, final String [] paths,
SVNRevision revStart, SVNRevision revEnd,
boolean stopOnCopy, boolean fetchChangePath)
throws SVNClientException;
/**
* Get the log messages for a set of revision(s)
* @param path
* @param revisionStart
* @param revisionEnd
* @return The list of log messages.
* @throws SVNClientException
*/
public abstract ISVNLogMessage[] getLogMessages(
File path,
SVNRevision revisionStart,
SVNRevision revisionEnd)
throws SVNClientException;
/**
* Get the log messages for a set of revision(s)
* @param path
* @param revisionStart
* @param revisionEnd
* @param fetchChangePath Whether or not to interogate the
* repository for the verbose log information containing the list
* of paths touched by the delta specified by
* <code>revisionStart</code> and <code>revisionEnd</code>.
* Setting this to <code>false</code> results in a more performant
* and memory efficient operation.
* @return The list of log messages.
* @throws SVNClientException
*/
public abstract ISVNLogMessage[] getLogMessages(
File path,
SVNRevision revisionStart,
SVNRevision revisionEnd,
boolean fetchChangePath)
throws SVNClientException;
/**
* Retrieve the log messages for an item
* @param path path or url to get the log message for.
* @param revisionStart first revision to show
* @param revisionEnd last revision to show
* @param stopOnCopy do not continue on copy operations
* @param fetchChangePath returns the paths of the changed items in the
* returned objects
* @return array of LogMessages
* @throws SVNClientException
*/
public abstract ISVNLogMessage[] getLogMessages(
File path,
SVNRevision revisionStart,
SVNRevision revisionEnd,
boolean stopOnCopy,
boolean fetchChangePath)
throws SVNClientException;
/**
* Retrieve the log messages for an item
* @param path path to get the log message for.
* @param revisionStart first revision to show
* @param revisionEnd last revision to show
* @param stopOnCopy do not continue on copy operations
* @param fetchChangePath returns the paths of the changed items in the
* returned objects
* @param limit limit the number of log messages (if 0 or less no
* limit)
* @return array of LogMessages
* @throws SVNClientException
*/
public abstract ISVNLogMessage[] getLogMessages(
File path,
SVNRevision revisionStart,
SVNRevision revisionEnd,
boolean stopOnCopy,
boolean fetchChangePath,
long limit)
throws SVNClientException;
/**
* Retrieve the log messages for an item
* @param path path to get the log message for.
* @param pegRevision peg revision for URL
* @param revisionStart first revision to show
* @param revisionEnd last revision to show
* @param stopOnCopy do not continue on copy operations
* @param fetchChangePath returns the paths of the changed items in the
* returned objects
* @param limit limit the number of log messages (if 0 or less no
* limit)
* @param includeMergedRevisions include revisions that were merged
* @return array of LogMessages
* @throws SVNClientException
*/
public abstract ISVNLogMessage[] getLogMessages(
File path,
SVNRevision pegRevision,
SVNRevision revisionStart,
SVNRevision revisionEnd,
boolean stopOnCopy,
boolean fetchChangePath,
long limit,
boolean includeMergedRevisions)
throws SVNClientException;
/**
* Retrieve the log messages for an item
* @param url url to get the log message for.
* @param pegRevision peg revision for URL
* @param revisionStart first revision to show
* @param revisionEnd last revision to show
* @param stopOnCopy do not continue on copy operations
* @param fetchChangePath returns the paths of the changed items in the
* returned objects
* @param limit limit the number of log messages (if 0 or less no
* limit)
* @return array of LogMessages
* @throws SVNClientException
*/
public abstract ISVNLogMessage[] getLogMessages(
SVNUrl url,
SVNRevision pegRevision,
SVNRevision revisionStart,
SVNRevision revisionEnd,
boolean stopOnCopy,
boolean fetchChangePath,
long limit)
throws SVNClientException;
/**
* Retrieve the log messages for an item
* @param url url to get the log message for.
* @param pegRevision peg revision for URL
* @param revisionStart first revision to show
* @param revisionEnd last revision to show
* @param stopOnCopy do not continue on copy operations
* @param fetchChangePath returns the paths of the changed items in the
* returned objects
* @param limit limit the number of log messages (if 0 or less no
* limit)
* @param includeMergedRevisions include revisions that were merged
* @return array of LogMessages
* @throws SVNClientException
*/
public abstract ISVNLogMessage[] getLogMessages(
SVNUrl url,
SVNRevision pegRevision,
SVNRevision revisionStart,
SVNRevision revisionEnd,
boolean stopOnCopy,
boolean fetchChangePath,
long limit,
boolean includeMergedRevisions)
throws SVNClientException;
/**
* Retrieve the log messages for an item
* @param path path to get the log message for.
* @param pegRevision peg revision for URL
* @param revisionStart first revision to show
* @param revisionEnd last revision to show
* @param stopOnCopy do not continue on copy operations
* @param fetchChangePath returns the paths of the changed items in the
* returned objects
* @param limit limit the number of log messages (if 0 or less no
* limit)
* @param includeMergedRevisions include revisions that were merged
* @param requestedProperties the revision properties to return for each entry
* @param callback callback class to receive log messages
* @throws SVNClientException
*/
public abstract void getLogMessages(
File path,
SVNRevision pegRevision,
SVNRevision revisionStart,
SVNRevision revisionEnd,
boolean stopOnCopy,
boolean fetchChangePath,
long limit,
boolean includeMergedRevisions,
String[] requestedProperties,
ISVNLogMessageCallback callback)
throws SVNClientException;
/**
* Retrieve the log messages for an item
* @param url url to get the log message for.
* @param pegRevision peg revision for URL
* @param revisionStart first revision to show
* @param revisionEnd last revision to show
* @param stopOnCopy do not continue on copy operations
* @param fetchChangePath returns the paths of the changed items in the
* returned objects
* @param limit limit the number of log messages (if 0 or less no
* limit)
* @param includeMergedRevisions include revisions that were merged
* @param requestedProperties the revision properties to return for each entry
* @param callback callback class to receive log messages
* @throws SVNClientException
*/
public abstract void getLogMessages(
SVNUrl url,
SVNRevision pegRevision,
SVNRevision revisionStart,
SVNRevision revisionEnd,
boolean stopOnCopy,
boolean fetchChangePath,
long limit,
boolean includeMergedRevisions,
String[] requestedProperties,
ISVNLogMessageCallback callback)
throws SVNClientException;
/**
* get the content of a file
* @param url
* @param revision
* @param peg revision
* @return the input stream with a content of the file
* @throws SVNClientException
*/
public abstract InputStream getContent(SVNUrl url, SVNRevision revision, SVNRevision pegRevision)
throws SVNClientException;
/**
* get the content of a file
* @param url
* @param revision
* @return the input stream with a content of the file
* @throws SVNClientException
*/
public abstract InputStream getContent(SVNUrl url, SVNRevision revision)
throws SVNClientException;
/**
* get the content of a file
* @param path
* @param revision
* @return the input stream with a content of the file
* @throws SVNClientException
*/
public InputStream getContent(File path, SVNRevision revision)
throws SVNClientException;
/**
* set a property
* @param path
* @param propertyName
* @param propertyValue
* @param recurse
* @throws SVNClientException
*/
public abstract void propertySet(
File path,
String propertyName,
String propertyValue,
boolean recurse)
throws SVNClientException;
/**
* set a property
* @param url
* @param baseRev
* @param propertyName
* @param propertyValue
* @param recurse
* @throws SVNClientException
*/
public abstract void propertySet(
SVNUrl url,
SVNRevision.Number baseRev,
String propertyName,
String propertyValue,
String message)
throws SVNClientException;
/**
* set a property using the content of a file
* @param path
* @param propertyName
* @param propertyFile
* @param recurse
* @throws SVNClientException
* @throws IOException
*/
public abstract void propertySet(
File path,
String propertyName,
File propertyFile,
boolean recurse)
throws SVNClientException, IOException;
/**
* get a property or null if property is not found
* @param path
* @param propertyName
* @return a property or null
* @throws SVNClientException
*/
public abstract ISVNProperty propertyGet(File path, String propertyName)
throws SVNClientException;
/**
* get a property or null if property is not found
* @param url
* @param propertyName
* @return a property or null
* @throws SVNClientException
*/
public abstract ISVNProperty propertyGet(SVNUrl url, String propertyName)
throws SVNClientException;
/**
* get a property or null if property is not found
* @param url
* @param revision
* @param peg
* @param propertyName
* @return a property or null
* @throws SVNClientException
*/
public abstract ISVNProperty propertyGet(SVNUrl url, SVNRevision revision,
SVNRevision peg, String propertyName)
throws SVNClientException;
/**
* delete a property
* @param path
* @param propertyName
* @param recurse
* @throws SVNClientException
*/
public abstract void propertyDel(
File path,
String propertyName,
boolean recurse)
throws SVNClientException;
/**
* set the revision property for a given revision
* @param path
* @param revisionNo
* @param propName
* @param propertyData
* @param force
* @throws SVNClientException
*/
public abstract void setRevProperty(SVNUrl path,
SVNRevision.Number revisionNo, String propName,
String propertyData, boolean force) throws SVNClientException;
/**
* get a revision property for a given revision
* @param path
* @param revisionNo
* @param propName
* @throws SVNClientException
*/
public abstract String getRevProperty(SVNUrl path,
SVNRevision.Number revisionNo, String propName)
throws SVNClientException;
/**
* get the ignored patterns for the given directory
* if path is not a directory, returns null
* @param path
* @return list of ignored patterns
* @throws SVNClientException
*/
public abstract List getIgnoredPatterns(File path)
throws SVNClientException;
/**
* add a pattern to svn:ignore property
* @param path
* @param pattern
* @throws SVNClientException
*/
public abstract void addToIgnoredPatterns(File path, String pattern)
throws SVNClientException;
/**
* set the ignored patterns for the given directory
* @param path
* @param patterns
* @throws SVNClientException
*/
public abstract void setIgnoredPatterns(File path, List patterns)
throws SVNClientException;
/**
* display the differences between two paths.
* @param oldPath
* @param oldPathRevision
* @param newPath
* @param newPathRevision
* @param outFile
* @param recurse
* @throws SVNClientException
*/
public abstract void diff(
File oldPath,
SVNRevision oldPathRevision,
File newPath,
SVNRevision newPathRevision,
File outFile,
boolean recurse)
throws SVNClientException;
/**
* display the differences between two paths.
* @param oldPath
* @param oldPathRevision
* @param newPath
* @param newPathRevision
* @param outFile
* @param recurse
* @param ignoreAncestry
* @param noDiffDeleted
* @param force
* @throws SVNClientException
*/
public abstract void diff(
File oldPath,
SVNRevision oldPathRevision,
File newPath,
SVNRevision newPathRevision,
File outFile,
boolean recurse,
boolean ignoreAncestry,
boolean noDiffDeleted,
boolean force)
throws SVNClientException;
/**
* display the differences between two paths.
* @param path
* @param outFile
* @param recurse
* @throws SVNClientException
*/
public abstract void diff(
File path,
File outFile,
boolean recurse)
throws SVNClientException;
/**
* display the combined differences for an array of paths.
* @param paths
* @param outFile
* @param recurse
* @throws SVNClientException
*/
public abstract void diff(
File[] paths,
File outFile,
boolean recurse)
throws SVNClientException;
/**
* create a patch from local differences.
* @param paths
* @param relativeToPath - create patch relative to this location
* @param outFile
* @param recurse
* @throws SVNClientException
*/
public abstract void createPatch(
File[] paths,
File relativeToPath,
File outFile,
boolean recurse)
throws SVNClientException;
/**
* display the differences between two urls.
* @param oldUrl
* @param oldUrlRevision
* @param newUrl
* @param newUrlRevision
* @param outFile
* @param recurse
* @throws SVNClientException
*/
public abstract void diff(
SVNUrl oldUrl,
SVNRevision oldUrlRevision,
SVNUrl newUrl,
SVNRevision newUrlRevision,
File outFile,
boolean recurse)
throws SVNClientException;
/**
* display the differences between two urls.
* @param oldUrl
* @param oldUrlRevision
* @param newUrl
* @param newUrlRevision
* @param outFile
* @param recurse
* @param ignoreAncestry
* @param noDiffDeleted
* @param force
* @throws SVNClientException
*/
public abstract void diff(
SVNUrl oldUrl,
SVNRevision oldUrlRevision,
SVNUrl newUrl,
SVNRevision newUrlRevision,
File outFile,
boolean recurse,
boolean ignoreAncestry,
boolean noDiffDeleted,
boolean force)
throws SVNClientException;
/**
* Display the differences between two paths.
* @param target
* @param pegRevision
* @param startRevision
* @param endRevision
* @param outFile
* @param depth
* @param ignoreAncestry
* @param noDiffDeleted
* @param force
* @throws SVNClientException
*/
public abstract void diff(
SVNUrl target,
SVNRevision pegRevision,
SVNRevision startRevision,
SVNRevision endRevision,
File outFile,
int depth,
boolean ignoreAncestry,
boolean noDiffDeleted,
boolean force)
throws SVNClientException;
/**
* Display the differences between two paths.
* @param target
* @param pegRevision
* @param startRevision
* @param endRevision
* @param outFile
* @param recurse
* @throws SVNClientException
*/
public abstract void diff(
SVNUrl target,
SVNRevision pegRevision,
SVNRevision startRevision,
SVNRevision endRevision,
File outFile,
boolean recurse)
throws SVNClientException;
/**
* display the differences between two urls.
* @param url
* @param oldUrlRevision
* @param newUrlRevision
* @param outFile
* @param recurse
* @throws SVNClientException
*/
public abstract void diff(
SVNUrl url,
SVNRevision oldUrlRevision,
SVNRevision newUrlRevision,
File outFile,
boolean recurse)
throws SVNClientException;
/**
* display the differences between WC and url.
* @param path
* @param url
* @param urlRevision
* @param outFile
* @param recurse
* @throws SVNClientException
*/
public abstract void diff(
File path,
SVNUrl url,
SVNRevision urlRevision,
File outFile,
boolean recurse)
throws SVNClientException;
/**
* returns the keywords used for substitution for the given resource
* @param path
* @return the keywords used for substitution
* @throws SVNClientException
*/
public abstract SVNKeywords getKeywords(File path) throws SVNClientException;
/**
* set the keywords substitution for the given resource
* @param path
* @param keywords
* @param recurse
* @throws SVNClientException
*/
public abstract void setKeywords(File path, SVNKeywords keywords, boolean recurse) throws SVNClientException;
/**
* add some keyword to the keywords substitution list
* @param path
* @param keywords
* @return keywords valid after this method call
* @throws SVNClientException
*/
public abstract SVNKeywords addKeywords(File path, SVNKeywords keywords) throws SVNClientException;
/**
* remove some keywords to the keywords substitution list
* @param path
* @param keywords
* @return keywords valid after this method call
* @throws SVNClientException
*/
public SVNKeywords removeKeywords(File path, SVNKeywords keywords) throws SVNClientException;
/**
* Output the content of specified url with revision and
* author information in-line.
* @param url
* @param revisionStart
* @param revisionEnd
* @return annotations for the given url
* @throws SVNClientException
*/
public ISVNAnnotations annotate(SVNUrl url, SVNRevision revisionStart, SVNRevision revisionEnd)
throws SVNClientException;
/**
* Output the content of specified file with revision and
* author information in-line.
* @param file
* @param revisionStart
* @param revisionEnd
* @return annotations for the given file
* @throws SVNClientException
*/
public ISVNAnnotations annotate(File file, SVNRevision revisionStart, SVNRevision revisionEnd)
throws SVNClientException;
/**
* Output the content of specified url with revision and
* author information in-line.
* @param url
* @param revisionStart
* @param revisionEnd
* @param pegRevision
* @param ignoreMimeType
* @param includeMergedRevisons
* @return annotations for the given url
* @throws SVNClientException
*/
public ISVNAnnotations annotate(SVNUrl url, SVNRevision revisionStart, SVNRevision revisionEnd, SVNRevision pegRevision,
boolean ignoreMimeType, boolean includeMergedRevisions)
throws SVNClientException;
/**
* Output the content of specified file with revision and
* author information in-line.
* @param file
* @param revisionStart
* @param revisionEnd
* @param ignoreMimeType
* @param includeMergedRevisons
* @return annotations for the given file
* @throws SVNClientException
*/
public ISVNAnnotations annotate(File file, SVNRevision revisionStart, SVNRevision revisionEnd,
boolean ignoreMimeType, boolean includeMergedRevisions)
throws SVNClientException;
/**
* Output the content of specified file with revision and
* author information in-line.
* @param file
* @param revisionStart
* @param revisionEnd
* @param pegRevision;
* @param ignoreMimeType
* @param includeMergedRevisons
* @return annotations for the given file
* @throws SVNClientException
*/
public ISVNAnnotations annotate(File file, SVNRevision revisionStart, SVNRevision revisionEnd, SVNRevision pegRevision,
boolean ignoreMimeType, boolean includeMergedRevisions)
throws SVNClientException;
/**
* Get all the properties for the given file or dir
* @param path
* @return the properties for the given url
* @throws SVNClientException
*/
public abstract ISVNProperty[] getProperties(File path) throws SVNClientException;
/**
* Get all the properties for the given file or dir
* @param path
* @param descend get properties recursively
* @return the properties for the given url
* @throws SVNClientException
*/
public abstract ISVNProperty[] getProperties(File path, boolean descend) throws SVNClientException;
/**
* Get all the properties for the given url
* @param url
* @param revision
* @param peg
* @param recurse
* @return information about an URL.
* @throws SVNClientException
*/
public abstract ISVNProperty[] getProperties(SVNUrl url, SVNRevision revision, SVNRevision peg, boolean recurse) throws SVNClientException;
/**
* Get all the properties for the given url
* @param url
* @param revision
* @param peg
* @return information about an URL.
* @throws SVNClientException
*/
public abstract ISVNProperty[] getProperties(SVNUrl url, SVNRevision revision, SVNRevision peg) throws SVNClientException;
/**
* Get all the properties for the given url
* @param url
* @return the properties for the given url
* @throws SVNClientException
*/
public abstract ISVNProperty[] getProperties(SVNUrl url) throws SVNClientException;
/**
* Get all the revision properties for the given url at a revision
* @param url
* @param revision
* @return information about an URL.
* @throws SVNClientException
*/
public abstract ISVNProperty[] getRevProperties(SVNUrl url, SVNRevision.Number revision) throws SVNClientException;
/**
* Remove 'conflicted' state on working copy files or directories
* @param path
* @throws SVNClientException
*/
public abstract void resolved(File path) throws SVNClientException;
/**
* Remove 'conflicted' state on working copy files or directories
* @param path
* @param result - choose resolve option - {@link ISVNConflictResolver.Choice}
* @throws SVNClientException
*/
public abstract void resolve(File path, int result) throws SVNClientException;
/**
* Create a new, empty repository at path
*
* @param path
* @param repositoryType either {@link ISVNClientAdapter#REPOSITORY_FSTYPE_BDB} or
* {@link ISVNClientAdapter#REPOSITORY_FSTYPE_FSFS} or null (will use svnadmin default)
* @throws SVNClientException
*/
public abstract void createRepository(File path, String repositoryType) throws SVNClientException;
/**
* Cancel the current operation
*
* @throws SVNClientException
*/
public void cancelOperation() throws SVNClientException;
/**
* Get information about a file or directory from working copy.
* Uses info() call which does NOT contact the repository
* @param file
* @return information about a file or directory from working copy.
* @throws SVNClientException
*/
public ISVNInfo getInfoFromWorkingCopy(File file) throws SVNClientException;
/**
* Get information about a file or directory.
* Uses info2() call which contacts the repository
* @param file
* @return information about a file or directory.
* @throws SVNClientException
*/
public ISVNInfo getInfo(File file) throws SVNClientException;
/**
* Get information about a file or directory.
* Uses info2() call which contacts the repository
* @param file
* @param descend get recursive information
* @return information about a file or directory.
* @throws SVNClientException
*/
public ISVNInfo[] getInfo(File file, boolean descend) throws SVNClientException;
/**
* Get information about an URL.
* Uses info2() call which contacts the repository
* @param url
* @return information about an URL.
* @throws SVNClientException
*/
public ISVNInfo getInfo(SVNUrl url) throws SVNClientException;
/**
* Get information about an URL.
* Uses info2() call which contacts the repository
* @param url
* @param revision
* @param peg
* @return information about an URL.
* @throws SVNClientException
*/
public ISVNInfo getInfo(SVNUrl url, SVNRevision revision, SVNRevision peg) throws SVNClientException;
/**
* Update the working copy to mirror a new URL within the repository.
* This behaviour is similar to 'svn update', and is the way to
* move a working copy to a branch or tag within the same repository.
* @param url
* @param path
* @param revision
* @param recurse
* @throws SVNClientException
*/
public void switchToUrl(File path, SVNUrl url, SVNRevision revision, boolean recurse) throws SVNClientException;
/**
* Update the working copy to mirror a new URL within the repository.
* This behaviour is similar to 'svn update', and is the way to
* move a working copy to a branch or tag within the same repository.
* @param url
* @param path
* @param revision
* @param depth
* @param setDepth
* @param ignoreExternals
* @param force
* @throws SVNClientException
*/
public void switchToUrl(File path, SVNUrl url, SVNRevision revision, int depth, boolean setDepth, boolean ignoreExternals, boolean force) throws SVNClientException;
/**
* Update the working copy to mirror a new URL within the repository.
* This behaviour is similar to 'svn update', and is the way to
* move a working copy to a branch or tag within the same repository.
* @param url
* @param path
* @param revision
* @param pegRevision
* @param depth
* @param setDepth
* @param ignoreExternals
* @param force
* @throws SVNClientException
*/
public void switchToUrl(File path, SVNUrl url, SVNRevision revision, SVNRevision pegRevision, int depth, boolean setDepth, boolean ignoreExternals, boolean force) throws SVNClientException;
/**
* Update the working copy to mirror a new URL within the repository.
* This behaviour is similar to 'svn update', and is the way to
* move a working copy to a branch or tag within the same repository.
* @param url
* @param path
* @param revision
* @param pegRevision
* @param depth
* @param setDepth
* @param ignoreExternals
* @param force
* @param ignoreAncestry
* @throws SVNClientException
*/
public void switchToUrl(File path, SVNUrl url, SVNRevision revision, SVNRevision pegRevision, int depth, boolean setDepth, boolean ignoreExternals, boolean force, boolean ignoreAncestry) throws SVNClientException;
/**
* Set the configuration directory.
* @param dir
* @throws SVNClientException
*/
public void setConfigDirectory(File dir) throws SVNClientException;
/**
* Perform a clanup on the working copy. This will remove any stale transactions
* @param dir
* @throws SVNClientException
*/
public abstract void cleanup(File dir) throws SVNClientException;
/**
* Recursively upgrade a working copy to a new metadata storage format.
* @param dir
* @throws SVNClientException
*/
public abstract void upgrade(File dir) throws SVNClientException;
/**
* Merge changes from two paths into a new local path.
* @param path1 first path or url
* @param revision1 first revision
* @param path2 second path or url
* @param revision2 second revision
* @param localPath target local path
* @param force overwrite local changes
* @param recurse traverse into subdirectories
* @exception SVNClientException
*/
public abstract void merge(SVNUrl path1, SVNRevision revision1, SVNUrl path2,
SVNRevision revision2, File localPath, boolean force,
boolean recurse) throws SVNClientException;
/**
* Merge changes from two paths into a new local path.
* @param path1 first path or url
* @param revision1 first revision
* @param path2 second path or url
* @param revision2 second revision
* @param localPath target local path
* @param force overwrite local changes
* @param recurse traverse into subdirectories
* @param dryRun do not update working copy
* @exception SVNClientException
*/
public abstract void merge(SVNUrl path1, SVNRevision revision1, SVNUrl path2,
SVNRevision revision2, File localPath, boolean force,
boolean recurse, boolean dryRun) throws SVNClientException;
/**
* Merge changes from two paths into a new local path.
* @param path1 first path or url
* @param revision1 first revision
* @param path2 second path or url
* @param revision2 second revision
* @param localPath target local path
* @param force overwrite local changes
* @param recurse traverse into subdirectories
* @param dryRun do not update working copy
* @param ignoreAncestry ignore ancestry when calculating merges
* @exception SVNClientException
*/
public abstract void merge(SVNUrl path1, SVNRevision revision1, SVNUrl path2,
SVNRevision revision2, File localPath, boolean force,
boolean recurse, boolean dryRun, boolean ignoreAncestry) throws SVNClientException;
/**
* Merge changes from two paths into a new local path.
* @param path1 first path or url
* @param revision1 first revision
* @param path2 second path or url
* @param revision2 second revision
* @param localPath target local path
* @param force overwrite local changes
* @param int depth
* @param dryRun do not update working copy
* @param ignoreAncestry ignore ancestry when calculating merges
* @param recordOnly just records mergeinfo, does not perform merge
* @exception SVNClientException
*/
public abstract void merge(SVNUrl path1, SVNRevision revision1, SVNUrl path2,
SVNRevision revision2, File localPath, boolean force,
int depth, boolean dryRun, boolean ignoreAncestry,
boolean recordOnly) throws SVNClientException;
/**
* Perform a reintegration merge of path into localPath.
* localPath must be a single-revision, infinite depth,
* pristine, unswitched working copy -- in other words, it must
* reflect a single revision tree, the "target". The mergeinfo on
* path must reflect that all of the target has been merged into it.
* Then this behaves like a merge from the target's URL to the
* localPath.
*
* The depth of the merge is always infinity.
* @param path path or url
* @param pegRevision revision to interpret path
* @param localPath target local path
* @param force THIS IS NOT CURRENTLY USED
* @param dryRun do not update working copy
* @exception SVNClientException
*/
public abstract void mergeReintegrate(SVNUrl path, SVNRevision pegRevision,
File localPath, boolean force, boolean dryRun) throws SVNClientException;
/**
* Lock a working copy item
* @param paths path of the items to lock
* @param comment
* @param force break an existing lock
* @throws SVNClientException
*/
public abstract void lock(SVNUrl[] paths, String comment, boolean force)
throws SVNClientException;
/**
* Unlock a working copy item
* @param paths path of the items to unlock
* @param force break an existing lock
* @throws SVNClientException
*/
public abstract void unlock(SVNUrl[] paths, boolean force)
throws SVNClientException;
/**
* Lock a working copy item
* @param paths path of the items to lock
* @param comment
* @param force break an existing lock
* @throws SVNClientException
*/
public abstract void lock(File[] paths, String comment, boolean force)
throws SVNClientException;
/**
* Unlock a working copy item
* @param paths path of the items to unlock
* @param force break an existing lock
* @throws SVNClientException
*/
public abstract void unlock(File[] paths, boolean force)
throws SVNClientException;
/**
* Indicates whether a status call that contacts the
* server includes the remote info in the status object
* @return true when the client adapter implementation delivers remote info within status
*/
public abstract boolean statusReturnsRemoteInfo();
/**
* Indicates whether the commitAcrossWC method is
* supported in the adapter
* @return true when the client adapter implementation supports commitAcrossWC
*/
public abstract boolean canCommitAcrossWC();
/**
* Returns the name of the Subversion administrative
* working copy directory. Typically will be ".svn".
* @return the name of the Subversion administrative wc dir
*/
public abstract String getAdminDirectoryName();
/**
* Returns whether the passed folder name is a Subversion
* administrative working copy directory. Will always return
* true if ".svn" is passed. Otherwise, will be based on the
* Subversion runtime
* @param name
* @return true whether the folder is a Subversion administrative dir
*/
public abstract boolean isAdminDirectory(String name);
/**
* Rewrite the url's in the working copy
* @param from old url
* @param to new url
* @param path working copy path
* @param recurse recurse into subdirectories
* @throws SVNClientException
*/
public abstract void relocate(String from, String to, String path, boolean recurse)
throws SVNClientException;
/**
* Merge set of revisions into a new local path.
* @param url url
* @param pegRevision revision to interpret path
* @param revisions revisions to merge (must be in the form N-1:M)
* @param localPath target local path
* @param force overwrite local changes
* @param depth how deep to traverse into subdirectories
* @param ignoreAncestry ignore if files are not related
* @param dryRun do not change anything
* @param recordOnly just records mergeinfo, does not perform merge
* @throws SVNClientException
*/
public abstract void merge(SVNUrl url, SVNRevision pegRevision, SVNRevisionRange[] revisions,
File localPath, boolean force, int depth,
boolean ignoreAncestry, boolean dryRun,
boolean recordOnly) throws SVNClientException;
/**
* Get merge info for <code>path</code> at <code>revision</code>.
* @param path Local Path.
* @param revision SVNRevision at which to get the merge info for
* <code>path</code>.
* @throws SVNClientException
*/
public abstract ISVNMergeInfo getMergeInfo(File path, SVNRevision revision)
throws SVNClientException;
/**
* Get merge info for <code>url</code> at <code>revision</code>.
* @param url URL.
* @param revision SVNRevision at which to get the merge info for
* <code>path</code>.
* @throws SVNClientException
*/
public abstract ISVNMergeInfo getMergeInfo(SVNUrl url, SVNRevision revision)
throws SVNClientException;
/**
* Retrieve either merged or eligible-to-be-merged revisions.
* @param kind kind of revisions to receive
* @param path target of merge
* @param pegRevision peg rev for path
* @param mergeSourceUrl the source of the merge
* @param srcPegRevision peg rev for mergeSourceUrl
* @param discoverChangedPaths return paths of changed items
* @return array of log messages
* @throws SVNClientException
*/
public abstract ISVNLogMessage[] getMergeinfoLog(int kind, File path,
SVNRevision pegRevision, SVNUrl mergeSourceUrl, SVNRevision srcPegRevision,
boolean discoverChangedPaths) throws SVNClientException;
/**
* Retrieve either merged or eligible-to-be-merged revisions.
* @param kind kind of revisions to receive
* @param url target of merge
* @param pegRevision peg rev for path
* @param mergeSourceUrl the source of the merge
* @param srcPegRevision peg rev for mergeSourceUrl
* @param discoverChangedPaths return paths of changed items
* @return array of log messages
* @throws SVNClientException
*/
public abstract ISVNLogMessage[] getMergeinfoLog(int kind, SVNUrl url,
SVNRevision pegRevision, SVNUrl mergeSourceUrl, SVNRevision srcPegRevision,
boolean discoverChangedPaths) throws SVNClientException;
/**
* Produce a diff summary which lists the items changed between
* path and revision pairs.
*
* @param target1 URL.
* @param revision1 Revision of <code>target1</code>.
* @param target2 URL.
* @param revision2 Revision of <code>target2</code>.
* @param depth how deep to recurse.
* @param ignoreAncestry Whether to ignore unrelated files during
* comparison. False positives may potentially be reported if
* this parameter <code>false</code>, since a file might have been
* modified between two revisions, but still have the same
* contents.
* @return the list of differences
*
* @throws SVNClientException
*/
public abstract SVNDiffSummary[] diffSummarize(SVNUrl target1, SVNRevision revision1,
SVNUrl target2, SVNRevision revision2,
int depth, boolean ignoreAncestry)
throws SVNClientException;
/**
* Produce a diff summary which lists the items changed between
* path and revision pairs.
*
* @param target URL.
* @param pegRevision Revision at which to interpret
* <code>target</code>. If {@link RevisionKind#unspecified} or
* <code>null</code>, behave identically to {@link
* diffSummarize(String, Revision, String, Revision, boolean,
* boolean, DiffSummaryReceiver)}, using <code>path</code> for
* both of that method's targets.
* @param startRevision Beginning of range for comparsion of
* <code>target</code>.
* @param endRevision End of range for comparsion of
* <code>target</code>.
* @param depth how deep to recurse.
* @param ignoreAncestry Whether to ignore unrelated files during
* comparison. False positives may potentially be reported if
* this parameter <code>false</code>, since a file might have been
* modified between two revisions, but still have the same
* contents.
* @return the list of differences
*
* @throws SVNClientException
*/
public abstract SVNDiffSummary[] diffSummarize(SVNUrl target, SVNRevision pegRevision,
SVNRevision startRevision, SVNRevision endRevision,
int depth, boolean ignoreAncestry)
throws SVNClientException;
public abstract SVNDiffSummary[] diffSummarize(File path, SVNUrl toUrl, SVNRevision toRevision, boolean recurse)
throws SVNClientException;
/**
* Return an ordered list of suggested merge source URLs.
* @param path The merge target path for which to suggest sources.
* @return The list of URLs, empty if there are no suggestions.
* @throws SVNClientException If an error occurs.
*/
public abstract String[] suggestMergeSources(File path)
throws SVNClientException;
/**
* Return an ordered list of suggested merge source URLs.
* @param url The merge target path for which to suggest sources.
* @param peg The peg revision for the URL
* @return The list of URLs, empty if there are no suggestions.
* @throws SVNClientException If an error occurs.
*/
public abstract String[] suggestMergeSources(SVNUrl url, SVNRevision peg)
throws SVNClientException;
/**
* release the native peer (should not depend on finalize)
*/
public abstract void dispose();
}
CmdLineClientAdapter.java - Implemented Abstarct method of Copy with force option
Posted 2013-03-26 00:24:39 by sendhilsubramani
/*******************************************************************************
* Copyright (c) 2003, 2006 svnClientAdapter project and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* svnClientAdapter project committers - initial API and implementation
******************************************************************************/
package org.tigris.subversion.svnclientadapter.commandline;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;
import org.tigris.subversion.svnclientadapter.AbstractClientAdapter;
import org.tigris.subversion.svnclientadapter.ISVNAnnotations;
import org.tigris.subversion.svnclientadapter.ISVNConflictResolver;
import org.tigris.subversion.svnclientadapter.ISVNDirEntry;
import org.tigris.subversion.svnclientadapter.ISVNDirEntryWithLock;
import org.tigris.subversion.svnclientadapter.ISVNInfo;
import org.tigris.subversion.svnclientadapter.ISVNLogMessage;
import org.tigris.subversion.svnclientadapter.ISVNLogMessageCallback;
import org.tigris.subversion.svnclientadapter.ISVNMergeInfo;
import org.tigris.subversion.svnclientadapter.ISVNNotifyListener;
import org.tigris.subversion.svnclientadapter.ISVNProgressListener;
import org.tigris.subversion.svnclientadapter.ISVNProperty;
import org.tigris.subversion.svnclientadapter.ISVNStatus;
import org.tigris.subversion.svnclientadapter.ISVNStatusCallback;
import org.tigris.subversion.svnclientadapter.SVNBaseDir;
import org.tigris.subversion.svnclientadapter.SVNClientException;
import org.tigris.subversion.svnclientadapter.SVNDiffSummary;
import org.tigris.subversion.svnclientadapter.SVNNotificationHandler;
import org.tigris.subversion.svnclientadapter.SVNRevision;
import org.tigris.subversion.svnclientadapter.SVNRevision.Number;
import org.tigris.subversion.svnclientadapter.SVNRevisionRange;
import org.tigris.subversion.svnclientadapter.SVNScheduleKind;
import org.tigris.subversion.svnclientadapter.SVNStatusUnversioned;
import org.tigris.subversion.svnclientadapter.SVNUrl;
/**
* <p>
* Implements a <tt>ISVNClientAdapter</tt> using the
* Command line client. This expects the <tt>svn</tt>
* executible to be in the path.</p>
*
* @author Philip Schatz (schatz at tigris)
* @author C~dric Chabanois (cchabanois at no-log.org)
*/
public class CmdLineClientAdapter extends AbstractClientAdapter {
//Fields
final protected CmdLineNotificationHandler notificationHandler;
final protected SvnCommandLine _cmd;
final protected SvnMultiArgCommandLine _cmdMulti;
final protected SvnAdminCommandLine svnAdminCmd;
protected String version = null;
private static boolean availabilityCached = false;
private static boolean available;
private static String dirName;
public CmdLineClientAdapter(CmdLineNotificationHandler notificationHandler)
{
this(notificationHandler,
new SvnCommandLine("svn", notificationHandler),
new SvnMultiArgCommandLine("svn", notificationHandler),
new SvnAdminCommandLine("svnadmin", notificationHandler));
}
protected CmdLineClientAdapter(CmdLineNotificationHandler notificationHandler, SvnCommandLine cmd, SvnMultiArgCommandLine multiCmd, SvnAdminCommandLine adminCmd) {
super();
this.notificationHandler = notificationHandler;
this._cmd = cmd;
this._cmdMulti = multiCmd;
this.svnAdminCmd = adminCmd;
}
public boolean isThreadsafe() {
return false;
}
//Methods
public static boolean isAvailable() {
// availabilityCached flag must be reset if location of client changes
if (!availabilityCached) {
// this will need to be fixed when path to svn will be customizable
SvnCommandLine cmd = new SvnCommandLine("svn", new CmdLineNotificationHandler());
try {
String version = cmd.version();
int i = version.indexOf(System.getProperty("line.separator")); // NOI18N
version = version.substring(0,i);
available = true;
available &= version.indexOf("version 0.") == -1;
available &= version.indexOf("version 1.0") == -1;
available &= version.indexOf("version 1.1") == -1;
available &= version.indexOf("version 1.2") == -1;
} catch (Exception e) {
e.printStackTrace();
available = false;
}
availabilityCached = true;
}
return available;
}
/**
* @return something like "svn, version 0.35.1 (r8050)"
* @throws SVNClientException
*/
public String getVersion() throws SVNClientException {
if (version != null)
return version;
try {
// we don't want to log this ...
notificationHandler.disableLog();
version = _cmd.version();
int i = version.indexOf(System.getProperty("line.separator")); // NOI18N
version = version.substring(0,i);
return version;
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
} finally {
notificationHandler.enableLog();
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#addNotifyListener(org.tigris.subversion.subclipse.client.ISVNClientNotifyListener)
*/
public void addNotifyListener(ISVNNotifyListener listener) {
notificationHandler.add(listener);
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#removeNotifyListener(org.tigris.subversion.subclipse.client.ISVNClientNotifyListener)
*/
public void removeNotifyListener(ISVNNotifyListener listener) {
notificationHandler.remove(listener);
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getNotificationHandler()
*/
public SVNNotificationHandler getNotificationHandler() {
return notificationHandler;
}
private boolean isManaged(File file) {
if (file.isDirectory()) {
return isManagedDir(file.getParentFile()) || isManagedDir(file);
} else {
return isManagedDir(file.getParentFile());
}
}
private boolean isManagedDir(File dir) {
// all directories that do not have a .svn dir are not versioned
File entries = new File(dir, getAdminDirectoryName() + "/entries");
return entries.exists();
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#getStatus(java.io.File[])
*/
public ISVNStatus[] getStatus(File[] files) throws SVNClientException {
ISVNStatus[] statuses = new ISVNStatus[files.length];
// all files (and dirs) that are in nonmanaged dirs are unversioned
ArrayList pathsList = new ArrayList();
for (int i = 0; i < files.length;i++) {
File file = files[i];
if (isManaged(file)) {
pathsList.add(toString(file));
} else {
statuses[i] = new SVNStatusUnversioned(file,false);
}
}
String[] paths = (String[])pathsList.toArray(new String[pathsList.size()]);
// we must do a svn status and svn info only on resources that are in versioned dirs
// because otherwise svn will stop after the first "svn: 'resource' is not a working copy"
CmdLineStatuses cmdLineStatuses;
try {
CmdLineStatusPart[] cmdLineStatusParts = getCmdStatuses(paths, false, true, false, false);
List targetsInfo = new ArrayList(cmdLineStatusParts.length);
for (int i = 0; i < cmdLineStatusParts.length;i++) {
if (cmdLineStatusParts[i].isManaged()) {
targetsInfo.add(cmdLineStatusParts[i].getFile().toString());
}
}
String cmdLineInfoStrings = _cmd.info((String[]) targetsInfo.toArray(new String[targetsInfo.size()] ), null, null);
cmdLineStatuses = new CmdLineStatuses(cmdLineInfoStrings, cmdLineStatusParts);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
for (int i = 0; i < cmdLineStatuses.size();i++) {
ISVNStatus status = cmdLineStatuses.get(i);
for (int j=0; j < files.length;j++) {
if (files[j].getAbsoluteFile().equals(status.getFile())) {
statuses[j] = status;
}
}
}
for (int i = 0; i < statuses.length; i++) {
if (statuses[i] == null) {
statuses[i] = new SVNStatusUnversioned(files[i],false);
}
}
return statuses;
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getSingleStatus(java.io.File)
*/
public ISVNStatus getSingleStatus(File path)
throws SVNClientException {
return getStatus(new File[] {path})[0];
}
private ISVNDirEntry[] getList(String target, SVNRevision rev, boolean recursive)
throws SVNClientException {
byte[] listXml;
try {
listXml = _cmd.list(target, toString(rev), recursive);
return CmdLineRemoteDirEntry.createDirEntries(listXml);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#getList(java.net.URL, org.tigris.subversion.subclipse.client.ISVNRevision, boolean)
*/
public ISVNDirEntry[] getList(SVNUrl svnUrl, SVNRevision revision, boolean recurse)
throws SVNClientException {
return getList(toString(svnUrl), revision, recurse);
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getList(java.io.File, org.tigris.subversion.svnclientadapter.SVNRevision, boolean)
*/
public ISVNDirEntry[] getList(File path, SVNRevision revision,
boolean recurse) throws SVNClientException {
return getList(toString(path), revision, recurse);
}
public ISVNDirEntryWithLock[] getListWithLocks(SVNUrl url,
SVNRevision revision, SVNRevision pegRevision, boolean recurse)
throws SVNClientException {
ISVNDirEntry[] entries = getList(url, revision, pegRevision, recurse);
ISVNDirEntryWithLock[] entriesWithLocks = new ISVNDirEntryWithLock[entries.length];
for (int i = 0; i < entries.length; i++) {
entriesWithLocks[i] = new CmdLineRemoteDirEntryWithLock(entries[i], null);
}
return entriesWithLocks;
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getDirEntry(org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision)
*/
public ISVNDirEntry getDirEntry(SVNUrl url, SVNRevision revision)
throws SVNClientException {
// list give the DirEntrys of the elements of a directory or the DirEntry
// of a file
ISVNDirEntry[] entries = getList(url.getParent(),revision,false);
String expectedPath = url.getLastPathSegment();
for (int i = 0; i < entries.length;i++) {
if (entries[i].getPath().equals(expectedPath)) {
return entries[i];
}
}
return null; // not found
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getDirEntry(java.io.File, org.tigris.subversion.svnclientadapter.SVNRevision)
*/
public ISVNDirEntry getDirEntry(File path, SVNRevision revision)
throws SVNClientException {
// list give the DirEntrys of the elements of a directory or the DirEntry
// of a file
ISVNDirEntry[] entries = getList(path.getParentFile(),revision,false);
String expectedPath = path.getName();
for (int i = 0; i < entries.length;i++) {
if (entries[i].getPath().equals(expectedPath)) {
return entries[i];
}
}
return null; // not found
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#remove(java.io.File[], boolean)
*/
public void remove(File[] files, boolean force) throws SVNClientException {
String[] paths = new String[files.length];
try {
for (int i = 0; i < files.length; i++) {
paths[i] = files[i].toString();
}
_cmd.delete(paths, null,force);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#revert(java.io.File, boolean)
*/
public void revert(File file, boolean recursive) throws SVNClientException {
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(file));
_cmd.revert(new String[] { toString(file) }, recursive);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#getContent(java.net.SVNUrl, org.tigris.subversion.subclipse.client.ISVNRevision)
*/
public InputStream getContent(SVNUrl arg0, SVNRevision arg1) throws SVNClientException {
try {
InputStream content = _cmd.cat(toString(arg0), toString(arg1));
//read byte-by-byte and put it in a vector.
//then take the vector and fill a byteArray.
byte[] byteArray;
byteArray = streamToByteArray(content);
content.close();
return new ByteArrayInputStream(byteArray);
} catch (IOException e) {
throw SVNClientException.wrapException(e);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getContent(java.io.File, org.tigris.subversion.svnclientadapter.SVNRevision)
*/
public InputStream getContent(File path, SVNRevision revision) throws SVNClientException {
try {
InputStream content = _cmd.cat(toString(path), toString(revision));
//read byte-by-byte and put it in a vector.
//then take the vector and fill a byteArray.
byte[] byteArray;
byteArray = streamToByteArray(content);
content.close();
return new ByteArrayInputStream(byteArray);
} catch (IOException e) {
throw SVNClientException.wrapException(e);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#mkdir(java.net.URL, java.lang.String)
*/
public void mkdir(SVNUrl arg0, String arg1) throws SVNClientException {
try {
_cmd.mkdir(toString(arg0), arg1);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#remove(java.net.URL[], java.lang.String)
*/
public void remove(SVNUrl[] urls, String message) throws SVNClientException {
String[] urlsStrings = new String[urls.length];
for (int i = 0; i < urls.length; i++) {
urlsStrings[i] = urls[i].toString();
}
try {
_cmd.delete(urlsStrings, message,false);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#copy(java.net.URL, java.net.URL, java.lang.String, org.tigris.subversion.subclipse.client.ISVNRevision)
*/
public void copy(SVNUrl src, SVNUrl dest, String message, SVNRevision rev)
throws SVNClientException {
try {
if (message == null)
message = "";
_cmd.copy(toString(src), toString(dest), message, toString(rev), false);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#copy(java.io.File, java.io.File)
*/
public void copy(File srcPath, File destPath) throws SVNClientException {
try {
_cmd.copy(toString(srcPath), toString(destPath));
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
//sometimes the dir has not yet been created.
//wait up to 5 sec for the dir to be created.
for (int i = 0; i < 50 && !destPath.exists(); i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e2) {
//do nothing if interrupted
}
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#move(java.net.URL, java.net.URL, java.lang.String, org.tigris.subversion.subclipse.client.ISVNRevision)
*/
public void move(SVNUrl url, SVNUrl destUrl, String message, SVNRevision revision)
throws SVNClientException {
try {
notificationHandler.setBaseDir(new File("."));
_cmd.move(toString(url), toString(destUrl), message, toString(revision), false);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#move(java.io.File, java.io.File, boolean)
*/
public void move(File file, File file2, boolean force) throws SVNClientException {
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(new File[] {file,file2}));
_cmd.move(toString(file), toString(file2), null, null, force);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#setUsername(java.lang.String)
*/
public void setUsername(String string) {
if (string == null || string.length() == 0)
return;
_cmd.setUsername(string);
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#setPassword(java.lang.String)
*/
public void setPassword(String password) {
if (password == null)
return;
_cmd.setPassword(password);
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#addDirectory(java.io.File, boolean)
*/
public void addDirectory(File file, boolean recurse) throws SVNClientException {
addDirectory(file, recurse, false);
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#addDirectory(java.io.File, boolean, boolean)
*/
public void addDirectory(File file, boolean recurse, boolean force) throws SVNClientException {
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(file));
_cmd.add(toString(file), recurse, force);
} catch (CmdLineException e) {
//if something is already in svn and we
//try to add it, we get a warning.
//ignore it.\
if (e.getMessage().startsWith("svn: warning: "))
return;
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#addFile(java.io.File)
*/
public void addFile(File file) throws SVNClientException {
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(file));
_cmd.add(toString(file), false, false);
} catch (CmdLineException e) {
//if something is already in svn and we
//try to add it, we get a warning.
//ignore it.\
if (e.getMessage().startsWith("svn: warning: "))
return;
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#commit(java.io.File[], java.lang.String, boolean)
*/
public long commit(File[] parents, String comment, boolean recurse) throws SVNClientException {
return commit(parents, comment, recurse , false);
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#commit(java.io.File[], java.lang.String, boolean, boolean)
*/
public long commit(File[] parents, String comment, boolean recurse, boolean keepLocks) throws SVNClientException {
String[] paths = new String[parents.length];
for (int i = 0; i < parents.length; i++) {
paths[i] = toString(parents[i]);
}
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(parents));
_cmd.checkin(paths, comment, keepLocks);
return _cmd.getRevision();
} catch (CmdLineException e) {
if ("".equals(e.getMessage()))
return SVNRevision.SVN_INVALID_REVNUM;
if (e.getMessage().startsWith("svn: Attempted to lock an already-locked dir")) {
//PHIL is this the best way to handle pending locks? (ie caused by "svn cp")
//loop through up to 5 sec, waiting for locks
//to be removed.
for (int i = 0; i < 50; i++) {
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(parents));
_cmd.checkin(paths, comment, keepLocks);
return _cmd.getRevision();
} catch (CmdLineException e1) {
try {
Thread.sleep(100);
} catch (InterruptedException e2) {
//do nothing if interrupted
}
}
}
}
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#update(java.io.File, org.tigris.subversion.subclipse.client.ISVNRevision, boolean)
*/
public long update(File file, SVNRevision revision, boolean b) throws SVNClientException {
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(file));
_cmd.update(toString(file), toString(revision));
return _cmd.getRevision();
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#update(java.io.File[], org.tigris.subversion.svnclientadapter.SVNRevision, boolean, boolean)
*/
public long[] update(File[] files, SVNRevision revision, boolean recurse, boolean ignoreExternals) throws SVNClientException
{
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(files[0]));
_cmdMulti.update(toString(files), toString(revision));
return _cmdMulti.getRevisions();
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.subclipse.client.ISVNClientAdapter#checkout(java.net.URL, java.io.File, org.tigris.subversion.subclipse.client.ISVNRevision, boolean)
*/
public void checkout(SVNUrl url, File destPath, SVNRevision revision, boolean b)
throws SVNClientException {
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(destPath));
_cmd.checkout(toString(url), toString(destPath), toString(revision), b);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getStatus(java.io.File, boolean, boolean)
*/
public ISVNStatus[] getStatus(File path, boolean descend, boolean getAll)
throws SVNClientException {
return getStatus(path, descend, getAll, false);
}
protected CmdLineStatusPart[] getCmdStatuses(File[] paths, boolean descend, boolean getAll, boolean contactServer, boolean ignoreExternals) throws CmdLineException
{
String[] pathNames = new String[paths.length];
for (int i = 0; i < pathNames.length; i++) {
pathNames[i] = toString(paths[i]);
}
return getCmdStatuses(pathNames, descend, getAll, contactServer, ignoreExternals);
}
protected CmdLineStatusPart[] getCmdStatuses(String[] paths, boolean descend, boolean getAll, boolean contactServer, boolean ignoreExternals) throws CmdLineException
{
if (paths.length == 0) {
return new CmdLineStatusPart[0];
}
byte[] listXml;
listXml = _cmd.status(paths, descend, getAll, contactServer, ignoreExternals);
return CmdLineStatusPart.CmdLineStatusPartFromXml.createStatusParts(listXml);
}
private void diff(
String oldPath,
SVNRevision oldPathRevision,
String newPath,
SVNRevision newPathRevision,
File outFile,
boolean recurse,
boolean ignoreAncestry,
boolean noDiffDeleted,
boolean force) throws SVNClientException {
if (newPath == null)
newPath = oldPath;
if (oldPathRevision == null)
oldPathRevision = SVNRevision.BASE;
if (newPathRevision == null)
newPathRevision = SVNRevision.WORKING;
try {
InputStream is =
_cmd.diff(
oldPath,
toString(oldPathRevision),
newPath,
toString(newPathRevision),
recurse,
ignoreAncestry,
noDiffDeleted,
force);
streamToFile(is, outFile);
is.close();
} catch (IOException e) {
//this should never happen
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#diff(java.io.File, org.tigris.subversion.svnclientadapter.SVNRevision, java.io.File, org.tigris.subversion.svnclientadapter.SVNRevision, java.io.File, boolean)
*/
public void diff(
File oldPath,
SVNRevision oldPathRevision,
File newPath,
SVNRevision newPathRevision,
File outFile,
boolean recurse)
throws SVNClientException {
if (oldPath == null)
oldPath = new File(".");
diff(oldPath,
oldPathRevision,
newPath,
newPathRevision,
outFile,
recurse, true, false, false);
}
public void diff(
File oldPath,
SVNRevision oldPathRevision,
File newPath,
SVNRevision newPathRevision,
File outFile,
boolean recurse,
boolean ignoreAncestry,
boolean noDiffDeleted,
boolean force)
throws SVNClientException {
if (oldPath == null)
oldPath = new File(".");
diff(
toString(oldPath),
oldPathRevision,
toString(newPath),
newPathRevision,
outFile,
recurse, ignoreAncestry, noDiffDeleted, force);
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#diff(java.io.File, java.io.File, boolean)
*/
public void diff(File path, File outFile, boolean recurse) throws SVNClientException {
diff(path, null, null, null, outFile, recurse);
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#diff(org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision, java.io.File, boolean)
*/
public void diff(
SVNUrl oldUrl,
SVNRevision oldUrlRevision,
SVNUrl newUrl,
SVNRevision newUrlRevision,
File outFile,
boolean recurse)
throws SVNClientException {
diff(oldUrl, oldUrlRevision, newUrl, newUrlRevision, outFile, recurse, true, false, false);
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#diff(org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision, java.io.File, boolean, boolean, boolean, boolean)
*/
public void diff(
SVNUrl oldUrl,
SVNRevision oldUrlRevision,
SVNUrl newUrl,
SVNRevision newUrlRevision,
File outFile,
boolean recurse,
boolean ignoreAncestry,
boolean noDiffDeleted,
boolean force)
throws SVNClientException {
diff(toString(oldUrl), oldUrlRevision, toString(newUrl), newUrlRevision, outFile, recurse, ignoreAncestry, noDiffDeleted, force);
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#diff(org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNRevision, java.io.File, boolean)
*/
public void diff(
SVNUrl url,
SVNRevision oldUrlRevision,
SVNRevision newUrlRevision,
File outFile,
boolean recurse)
throws SVNClientException {
diff(url, oldUrlRevision, url, newUrlRevision, outFile, recurse);
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#propertyGet(java.io.File, java.lang.String)
*/
public ISVNProperty propertyGet(File path, String propertyName) throws SVNClientException {
try {
InputStream valueAndData = _cmd.propget(toString(path), propertyName);
byte[] bytes = streamToByteArray(valueAndData);
valueAndData.close();
if (bytes.length == 0) {
return null; // the property does not exist
}
return new CmdLineProperty(propertyName, new String(bytes), path, bytes);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
} catch (IOException e) {
throw SVNClientException.wrapException(e);
}
}
public ISVNProperty propertyGet(SVNUrl url, String propertyName) throws SVNClientException {
try {
InputStream valueAndData = _cmd.propget(url.toString(), propertyName);
byte[] bytes = streamToByteArray(valueAndData);
valueAndData.close();
if (bytes.length == 0) {
return null; // the property does not exist
}
return new CmdLineProperty(propertyName, new String(bytes), url, bytes);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
} catch (IOException e) {
throw SVNClientException.wrapException(e);
}
}
public ISVNProperty propertyGet(SVNUrl url, SVNRevision revision,
SVNRevision peg, String propertyName) throws SVNClientException {
try {
InputStream valueAndData = _cmd.propget(url.toString(), propertyName, toString(revision), toString(peg));
byte[] bytes = streamToByteArray(valueAndData);
if (bytes.length == 0) {
return null; // the property does not exist
}
return new CmdLineProperty(propertyName, new String(bytes), url, bytes);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
} catch (IOException e) {
throw SVNClientException.wrapException(e);
}
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#propertySet(java.io.File, java.lang.String, java.io.File, boolean)
*/
public void propertySet(File path, String propertyName, File propertyFile, boolean recurse)
throws SVNClientException, IOException {
try {
_cmd.propsetFile(propertyName, toString(propertyFile), toString(path), recurse);
// there is no notification (Notify.notify is not called) when we set a property
// so we will do notification ourselves
ISVNStatus[] statuses = getStatus(path,recurse,false);
for (int i = 0; i < statuses.length;i++) {
notificationHandler.notifyListenersOfChange(statuses[i].getFile().getAbsolutePath());
}
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#propertyDel(java.io.File, java.lang.String, boolean)
*/
public void propertyDel(File path, String propertyName, boolean recurse)
throws SVNClientException {
try {
_cmd.propdel(propertyName, toString(path), recurse);
// there is no notification (Notify.notify is not called) when we delete a property
// so we will do notification ourselves
ISVNStatus[] statuses = getStatus(path,recurse,false);
for (int i = 0; i < statuses.length;i++) {
notificationHandler.notifyListenersOfChange(statuses[i].getFile().getAbsolutePath());
}
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#setRevProperty(org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision.Number, java.lang.String, java.lang.String, boolean)
*/
public void setRevProperty(SVNUrl path, SVNRevision.Number revisionNo, String propName, String propertyData, boolean force) throws SVNClientException {
try {
_cmd.revpropset(propName, propertyData, toString(path), Long.toString(revisionNo.getNumber()), force);
// there is no notification to send
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#mkdir(java.io.File)
*/
public void mkdir(File file) throws SVNClientException {
try {
_cmd.mkdir(toString(file));
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
//sometimes the dir has not yet been created.
//wait up to 5 sec for the dir to be created.
for (int i = 0; i < 50 && !file.exists(); i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e2) {
//do nothing if interrupted
}
}
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#doImport(java.io.File, org.tigris.subversion.svnclientadapter.SVNUrl, java.lang.String, boolean)
*/
public void doImport(File path, SVNUrl url, String message, boolean recurse)
throws SVNClientException {
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(path));
_cmd.importFiles(toString(path), toString(url), message, recurse);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#doExport(org.tigris.subversion.svnclientadapter.SVNUrl, java.io.File, org.tigris.subversion.svnclientadapter.SVNRevision, boolean)
*/
public void doExport(SVNUrl srcUrl, File destPath, SVNRevision revision, boolean force)
throws SVNClientException {
try {
_cmd.export(toString(srcUrl), toString(destPath), toString(revision), force);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#doExport(java.io.File, java.io.File, boolean)
*/
public void doExport(File srcPath, File destPath, boolean force) throws SVNClientException {
try {
_cmd.export(toString(srcPath), toString(destPath), null, force);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#copy(java.io.File, org.tigris.subversion.svnclientadapter.SVNUrl, java.lang.String)
*/
public void copy(File srcPath, SVNUrl destUrl, String message) throws SVNClientException {
try {
if (message == null)
message = "";
_cmd.copy(toString(srcPath), toString(destUrl), message, null, false);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#copy(org.tigris.subversion.svnclientadapter.SVNUrl, java.io.File, org.tigris.subversion.svnclientadapter.SVNRevision)
*/
public void copy(SVNUrl srcUrl, File destPath, SVNRevision revision)
throws SVNClientException {
try {
_cmd.copy(toString(srcUrl), toString(destPath), null, toString(revision), false);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#propertySet(java.io.File, java.lang.String, java.lang.String, boolean)
*/
public void propertySet(File path, String propertyName, String propertyValue, boolean recurse)
throws SVNClientException {
try {
_cmd.propset(propertyName, propertyValue, toString(path), recurse);
// there is no notification (Notify.notify is not called) when we set a property
// so we will do notification ourselves
ISVNStatus[] statuses = getStatus(path,recurse,false);
for (int i = 0; i < statuses.length;i++) {
notificationHandler.notifyListenersOfChange(statuses[i].getFile().getAbsolutePath());
}
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/**
* A safe <code>toString()</code> implementation which implements
* <code>null</code> checking on <code>obj</code>.
*/
protected static String toString(Object obj) {
return (obj == null) ? null : obj.toString();
}
/**
* Implementation used by overloads of <code>getLogMessages()</code>.
*
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getLogMessages(org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNRevision, boolean)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getLogMessages(java.io.File, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNRevision, boolean)
*/
private ISVNLogMessage[] getLogMessages(
String pathOrUrl,
String [] paths,
SVNRevision revisionStart,
SVNRevision revisionEnd,
boolean stopOnCopy,
boolean fetchChangePath,
long limit)
throws SVNClientException {
String revRange = toString(revisionStart) + ":" +
toString(revisionEnd);
try {
byte[] messages;
// To acquire the paths associated with each delta, we'd
// have to include the --verbose argument.
if (fetchChangePath) {
messages = _cmd.logVerbose(pathOrUrl, paths, revRange, stopOnCopy, limit);
} else {
messages = _cmd.log(pathOrUrl, revRange, stopOnCopy, limit);
}
return CmdLineLogMessage.createLogMessages(messages);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
private static void streamToFile(InputStream stream, File outFile) throws IOException {
int tempByte;
try {
FileOutputStream os = new FileOutputStream(outFile);
while ((tempByte = stream.read()) != -1) {
os.write(tempByte);
}
os.close();
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private static byte[] streamToByteArray(InputStream stream)
throws IOException {
//read byte-by-byte and put it in a vector.
//then take the vector and fill a byteArray.
Vector buffer = new Vector(1024);
int tempByte;
while ((tempByte = stream.read()) != -1) {
buffer.add(new Byte((byte) tempByte));
}
byte[] byteArray = new byte[buffer.size()];
for (int i = 0; i < byteArray.length; i++) {
Byte b = (Byte) buffer.get(i);
byteArray[i] = b.byteValue();
}
return byteArray;
}
protected ISVNAnnotations annotate(String target, SVNRevision revisionStart, SVNRevision revisionEnd) throws SVNClientException {
try {
notificationHandler.setCommand(ISVNNotifyListener.Command.ANNOTATE);
if(revisionStart == null)
revisionStart = new SVNRevision.Number(1);
if(revisionEnd == null)
revisionEnd = SVNRevision.HEAD;
byte[] annotations = _cmd.annotate(target,toString(revisionStart),toString(revisionEnd));
InputStream contents = _cmd.cat(target, revisionEnd.toString());
CmdLineAnnotations result = CmdLineAnnotations.createFromXml(annotations, contents);
try {
contents.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#blame(org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNRevision)
*/
public ISVNAnnotations annotate(SVNUrl url, SVNRevision revisionStart, SVNRevision revisionEnd)
throws SVNClientException
{
return annotate(toString(url), revisionStart, revisionEnd);
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#annotate(java.io.File, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNRevision)
*/
public ISVNAnnotations annotate(File file, SVNRevision revisionStart, SVNRevision revisionEnd)
throws SVNClientException
{
String target = toString(file);
//If the file is an uncommitted rename/move, we have to refer to original/source, not the new copy.
ISVNInfo info = getInfoFromWorkingCopy(file);
if ((SVNScheduleKind.ADD == info.getSchedule()) && (info.getCopyUrl() != null)) {
target = info.getCopyUrl().toString();
}
return annotate(target, revisionStart, revisionEnd);
}
/*
* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getProperties(java.io.File)
*/
public ISVNProperty[] getProperties(File path) throws SVNClientException {
try {
String propertiesString = _cmd.proplist(toString(path), false);
String propertyName;
List properties = new LinkedList();
StringTokenizer st = new StringTokenizer(propertiesString, Helper.NEWLINE);
while (st.hasMoreTokens()) {
String propertyLine = st.nextToken();
if (propertyLine.startsWith("Properties on '")) {
} else {
propertyName = propertyLine.substring(2);
properties.add(propertyGet(path,propertyName));
}
}
return (ISVNProperty[]) properties.toArray(new ISVNProperty[0]);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
public ISVNProperty[] getProperties(SVNUrl url) throws SVNClientException {
try {
String propertiesString = _cmd.proplist(url.toString(), false);
String propertyName;
List properties = new LinkedList();
StringTokenizer st = new StringTokenizer(propertiesString, Helper.NEWLINE);
while (st.hasMoreTokens()) {
String propertyLine = st.nextToken();
if (propertyLine.startsWith("Properties on '")) {
} else {
propertyName = propertyLine.substring(2);
properties.add(propertyGet(url,propertyName));
}
}
return (ISVNProperty[]) properties.toArray(new ISVNProperty[0]);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/**
* Remove 'conflicted' state on working copy files or directories
* @param path
* @throws SVNClientException
*/
public void resolved(File path)
throws SVNClientException
{
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(path));
_cmd.resolved(new String[] { toString(path) }, false);
// there is no notification when we do svn resolve, we will do notification ourselves
notificationHandler.notifyListenersOfChange(path.getAbsolutePath());
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#createRepository(java.io.File)
*/
public void createRepository(File path, String repositoryType) throws SVNClientException {
try {
svnAdminCmd.create(toString(path), repositoryType);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getStatus(java.io.File, boolean, boolean, boolean)
*/
public ISVNStatus[] getStatus(File path, boolean descend, boolean getAll, boolean contactServer) throws SVNClientException {
return getStatus(path, descend, getAll, contactServer, false);
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getStatus(java.io.File, boolean, boolean, boolean, boolean)
*/
public ISVNStatus[] getStatus(File path, boolean descend, boolean getAll, boolean contactServer, boolean ignoreExternals) throws SVNClientException {
try {
// first we get the status of the files
CmdLineStatusPart[] cmdLineStatusParts = getCmdStatuses(new File[] {path},descend, getAll, contactServer, ignoreExternals);
List targetsInfo = new ArrayList(cmdLineStatusParts.length);
List nonManagedParts = new ArrayList();
for (int i = 0; i < cmdLineStatusParts.length;i++) {
if (cmdLineStatusParts[i].isManaged()) {
targetsInfo.add(cmdLineStatusParts[i].getFile().toString());
} else {
nonManagedParts.add(new Integer(i));
}
}
// this is not enough, so we get info from the files
String infoLinesString = _cmd.info((String[]) targetsInfo.toArray(new String[targetsInfo.size()] ), null, null);
String[] parts = CmdLineInfoPart.parseInfoParts(infoLinesString);
CmdLineInfoPart[] cmdLineInfoParts = new CmdLineInfoPart[parts.length];
for (int i = 0; i < parts.length;i++) {
cmdLineInfoParts[i] = new CmdLineInfoPart(parts[i]);
}
CmdLineInfoPart[] allInfoParts = new CmdLineInfoPart[cmdLineStatusParts.length];
//Put the unversioned at corrent indexes.
for (Iterator iter = nonManagedParts.iterator(); iter.hasNext();) {
Integer indexOfNonManaged = (Integer) iter.next();
allInfoParts[indexOfNonManaged.intValue()] = CmdLineInfoPart.createUnversioned(null);
}
//Fill the remaining indexes with versioned infos.
for (int i = 0; i < cmdLineInfoParts.length; i++) {
for (int j = i; j < allInfoParts.length; j++) {
if (allInfoParts[j] == null) {
allInfoParts[j] = cmdLineInfoParts[i];
break;
}
}
}
CmdLineStatuses cmdLineStatuses = new CmdLineStatuses(cmdLineInfoParts, cmdLineStatusParts);
return cmdLineStatuses.toArray();
} catch (CmdLineException e) {
if (e.getMessage().trim().matches("svn:.*is not a working copy.*")) {
return new ISVNStatus[] {new SVNStatusUnversioned(path)};
}
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#cancelOperation()
*/
public void cancelOperation() throws SVNClientException {
notificationHandler.logMessage("Warning: operation canceled.");
_cmd.stopProcess();
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getInfoFromWorkingCopy(java.io.File)
*/
public ISVNInfo getInfoFromWorkingCopy(File path) throws SVNClientException {
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(path));
// first we get the status of the files to find out whether it is versioned
CmdLineStatusPart[] cmdLineStatusParts = getCmdStatuses(new File[] {path}, false, true, false, false);
// if the file is managed, it is safe to call info
if ((cmdLineStatusParts.length > 0) && (cmdLineStatusParts[0].isManaged())) {
String cmdLineInfoStrings = _cmd.info(new String[] { toString(path) }, null, null);
return new CmdLineInfoPart(cmdLineInfoStrings);
} else {
return CmdLineInfoPart.createUnversioned(path.getPath());
}
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getInfo(java.io.File)
*/
public ISVNInfo getInfo(File path) throws SVNClientException {
return getInfoFromWorkingCopy(path);
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getInfo(org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNRevision)
*/
public ISVNInfo getInfo(SVNUrl url, SVNRevision revision, SVNRevision peg) throws SVNClientException {
return getInfo(new SVNUrl[] { url }, revision, peg);
}
private ISVNInfo getInfo(SVNUrl[] urls, SVNRevision revision, SVNRevision peg) throws SVNClientException {
try {
String[] urlStrings = new String[urls.length];
for (int i = 0; i < urls.length; i++) {
urlStrings[i] = toString(urls[i]);
}
//notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(urls));
String cmdLineInfoStrings = _cmd.info(urlStrings, toString(revision), toString(peg));
return new CmdLineInfoPart(cmdLineInfoStrings);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getInfo(org.tigris.subversion.svnclientadapter.SVNUrl[])
*/
public ISVNInfo getInfo(SVNUrl[] urls) throws SVNClientException {
return getInfo(urls, null, null);
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#switchUrl(org.tigris.subversion.svnclientadapter.SVNUrl, java.io.File, org.tigris.subversion.svnclientadapter.SVNRevision, boolean)
*/
public void switchToUrl(File path, SVNUrl url, SVNRevision revision, boolean recurse) throws SVNClientException {
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(path));
_cmd.switchUrl(toString(path), toString(url), toString(revision), recurse);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#setConfigDirectory(java.io.File)
*/
public void setConfigDirectory(File dir) throws SVNClientException {
_cmd.setConfigDirectory(toString(dir));
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#cleanup(java.io.File)
*/
public void cleanup(File path) throws SVNClientException {
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(path));
_cmd.cleanup(toString(path));
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#merge(org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision, java.io.File, boolean, boolean, boolean, boolean)
*/
public void merge(SVNUrl path1, SVNRevision revision1, SVNUrl path2,
SVNRevision revision2, File localPath, boolean force,
boolean recurse, boolean dryRun, boolean ignoreAncestry) throws SVNClientException {
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(localPath));
_cmd.merge(toString(path1), toString(revision1), toString(path2), toString(revision2), toString(localPath), force, recurse, dryRun, ignoreAncestry);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#lock(SVNUrl[], java.lang.String, boolean)
*/
public void lock(SVNUrl[] uris, String comment, boolean force)
throws SVNClientException {
// notificationHandler isn't used because we're operating on
// the repository (rather than the WC).
try {
_cmd.lock(uris, comment, force);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#unlock(SVNUrl[], boolean)
*/
public void unlock(SVNUrl[] uris, boolean force)
throws SVNClientException {
// notificationHandler isn't used because we're operating on
// the repository (rather than the WC).
try {
_cmd.unlock(uris, force);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#lock(java.io.File[], java.lang.String, boolean)
*/
public void lock(File[] paths, String comment, boolean force)
throws SVNClientException {
String[] files = new String[paths.length];
for (int i = 0; i < paths.length; i++) {
files[i] = toString(paths[i]);
}
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(paths));
_cmd.lock(files, comment, force);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
finally {
for (int i = 0; i < files.length; i++) {
notificationHandler.notifyListenersOfChange(files[i]);
}
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#unlock(java.lang.String[], boolean)
*/
public void unlock(File[] paths, boolean force) throws SVNClientException {
String[] files = new String[paths.length];
for (int i = 0; i < paths.length; i++) {
files[i] = toString(paths[i]);
}
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(paths));
_cmd.unlock(files, force);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
finally {
for (int i = 0; i < files.length; i++) {
notificationHandler.notifyListenersOfChange(files[i]);
}
}
}
public String getAdminDirectoryName(){
if (dirName == null) {
// svn only supports this feature on Windows
if (isOsWindows())
dirName = getEnvironmentVariable("SVN_ASP_DOT_NET_HACK");
// If the environment variable was present, then use _svn
// as the directory name, otherwise the default of .svn
if (dirName != null)
dirName = "_svn";
else
dirName = ".svn";
}
return dirName;
}
public boolean isAdminDirectory(String name) {
return getAdminDirectoryName().equals(name);
}
public static String getEnvironmentVariable(String var) {
try {
// pre-Java 1.5 this throws an Error. On Java 1.5 it
// returns the environment variable
return System.getenv(var);
} catch(Error e) {
try {
// This means we are on 1.4. Get all variables into
// a Properties object and get the variable from that
return getEnvVars().getProperty(var);
} catch (Throwable e1) {
return null;
}
}
}
public static Properties getEnvVars() throws Throwable {
Process p = null;
Properties envVars = new Properties();
Runtime r = Runtime.getRuntime();
if (isOsWindows()) {
if (System.getProperty("os.name").toLowerCase().indexOf("windows 9") > -1)
p = r.exec( "command.com /c set" );
else
p = r.exec( "cmd.exe /c set" );
} else {
p = r.exec( "env" );
}
if (p != null) {
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line;
while( (line = br.readLine()) != null ) {
int idx = line.indexOf( '=' );
String key = line.substring( 0, idx );
String value = line.substring( idx+1 );
envVars.setProperty( key, value );
}
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
}
return envVars;
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getLogMessages(java.io.File, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNRevision, boolean)
*/
public ISVNLogMessage[] getLogMessages(File path, SVNRevision revStart,
SVNRevision revEnd, boolean fetchChangePath)
throws SVNClientException {
return getLogMessages(path, revStart, revEnd, false, fetchChangePath);
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getLogMessages(java.io.File, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNRevision, boolean, boolean)
*/
public ISVNLogMessage[] getLogMessages(File path, SVNRevision revStart,
SVNRevision revEnd, boolean stopOnCopy, boolean fetchChangePath)
throws SVNClientException {
return getLogMessages(path, revStart, revEnd, stopOnCopy,
fetchChangePath, 0);
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getLogMessages(java.io.File, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNRevision, boolean, boolean, long)
*/
public ISVNLogMessage[] getLogMessages(File path, SVNRevision revStart,
SVNRevision revEnd, boolean stopOnCopy, boolean fetchChangePath,
long limit) throws SVNClientException {
String target = toString(path);
//If the file is an uncommitted rename/move, we have to refer to original/source, not the new copy.
ISVNInfo info = getInfoFromWorkingCopy(path);
if ((SVNScheduleKind.ADD == info.getSchedule()) && (info.getCopyUrl() != null)) {
target = info.getCopyUrl().toString();
}
return getLogMessages(target, null, revStart, revEnd, stopOnCopy,
fetchChangePath, limit);
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getLogMessages(org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNRevision, boolean)
*/
public ISVNLogMessage[] getLogMessages(SVNUrl url, SVNRevision revStart,
SVNRevision revEnd, boolean fetchChangePath)
throws SVNClientException {
return getLogMessages(url, null, revStart, revEnd, false,
fetchChangePath);
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getLogMessages(org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNRevision, boolean, boolean, long)
*/
public ISVNLogMessage[] getLogMessages(SVNUrl url, SVNRevision pegRevision,
SVNRevision revStart, SVNRevision revEnd, boolean stopOnCopy,
boolean fetchChangePath, long limit) throws SVNClientException {
//TODO pegRevision not supported !
return getLogMessages(toString(url), null, revStart, revEnd, stopOnCopy,
fetchChangePath, limit);
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#getLogMessages(org.tigris.subversion.svnclientadapter.SVNUrl, java.lang.String[], org.tigris.subversion.svnclientadapter.SVNRevision, org.tigris.subversion.svnclientadapter.SVNRevision, boolean, boolean)
*/
public ISVNLogMessage[] getLogMessages(SVNUrl url, String[] paths,
SVNRevision revStart, SVNRevision revEnd, boolean stopOnCopy,
boolean fetchChangePath) throws SVNClientException {
return getLogMessages(toString(url), paths, revStart, revEnd, stopOnCopy,
fetchChangePath, 0);
}
public void relocate(String from, String to, String path, boolean recurse)
throws SVNClientException {
try {
notificationHandler.setBaseDir(SVNBaseDir.getBaseDir(new File(path)));
_cmd.relocate(from, to, path, recurse);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
/* (non-Javadoc)
* @see org.tigris.subversion.svnclientadapter.ISVNClientAdapter#diff(java.io.File, org.tigris.subversion.svnclientadapter.SVNUrl, org.tigris.subversion.svnclientadapter.SVNRevision, java.io.File, boolean)
*/
public void diff(File path, SVNUrl url, SVNRevision urlRevision,
File outFile, boolean recurse) throws SVNClientException {
diff(
toString(path),
null,
toString(url) + "@" + toString(urlRevision),
null,
outFile,
recurse, true, false, false);
}
public void addConflictResolutionCallback(ISVNConflictResolver callback) {
// TODO
}
public ISVNAnnotations annotate(File file, SVNRevision revisionStart,
SVNRevision revisionEnd, boolean ignoreMimeType,
boolean includeMergedRevisions) throws SVNClientException {
notImplementedYet();
return null;
}
public ISVNAnnotations annotate(SVNUrl url, SVNRevision revisionStart,
SVNRevision revisionEnd, boolean ignoreMimeType,
boolean includeMergedRevisions) throws SVNClientException {
notImplementedYet();
return null;
}
public ISVNLogMessage[] getLogMessages(File path, SVNRevision pegRevision,
SVNRevision revisionStart, SVNRevision revisionEnd,
boolean stopOnCopy, boolean fetchChangePath, long limit,
boolean includeMergedRevisions) throws SVNClientException {
notImplementedYet();
return null;
}
public ISVNLogMessage[] getLogMessages(SVNUrl url, SVNRevision pegRevision,
SVNRevision revisionStart, SVNRevision revisionEnd,
boolean stopOnCopy, boolean fetchChangePath, long limit,
boolean includeMergedRevisions) throws SVNClientException {
notImplementedYet();
return null;
}
public ISVNMergeInfo getMergeInfo(File path, SVNRevision revision)
throws SVNClientException {
notImplementedYet();
return null;
}
public ISVNMergeInfo getMergeInfo(SVNUrl url, SVNRevision revision)
throws SVNClientException {
notImplementedYet();
return null;
}
public void merge(SVNUrl url, SVNRevision pegRevision,
SVNRevisionRange[] revisions, File localPath, boolean force,
int depth, boolean ignoreAncestry, boolean dryRun)
throws SVNClientException {
notImplementedYet();
}
public SVNDiffSummary[] diffSummarize(File target, SVNRevision pegRevision, SVNRevision startRevision, SVNRevision endRevision, int depth, boolean ignoreAncestry) throws SVNClientException {
notImplementedYet();
return null;
}
public SVNDiffSummary[] diffSummarize(File target1, SVNRevision revision1, SVNUrl target2, SVNRevision revision2, int depth, boolean ignoreAncestry) throws SVNClientException {
notImplementedYet();
return null;
}
public SVNDiffSummary[] diffSummarize(SVNUrl target, SVNRevision pegRevision, SVNRevision startRevision, SVNRevision endRevision, int depth, boolean ignoreAncestry) throws SVNClientException {
notImplementedYet();
return null;
}
public SVNDiffSummary[] diffSummarize(SVNUrl target1, SVNRevision revision1, SVNUrl target2, SVNRevision revision2, int depth, boolean ignoreAncestry) throws SVNClientException {
notImplementedYet();
return null;
}
public String[] suggestMergeSources(File path) throws SVNClientException {
notImplementedYet();
return null;
}
public String[] suggestMergeSources(SVNUrl url, SVNRevision peg) throws SVNClientException {
notImplementedYet();
return null;
}
public void checkout(SVNUrl moduleName, File destPath,
SVNRevision revision, int depth, boolean ignoreExternals,
boolean force) throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public void copy(SVNUrl srcUrl, SVNUrl destUrl, String message,
SVNRevision revision, boolean makeParents)
throws SVNClientException {
try {
if (message == null)
message = "";
_cmd.copy(toString(srcUrl), toString(destUrl), message, toString(revision), makeParents);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
public void diff(SVNUrl target, SVNRevision pegRevision,
SVNRevision startRevision, SVNRevision endRevision, File outFile,
int depth, boolean ignoreAncestry, boolean noDiffDeleted,
boolean force) throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public void diff(SVNUrl target, SVNRevision pegRevision,
SVNRevision startRevision, SVNRevision endRevision, File outFile,
boolean recurse) throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public void dispose() {
// TODO Auto-generated method stub
}
public InputStream getContent(SVNUrl url, SVNRevision revision,
SVNRevision pegRevision) throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
return null;
}
public ISVNDirEntry[] getList(SVNUrl url, SVNRevision revision,
SVNRevision pegRevision, boolean recurse) throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
return null;
}
public ISVNDirEntry[] getList(File path, SVNRevision revision,
SVNRevision pegRevision, boolean recurse) throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
return null;
}
public void resolve(File path, int result) throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public void setProgressListener(ISVNProgressListener progressListener) {
// TODO Auto-generated method stub
}
public void merge(SVNUrl url, SVNRevision pegRevision,
SVNRevisionRange[] revisions, File localPath, boolean force,
int depth, boolean ignoreAncestry, boolean dryRun,
boolean recordOnly) throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public void merge(SVNUrl path1, SVNRevision revision1, SVNUrl path2,
SVNRevision revision2, File localPath, boolean force, int depth,
boolean dryRun, boolean ignoreAncestry, boolean recordOnly)
throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public void copy(File[] srcPaths, SVNUrl destUrl, String message,
boolean copyAsChild, boolean makeParents) throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public void copy(SVNUrl[] srcUrls, SVNUrl destUrl, String message,
SVNRevision revision, boolean copyAsChild, boolean makeParents)
throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public void switchToUrl(File path, SVNUrl url, SVNRevision revision,
int depth, boolean setDepth, boolean ignoreExternals, boolean force)
throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public void switchToUrl(File path, SVNUrl url, SVNRevision revision,
SVNRevision pegRevision, int depth, boolean setDepth,
boolean ignoreExternals, boolean force) throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public long update(File path, SVNRevision revision, int depth,
boolean setDepth, boolean ignoreExternals, boolean force)
throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
return 0;
}
public long[] update(File[] path, SVNRevision revision, int depth,
boolean setDepth, boolean ignoreExternals, boolean force)
throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
return null;
}
public void mergeReintegrate(SVNUrl path, SVNRevision pegRevision,
File localPath, boolean force, boolean dryRun)
throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public void copy(SVNUrl srcUrl, File destPath, SVNRevision revision,
boolean copyAsChild, boolean makeParents) throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public ISVNLogMessage[] getMergeinfoLog(int kind, File path,
SVNRevision pegRevision, SVNUrl mergeSourceUrl,
SVNRevision srcPegRevision, boolean discoverChangedPaths)
throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
return null;
}
public ISVNLogMessage[] getMergeinfoLog(int kind, SVNUrl url,
SVNRevision pegRevision, SVNUrl mergeSourceUrl,
SVNRevision srcPegRevision, boolean discoverChangedPaths)
throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
return null;
}
public void getLogMessages(File path, SVNRevision pegRevision,
SVNRevision revisionStart, SVNRevision revisionEnd,
boolean stopOnCopy, boolean fetchChangePath, long limit,
boolean includeMergedRevisions, String[] requestedProperties,
ISVNLogMessageCallback callback) throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public void getLogMessages(SVNUrl url, SVNRevision pegRevision,
SVNRevision revisionStart, SVNRevision revisionEnd,
boolean stopOnCopy, boolean fetchChangePath, long limit,
boolean includeMergedRevisions, String[] requestedProperties,
ISVNLogMessageCallback callback) throws SVNClientException {
// TODO Auto-generated method stub
notImplementedYet();
}
public void copy(SVNUrl srcUrl, File destPath, SVNRevision revision,
SVNRevision pegRevision, boolean copyAsChild, boolean makeParents)
throws SVNClientException {
// TODO Auto-generated method stub
}
public ISVNInfo[] getInfo(File file, boolean descend)
throws SVNClientException {
// TODO Auto-generated method stub
return null;
}
public String getRevProperty(SVNUrl path, Number revisionNo, String propName)
throws SVNClientException {
// TODO Auto-generated method stub
return null;
}
public ISVNAnnotations annotate(SVNUrl url, SVNRevision revisionStart,
SVNRevision revisionEnd, SVNRevision pegRevision,
boolean ignoreMimeType, boolean includeMergedRevisions)
throws SVNClientException {
// TODO Auto-generated method stub
return null;
}
public ISVNAnnotations annotate(File file, SVNRevision revisionStart,
SVNRevision revisionEnd, SVNRevision pegRevision,
boolean ignoreMimeType, boolean includeMergedRevisions)
throws SVNClientException {
// TODO Auto-generated method stub
return null;
}
public ISVNProperty[] getProperties(SVNUrl url, SVNRevision revision,
SVNRevision peg) throws SVNClientException {
// TODO Auto-generated method stub
return null;
}
public ISVNProperty[] getRevProperties(SVNUrl url, Number revision)
throws SVNClientException {
// TODO Auto-generated method stub
return null;
}
public SVNDiffSummary[] diffSummarize(File path, SVNUrl toUrl,
SVNRevision toRevision, boolean recurse) throws SVNClientException {
// TODO Auto-generated method stub
return null;
}
@Override
public String getPostCommitError() {
// TODO Auto-generated method stub
return null;
}
@Override
public ISVNStatus[] getStatus(File path, boolean descend, boolean getAll,
boolean contactServer, boolean ignoreExternals,
ISVNStatusCallback callback) throws SVNClientException {
// TODO Auto-generated method stub
return null;
}
@Override
public void propertySet(SVNUrl url, Number baseRev, String propertyName,
String propertyValue, String message) throws SVNClientException {
// TODO Auto-generated method stub
}
@Override
public ISVNProperty[] getProperties(File path, boolean descend)
throws SVNClientException {
// TODO Auto-generated method stub
return null;
}
@Override
public ISVNProperty[] getProperties(SVNUrl url, SVNRevision revision,
SVNRevision peg, boolean recurse) throws SVNClientException {
// TODO Auto-generated method stub
return null;
}
@Override
public void switchToUrl(File path, SVNUrl url, SVNRevision revision,
SVNRevision pegRevision, int depth, boolean setDepth,
boolean ignoreExternals, boolean force, boolean ignoreAncestry)
throws SVNClientException {
// TODO Auto-generated method stub
}
@Override
public void upgrade(File dir) throws SVNClientException {
// TODO Auto-generated method stub
}
@Override
public void copy(SVNUrl srcUrl, SVNUrl destUrl, String message,
SVNRevision revision, boolean makeParents, boolean force)
throws SVNClientException {
// TODO Auto-generated method stub
try {
if (message == null)
message = "";
_cmd.copy(toString(srcUrl), toString(destUrl), message, toString(revision), false, false);
} catch (CmdLineException e) {
throw SVNClientException.wrapException(e);
}
}
}
SvnCommandLine.java - Included Force option into actual svncopy command
Posted 2013-03-26 00:25:13 by sendhilsubramani
LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioKICogQ29weXJpZ2h0IChjKSAyMDA0LCAyMDA2IHN2bkNs
aWVudEFkYXB0ZXIgcHJvamVjdCBhbmQgb3RoZXJzLgogKgogKiBMaWNlbnNlZCB1bmRlciB0aGUg
QXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKICogeW91IG1heSBu
b3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLgog
KiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKICoKICogICAgIGh0dHA6
Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKgogKiBVbmxlc3MgcmVxdWly
ZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiAq
IGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICJBUyBJ
UyIgQkFTSVMsCiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5E
LCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLgogKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBz
cGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiAqIGxpbWl0YXRpb25z
IHVuZGVyIHRoZSBMaWNlbnNlLgogKgogKiBDb250cmlidXRvcnM6CiAqICAgICBzdm5DbGllbnRB
ZGFwdGVyIHByb2plY3QgY29tbWl0dGVycyAtIGluaXRpYWwgQVBJIGFuZCBpbXBsZW1lbnRhdGlv
bgogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqLwpwYWNrYWdlIG9yZy50aWdyaXMuc3VidmVyc2lvbi5z
dm5jbGllbnRhZGFwdGVyLmNvbW1hbmRsaW5lOwoKaW1wb3J0IGphdmEuaW8uSW5wdXRTdHJlYW07
CgppbXBvcnQgb3JnLnRpZ3Jpcy5zdWJ2ZXJzaW9uLnN2bmNsaWVudGFkYXB0ZXIuSVNWTk5vdGlm
eUxpc3RlbmVyOwppbXBvcnQgb3JnLnRpZ3Jpcy5zdWJ2ZXJzaW9uLnN2bmNsaWVudGFkYXB0ZXIu
U1ZOUmV2aXNpb247CmltcG9ydCBvcmcudGlncmlzLnN1YnZlcnNpb24uc3ZuY2xpZW50YWRhcHRl
ci5jb21tYW5kbGluZS5wYXJzZXIuU3ZuT3V0cHV0UGFyc2VyOwoKLyoqCiAqIDxwPgogKiBQZXJm
b3JtcyB0aGUgZ3J1bnR3b3JrIG9mIGNhbGxpbmcgInN2biIuCiAqIElzIGEgYmFyZS1ib25lcyBp
bnRlcmZhY2UgdG8gdXNpbmcgdGhlIFN1YnZlcnNpb24gY29tbWFuZGxpbmUgY2xpZW50LjwvcD4K
ICogIAogKiBAYXV0aG9yIFBoaWxpcCBTY2hhdHogKHNjaGF0eiBhdCB0aWdyaXMpCiAqIEBhdXRo
b3IgQ++/vWRyaWMgQ2hhYmFub2lzIChjY2hhYmFub2lzIGF0IG5vLWxvZy5vcmcpCiAqIEBhdXRo
b3IgSm9obiBNIEZsaW5jaGJhdWdoIChqb2huIGF0IGhqc29mdC5jb20pCiAqLwpwdWJsaWMgY2xh
c3MgU3ZuQ29tbWFuZExpbmUgZXh0ZW5kcyBDb21tYW5kTGluZSB7Cglwcm90ZWN0ZWQgU3RyaW5n
IHVzZXI7Cglwcm90ZWN0ZWQgU3RyaW5nIHBhc3M7CQogICAgcHJvdGVjdGVkIFN2bk91dHB1dFBh
cnNlciBzdm5PdXRwdXRQYXJzZXIgPSBuZXcgU3ZuT3V0cHV0UGFyc2VyKCk7CiAgICBwcm90ZWN0
ZWQgbG9uZyByZXYgPSBTVk5SZXZpc2lvbi5TVk5fSU5WQUxJRF9SRVZOVU07CiAgICBwcm90ZWN0
ZWQgYm9vbGVhbiBwYXJzZVN2bk91dHB1dCA9IGZhbHNlOwogICAgcHJvdGVjdGVkIFN0cmluZyBj
b25maWdEaXIgPSBudWxsOwogICAgCiAgICAKCS8vQ29uc3RydWN0b3JzCglTdm5Db21tYW5kTGlu
ZShTdHJpbmcgc3ZuUGF0aCxDbWRMaW5lTm90aWZpY2F0aW9uSGFuZGxlciBub3RpZmljYXRpb25I
YW5kbGVyKSB7CgkJc3VwZXIoc3ZuUGF0aCxub3RpZmljYXRpb25IYW5kbGVyKTsKCX0JCgkKICAg
IC8qKgogICAgICogCiAgICAgKiBAcGFyYW0gcmV2aXNpb24KICAgICAqIEByZXR1cm4gIkhFQUQi
IGlmIHJldmlzaW9uIGlzIGEgbnVsbCBvciBlbXB0eSBzdHJpbmcsIHJldHVybiByZXZpc2lvbiBv
dGhlcndpc2UKICAgICAqLwoJcHJvdGVjdGVkIHN0YXRpYyBTdHJpbmcgdmFsaWRSZXYoU3RyaW5n
IHJldmlzaW9uKSB7CgkJcmV0dXJuIChyZXZpc2lvbiA9PSBudWxsIHx8ICIiLmVxdWFscyhyZXZp
c2lvbikpID8gIkhFQUQiIDogcmV2aXNpb247Cgl9CQoJCgkvKioKCSAqIDxwPgoJICogU2V0cyB0
aGUgdXNlcm5hbWUgdXNlZCBieSB0aGlzIGNsaWVudC48L3A+CgkgKiAKCSAqIEBwYXJhbSB1c2Vy
bmFtZSBUaGUgdXNlcm5hbWUgdG8gdXNlIGZvciBhdXRoZW50aWNhdGlvbi4KCSAqLwoJdm9pZCBz
ZXRVc2VybmFtZShTdHJpbmcgdXNlcm5hbWUpIHsKCQl1c2VyID0gdXNlcm5hbWU7Cgl9CgoJLyoq
CgkgKiA8cD4KCSAqIFNldHMgdGhlIHBhc3N3b3JkIHVzZWQgYnkgdGhpcyBjbGllbnQuPC9wPgoJ
ICogCgkgKiBAcGFyYW0gcGFzc3dvcmQgVGhlIHBhc3N3b3JkIHRvIHVzZSBmb3IgYXV0aGVudGlj
YXRpb24uCgkgKi8KCXZvaWQgc2V0UGFzc3dvcmQoU3RyaW5nIHBhc3N3b3JkKSB7CgkJcGFzcyA9
IHBhc3N3b3JkOwoJfQkKCiAgICAKICAgIC8qKgogICAgICogc2V0IHRoZSBkaXJlY3RvcnkgZnJv
bSB3aGljaCB1c2VyIGNvbmZpZ3VyYXRpb24gZmlsZXMgd2lsbCBiZSByZWFkCiAgICAgKi8KICAg
IHZvaWQgc2V0Q29uZmlnRGlyZWN0b3J5KFN0cmluZyBkaXIpIHsKICAgIAljb25maWdEaXIgPSBk
aXI7CiAgICB9CiAgICAKCQoJLyogKG5vbi1KYXZhZG9jKQoJICogQHNlZSBvcmcudGlncmlzLnN1
YnZlcnNpb24uc3ZuY2xpZW50YWRhcHRlci5jb21tYW5kbGluZS5Db21tYW5kTGluZSN2ZXJzaW9u
KCkKCSAqLwoJU3RyaW5nIHZlcnNpb24oKSB0aHJvd3MgQ21kTGluZUV4Y2VwdGlvbiB7CgkJc2V0
Q29tbWFuZChJU1ZOTm90aWZ5TGlzdGVuZXIuQ29tbWFuZC5VTkRFRklORUQsIGZhbHNlKTsKCQly
ZXR1cm4gc3VwZXIudmVyc2lvbigpOwoJfQoJCgkvKioKCSAqIDxwPgoJICogQWRkcyBhbiB1bnZl
cnNpb25lZCBmaWxlIGludG8gdGhlIHJlcG9zaXRvcnkuPC9wPgoJICogCgkgKiBAcGFyYW0gcmVz
b3VyY2UgTG9jYWwgcGF0aCBvZiByZXNvdXJjZSB0byBhZGQuCgkgKiBAcGFyYW0gcmVjdXJzaXZl
IHRydWUgaWYgdGhpcyBpcyBhIGRpcmVjdG9yeQoJICogICBhbmQgaXRzIGNoaWxkcmVuIHNob3Vs
ZCBiZSB0cmF2ZXJzZWQKCSAqICAgcmVjdXJzaXZlbHkuCgkgKiBAcGFyYW0gZm9yY2UgdHJ1ZSBp
ZiB0aGlzIGlzIGEgZGlyZWN0b3J5IHRoYXQgCgkgKiAgIHNob3VsZCBiZSBzY2FubmVkIGV2ZW4g
aWYgaXQncyBhbHJlYWR5IGFkZGVkCgkgKgkgdG8gdGhlIHJlcG9zaXRvcnkKCSAqLwoJU3RyaW5n
IGFkZChTdHJpbmcgcGF0aCwgYm9vbGVhbiByZWN1cnNpdmUsIGJvb2xlYW4gZm9yY2UpIHRocm93
cyBDbWRMaW5lRXhjZXB0aW9uIHsKCQlzZXRDb21tYW5kKElTVk5Ob3RpZnlMaXN0ZW5lci5Db21t
YW5kLkFERCwgdHJ1ZSk7CgkJQ21kQXJndW1lbnRzIGFyZ3MgPSBuZXcgQ21kQXJndW1lbnRzKCk7
CgkJYXJncy5hZGQoImFkZCIpOwoJCWlmICghcmVjdXJzaXZlKQoJCQlhcmdzLmFkZCgiLU4iKTsK
CQlpZiAoZm9yY2UpCgkJCWFyZ3MuYWRkKCItLWZvcmNlIik7CgkJYXJncy5hZGQocGF0aCk7CgkJ
cmV0dXJuIGV4ZWNTdHJpbmcoYXJncyxmYWxzZSk7Cgl9CgoJLyoqCgkgKiA8cD4KCSAqIE91dHB1
dCB0aGUgY29udGVudCBvZiBzcGVjaWZpZWQgZmlsZSBvciBVUkwuPC9wPgoJICogCgkgKiBAcGFy
YW0gdXJsIEVpdGhlciB0aGUgbG9jYWwgcGF0aCB0byBhIGZpbGUsIG9yIFVSTAoJICogICB0byBw
cmludCB0aGUgY29udGVudHMgb2YuCgkgKiBAcmV0dXJuIEFuIHN0cmVhbSBjb250YWluaW5nIHRo
ZSBjb250ZW50cyBvZiB0aGUgZmlsZS4KCSAqLwoJSW5wdXRTdHJlYW0gY2F0KFN0cmluZyB1cmws
IFN0cmluZyByZXZpc2lvbikgdGhyb3dzIENtZExpbmVFeGNlcHRpb24gewogICAgICAgIHNldENv
bW1hbmQoSVNWTk5vdGlmeUxpc3RlbmVyLkNvbW1hbmQuQ0FULCBmYWxzZSk7CgkJQ21kQXJndW1l
bnRzIGFyZ3MgPSBuZXcgQ21kQXJndW1lbnRzKCk7CgkJYXJncy5hZGQoImNhdCIpOwoJCWFyZ3Mu
YWRkKCItciIpOwoJCWFyZ3MuYWRkKHZhbGlkUmV2KHJldmlzaW9uKSk7CgkJYXJncy5hZGQodXJs
KTsKCQlhcmdzLmFkZEF1dGhJbmZvKHRoaXMudXNlciwgdGhpcy5wYXNzKTsKICAgICAgICBhcmdz
LmFkZENvbmZpZ0luZm8odGhpcy5jb25maWdEaXIpOwoJCXJldHVybiBleGVjSW5wdXRTdHJlYW0o
YXJncyk7Cgl9CgoJLyoqCgkgKiA8cD4KCSAqIFNlbmQgY2hhbmdlcyBmcm9tIHlvdXIgd29ya2lu
ZyBjb3B5IHRvIHRoZSAKCSAqIHJlcG9zaXRvcnkuPC9wPgoJICogICAKCSAqIEBwYXJhbSBwYXRo
IFRoZSBsb2NhbCBwYXRoIHRvIHRoZSBmb2xkZXIocykvZmlsZShzKQoJICogICB0byBjb21taXQu
CgkgKiBAcGFyYW0gbWVzc2FnZSBUaGUgbWVzc2FnZSBhc3NvY2lhdGVkIHdpdGggdGhlCgkgKiAg
IGNvbW1pdHRlZCByZXNvdXJjZXMuCgkgKiBAdGhyb3dzIENtZExpbmVFeGNlcHRpb24KCSAqLwoJ
U3RyaW5nIGNoZWNraW4oU3RyaW5nW10gcGF0aCwgU3RyaW5nIG1lc3NhZ2UsIGJvb2xlYW4ga2Vl
cExvY2tzKSB0aHJvd3MgQ21kTGluZUV4Y2VwdGlvbiB7CiAgICAgICAgc2V0Q29tbWFuZChJU1ZO
Tm90aWZ5TGlzdGVuZXIuQ29tbWFuZC5DT01NSVQsIHRydWUpOwoJCUNtZEFyZ3VtZW50cyBhcmdz
ID0gbmV3IENtZEFyZ3VtZW50cygpOwoJCWFyZ3MuYWRkKCJjaSIpOwoJCWlmIChrZWVwTG9ja3Mp
CgkJICAgIGFyZ3MuYWRkKCItLW5vLXVubG9jayIpOwoJCWFyZ3MuYWRkTG9nTWVzc2FnZShtZXNz
YWdlKTsKCQlhcmdzLmFkZEF1dGhJbmZvKHRoaXMudXNlciwgdGhpcy5wYXNzKTsKICAgICAgICBh
cmdzLmFkZENvbmZpZ0luZm8odGhpcy5jb25maWdEaXIpOwoJCSAgICAgICAgCiAgICAgICAgZm9y
IChpbnQgaSA9IDA7IGkgPCBwYXRoLmxlbmd0aDtpKyspIHsKICAgICAgICAJYXJncy5hZGQocGF0
aFtpXSk7CiAgICAgICAgfQogICAgICAgIAoJCXJldHVybiBleGVjU3RyaW5nKGFyZ3MsZmFsc2Up
OwoJfQoKCS8qKgoJICogPHA+CgkgKiBSZWN1cnNpdmVseSBjbGVhbiB1cCB0aGUgd29ya2luZyBj
b3B5LCAKCSAqIHJlbW92aW5nIGxvY2tzLCByZXN1bWluZyB1bmZpbmlzaGVkIG9wZXJhdGlvbnMu
PC9wPgoJICogCgkgKiBAcGFyYW0gcGF0aCBUaGUgbG9jYWwgcGF0aCB0byBjbGVhbiB1cC4KCSAq
LwoJdm9pZCBjbGVhbnVwKFN0cmluZyBwYXRoKSB0aHJvd3MgQ21kTGluZUV4Y2VwdGlvbiB7CiAg
ICAgICAgc2V0Q29tbWFuZChJU1ZOTm90aWZ5TGlzdGVuZXIuQ29tbWFuZC5DTEVBTlVQLCB0cnVl
KTsKCQlDbWRBcmd1bWVudHMgYXJncyA9IG5ldyBDbWRBcmd1bWVudHMoKTsKCQlhcmdzLmFkZCgi
Y2xlYW51cCIpOwoJCWFyZ3MuYWRkKHBhdGgpOwogICAgICAgIGFyZ3MuYWRkQ29uZmlnSW5mbyh0
aGlzLmNvbmZpZ0Rpcik7ICAgICAgICAKCQlleGVjVm9pZChhcmdzKTsKCX0KCgkvKioKCSAqIDxw
PgoJICogQ2hlY2sgb3V0IGEgd29ya2luZyBjb3B5IGZyb20gYSByZXBvc2l0b3J5LjwvcD4KCSAq
CgkgKiBAcGFyYW0gdXJsIFRoZSBVUkwgdG8gY2hlY2sgb3V0IGZyb20uCgkgKiBAcGFyYW0gZGVz
dGluYXRpb24gVGhlIGxvY2FsIGRpcmVjdG9yeSB0byBjaGVjayBvdXQgdG8uCgkgKiBAcGFyYW0g
cmV2aXNpb24gVGhlIHJldmlzaW9uIHRvIGNoZWNrIG91dC4KCSAqICAgRGVmYXVsdHMgdG8gPHR0
PiJIRUFEIjwvdHQ+LgoJICogQHBhcmFtIHJlY3Vyc2l2ZSB0cnVlIGlmIHN1YmRpcnMgc2hvdWxk
IGJlIGNoZWNrZWQgb3V0IHJlY3Vyc2l2ZWx5LgoJICogQHRocm93cyBDbWRMaW5lRXhjZXB0aW9u
CgkgKi8KCVN0cmluZyBjaGVja291dChTdHJpbmcgdXJsLCBTdHJpbmcgZGVzdGluYXRpb24sIFN0
cmluZyByZXZpc2lvbiwgYm9vbGVhbiByZWN1cnNpdmUpCgkJdGhyb3dzIENtZExpbmVFeGNlcHRp
b24gewogICAgICAgIHNldENvbW1hbmQoSVNWTk5vdGlmeUxpc3RlbmVyLkNvbW1hbmQuQ0hFQ0tP
VVQsIHRydWUpOwoJCUNtZEFyZ3VtZW50cyBhcmdzID0gbmV3IENtZEFyZ3VtZW50cygpOwoJCWFy
Z3MuYWRkKCJjbyIpOwoJCWFyZ3MuYWRkKCItciIpOwoJCWFyZ3MuYWRkKHZhbGlkUmV2KHJldmlz
aW9uKSk7CgkJYXJncy5hZGQodXJsICsgIkAiICsgdmFsaWRSZXYocmV2aXNpb24pKTsKCQlhcmdz
LmFkZChkZXN0aW5hdGlvbik7CgkJCgkJaWYgKCFyZWN1cnNpdmUpCgkJCWFyZ3MuYWRkKCItTiIp
OwoJCWFyZ3MuYWRkQXV0aEluZm8odGhpcy51c2VyLCB0aGlzLnBhc3MpOwogICAgICAgIGFyZ3Mu
YWRkQ29uZmlnSW5mbyh0aGlzLmNvbmZpZ0Rpcik7CgkJcmV0dXJuIGV4ZWNTdHJpbmcoYXJncyxm
YWxzZSk7Cgl9CgoJLyoqCgkgKiA8cD4KCSAqIER1cGxpY2F0ZSBzb21ldGhpbmcgaW4gd29ya2lu
ZyBjb3B5IG9yIHJlcG9zLAoJICogcmVtZW1iZXJpbmcgaGlzdG9yeS48L3A+CgkgKiAKCSAqIDxw
PgoJICogPHR0PnNyYzwvdHQ+IGFuZCA8dHQ+ZGVzdDwvdHQ+IGNhbiBlYWNoIGJlIGVpdGhlciBh
IHdvcmtpbmcgY29weSAoV0MpIHBhdGggb3IgVVJMLjwvcD4KCSAqIDxkbD4KCSAqIDxkdD5XQyAt
Jmd0OyBXQzwvZHQ+CgkgKiA8ZGQ+Y29weSBhbmQgc2NoZWR1bGUgZm9yIGFkZGl0aW9uICh3aXRo
IGhpc3RvcnkpPC9kZD4KCSAqIAoJICogPGR0PldDIC0mZ3Q7IFVSTDwvZHQ+CgkgKiA8ZGQ+aW1t
ZWRpYXRlbHkgY29tbWl0IGEgY29weSBvZiBXQyB0byBVUkw8L2RkPgoJICogCgkgKiA8ZHQ+VVJM
IC0mZ3Q7IFdDPC9kdD4KCSAqIDxkZD5jaGVjayBvdXQgVVJMIGludG8gV0MsIHNjaGVkdWxlIGZv
ciBhZGRpdGlvbjwvZGQ+CgkgKiAKCSAqIDxkdD5VUkwgLSZndDsgVVJMPC9kdD4KCSAqIDxkZD5j
b21wbGV0ZSBzZXJ2ZXItc2lkZSBjb3B5OyAgdXNlZCB0byBicmFuY2ggYW5kIHRhZzwvZGQ+Cgkg
KiA8L2RsPgoJICogCgkgKiBAcGFyYW0gc3JjIExvY2FsIHBhdGggb3IgVVJMIHRvIGNvcHkgZnJv
bS4KCSAqIEBwYXJhbSBkZXN0IExvY2FsIHBhdGggb3IgVVJMIHRvIGNvcHkgdG8uCgkgKiBAcGFy
YW0gbWVzc2FnZSBDb21taXQgbWVzc2FnZS4KCSAqIEBwYXJhbSByZXZpc2lvbiBPcHRpb25hbCBy
ZXZpc2lvbiB0byBjb3B5IGZyb20uIAoJICogQHBhcmFtIG1ha2VwYXJlbnRzICAgPGNvZGU+dHJ1
ZTwvY29kZT4gPD0+IENyZWF0ZSBwYXJlbnRzIGZpcnN0IHdoZW4gY29weWluZyBmcm9tIHNvdXJj
ZSB1cmwgdG8gZGVzdCB1cmwuCgkgKi8KCXZvaWQgY29weShTdHJpbmcgc3JjLCBTdHJpbmcgZGVz
dCwgU3RyaW5nIG1lc3NhZ2UsIFN0cmluZyByZXZpc2lvbiwgYm9vbGVhbiBtYWtlcGFyZW50cykg
dGhyb3dzIENtZExpbmVFeGNlcHRpb24gewogICAgICAgIHNldENvbW1hbmQoSVNWTk5vdGlmeUxp
c3RlbmVyLkNvbW1hbmQuQ09QWSwgdHJ1ZSk7ICAgICAgICAKCQlDbWRBcmd1bWVudHMgYXJncyA9
IG5ldyBDbWRBcmd1bWVudHMoKTsKCQlhcmdzLmFkZCgiY3AiKTsKCQlpZiAocmV2aXNpb24gIT0g
bnVsbCkgewoJCQlhcmdzLmFkZCgiLXIiKTsKCQkJYXJncy5hZGQodmFsaWRSZXYocmV2aXNpb24p
KTsKCQl9CgkJaWYgKG1ha2VwYXJlbnRzKSB7CgkJICBhcmdzLmFkZCgiLS1wYXJlbnRzIik7CgkJ
fQoJCWlmIChtZXNzYWdlICE9IG51bGwpCgkJCWFyZ3MuYWRkTG9nTWVzc2FnZShtZXNzYWdlKTsK
CQlhcmdzLmFkZChzcmMpOwoJCWFyZ3MuYWRkKGRlc3QpOwoJCWFyZ3MuYWRkQXV0aEluZm8odGhp
cy51c2VyLCB0aGlzLnBhc3MpOwogICAgICAgIGFyZ3MuYWRkQ29uZmlnSW5mbyh0aGlzLmNvbmZp
Z0Rpcik7CQkKCQlleGVjVm9pZChhcmdzKTsKCX0KCgkvKioKCSAqIDxwPgoJICogRHVwbGljYXRl
IHNvbWV0aGluZyBpbiB3b3JraW5nIGNvcHkgb3IgcmVwb3MsCgkgKiByZW1lbWJlcmluZyBoaXN0
b3J5LjwvcD4KCSAqIAoJICogPHA+CgkgKiA8dHQ+c3JjPC90dD4gYW5kIDx0dD5kZXN0PC90dD4g
Y2FuIGVhY2ggYmUgZWl0aGVyIGEgd29ya2luZyBjb3B5IChXQykgcGF0aCBvciBVUkwuPC9wPgoJ
ICogPGRsPgoJICogPGR0PldDIC0mZ3Q7IFdDPC9kdD4KCSAqIDxkZD5jb3B5IGFuZCBzY2hlZHVs
ZSBmb3IgYWRkaXRpb24gKHdpdGggaGlzdG9yeSk8L2RkPgoJICogCgkgKiA8ZHQ+V0MgLSZndDsg
VVJMPC9kdD4KCSAqIDxkZD5pbW1lZGlhdGVseSBjb21taXQgYSBjb3B5IG9mIFdDIHRvIFVSTDwv
ZGQ+CgkgKiAKCSAqIDxkdD5VUkwgLSZndDsgV0M8L2R0PgoJICogPGRkPmNoZWNrIG91dCBVUkwg
aW50byBXQywgc2NoZWR1bGUgZm9yIGFkZGl0aW9uPC9kZD4KCSAqIAoJICogPGR0PlVSTCAtJmd0
OyBVUkw8L2R0PgoJICogPGRkPmNvbXBsZXRlIHNlcnZlci1zaWRlIGNvcHk7ICB1c2VkIHRvIGJy
YW5jaCBhbmQgdGFnPC9kZD4KCSAqIDwvZGw+CgkgKiAKCSAqIEBwYXJhbSBzcmMgTG9jYWwgcGF0
aCBvciBVUkwgdG8gY29weSBmcm9tLgoJICogQHBhcmFtIGRlc3QgTG9jYWwgcGF0aCBvciBVUkwg
dG8gY29weSB0by4KCSAqIEBwYXJhbSBtZXNzYWdlIENvbW1pdCBtZXNzYWdlLgoJICogQHBhcmFt
IHJldmlzaW9uIE9wdGlvbmFsIHJldmlzaW9uIHRvIGNvcHkgZnJvbS4gCgkgKiBAcGFyYW0gbWFr
ZXBhcmVudHMgICA8Y29kZT50cnVlPC9jb2RlPiA8PT4gQ3JlYXRlIHBhcmVudHMgZmlyc3Qgd2hl
biBjb3B5aW5nIGZyb20gc291cmNlIHVybCB0byBkZXN0IHVybC4KCSAqLwoJdm9pZCBjb3B5KFN0
cmluZyBzcmMsIFN0cmluZyBkZXN0LCBTdHJpbmcgbWVzc2FnZSwgU3RyaW5nIHJldmlzaW9uLCBi
b29sZWFuIG1ha2VwYXJlbnRzLCBib29sZWFuIGZvcmNlKSB0aHJvd3MgQ21kTGluZUV4Y2VwdGlv
biB7CiAgICAgICAgc2V0Q29tbWFuZChJU1ZOTm90aWZ5TGlzdGVuZXIuQ29tbWFuZC5DT1BZLCB0
cnVlKTsgICAgICAgIAoJCUNtZEFyZ3VtZW50cyBhcmdzID0gbmV3IENtZEFyZ3VtZW50cygpOwoJ
CWFyZ3MuYWRkKCJjcCIpOwoJCWlmIChyZXZpc2lvbiAhPSBudWxsKSB7CgkJCWFyZ3MuYWRkKCIt
ciIpOwoJCQlhcmdzLmFkZCh2YWxpZFJldihyZXZpc2lvbikpOwoJCX0KCQlpZiAobWFrZXBhcmVu
dHMpIHsKCQkgIGFyZ3MuYWRkKCItLXBhcmVudHMiKTsKCQl9CgkJaWYoZm9yY2UpCgkJewoJCQlh
cmdzLmFkZCgiLS1mb3JjZSIpOwoJCX0KCQlpZiAobWVzc2FnZSAhPSBudWxsKQoJCQlhcmdzLmFk
ZExvZ01lc3NhZ2UobWVzc2FnZSk7CgkJYXJncy5hZGQoc3JjKTsKCQlhcmdzLmFkZChkZXN0KTsK
CQlhcmdzLmFkZEF1dGhJbmZvKHRoaXMudXNlciwgdGhpcy5wYXNzKTsKICAgICAgICBhcmdzLmFk
ZENvbmZpZ0luZm8odGhpcy5jb25maWdEaXIpOwkJCgkJZXhlY1ZvaWQoYXJncyk7Cgl9CgkvKioK
CSAqIDxwPgoJICogRHVwbGljYXRlIGEgcmVzb3VyY2UgaW4gbG9jYWwgZmlsZSBzeXN0ZW0uPC9w
PgoJICogCgkgKiBAcGFyYW0gc3JjIExvY2FsIHBhdGggdG8gY29weSBmcm9tLgoJICogQHBhcmFt
IGRlc3QgTG9jYWwgZGVzdGluYXRpb24gcGF0aC4KCSAqIEB0aHJvd3MgQ21kTGluZUV4Y2VwdGlv
bgoJICovCgl2b2lkIGNvcHkoU3RyaW5nIHNyYywgU3RyaW5nIGRlc3QpIHRocm93cyBDbWRMaW5l
RXhjZXB0aW9uIHsKICAgICAgICBzZXRDb21tYW5kKElTVk5Ob3RpZnlMaXN0ZW5lci5Db21tYW5k
LkNPUFksIHRydWUpOwoJCUNtZEFyZ3VtZW50cyBhcmdzID0gbmV3IENtZEFyZ3VtZW50cygpOwoJ
CWFyZ3MuYWRkKCJjcCIpOwoJCWFyZ3MuYWRkKHNyYyk7CgkJYXJncy5hZGQoZGVzdCk7CgkJYXJn
cy5hZGRBdXRoSW5mbyh0aGlzLnVzZXIsIHRoaXMucGFzcyk7CiAgICAgICAgYXJncy5hZGRDb25m
aWdJbmZvKHRoaXMuY29uZmlnRGlyKTsgICAgICAgIAoJCWV4ZWNWb2lkKGFyZ3MpOwoJfQoKCS8q
KgoJICogPHA+CgkgKiBSZW1vdmUgZmlsZXMgYW5kIGRpcmVjdG9yaWVzIGZyb20gdmVyc2lvbiBj
b250cm9sLjwvcD4KCSAqICAgCgkgKiBAcGFyYW0gdGFyZ2V0IExvY2FsIHBhdGggb3IgVVJMIHRv
IHJlbW92ZS4KCSAqIEBwYXJhbSBtZXNzYWdlIEFzc29jaWF0ZWQgbWVzc2FnZSB3aGVuIGRlbGV0
aW5nIGZyb20KCSAqICAgVVJMLgoJICovCglTdHJpbmcgZGVsZXRlKFN0cmluZ1tdIHRhcmdldCwg
U3RyaW5nIG1lc3NhZ2UsIGJvb2xlYW4gZm9yY2UpIHRocm93cyBDbWRMaW5lRXhjZXB0aW9uIHsK
ICAgICAgICBzZXRDb21tYW5kKElTVk5Ob3RpZnlMaXN0ZW5lci5Db21tYW5kLlJFTU9WRSwgdHJ1
ZSk7CgkJQ21kQXJndW1lbnRzIGFyZ3MgPSBuZXcgQ21kQXJndW1lbnRzKCk7CgkJYXJncy5hZGQo
InJtIik7CgkJaWYgKG1lc3NhZ2UgIT0gbnVsbCkgewoJCQlhcmdzLmFkZExvZ01lc3NhZ2UobWVz
c2FnZSk7CgkJfQogICAgICAgIGlmIChmb3JjZSkgewogICAgICAgIAlhcmdzLmFkZCgiLS1mb3Jj
ZSIpOwogICAgICAgIH0KCQlmb3IgKGludCBpID0gMDtpIDwgdGFyZ2V0Lmxlbmd0aDtpKyspIHsK
CQkJYXJncy5hZGQodGFyZ2V0W2ldKTsKCQl9CiAgICAgICAgYXJncy5hZGRBdXRoSW5mbyh0aGlz
LnVzZXIsIHRoaXMucGFzcyk7CiAgICAgICAgYXJncy5hZGRDb25maWdJbmZvKHRoaXMuY29uZmln
RGlyKTsgICAgICAgIAoJCXJldHVybiBleGVjU3RyaW5nKGFyZ3MsZmFsc2UpOwoJfQoKCS8qKgoJ
ICogPHA+CgkgKiBEaXNwbGF5IHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHR3byBwYXRocy48L3A+
CgkgKiAKCSAqLwoJSW5wdXRTdHJlYW0gZGlmZihTdHJpbmcgb2xkUGF0aCwgU3RyaW5nIG9sZFJl
diwgU3RyaW5nIG5ld1BhdGgsIFN0cmluZyBuZXdSZXYsIGJvb2xlYW4gcmVjdXJzZSwgCgkJCWJv
b2xlYW4gaWdub3JlQW5jZXN0cnksIGJvb2xlYW4gbm9EaWZmRGVsZXRlZCwgYm9vbGVhbiBmb3Jj
ZSkgdGhyb3dzIENtZExpbmVFeGNlcHRpb24gewogICAgICAgIHNldENvbW1hbmQoSVNWTk5vdGlm
eUxpc3RlbmVyLkNvbW1hbmQuRElGRiwgZmFsc2UpOwoJCUNtZEFyZ3VtZW50cyBhcmdzID0gbmV3
IENtZEFyZ3VtZW50cygpOwoJCWFyZ3MuYWRkKCJkaWZmIik7CgkJaWYgKG5ld1JldiAhPSBudWxs
KSB7CgkJCWFyZ3MuYWRkKCItciIpOwoJCQlpZiAobmV3UmV2LmVxdWFscygiV09SS0lORyIpKSB7
IC8vICJXT1JLSU5HIiBpcyBub3QgYSB2YWxpZCByZXZpc2lvbiBhcmd1bWVudCBhdCBsZWFzdCBp
biAwLDM1LDEKCQkJCWFyZ3MuYWRkKG9sZFJldik7CgkJCX0gZWxzZSB7CgkJCQlhcmdzLmFkZChv
bGRSZXYrIjoiK25ld1Jldik7CQkJCgkJCX0KCQl9CiAgICAgICAgaWYgKCFyZWN1cnNlKSB7CiAg
ICAgICAgICAgIGFyZ3MuYWRkKCItTiIpOwogICAgICAgIH0KICAgICAgICBpZiAoIWlnbm9yZUFu
Y2VzdHJ5KSB7CiAgICAgICAgCWFyZ3MuYWRkKCItLW5vdGljZS1hbmNlc3RyeSIpOwogICAgICAg
IH0KICAgICAgICBpZiAobm9EaWZmRGVsZXRlZCkgewogICAgICAgIAlhcmdzLmFkZCgiLS1uby1k
aWZmLWRlbGV0ZWQiKTsKICAgICAgICB9CiAgICAgICAgaWYgKGZvcmNlKSB7CiAgICAgICAgCWFy
Z3MuYWRkKCItLWZvcmNlIik7CiAgICAgICAgfQoJCWFyZ3MuYWRkKCItLW9sZCIpOwoJCWFyZ3Mu
YWRkKG9sZFBhdGgpOwoJCWFyZ3MuYWRkKCItLW5ldyIpOwoJCWFyZ3MuYWRkKG5ld1BhdGgpOwog
ICAgICAgIGFyZ3MuYWRkQ29uZmlnSW5mbyh0aGlzLmNvbmZpZ0Rpcik7CQkgICAgICAgIAoJCXJl
dHVybiBleGVjSW5wdXRTdHJlYW0oYXJncyk7Cgl9CgoJLyoqCgkgKiA8cD4KCSAqIGV4cG9ydCBm
aWxlcyBhbmQgZGlyZWN0b3JpZXMgZnJvbSByZW1vdGUgVVJMLjwvcD4KCSAqIAoJICovCgl2b2lk
IGV4cG9ydChTdHJpbmcgdXJsLCBTdHJpbmcgcGF0aCwgU3RyaW5nIHJldmlzaW9uLCBib29sZWFu
IGZvcmNlKSB0aHJvd3MgQ21kTGluZUV4Y2VwdGlvbiB7CiAgICAgICAgc2V0Q29tbWFuZChJU1ZO
Tm90aWZ5TGlzdGVuZXIuQ29tbWFuZC5FWFBPUlQsIHRydWUpOyAgICAgICAgCgkJQ21kQXJndW1l
bnRzIGFyZ3MgPSBuZXcgQ21kQXJndW1lbnRzKCk7CgkJYXJncy5hZGQoImV4cG9ydCIpOwoJCWFy
Z3MuYWRkKCItciIpOwoJCWFyZ3MuYWRkKHZhbGlkUmV2KHJldmlzaW9uKSk7CgkJYXJncy5hZGQo
dXJsKTsKCQlhcmdzLmFkZChwYXRoKTsKCQlpZiAoZm9yY2UpCgkJCWFyZ3MuYWRkKCItLWZvcmNl
Iik7CiAgICAgICAgYXJncy5hZGRDb25maWdJbmZvKHRoaXMuY29uZmlnRGlyKTsJCQkKCQlleGVj
Vm9pZChhcmdzKTsKCX0KCgkvKioKCSAqIDxwPgoJICogQ29tbWl0IGFuIHVudmVyc2lvbmVkIGZp
bGUgb3IgZGlyZWN0b3J5IGludG8gdGhlIHJlcG9zaXRvcnkuPC9wPgogICAgICoKICAgICAqIEBw
YXJhbSBwYXRoIExvY2FsIHBhdGggdG8gaW1wb3J0IGZyb20uCgkgKiBAcGFyYW0gdXJsIFJlbW90
ZSBVUkwgdG8gaW1wb3J0IHRvLgoJICogQHBhcmFtIG1lc3NhZ2UgY29tbWl0IG1lc3NhZ2UKCSAq
LwoJU3RyaW5nIGltcG9ydEZpbGVzKFN0cmluZyBwYXRoLCBTdHJpbmcgdXJsLCBTdHJpbmcgbWVz
c2FnZSwgYm9vbGVhbiByZWN1cnNpdmUpCgkJdGhyb3dzIENtZExpbmVFeGNlcHRpb24gewogICAg
ICAgIHNldENvbW1hbmQoSVNWTk5vdGlmeUxpc3RlbmVyLkNvbW1hbmQuSU1QT1JULCB0cnVlKTsK
CQlDbWRBcmd1bWVudHMgYXJncyA9IG5ldyBDbWRBcmd1bWVudHMoKTsKCQlhcmdzLmFkZCgiaW1w
b3J0Iik7CgkJYXJncy5hZGQocGF0aCk7CiAgICAgICAgYXJncy5hZGQodXJsKTsKICAgICAgICBp
ZiAoIXJlY3Vyc2l2ZSkgewogICAgICAgIAlhcmdzLmFkZCgiLU4iKTsKICAgICAgICB9CgkJYXJn
cy5hZGRMb2dNZXNzYWdlKG1lc3NhZ2UpOwoJCWFyZ3MuYWRkQXV0aEluZm8odGhpcy51c2VyLCB0
aGlzLnBhc3MpOwogICAgICAgIGFyZ3MuYWRkQ29uZmlnSW5mbyh0aGlzLmNvbmZpZ0Rpcik7ICAg
ICAgICAKCQlyZXR1cm4gZXhlY1N0cmluZyhhcmdzLGZhbHNlKTsKCX0KCgkvKioKCSAqIGluZm86
IERpc3BsYXkgaW5mbyBhYm91dCBhIHJlc291cmNlLgoJICogdXNhZ2U6IGluZm8gW1BBVEggW1BB
VEggLi4uIF1dCgkgKgoJICogICBQcmludCBpbmZvcm1hdGlvbiBhYm91dCBQQVRIcy4KCSAqCgkg
KiBWYWxpZCBvcHRpb25zOgoJICogICAtLXRhcmdldHMgYXJnICAgICAgICAgICAgOiBwYXNzIGNv
bnRlbnRzIG9mIGZpbGUgQVJHIGFzIGFkZGl0aW9uYWwgYXJncwoJICogICAtUiBbLS1yZWN1cnNp
dmVdICAgICAgICAgOiBkZXNjZW5kIHJlY3Vyc2l2ZWx5CgkgKiAKCSAqIEBwYXJhbSBwYXRoCgkg
KiBAcmV0dXJuIFN0cmluZyB3aXRoIHRoZSBpbmZvIGNhbGwgcmVzdWx0CgkgKi8KCVN0cmluZyBp
bmZvKFN0cmluZ1tdIHRhcmdldCwgU3RyaW5nIHJldmlzaW9uLCBTdHJpbmcgcGVnKSB0aHJvd3Mg
Q21kTGluZUV4Y2VwdGlvbiB7CiAgICAgICAgaWYgKHRhcmdldC5sZW5ndGggPT0gMCkgewogICAg
ICAgICAgICAvLyBvdGhlcndpc2Ugd2Ugd291bGQgZG8gYSAic3ZuIGluZm8iIHdpdGhvdXQgYXJn
cwogICAgICAgICAgICByZXR1cm4gIiI7IAogICAgICAgIH0KICAgICAgICAKICAgICAgICBzZXRD
b21tYW5kKElTVk5Ob3RpZnlMaXN0ZW5lci5Db21tYW5kLklORk8sIGZhbHNlKTsKCQlDbWRBcmd1
bWVudHMgYXJncyA9IG5ldyBDbWRBcmd1bWVudHMoKTsKCQlhcmdzLmFkZCgiaW5mbyIpOwogICAg
ICAgIGFyZ3MuYWRkQXV0aEluZm8odGhpcy51c2VyLCB0aGlzLnBhc3MpOwogICAgICAgIGFyZ3Mu
YWRkQ29uZmlnSW5mbyh0aGlzLmNvbmZpZ0Rpcik7CiAgICAgICAgaWYgKHJldmlzaW9uICE9IG51
bGwpIHsKICAgICAgICAJYXJncy5hZGQoIi1yIik7CiAgICAgICAgCWFyZ3MuYWRkKHJldmlzaW9u
KTsKICAgICAgICB9CiAgICAgICAgZm9yIChpbnQgaSA9IDA7aSA8IHRhcmdldC5sZW5ndGg7aSsr
KSB7CiAgICAgICAgCWlmIChwZWcgPT0gbnVsbCkKICAgICAgICAJCWFyZ3MuYWRkKHRhcmdldFtp
XSk7CiAgICAgICAgCWVsc2UKICAgICAgICAJCWFyZ3MuYWRkKHRhcmdldFtpXSArICJAIiArIHBl
Zyk7CiAgICAgICAgfQoKCQlyZXR1cm4gZXhlY1N0cmluZyhhcmdzLGZhbHNlKTsKCX0KCgkvKioK
CSAqIDxwPgoJICogTGlzdCBkaXJlY3RvcnkgZW50cmllcyBvZiBhIFVSTC48L3A+CgkgKiAKCSAq
IEBwYXJhbSB1cmwgUmVtb3RlIFVSTC4KCSAqIEBwYXJhbSByZXZpc2lvbiBSZXZpc2lvbiB0byB1
c2UuIGNhbiBiZSA8dHQ+bnVsbDwvdHQ+CgkgKiAgIERlZmF1bHRzIHRvIDx0dD5IRUFEPC90dD4u
CgkgKiBAcGFyYW0gcmVjdXJzaXZlIFNob3VsZCB0aGlzIG9wZXJhdGlvbiByZWN1cnNlIGludG8g
c3ViLWRpcmVjdG9yaWVzCgkgKi8KCWJ5dGVbXSBsaXN0KFN0cmluZyB1cmwsIFN0cmluZyByZXZp
c2lvbiwgYm9vbGVhbiByZWN1cnNpdmUpIHRocm93cyBDbWRMaW5lRXhjZXB0aW9uIHsKICAgICAg
ICBzZXRDb21tYW5kKElTVk5Ob3RpZnlMaXN0ZW5lci5Db21tYW5kLkxTLCBmYWxzZSk7CgkJQ21k
QXJndW1lbnRzIGFyZ3MgPSBuZXcgQ21kQXJndW1lbnRzKCk7CgkJYXJncy5hZGQoImxpc3QiKTsK
CQlpZiAocmVjdXJzaXZlKSB7CgkJCWFyZ3MuYWRkKCItUiIpOwoJCX0KCQlhcmdzLmFkZCgiLS14
bWwiKTsKCQlhcmdzLmFkZCgiLXIiKTsKCQlhcmdzLmFkZChyZXZpc2lvbik7CgkJYXJncy5hZGQo
dXJsKTsKCQlhcmdzLmFkZEF1dGhJbmZvKHRoaXMudXNlciwgdGhpcy5wYXNzKTsKICAgICAgICBh
cmdzLmFkZENvbmZpZ0luZm8odGhpcy5jb25maWdEaXIpOwkJCgkJcmV0dXJuIGV4ZWNCeXRlcyhh
cmdzLGZhbHNlKTsKCX0KCgkvKioKCSAqIDxwPgoJICogU2hvdyB0aGUgbG9nIG1lc3NhZ2VzIGZv
ciBhIHNldCBvZiByZXZpc2lvbihzKSBhbmQvb3IgZmlsZShzKS48L3A+CgkgKiAKCSAqIEBwYXJh
bSB0YXJnZXQgTG9jYWwgcGF0aCBvciBVUkwuCgkgKiBAcGFyYW0gcmV2aXNpb24gT3B0aW9uYWwg
cmV2aXNpb24gcmFuZ2UgdG8gZ2V0IGxvZwoJICogICBtZXNzYWdlcyBmcm9tLgoJICovCglieXRl
W10gbG9nKFN0cmluZyB0YXJnZXQsIFN0cmluZyByZXZpc2lvbiwgYm9vbGVhbiBzdG9wT25Db3B5
LCBsb25nIGxpbWl0ICkgdGhyb3dzIENtZExpbmVFeGNlcHRpb24gewogICAgICAgIHNldENvbW1h
bmQoSVNWTk5vdGlmeUxpc3RlbmVyLkNvbW1hbmQuTE9HLCBmYWxzZSk7CQkKCQlDbWRBcmd1bWVu
dHMgYXJncyA9IG5ldyBDbWRBcmd1bWVudHMoKTsKCQlhcmdzLmFkZCgibG9nIik7CgkJYXJncy5h
ZGQoIi1yIik7CgkJYXJncy5hZGQodmFsaWRSZXYocmV2aXNpb24pKTsKCQlhcmdzLmFkZCh0YXJn
ZXQpOwoJCWFyZ3MuYWRkKCItLXhtbCIpOwoJCWlmIChzdG9wT25Db3B5KQoJCSAgICBhcmdzLmFk
ZCgiLS1zdG9wLW9uLWNvcHkiKTsKCQlpZiAobGltaXQgPiAwKSB7CgkJICAgIGFyZ3MuYWRkKCIt
LWxpbWl0Iik7CgkJICAgIGFyZ3MuYWRkKExvbmcudG9TdHJpbmcobGltaXQpKTsKCQl9CgkJYXJn
cy5hZGRBdXRoSW5mbyh0aGlzLnVzZXIsIHRoaXMucGFzcyk7CiAgICAgICAgYXJncy5hZGRDb25m
aWdJbmZvKHRoaXMuY29uZmlnRGlyKTsKICAgICAgICByZXR1cm4gZXhlY0J5dGVzKGFyZ3MsIHRy
dWUpOwoJfQoJCgkvKioKCSAqIDxwPgoJICogU2hvdyB0aGUgbG9nIG1lc3NhZ2VzIGZvciBhIHNl
dCBvZiByZXZpc2lvbihzKSBhbmQvb3IgZmlsZShzKS48L3A+CgkgKiA8cD4gVGhlIGRpZmZlcmVu
Y2UgdG8gdGhlIG1ldGhvZGUgbG9nIGlzIHRoZSBwYXJhbWV0ZXIgLXYKCSAqIAoJICogQHBhcmFt
IHRhcmdldCBMb2NhbCBwYXRoIG9yIFVSTC4KICAgICAgICAgKiBAcGFyYW0gcGF0aHMgbGlzdCBv
ZiBwYXRocyByZWxhdGl2ZSB0byB0YXJnZXQsIG1heSBiZSBudWxsIAoJICogQHBhcmFtIHJldmlz
aW9uIE9wdGlvbmFsIHJldmlzaW9uIHJhbmdlIHRvIGdldCBsb2cKCSAqICAgbWVzc2FnZXMgZnJv
bS4KCSAqLwoJYnl0ZVtdIGxvZ1ZlcmJvc2UoU3RyaW5nIHRhcmdldCwgU3RyaW5nIFtdIHBhdGhz
LCBTdHJpbmcgcmV2aXNpb24sIGJvb2xlYW4gc3RvcE9uQ29weSwgbG9uZyBsaW1pdCApIHRocm93
cyBDbWRMaW5lRXhjZXB0aW9uIHsKICAgICAgICBzZXRDb21tYW5kKElTVk5Ob3RpZnlMaXN0ZW5l
ci5Db21tYW5kLkxPRywgZmFsc2UpOwkJCiAgICAgICAgQ21kQXJndW1lbnRzIGFyZ3MgPSBuZXcg
Q21kQXJndW1lbnRzKCk7CiAgICAgICAgYXJncy5hZGQoImxvZyIpOwogICAgICAgIGFyZ3MuYWRk
KCItciIpOwogICAgICAgIGFyZ3MuYWRkKHZhbGlkUmV2KHJldmlzaW9uKSk7CiAgICAgICAgYXJn
cy5hZGQodGFyZ2V0KTsKICAgICAgICBpZiAocGF0aHMgIT0gbnVsbCkgewogICAgICAgICAgICBm
b3IgKGludCBpID0gMDsgaSA8IHBhdGhzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBh
cmdzLmFkZChwYXRoc1tpXSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYXJncy5h
ZGQoIi0teG1sIik7CiAgICAgICAgYXJncy5hZGQoIi12Iik7CiAgICAgICAgaWYgKHN0b3BPbkNv
cHkpCiAgICAgICAgICAgIGFyZ3MuYWRkKCItLXN0b3Atb24tY29weSIpOwogICAgICAgIGlmIChs
aW1pdCA+IDApIHsKICAgICAgICAgICAgYXJncy5hZGQoIi0tbGltaXQiKTsKICAgICAgICAgICAg
YXJncy5hZGQoTG9uZy50b1N0cmluZyhsaW1pdCkpOwogICAgICAgIH0KICAgICAgICBhcmdzLmFk
ZEF1dGhJbmZvKHRoaXMudXNlciwgdGhpcy5wYXNzKTsKICAgICAgICBhcmdzLmFkZENvbmZpZ0lu
Zm8odGhpcy5jb25maWdEaXIpOwogICAgICAgIHJldHVybiBleGVjQnl0ZXMoYXJncywgdHJ1ZSk7
Cgl9CgoJLyoqCgkgKiA8cD4KCSAqIENyZWF0ZSBhIG5ldyBkaXJlY3RvcnkgdW5kZXIgcmV2aXNp
b24gY29udHJvbC48L3A+CgkgKiAKCSAqIEBwYXJhbSB1cmwgVVJMIHRvIGNyZWF0ZS4gKGNvbnRh
aW5zIGV4aXN0aW5nIHVybCwgCgkgKiAgIGZvbGxvd2VkIGJ5ICIvbmV3RGlyZWN0b3J5TmFtZSIp
LgoJICogQHBhcmFtIG1lc3NhZ2UgQ29tbWl0IG1lc3NhZ2UgdG8gc2VuZC4KCSAqLwoJdm9pZCBt
a2RpcihTdHJpbmcgdXJsLCBTdHJpbmcgbWVzc2FnZSkgdGhyb3dzIENtZExpbmVFeGNlcHRpb24g
ewogICAgICAgIHNldENvbW1hbmQoSVNWTk5vdGlmeUxpc3RlbmVyLkNvbW1hbmQuTUtESVIsIHRy
dWUpOwoJCUNtZEFyZ3VtZW50cyBhcmdzID0gbmV3IENtZEFyZ3VtZW50cygpOwoJCWFyZ3MuYWRk
KCJta2RpciIpOwoJCWFyZ3MuYWRkTG9nTWVzc2FnZShtZXNzYWdlKTsKCQlhcmdzLmFkZCh1cmwp
OwoJCWFyZ3MuYWRkQXV0aEluZm8odGhpcy51c2VyLCB0aGlzLnBhc3MpOwogICAgICAgIGFyZ3Mu
YWRkQ29uZmlnSW5mbyh0aGlzLmNvbmZpZ0Rpcik7ICAgICAgICAKCQlleGVjVm9pZChhcmdzKTsK
CX0KICAgIAoJdm9pZCBta2RpcihTdHJpbmcgbG9jYWxQYXRoKSB0aHJvd3MgQ21kTGluZUV4Y2Vw
dGlvbiB7CiAgICAgICAgc2V0Q29tbWFuZChJU1ZOTm90aWZ5TGlzdGVuZXIuQ29tbWFuZC5NS0RJ
UiwgdHJ1ZSk7CgkJQ21kQXJndW1lbnRzIGFyZ3MgPSBuZXcgQ21kQXJndW1lbnRzKCk7CgkJYXJn
cy5hZGQoIm1rZGlyIik7CgkJYXJncy5hZGQobG9jYWxQYXRoKTsKICAgICAgICBhcmdzLmFkZENv
bmZpZ0luZm8odGhpcy5jb25maWdEaXIpOyAgICAgICAgCgkJZXhlY1ZvaWQoYXJncyk7Cgl9CgoJ
LyoqCgkgKiA8cD4KCSAqIE1vdmUvcmVuYW1lIHNvbWV0aGluZyBpbiB3b3JraW5nIGNvcHkgb3Ig
cmVwb3NpdG9yeS48L3A+CgkgKiAKCSAqIDxwPgoJICogPHR0PnNvdXJjZTwvdHQ+IGFuZCA8dHQ+
ZGVzdDwvdHQ+IGNhbiBib3RoIGJlIHdvcmtpbmcgY29weSAoV0MpIHBhdGhzIG9yIFVSTHMuPC9w
PgoJICogPGRsPgoJICogPGR0PldDIC0mZ3Q7IFdDPC9kdD4KCSAqIDxkZD5tb3ZlIGFuZCBzY2hl
ZHVsZSBmb3IgYWRkaXRpb24gKHdpdGggaGlzdG9yeSk8L2RkPgoJICogPGR0PlVSTCAtJmd0OyBV
Ukw8L2R0PgoJICogPGRkPmNvbXBsZXRlIHNlcnZlci1zaWRlIHJlbmFtZS48L2RkPgoJICogCgkg
KiBAcGFyYW0gc291cmNlIExvY2FsIHBhdGggb3IgVVJMIHRvIG1vdmUgZnJvbS4KCSAqIEBwYXJh
bSBkZXN0IExvY2FsIHBhdGggb3IgVVJMIHRvIG1vdmUgdG8uCgkgKiBAcGFyYW0gbWVzc2FnZSBP
cHRpb25hbCBtZXNzYWdlIHRvIHNlbmQgd2l0aCBVUkwuCgkgKiBAcGFyYW0gZm9yY2UgUGVyZm9y
bSBtb3ZlIGV2ZW4gaWYgdGhlcmUgYXJlIG1vZGlmaWNhdGlvbnMgdG8gd29ya2luZyBjb3B5Cgkg
Ki8KCVN0cmluZyBtb3ZlKFN0cmluZyBzb3VyY2UsIFN0cmluZyBkZXN0LCBTdHJpbmcgbWVzc2Fn
ZSwgU3RyaW5nIHJldmlzaW9uLCBib29sZWFuIGZvcmNlKQoJCXRocm93cyBDbWRMaW5lRXhjZXB0
aW9uIHsKICAgICAgICBzZXRDb21tYW5kKElTVk5Ob3RpZnlMaXN0ZW5lci5Db21tYW5kLk1PVkUs
IHRydWUpOyAgICAgICAgICAgIAoJCUNtZEFyZ3VtZW50cyBhcmdzID0gbmV3IENtZEFyZ3VtZW50
cygpOwoJCWFyZ3MuYWRkKCJtdiIpOwoJCWFyZ3MuYWRkKCItciIpOwoJCWFyZ3MuYWRkKHZhbGlk
UmV2KHJldmlzaW9uKSk7CgkJYXJncy5hZGQoc291cmNlKTsKCQlhcmdzLmFkZChkZXN0KTsKCQlp
ZiAobWVzc2FnZSAhPSBudWxsKSB7CgkJCWFyZ3MuYWRkTG9nTWVzc2FnZShtZXNzYWdlKTsKCQl9
CgkJaWYgKGZvcmNlKSB7CgkJCWFyZ3MuYWRkKCItLWZvcmNlIik7CgkJfQoJCWFyZ3MuYWRkQXV0
aEluZm8odGhpcy51c2VyLCB0aGlzLnBhc3MpOwkJCQkKICAgICAgICBhcmdzLmFkZENvbmZpZ0lu
Zm8odGhpcy5jb25maWdEaXIpOwoJCXJldHVybiBleGVjU3RyaW5nKGFyZ3MsZmFsc2UpOwoJfQoK
CS8qKgoJICogPHA+CgkgKiBQcmludCB2YWx1ZSBvZiA8dHQ+cHJvcE5hbWU8L3R0PiBvbiBmaWxl
cywgZGlycywgb3IgcmV2aXNpb25zLjwvcD4KCSAqCgkgKiBAcGFyYW0gTG9jYWwgcGF0aCBvZiBy
ZXNvdXJjZS4KCSAqIEBwYXJhbSBwcm9wTmFtZSBQcm9wZXJ0eSBuYW1lIHdob3NlIHZhbHVlIHdl
IHdpc2ggdG8gZmluZC4KCSAqLwoJSW5wdXRTdHJlYW0gcHJvcGdldChTdHJpbmcgcGF0aCwgU3Ry
aW5nIHByb3BOYW1lKSB0aHJvd3MgQ21kTGluZUV4Y2VwdGlvbiB7CiAgICAgICAgc2V0Q29tbWFu
ZChJU1ZOTm90aWZ5TGlzdGVuZXIuQ29tbWFuZC5QUk9QR0VULCBmYWxzZSk7CgkJQ21kQXJndW1l
bnRzIGFyZ3MgPSBuZXcgQ21kQXJndW1lbnRzKCk7CgkJYXJncy5hZGQoInByb3BnZXQiKTsKCQlh
cmdzLmFkZCgiLS1zdHJpY3QiKTsKCQlhcmdzLmFkZChwcm9wTmFtZSk7CgkJYXJncy5hZGQocGF0
aCk7CiAgICAgICAgYXJncy5hZGRBdXRoSW5mbyh0aGlzLnVzZXIsIHRoaXMucGFzcyk7CiAgICAg
ICAgYXJncy5hZGRDb25maWdJbmZvKHRoaXMuY29uZmlnRGlyKTsgICAgICAgIAoJCXJldHVybiBl
eGVjSW5wdXRTdHJlYW0oYXJncyk7Cgl9CgoJLyoqCgkgKiA8cD4KCSAqIFByaW50IHZhbHVlIG9m
IDx0dD5wcm9wTmFtZTwvdHQ+IG9uIGZpbGVzLCBkaXJzLCBvciByZXZpc2lvbnMuPC9wPgoJICoK
CSAqIEBwYXJhbSBMb2NhbCBwYXRoIG9mIHJlc291cmNlLgoJICogQHBhcmFtIHByb3BOYW1lIFBy
b3BlcnR5IG5hbWUgd2hvc2UgdmFsdWUgd2Ugd2lzaCB0byBmaW5kLgoJICovCglJbnB1dFN0cmVh
bSBwcm9wZ2V0KFN0cmluZyBwYXRoLCBTdHJpbmcgcHJvcE5hbWUsIFN0cmluZyByZXZpc2lvbiwg
U3RyaW5nIHBlZykgdGhyb3dzIENtZExpbmVFeGNlcHRpb24gewogICAgICAgIHNldENvbW1hbmQo
SVNWTk5vdGlmeUxpc3RlbmVyLkNvbW1hbmQuUFJPUEdFVCwgZmFsc2UpOwogICAgICAgIENtZEFy
Z3VtZW50cyBhcmdzID0gbmV3IENtZEFyZ3VtZW50cygpOwoJCWFyZ3MuYWRkKCJwcm9wZ2V0Iik7
CgkJYXJncy5hZGQoIi0tc3RyaWN0Iik7CgkJYXJncy5hZGQoIi1yIik7CgkJYXJncy5hZGQocmV2
aXNpb24pOwoJCWFyZ3MuYWRkKHByb3BOYW1lKTsKCQlhcmdzLmFkZChwYXRoICsgIkAiICsgcGVn
KTsKICAgICAgICBhcmdzLmFkZEF1dGhJbmZvKHRoaXMudXNlciwgdGhpcy5wYXNzKTsKICAgICAg
ICBhcmdzLmFkZENvbmZpZ0luZm8odGhpcy5jb25maWdEaXIpOyAgICAgICAgCgkJcmV0dXJuIGV4
ZWNJbnB1dFN0cmVhbShhcmdzKTsKCX0KCgkvKioKCSAqIDxwPgoJICogU2V0IDx0dD5wcm9wTmFt
ZTwvdHQ+IHRvIDx0dD5wcm9wVmFsPC90dD4gb24gZmlsZXMgb3IgZGlycy48L3A+CgkgKiAKCSAq
IEBwYXJhbSBwcm9wTmFtZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eS4KCSAqIEBwYXJhbSBwcm9wVmFs
dWUgTmV3IHZhbHVlIHRvIHNldCA8dHQ+cHJvcE5hbWU8L3R0PiB0by4KCSAqIEBwYXJhbSB0YXJn
ZXQgTG9jYWwgcGF0aCB0byByZXNvdXJjZS4KCSAqLwoJdm9pZCBwcm9wc2V0KFN0cmluZyBwcm9w
TmFtZSwgU3RyaW5nIHByb3BWYWx1ZSwgU3RyaW5nIHRhcmdldCwgYm9vbGVhbiByZWN1cnNlKQoJ
CXRocm93cyBDbWRMaW5lRXhjZXB0aW9uIHsKICAgICAgICBzZXRDb21tYW5kKElTVk5Ob3RpZnlM
aXN0ZW5lci5Db21tYW5kLlBST1BTRVQsIGZhbHNlKTsKCQlDbWRBcmd1bWVudHMgYXJncyA9IG5l
dyBDbWRBcmd1bWVudHMoKTsKCQlhcmdzLmFkZCgicHJvcHNldCIpOwoJCWlmIChyZWN1cnNlKQoJ
CQlhcmdzLmFkZCgiLVIiKTsKCQlhcmdzLmFkZChwcm9wTmFtZSk7CgkJYXJncy5hZGQocHJvcFZh
bHVlKTsKCQlhcmdzLmFkZCh0YXJnZXQpOwogICAgICAgIGFyZ3MuYWRkQXV0aEluZm8odGhpcy51
c2VyLCB0aGlzLnBhc3MpOwogICAgICAgIGFyZ3MuYWRkQ29uZmlnSW5mbyh0aGlzLmNvbmZpZ0Rp
cik7ICAgICAgICAKCQlleGVjVm9pZChhcmdzKTsKCX0KICAgIC8qKgogICAgICogTGlzdCB0aGUg
cHJvcGVydGllcyBmb3IgdGhlIGdpdmVuIGZpbGUgb3IgZGlyCiAgICAgKiAKICAgICAqIEBwYXJh
bSB0YXJnZXQKICAgICAqIEByZXR1cm4gU3RyaW5nIHdpdGggdGhlIHJlc291cmNlIHByb3BlcnRp
ZXMKICAgICAqIEB0aHJvd3MgQ21kTGluZUV4Y2VwdGlvbgogICAgICovCiAgICBTdHJpbmcgcHJv
cGxpc3QoU3RyaW5nIHRhcmdldCwgYm9vbGVhbiByZWN1cnNlKSB0aHJvd3MgQ21kTGluZUV4Y2Vw
dGlvbiB7CgkJc2V0Q29tbWFuZChJU1ZOTm90aWZ5TGlzdGVuZXIuQ29tbWFuZC5QUk9QTElTVCwg
ZmFsc2UpOwoJCUNtZEFyZ3VtZW50cyBhcmdzID0gbmV3IENtZEFyZ3VtZW50cygpOwoJCWFyZ3Mu
YWRkKCJwcm9wbGlzdCIpOwoJCWlmIChyZWN1cnNlKQoJCQlhcmdzLmFkZCgiLVIiKTsKCQlhcmdz
LmFkZCh0YXJnZXQpOwogICAgICAgIGFyZ3MuYWRkQXV0aEluZm8odGhpcy51c2VyLCB0aGlzLnBh
c3MpOwogICAgICAgIGFyZ3MuYWRkQ29uZmlnSW5mbyh0aGlzLmNvbmZpZ0Rpcik7ICAgICAgICAK
ICAgICAgICAKCQlyZXR1cm4gZXhlY1N0cmluZyhhcmdzLGZhbHNlKTsKICAgIH0KICAgIAogICAg
LyoqCiAgICAgKiBSZW1vdmUgPHR0PnByb3BOYW1lPC90dD4gZnJvbSBmaWxlcywgZGlycy4gCiAg
ICAgKiAKICAgICAqIEBwYXJhbSBwcm9wTmFtZQogICAgICogQHBhcmFtIHRhcmdldAogICAgICog
QHBhcmFtIHJlY3Vyc2UKICAgICAqIEB0aHJvd3MgQ21kTGluZUV4Y2VwdGlvbgogICAgICovCiAg
ICB2b2lkIHByb3BkZWwoU3RyaW5nIHByb3BOYW1lLCBTdHJpbmcgdGFyZ2V0LCBib29sZWFuIHJl
Y3Vyc2UpIHRocm93cyBDbWRMaW5lRXhjZXB0aW9uIHsKICAgICAgICBzZXRDb21tYW5kKElTVk5O
b3RpZnlMaXN0ZW5lci5Db21tYW5kLlBST1BERUwsIHRydWUpOwoJCUNtZEFyZ3VtZW50cyBhcmdz
ID0gbmV3IENtZEFyZ3VtZW50cygpOwoJCWFyZ3MuYWRkKCJwcm9wZGVsIik7CgkJaWYgKHJlY3Vy
c2UpCgkJCWFyZ3MuYWRkKCItUiIpOwoJCWFyZ3MuYWRkKHByb3BOYW1lKTsKCQlhcmdzLmFkZCh0
YXJnZXQpOwkKICAgICAgICBhcmdzLmFkZEF1dGhJbmZvKHRoaXMudXNlciwgdGhpcy5wYXNzKTsK
ICAgICAgICBhcmdzLmFkZENvbmZpZ0luZm8odGhpcy5jb25maWdEaXIpOyAgICAgICAgCiAgICAg
ICAgCiAgICAgICAgZXhlY1ZvaWQoYXJncyk7CiAgICB9CiAgICAKCS8qKgoJICogPHA+CgkgKiBT
ZXRzIGEgYmluYXJ5IGZpbGUgYXMgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHkuPC9wPgoJICogCgkg
KiBAcGFyYW0gcHJvcE5hbWUgbmFtZSBvZiB0aGUgcHJvcGVydHkuCgkgKiBAcGFyYW0gcHJvcEZp
bGUgTG9jYWwgcGF0aCB0byBiaW5hcnkgZmlsZS4KCSAqIEBwYXJhbSB0YXJnZXQgTG9jYWwgcGF0
aCB0byByZXNvdXJjZS4KCSAqLwoJdm9pZCBwcm9wc2V0RmlsZShTdHJpbmcgcHJvcE5hbWUsIFN0
cmluZyBwcm9wRmlsZSwgU3RyaW5nIHRhcmdldCwgYm9vbGVhbiByZWN1cnNlKQoJCXRocm93cyBD
bWRMaW5lRXhjZXB0aW9uIHsKICAgICAgICBzZXRDb21tYW5kKElTVk5Ob3RpZnlMaXN0ZW5lci5D
b21tYW5kLlBST1BTRVQsIGZhbHNlKTsKCQlDbWRBcmd1bWVudHMgYXJncyA9IG5ldyBDbWRBcmd1
bWVudHMoKTsKCQlhcmdzLmFkZCgicHJvcHNldCIpOwoJCWlmIChyZWN1cnNlKQoJCQlhcmdzLmFk
ZCgiLVIiKTsKCQlhcmdzLmFkZChwcm9wTmFtZSk7CgkJYXJncy5hZGQoIi1GIik7CgkJYXJncy5h
ZGQocHJvcEZpbGUpOwoJCWFyZ3MuYWRkKHRhcmdldCk7CQogICAgICAgIGFyZ3MuYWRkQXV0aElu
Zm8odGhpcy51c2VyLCB0aGlzLnBhc3MpOwogICAgICAgIGFyZ3MuYWRkQ29uZmlnSW5mbyh0aGlz
LmNvbmZpZ0Rpcik7ICAgICAgICAKICAgICAgICAKCQlleGVjVm9pZChhcmdzKTsKCX0KCgkvKioK
CSAqIDxwPgoJICogUmVzdG9yZSBwcmlzdGluZSB3b3JraW5nIGNvcHkgZmlsZSAodW5kbyBhbGwg
bG9jYWwgZWRpdHMpPC9wPgoJICogCgkgKiBAcGFyYW0gcGF0aHMgTG9jYWwgcGF0aHMgdG8gcmV2
ZXJ0LgoJICogQHBhcmFtIHJlY3Vyc2l2ZSA8dHQ+dHJ1ZTwvdHQ+IGlmIHJldmVydGluZyBzdWJk
aXJlY3Rvcmllcy4gCgkgKi8KCVN0cmluZyByZXZlcnQoU3RyaW5nW10gcGF0aHMsIGJvb2xlYW4g
cmVjdXJzaXZlKSB0aHJvd3MgQ21kTGluZUV4Y2VwdGlvbiB7CiAgICAgICAgc2V0Q29tbWFuZChJ
U1ZOTm90aWZ5TGlzdGVuZXIuQ29tbWFuZC5SRVZFUlQsIHRydWUpOwoJCUNtZEFyZ3VtZW50cyBh
cmdzID0gbmV3IENtZEFyZ3VtZW50cygpOwoJCWFyZ3MuYWRkKCJyZXZlcnQiKTsKCQlpZiAocmVj
dXJzaXZlKQoJCQlhcmdzLmFkZCgiLVIiKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IHBhdGhzLmxl
bmd0aDtpKyspIHsKCQkJYXJncy5hZGQocGF0aHNbaV0pOwoJCX0KICAgICAgICBhcmdzLmFkZENv
bmZpZ0luZm8odGhpcy5jb25maWdEaXIpOyAgICAgICAgCgkJCgkJcmV0dXJuIGV4ZWNTdHJpbmco
YXJncyxmYWxzZSk7Cgl9CgoJLyoqCgkgKiBSZW1vdmUgJ2NvbmZsaWN0ZWQnIHN0YXRlIG9uIHdv
cmtpbmcgY29weSBmaWxlcyBvciBkaXJlY3Rvcmllcy4KCSAqCgkgKiBAcGFyYW0gcGF0aHMKCSAq
IEBwYXJhbSByZWN1cnNpdmUKCSAqIEB0aHJvd3MgQ21kTGluZUV4Y2VwdGlvbgoJICovCgl2b2lk
IHJlc29sdmVkKFN0cmluZ1tdIHBhdGhzLCBib29sZWFuIHJlY3Vyc2l2ZSkgdGhyb3dzIENtZExp
bmVFeGNlcHRpb24gewoJCXNldENvbW1hbmQoSVNWTk5vdGlmeUxpc3RlbmVyLkNvbW1hbmQuUkVT
T0xWRUQsIHRydWUpOwoJCUNtZEFyZ3VtZW50cyBhcmdzID0gbmV3IENtZEFyZ3VtZW50cygpOwoJ
CWFyZ3MuYWRkKCJyZXNvbHZlZCIpOwoJCWlmIChyZWN1cnNpdmUpCgkJCWFyZ3MuYWRkKCItUiIp
OwoJCWZvciAoaW50IGkgPSAwOyBpIDwgcGF0aHMubGVuZ3RoO2krKykgewoJCQlhcmdzLmFkZChw
YXRoc1tpXSk7CgkJfQogICAgICAgIGFyZ3MuYWRkQ29uZmlnSW5mbyh0aGlzLmNvbmZpZ0Rpcik7
CQkKCQlleGVjVm9pZChhcmdzKTsJCQoJfQoKCS8qKgoJICogPHA+CgkgKiBQcmludCB0aGUgc3Rh
dHVzIG9mIHdvcmtpbmcgY29weSBmaWxlcyBhbmQgZGlyZWN0b3JpZXMuPC9wPgoJICogICAKCSAq
IEBwYXJhbSBwYXRoIExvY2FsIHBhdGggb2YgcmVzb3VyY2UgdG8gZ2V0IHN0YXR1cyBvZi4KCSAq
IEBwYXJhbSBhbGxFbnRyaWVzIGlmIGZhbHNlLCBvbmx5IGludGVyZXN0aW5nIGVudHJpZXMgd2ls
bCBiZSBnZXQgKGxvY2FsIG1vZHMgYW5kL29yIG91dC1vZi1kYXRlKS4KCSAqIEBwYXJhbSBjaGVj
a1VwZGF0ZXMgQ2hlY2sgZm9yIHVwZGF0ZXMgb24gc2VydmVyLgoJICovCglieXRlW10gc3RhdHVz
KFN0cmluZyBwYXRoW10sIGJvb2xlYW4gZGVzY2VuZCwgYm9vbGVhbiBhbGxFbnRyaWVzLCBib29s
ZWFuIGNoZWNrVXBkYXRlcywgYm9vbGVhbiBpZ25vcmVFeHRlcm5hbHMpIHRocm93cyBDbWRMaW5l
RXhjZXB0aW9uIHsKICAgICAgICBpZiAocGF0aC5sZW5ndGggPT0gMCkgewogICAgICAgICAgICAv
LyBvdGhlcndpc2Ugd2Ugd291bGQgZG8gYSAic3ZuIHN0YXR1cyIgd2l0aG91dCBhcmdzCiAgICAg
ICAgICAgIHJldHVybiBuZXcgYnl0ZVswXTsgCiAgICAgICAgfQogICAgICAgIHNldENvbW1hbmQo
SVNWTk5vdGlmeUxpc3RlbmVyLkNvbW1hbmQuU1RBVFVTLCBmYWxzZSk7CgkJQ21kQXJndW1lbnRz
IGFyZ3MgPSBuZXcgQ21kQXJndW1lbnRzKCk7CgkJYXJncy5hZGQoInN0YXR1cyIpOwogICAgICAg
IGFyZ3MuYWRkKCItLXhtbCIpOwogICAgICAgIGlmIChhbGxFbnRyaWVzKSB7CiAgICAgICAgICAg
IGFyZ3MuYWRkKCItdiIpOwogICAgICAgIH0KCQlpZiAoIWRlc2NlbmQpIAogICAgICAgICAgICBh
cmdzLmFkZCgiLU4iKTsKICAgICAgICBpZiAoY2hlY2tVcGRhdGVzKSB7CiAgICAgICAgICAgIGFy
Z3MuYWRkKCItdSIpOwogICAgICAgIH0KICAgICAgICBpZiAoYWxsRW50cmllcykgewogICAgICAg
IAlhcmdzLmFkZCgiLS1uby1pZ25vcmUiKTsgLy8gZGlzcmVnYXJkIGRlZmF1bHQgYW5kIHN2bjpp
Z25vcmUgcHJvcGVydHkgaWdub3JlcwogICAgICAgIH0KICAgICAgICBpZiAoaWdub3JlRXh0ZXJu
YWxzKSB7CiAgICAgICAgCWFyZ3MuYWRkKCItLWlnbm9yZS1leHRlcm5hbHMiKTsKICAgICAgICB9
CgkJCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYXRoLmxlbmd0aDtpKyspIHsgCiAgICAg
ICAgICAgIGFyZ3MuYWRkKHBhdGhbaV0pOwogICAgICAgIH0KCQkKICAgICAgICBhcmdzLmFkZEF1
dGhJbmZvKHRoaXMudXNlciwgdGhpcy5wYXNzKTsgIAogICAgICAgIGFyZ3MuYWRkQ29uZmlnSW5m
byh0aGlzLmNvbmZpZ0Rpcik7ICAgICAgICAKCQlyZXR1cm4gZXhlY0J5dGVzKGFyZ3MsIGZhbHNl
KTsKCX0KCgkvKioKCSAqIDxwPgoJICogQnJpbmcgY2hhbmdlcyBmcm9tIHRoZSByZXBvc2l0b3J5
IGludG8gdGhlIHdvcmtpbmcgY29weS48L3A+CgkgKiAKCSAqIEBwYXJhbSBwYXRoIExvY2FsIHBh
dGggdG8gcG9zc2libHkgdXBkYXRlLgoJICogQHBhcmFtIHJldmlzaW9uIE9wdGlvbmFsIHJldmlz
aW9uIHRvIHVwZGF0ZSB0by4KCSAqLwoJU3RyaW5nIHVwZGF0ZShTdHJpbmcgcGF0aCwgU3RyaW5n
IHJldmlzaW9uKSB0aHJvd3MgQ21kTGluZUV4Y2VwdGlvbiB7CiAgICAgICAgc2V0Q29tbWFuZChJ
U1ZOTm90aWZ5TGlzdGVuZXIuQ29tbWFuZC5VUERBVEUsIHRydWUpOwoJCUNtZEFyZ3VtZW50cyBh
cmdzID0gbmV3IENtZEFyZ3VtZW50cygpOwoJCWFyZ3MuYWRkKCJ1cCIpOwoJCWFyZ3MuYWRkKCIt
ciIpOwoJCWFyZ3MuYWRkKHZhbGlkUmV2KHJldmlzaW9uKSk7CgkJYXJncy5hZGQocGF0aCk7CgkJ
YXJncy5hZGRBdXRoSW5mbyh0aGlzLnVzZXIsIHRoaXMucGFzcyk7CiAgICAgICAgYXJncy5hZGRD
b25maWdJbmZvKHRoaXMuY29uZmlnRGlyKTsgICAgICAgIAoJCXJldHVybiBleGVjU3RyaW5nKGFy
Z3MsZmFsc2UpOwoJfQoKCS8qKgoJICogPHA+CgkgKiBCcmluZyBjaGFuZ2VzIGZyb20gdGhlIHJl
cG9zaXRvcnkgaW50byB0aGUgd29ya2luZyBjb3B5LjwvcD4KCSAqIAoJICogQHBhcmFtIHBhdGhz
IExvY2FsIHBhdGhzIHRvIHBvc3NpYmx5IHVwZGF0ZS4KCSAqIEBwYXJhbSByZXZpc2lvbiBPcHRp
b25hbCByZXZpc2lvbiB0byB1cGRhdGUgdG8uCgkgKi8KCVN0cmluZyB1cGRhdGUoU3RyaW5nW10g
cGF0aHMsIFN0cmluZyByZXZpc2lvbikgdGhyb3dzIENtZExpbmVFeGNlcHRpb24gewoJCVN0cmlu
Z0J1ZmZlciBwYXRoc0FyZyA9IG5ldyBTdHJpbmdCdWZmZXIoKTsKCQlmb3IgKGludCBpID0gMDsg
aSA8IHBhdGhzLmxlbmd0aDsgaSsrKSB7CgkJCXBhdGhzQXJnLmFwcGVuZChwYXRoc1tpXSk7CgkJ
CXBhdGhzQXJnLmFwcGVuZCgiICIpOwoJCX0KICAgICAgICBzZXRDb21tYW5kKElTVk5Ob3RpZnlM
aXN0ZW5lci5Db21tYW5kLlVQREFURSwgdHJ1ZSk7CgkJQ21kQXJndW1lbnRzIGFyZ3MgPSBuZXcg
Q21kQXJndW1lbnRzKCk7CgkJYXJncy5hZGQoInVwIik7CgkJYXJncy5hZGQoIi1yIik7CgkJYXJn
cy5hZGQodmFsaWRSZXYocmV2aXNpb24pKTsKCQlhcmdzLmFkZChwYXRoc0FyZy50b1N0cmluZygp
KTsKCQlhcmdzLmFkZEF1dGhJbmZvKHRoaXMudXNlciwgdGhpcy5wYXNzKTsKICAgICAgICBhcmdz
LmFkZENvbmZpZ0luZm8odGhpcy5jb25maWdEaXIpOyAgICAgICAgCgkJcmV0dXJuIGV4ZWNTdHJp
bmcoYXJncyxmYWxzZSk7Cgl9CgoJLyoqCgkgKiBPdXRwdXQgdGhlIGNvbnRlbnQgb2Ygc3BlY2lm
aWVkIGZpbGVzIG9yIFVSTHMgd2l0aCByZXZpc2lvbiBhbmQgCgkgKiBhdXRob3IgaW5mb3JtYXRp
b24gaW4tbGluZS4KCSAqIEBwYXJhbSBwYXRoCgkgKiBAcGFyYW0gcmV2aXNpb25TdGFydAoJICog
QHBhcmFtIHJldmlzaW9uRW5kCgkgKiBAcmV0dXJuIGJ5dGVbXSBhcnJheSBjb250YWluaW5nIHRo
ZSBYTUwgcmVwcmVzZW50YXRpb24gb2YgYW5ub3RhdGUgZGF0YQoJICogQHRocm93cyBDbWRMaW5l
RXhjZXB0aW9uCgkgKi8KCWJ5dGVbXSBhbm5vdGF0ZShTdHJpbmcgcGF0aCxTdHJpbmcgcmV2aXNp
b25TdGFydCwgU3RyaW5nIHJldmlzaW9uRW5kKSB0aHJvd3MgQ21kTGluZUV4Y2VwdGlvbiB7CgkJ
c2V0Q29tbWFuZChJU1ZOTm90aWZ5TGlzdGVuZXIuQ29tbWFuZC5BTk5PVEFURSwgZmFsc2UpOwoJ
CUNtZEFyZ3VtZW50cyBhcmdzID0gbmV3IENtZEFyZ3VtZW50cygpOwoJCWFyZ3MuYWRkKCJhbm5v
dGF0ZSIpOwoJCWFyZ3MuYWRkKCItLXhtbCIpOwoJCWFyZ3MuYWRkKCItciIpOwoJCWlmICgocmV2
aXNpb25TdGFydCAhPSBudWxsKSAmJiAocmV2aXNpb25TdGFydC5sZW5ndGgoKSA+IDApKQoJCXsK
CQkJYXJncy5hZGQodmFsaWRSZXYocmV2aXNpb25TdGFydCkgKyAiOiIgKyB2YWxpZFJldihyZXZp
c2lvbkVuZCkpOwkKCQl9CgkJZWxzZQoJCXsKCQkJYXJncy5hZGQodmFsaWRSZXYocmV2aXNpb25F
bmQpKTsJCQkKCQl9CgkJYXJncy5hZGQocGF0aCk7CgkJYXJncy5hZGRBdXRoSW5mbyh0aGlzLnVz
ZXIsIHRoaXMucGFzcyk7CiAgICAgICAgYXJncy5hZGRDb25maWdJbmZvKHRoaXMuY29uZmlnRGly
KTsgICAgICAgIAoJCXJldHVybiBleGVjQnl0ZXMoYXJncyxmYWxzZSk7Cgl9CgogICAgLyoqCiAg
ICAgKiBVcGRhdGUgdGhlIHdvcmtpbmcgY29weSB0byBtaXJyb3IgYSBuZXcgVVJMIHdpdGhpbiB0
aGUgcmVwb3NpdG9yeS4KICAgICAqLwogICAgU3RyaW5nIHN3aXRjaFVybChTdHJpbmcgcGF0aCwg
U3RyaW5nIHVybCwgU3RyaW5nIHJldmlzaW9uLCBib29sZWFuIHJlY3Vyc2UpIHRocm93cyBDbWRM
aW5lRXhjZXB0aW9uIHsKICAgICAgICBzZXRDb21tYW5kKElTVk5Ob3RpZnlMaXN0ZW5lci5Db21t
YW5kLlNXSVRDSCwgdHJ1ZSk7CiAgICAgICAgQ21kQXJndW1lbnRzIGFyZ3MgPSBuZXcgQ21kQXJn
dW1lbnRzKCk7CiAgICAgICAgYXJncy5hZGQoInN3Iik7CiAgICAgICAgYXJncy5hZGQodXJsKTsK
ICAgICAgICBhcmdzLmFkZChwYXRoKTsKICAgICAgICBpZiAoIXJlY3Vyc2UpCiAgICAgICAgICAg
IGFyZ3MuYWRkKCItTiIpOyAgICAgICAgICAgICAgICAKICAgICAgICBhcmdzLmFkZCgiLXIiKTsK
ICAgICAgICBhcmdzLmFkZCh2YWxpZFJldihyZXZpc2lvbikpOwogICAgICAgIGFyZ3MuYWRkQXV0
aEluZm8odGhpcy51c2VyLCB0aGlzLnBhc3MpOwogICAgICAgIGFyZ3MuYWRkQ29uZmlnSW5mbyh0
aGlzLmNvbmZpZ0Rpcik7ICAgICAgICAKICAgICAgICByZXR1cm4gZXhlY1N0cmluZyhhcmdzLGZh
bHNlKTsKICAgIH0KCiAgICAvKioKICAgICAqIFVwZGF0ZSB0aGUgd29ya2luZyBjb3B5IHRvIHBv
aW50IHRvIGEgbmV3IHJlcG9zaXRvcnkgVVJMLgogICAgICovCiAgICBTdHJpbmcgcmVsb2NhdGUo
U3RyaW5nIGZyb20sIFN0cmluZyB0bywgU3RyaW5nIHBhdGgsIGJvb2xlYW4gcmVjdXJzZSkgdGhy
b3dzIENtZExpbmVFeGNlcHRpb24gewogICAgICAgIHNldENvbW1hbmQoSVNWTk5vdGlmeUxpc3Rl
bmVyLkNvbW1hbmQuUkVMT0NBVEUsIGZhbHNlKTsKICAgICAgICBDbWRBcmd1bWVudHMgYXJncyA9
IG5ldyBDbWRBcmd1bWVudHMoKTsKICAgICAgICBhcmdzLmFkZCgic3ciKTsKICAgICAgICBhcmdz
LmFkZCgiLS1yZWxvY2F0ZSIpOwogICAgICAgIGlmICghcmVjdXJzZSkKICAgICAgICAgICAgYXJn
cy5hZGQoIi1OIik7CiAgICAgICAgYXJncy5hZGQoZnJvbSk7CiAgICAgICAgYXJncy5hZGQodG8p
OwogICAgICAgIGFyZ3MuYWRkKHBhdGgpOwogICAgICAgIGFyZ3MuYWRkQXV0aEluZm8odGhpcy51
c2VyLCB0aGlzLnBhc3MpOwogICAgICAgIGFyZ3MuYWRkQ29uZmlnSW5mbyh0aGlzLmNvbmZpZ0Rp
cik7ICAgICAgICAKICAgICAgICByZXR1cm4gZXhlY1N0cmluZyhhcmdzLGZhbHNlKTsKICAgIH0K
ICAgIAogICAgLyoqCiAgICAgKiBVcGRhdGUgdGhlIHdvcmtpbmcgY29weSB0byBtaXJyb3IgYSBu
ZXcgVVJMIHdpdGhpbiB0aGUgcmVwb3NpdG9yeS4KICAgICAqLwogICAgU3RyaW5nIG1lcmdlKFN0
cmluZyBwYXRoMSwgU3RyaW5nIHJldmlzaW9uMSwgU3RyaW5nIHBhdGgyLCBTdHJpbmcgcmV2aXNp
b24yLCBTdHJpbmcgbG9jYWxQYXRoLCBib29sZWFuIGZvcmNlLCBib29sZWFuIHJlY3Vyc2UsIGJv
b2xlYW4gZHJ5UnVuLCBib29sZWFuIGlnbm9yZUFuY2VzdHJ5KSB0aHJvd3MgQ21kTGluZUV4Y2Vw
dGlvbiB7CiAgICAgICAgc2V0Q29tbWFuZChJU1ZOTm90aWZ5TGlzdGVuZXIuQ29tbWFuZC5NRVJH
RSwgdHJ1ZSk7CiAgICAgICAgQ21kQXJndW1lbnRzIGFyZ3MgPSBuZXcgQ21kQXJndW1lbnRzKCk7
CiAgICAgICAgYXJncy5hZGQoIm1lcmdlIik7CiAgICAgICAgaWYgKCFyZWN1cnNlKQogICAgICAg
IAlhcmdzLmFkZCgiLU4iKTsKICAgICAgICBpZiAoZm9yY2UpCiAgICAgICAgCWFyZ3MuYWRkKCIt
LWZvcmNlIik7CiAgICAgICAgaWYgKGlnbm9yZUFuY2VzdHJ5KQogICAgICAgIAlhcmdzLmFkZCgi
LS1pZ25vcmUtYW5jZXN0cnkiKTsKICAgICAgICBpZiAoZHJ5UnVuKQogICAgICAgIAlhcmdzLmFk
ZCgiLS1kcnktcnVuIik7CiAgICAgICAgaWYgKHBhdGgxLmVxdWFscyhwYXRoMikpIHsKICAgICAg
ICAJYXJncy5hZGQoIi1yIik7CiAgICAgICAgCWFyZ3MuYWRkKHZhbGlkUmV2KHJldmlzaW9uMSkg
KyAiOiIgKyB2YWxpZFJldihyZXZpc2lvbjIpKTsKICAgICAgICAJYXJncy5hZGQocGF0aDEpOwog
ICAgICAgIH0gZWxzZSB7CiAgICAgICAgCWFyZ3MuYWRkKHBhdGgxICsgIkAiICsgdmFsaWRSZXYo
cmV2aXNpb24xKSk7CiAgICAgICAgCWFyZ3MuYWRkKHBhdGgyICsgIkAiICsgdmFsaWRSZXYocmV2
aXNpb24yKSk7CiAgICAgICAgfQogICAgICAgIGFyZ3MuYWRkKGxvY2FsUGF0aCk7CiAgICAgICAg
YXJncy5hZGRBdXRoSW5mbyh0aGlzLnVzZXIsIHRoaXMucGFzcyk7CiAgICAgICAgYXJncy5hZGRD
b25maWdJbmZvKHRoaXMuY29uZmlnRGlyKTsgICAgICAgIAogICAgICAgIHJldHVybiBleGVjU3Ry
aW5nKGFyZ3MsZmFsc2UpOwogICAgfQogICAgCgkvKioKCSAqIDxwPgoJICogU2V0IDx0dD5wcm9w
TmFtZTwvdHQ+IHRvIDx0dD5wcm9wVmFsPC90dD4gb24gcmV2aXNpb24gPHR0PnJldmlzaW9uPC90
dD4uPC9wPgoJICogCgkgKiBAcGFyYW0gcHJvcE5hbWUgbmFtZSBvZiB0aGUgcHJvcGVydHkuCgkg
KiBAcGFyYW0gcHJvcFZhbHVlIE5ldyB2YWx1ZSB0byBzZXQgPHR0PnByb3BOYW1lPC90dD4gdG8u
CgkgKiBAcGFyYW0gdGFyZ2V0IExvY2FsIHBhdGggb3IgVVJMIHRvIHJlc291cmNlLgoJICogQHBh
cmFtIGZvcmNlIElmIHRoZSBwcm9wc2V0IHNob3VsZCBiZSBmb3JjZWQuCgkgKi8KCXZvaWQgcmV2
cHJvcHNldChTdHJpbmcgcHJvcE5hbWUsIFN0cmluZyBwcm9wVmFsdWUsIFN0cmluZyB0YXJnZXQs
IFN0cmluZyByZXZpc2lvbiwgYm9vbGVhbiBmb3JjZSkKCQl0aHJvd3MgQ21kTGluZUV4Y2VwdGlv
biB7CiAgICAgICAgc2V0Q29tbWFuZChJU1ZOTm90aWZ5TGlzdGVuZXIuQ29tbWFuZC5QUk9QU0VU
LCBmYWxzZSk7CgkJQ21kQXJndW1lbnRzIGFyZ3MgPSBuZXcgQ21kQXJndW1lbnRzKCk7CgkJYXJn
cy5hZGQoInByb3BzZXQiKTsKCQlhcmdzLmFkZChwcm9wTmFtZSk7CgkJCgkJYXJncy5hZGQoIi0t
cmV2cHJvcCIpOwoJCQoJCWFyZ3MuYWRkKHByb3BWYWx1ZSk7CgkJYXJncy5hZGQodGFyZ2V0KTsK
CQkKCQlhcmdzLmFkZCgiLXIiKTsKCQlhcmdzLmFkZChyZXZpc2lvbik7CgoJCWlmIChmb3JjZSkK
CQkJYXJncy5hZGQoIi0tZm9yY2UiKTsKICAgICAgICBhcmdzLmFkZEF1dGhJbmZvKHRoaXMudXNl
ciwgdGhpcy5wYXNzKTsKICAgICAgICBhcmdzLmFkZENvbmZpZ0luZm8odGhpcy5jb25maWdEaXIp
OyAgICAgICAgCgkJZXhlY1ZvaWQoYXJncyk7Cgl9CgogICAgLyoqCiAgICAgKiBAcGFyYW0gcGF0
aHMgUmVwcmVzZW50cyBlaXRoZXIgV0MgcGF0aHMsIG9yIHJlcG9zaXRvcnkgVVJJcy4KICAgICAq
IEBwYXJhbSBjb21tZW50IFRoZSBjb21tZW50IHRvIHVzZSBmb3IgdGhlIGxvY2sgb3BlcmF0aW9u
LgogICAgICogQHBhcmFtIGZvcmNlIFdoZXRoZXIgdG8gaW5jbHVkZSA8Y29kZT4tLWZvcmNlPC9j
b2RlPiBpbiB0aGUKICAgICAqIGNvbW1hbmQtbGluZS4KICAgICAqLwogICAgU3RyaW5nIGxvY2so
T2JqZWN0W10gcGF0aHMsIFN0cmluZyBjb21tZW50LCBib29sZWFuIGZvcmNlKQogICAgICAgIHRo
cm93cyBDbWRMaW5lRXhjZXB0aW9uIHsKICAgICAgICBzZXRDb21tYW5kKElTVk5Ob3RpZnlMaXN0
ZW5lci5Db21tYW5kLkxPQ0ssIHRydWUpOwoJCUNtZEFyZ3VtZW50cyBhcmdzID0gbmV3IENtZEFy
Z3VtZW50cygpOwoJCWFyZ3MuYWRkKCJsb2NrIik7CgkJaWYgKGZvcmNlKQoJCSAgICBhcmdzLmFk
ZCgiLS1mb3JjZSIpOwoJCWlmIChjb21tZW50ICE9IG51bGwgJiYgIWNvbW1lbnQuZXF1YWxzKCIi
KSkgewoJCSAgICBhcmdzLmFkZCgiLW0iKTsKCQkgICAgYXJncy5hZGQoY29tbWVudCk7CgkJfQoJ
CWFyZ3MuYWRkQXV0aEluZm8odGhpcy51c2VyLCB0aGlzLnBhc3MpOwogICAgICAgIGFyZ3MuYWRk
Q29uZmlnSW5mbyh0aGlzLmNvbmZpZ0Rpcik7CgkJICAgICAgICAKICAgICAgICBmb3IgKGludCBp
ID0gMDsgaSA8IHBhdGhzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgCWFyZ3MuYWRkKHBhdGhzW2ld
KTsKICAgICAgICB9CiAgICAgICAgCgkJcmV0dXJuIGV4ZWNTdHJpbmcoYXJncywgZmFsc2UpOwog
ICAgfQoKICAgIC8qKgogICAgICogQHBhcmFtIHBhdGhzIFJlcHJlc2VudHMgZWl0aGVyIFdDIHBh
dGhzLCBvciByZXBvc2l0b3J5IFVSSXMuCiAgICAgKiBAcGFyYW0gY29tbWVudCBUaGUgY29tbWVu
dCB0byB1c2UgZm9yIHRoZSBsb2NrIG9wZXJhdGlvbi4KICAgICAqIEBwYXJhbSBmb3JjZSBXaGV0
aGVyIHRvIGluY2x1ZGUgPGNvZGU+LS1mb3JjZTwvY29kZT4gaW4gdGhlCiAgICAgKiBjb21tYW5k
LWxpbmUuCiAgICAgKi8KICAgIFN0cmluZyB1bmxvY2soT2JqZWN0W10gcGF0aHMsIGJvb2xlYW4g
Zm9yY2UpIHRocm93cyBDbWRMaW5lRXhjZXB0aW9uIHsKICAgICAgICBzZXRDb21tYW5kKElTVk5O
b3RpZnlMaXN0ZW5lci5Db21tYW5kLlVOTE9DSywgdHJ1ZSk7CgkJQ21kQXJndW1lbnRzIGFyZ3Mg
PSBuZXcgQ21kQXJndW1lbnRzKCk7CgkJYXJncy5hZGQoInVubG9jayIpOwoJCWlmIChmb3JjZSkK
CQkgICAgYXJncy5hZGQoIi0tZm9yY2UiKTsKCQlhcmdzLmFkZEF1dGhJbmZvKHRoaXMudXNlciwg
dGhpcy5wYXNzKTsKICAgICAgICBhcmdzLmFkZENvbmZpZ0luZm8odGhpcy5jb25maWdEaXIpOwoJ
CSAgICAgICAgCiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYXRocy5sZW5ndGg7aSsrKSB7
CiAgICAgICAgCWFyZ3MuYWRkKHBhdGhzW2ldKTsKICAgICAgICB9CiAgICAgICAgCgkJcmV0dXJu
IGV4ZWNTdHJpbmcoYXJncyxmYWxzZSk7CiAgICB9CgogICAgLyoKCSAqIChub24tSmF2YWRvYykK
CSAqIEBzZWUgb3JnLnRpZ3Jpcy5zdWJ2ZXJzaW9uLnN2bmNsaWVudGFkYXB0ZXIuY29tbWFuZGxp
bmUuQ29tbWFuZExpbmUjbm90aWZ5RnJvbVN2bk91dHB1dChqYXZhLmxhbmcuU3RyaW5nKQoJICov
Cglwcm90ZWN0ZWQgdm9pZCBub3RpZnlGcm9tU3ZuT3V0cHV0KFN0cmluZyBzdm5PdXRwdXQpIHsK
CQl0aGlzLnJldiA9IFNWTlJldmlzaW9uLlNWTl9JTlZBTElEX1JFVk5VTTsKCQkvLyB3ZSBjYWxs
IHRoZSBzdXBlciBpbXBsZW1lbnRhdGlvbiA6IGhhbmRsZXMgbG9nTWVzc2FnZSBhbmQgbG9nQ29t
cGxldGVkCgkJc3VwZXIubm90aWZ5RnJvbVN2bk91dHB1dChzdm5PdXRwdXQpOwoKCQlpZiAocGFy
c2VTdm5PdXRwdXQpIHsKCQkJLy8gd2UgcGFyc2UgdGhlIHN2biBvdXRwdXQKCQkJQ21kTGluZU5v
dGlmeSBub3RpZnkgPSBuZXcgQ21kTGluZU5vdGlmeSgpIHsKCQkKCQkJCXB1YmxpYyB2b2lkIG9u
Tm90aWZ5KAoJCQkJCQlTdHJpbmcgcGF0aCwKCQkJCSAgICAgICAgaW50IGFjdGlvbiwKCQkJCSAg
ICAgICAgaW50IGtpbmQsCgkJCQkgICAgICAgIFN0cmluZyBtaW1lVHlwZSwKCQkJCSAgICAgICAg
aW50IGNvbnRlbnRTdGF0ZSwKCQkJCSAgICAgICAgaW50IHByb3BTdGF0ZSwKCQkJCSAgICAgICAg
bG9uZyByZXZpc2lvbikgewoJCQkJCS8vIHdlIG9ubHkgY2FsbCBub3RpZnlMaXN0ZW5lcnNPZkNo
YW5nZSBhbmQgbG9nUmV2aXNpb24KCQkJCQkvLyBsb2dNZXNzYWdlIGFuZCBsb2dDb21wbGV0ZWQg
aGF2ZSBhbHJlYWR5IGJlZW4gY2FsbGVkCgkJCQkJaWYgKHBhdGggIT0gbnVsbCkgewoJCQkJCQlu
b3RpZmljYXRpb25IYW5kbGVyLm5vdGlmeUxpc3RlbmVyc09mQ2hhbmdlKHBhdGgpOwoJCQkJCX0K
CQkJCQlpZiAocmV2aXNpb24gIT0gU1ZOUmV2aXNpb24uU1ZOX0lOVkFMSURfUkVWTlVNKSB7CgkJ
CQkJCVN2bkNvbW1hbmRMaW5lLnRoaXMucmV2ID0gcmV2aXNpb247CgkJCQkJCW5vdGlmaWNhdGlv
bkhhbmRsZXIubG9nUmV2aXNpb24ocmV2aXNpb24sIHBhdGgpOwoJCQkJCX0KCQkJCX0KCQkJCQoJ
CQl9OwoJCQkKCQkKCQkJdHJ5IHsKCQkJCXN2bk91dHB1dFBhcnNlci5hZGRMaXN0ZW5lcihub3Rp
ZnkpOwoJCQkJc3ZuT3V0cHV0UGFyc2VyLnBhcnNlKHN2bk91dHB1dCk7CgkJCX0gZmluYWxseSB7
CgkJCQlzdm5PdXRwdXRQYXJzZXIucmVtb3ZlTGlzdGVuZXIobm90aWZ5KTsJCQkKCQkJfQoJCX0K
CQkKCX0KCQoJLyoqCgkgKiBXZSBjYWxsIHRoZSBzdXBlciBpbXBsZW1lbnRhdGlvbiA6IGhhbmRs
ZXMgbG9nTWVzc2FnZSBhbmQgbG9nQ29tcGxldGVkLgoJICogVGhpcyBtZXRob2QgbWFpbiByZWFz
b24gaXMgdG8gcHJvdmlkZSBzdWJjbGFzc2VzIHdheSB0byBjYWxsIHN1cGVyLnN1cGVyLm5vdGlm
eUZyb21Tdm5PdXRwdXQoKQoJICogQHBhcmFtIHN2bk91dHB1dAoJICovCglwcm90ZWN0ZWQgdm9p
ZCBub3RpZnlNZXNzYWdlc0Zyb21Tdm5PdXRwdXQoU3RyaW5nIHN2bk91dHB1dCkgewoJCXRoaXMu
cmV2ID0gU1ZOUmV2aXNpb24uU1ZOX0lOVkFMSURfUkVWTlVNOwoJCS8vIHdlIGNhbGwgdGhlIHN1
cGVyIGltcGxlbWVudGF0aW9uIDogaGFuZGxlcyBsb2dNZXNzYWdlIGFuZCBsb2dDb21wbGV0ZWQK
CQlzdXBlci5ub3RpZnlGcm9tU3ZuT3V0cHV0KHN2bk91dHB1dCk7Cgl9CgkKCS8qKgoJICogc2V0
IHRoZSBjb21tYW5kIHVzZWQgYW5kIHRlbGwgaWYgdGhlIHN2biBvdXB1dCBpcyBub3RpZmljYXRp
b24KCSAqIHRoYXQgbXVzdCBiZSBwYXJzZWQgdXNpbmcgU3ZuT3V0cHV0UGFyc2VyIDxicj4KCSAq
IFRoZSByZXN1bHQgb2YgY29tbWFuZHMgbGlrZSBsaXN0LCBjYXQgbXVzdCBub3QgYmUgcGFyc2Vk
IGhlcmUgYmVjYXVzZQoJICogaW4gdGhlc2UgY2FzZXMsIHRoZSBvdXRwdXQgaXMgbm90IG5vdGlm
aWNhdGlvbgoJICogQHBhcmFtIGNvbW1hbmQKCSAqIEBwYXJhbSBvdXB1dElzTm90aWZpY2F0aW9u
CgkgKi8KCXByb3RlY3RlZCB2b2lkIHNldENvbW1hbmQoaW50IGNvbW1hbmQsIGJvb2xlYW4gb3Vw
dXRJc05vdGlmaWNhdGlvbikgewoJCXRoaXMucGFyc2VTdm5PdXRwdXQgPSBvdXB1dElzTm90aWZp
Y2F0aW9uOwoJCW5vdGlmaWNhdGlvbkhhbmRsZXIuc2V0Q29tbWFuZChjb21tYW5kKTsKCX0KCQoJ
LyoqCgkgKiBnZXQgdGhlIHJldmlzaW9uIG5vdGlmaWVkIGZvciBsYXRlc3QgY29tbWFuZC4gSWYg
YW4gZXJyb3Igb2NjdXJlZCwgdGhlIHZhbHVlCgkgKiBvZiByZXZpc2lvbiBtdXN0IGJlIGlnbm9y
ZWQKCSAqIEByZXR1cm4gUmV0dXJucyB0aGUgcmV2aXNpb24uCgkgKi8KCXB1YmxpYyBsb25nIGdl
dFJldmlzaW9uKCkgewoJCXJldHVybiByZXY7Cgl9CiAgICAKfQkK
encoding=base64