Site cover image

Site icon imageきっとなにかの やくにたつから…

プログラミングや日常生活に関する備忘録

java.net.URLオブジェクトを作成したいが、対象がDefaultではないプロトコルであり、さらにプロトコル名に`-`を含む場合の対処方法

結論

次のように記述すれば良い。openConnectionについては必要である場合のみ記述する。

public class Main {

  private static final MyURLStreamHandler HANDLER = new MyURLStreamHandler();
  
  private static class MyURLStreamHandler extends URLStreamHandler {
    @Override
    protected URLConnection openConnection(URL u) {
      throw new UnsupportedOperationException("MyURLStreamHandler#openConnection(URL) is an unsupported operation.");
    }
  }

  public static void main(String[] args) throws Exception {
    URL url = new URL(null, "unknown-protocol://user:pass@example.com.:888/path", HANDLER);
    System.out.println(url);
  }
}


jshell> class MyURLStreamHandler extends URLStreamHandler {
   ...>             @Override
   ...>             protected URLConnection openConnection(URL u) {
   ...>               throw new UnsupportedOperationException("MyURLStreamHandler#openConnection(URL) is an unsupported operation.");
   ...>             }
   ...>           }
|  次を作成しました: クラス MyURLStreamHandler

jshell> MyURLStreamHandler HANDLER = new MyURLStreamHandler();
HANDLER ==> MyURLStreamHandler@12edcd21

jshell> URL url = new URL(null, "unknown-protocol://user:pass@example.com.:888/path", HANDLER);
url ==> unknown-protocol://user:pass@example.com.:888/path

背景

Javaのアプリケーションで、URLの文字列からprotocolやauthorityを取り出したいことがある。この用途にはjava.net.URLクラスの利用が考えられる。

しかし、java.net.URLの new URL(spec) コンストラクタは特殊なプロトコルのURLには利用できない。これは、 sun.net.www.protocol.<protocol_name>.Handler.java クラスが解決できないとExceptionが発生するように実装されているため。
逆に言えば、特殊なプロトコルの場合は上記のパッケージにHandler.javaを作れば良いことになる。

問題点

以下の食い違いからsun.net.www.protocol.<protocol_name>.Handler.java作成できない場合がある。

  • URL上のプロトコルの箇所は - (ハイフン)の利用が許可されている
  • Javaのパッケージ名は- (ハイフン)の利用が禁止されている

例えば、次のURLは正しいURLであるが、対応するパッケージを作ることができない。

  • unknown-protocol://user:pass@example.com.:888/path

解決策

独自にhandlerを作成し、 new URL(context, spec, handler) コンストラクタを利用する。具体的には記事冒頭の結論を参照してほしい。