SVNKitのSVNURLオブジェクトまわりがちょっと不思議
ちょっとしたツールを作成したくてSVNKitについて調べていたら、SVNURLオブジェクトで不思議なものを見つけた。
そもそもの発端は SVNURL . parseURIDecoded (String) メソッドが“Deprecated”と指定されているのに、Javadocにはその代替APIについて何も記載がなかったこと。というかこのポストでも指摘されているようにJavadocには廃止予定であること自体何らの記載もない。
SVNURL.parseURIDecoded has been deprecated in 1.7.5-v1, but the javadoc doesn't offer any explanation or alternative. What do we do if we are currently using this method?
(SVN.parseURIDecodedメソッドは1.7.5-v1時点で廃止予定となっている。けれどもJavadocには何らその説明がないし代替の提示もされていない。今現在このメソッドを使っている場合、一体どうしたらいいの?)
このメソッドはUTF-8エンコードされていないURL文字列を受け取ってパースし、そのURLをあらわすSVNURLオブジェクトを生成する。しかし廃止予定だという(ちなみに現在の最新バージョンは1.8系)。
それで前掲の記事や別の記事を参考にした結果、次のようにするのがよさそうだと判断した。
final String rawStringUrl = "..."; final String autoEncodedUrl = SVNEncodingUtil.autoURIEncode(rawStringUrl); final SVNURL svnUrl = SVNURL.parseURIEncoded(autoEncodedUrl);
しかし、一体どうちがうのだろうかと思い、検証してみた結果が以下の通り:
半角スペースあり
API | 文字列/URL |
---|---|
(処理前) | http://example.com/foo var/baz.txt#hash |
parseURIDecoded | http://example.com/foo%E3%80%80var/baz.txt%23hash |
parseURIEncoded | http://example.com/foo%E3%80%80var/baz.txt%23hash |
autoURIEncode + parseURIEncoded |
http://example.com/foo%E3%80%80var/baz.txt%23hash |
おおむね予想通りではあるけど、SVNURL.parseURIEncoded(String)メソッドの挙動が気になるところではある。何しろエンコード済みのはずの文字列をパースしているのに、勝手に再度エンコードを行っている。
マルチバイト文字あり
API | 文字列/URL |
---|---|
(処理前) | http://example.com/foo/var/ばず.txt#hash |
parseURIDecoded | http://example.com/foo/var/%E3%81%B0%E3%81%9A.txt%23hash |
parseURIEncoded | http://example.com/foo/var/%E3%81%B0%E3%81%9A.txt%23hash |
autoURIEncode + parseURIEncoded |
http://example.com/foo/var/%E3%81%B0%E3%81%9A.txt%23hash |
この結果も前回同様。
既エンコード+未エンコード
API | 文字列/URL |
---|---|
(処理前) | http://example.com/foo%20var/ばず.txt#hash |
parseURIDecoded | http://example.com/foo%2520var/%E3%81%B0%E3%81%9A.txt%23hash |
parseURIEncoded | http://example.com/foo%20var/%E3%81%B0%E3%81%9A.txt%23hash |
autoURIEncode + parseURIEncoded |
http://example.com/foo%20var/%E3%81%B0%E3%81%9A.txt%23hash |
やっとparseURIDecoded(String)メソッドの問題点が明らかになる。未エンコード文字が存在すると、とにかくURL全体が再度エンコードされるため、半角スペースがエンコードされた結果である“%20”が、再度エンコードされて“%2520”になってしまった。
とにかくいろいろ入れてみる
API | 文字列/URL |
---|---|
(処理前) | http://example.com/foo/var/,;:$&+=?!/baz.txt#hash |
parseURIDecoded | http://example.com/foo/var/,%3B:$&+=%3F!/baz.txt%23hash |
parseURIEncoded | http://example.com/foo/var/,%3B:$&+=%23hash |
autoURIEncode + parseURIEncoded |
http://example.com/foo/var/,%3B:$&+=%3F!/baz.txt%23hash |
URIの仕様を確認しながら扱いの微妙そうな文字をいろいろ突っ込んでみた。すると今度はparseURIEncoded(String)単体で用いた場合に変な結果となった。“?”のあとに続く文字列のパースに失敗している。