Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Force option is enabled in Copy command. [Tigris #1495] #23

Open
markphip opened this issue Sep 15, 2016 · 0 comments
Open

Force option is enabled in Copy command. [Tigris #1495] #23

markphip opened this issue Sep 15, 2016 · 0 comments

Comments

@markphip
Copy link
Contributor

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant