Skip to content

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

@markphip

Description

@markphip

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions