Indexer Reader で Maven central リポジトリのインデックスを走査する

先日の エントリ にて Maven central リポジトリのインデックスを利用する話題を取り上げたので、今回はそのインデックスを具体的に Java で読み込み、走査する方法についてメモします。

(Header image: A view of the map repository at The National Archives / Wikipedia)

Maven central リポジトリのインデックス

Maven central リポジトリでは、そのリポジトリに登録されているアーティファクトすべてをインデックスしたファイルを https://repo.maven.apache.org/maven2/.index/ にて週次更新で提供しています。

最新のインデックスは Maven - Central index に記載されているとおり、 nexus-maven-repository-index.gznexus-maven-repository-index.properties の 2 つのファイルで構成されています。インデックスの内容は こちら にあるとおりで、アーティファクトのグループ ID、アーティファクト ID、バージョンや、アーティファクトの最終更新日時などの基本的な情報が含まれています。

このインデックスを Java で扱うには、Maven IndexerIndexer Reader を利用するのが最も手短でしょう。このエントリでも、以降は Indexer Reader を利用したインデックスの取り扱いについて説明していきます。

Indexer Reader によるインデックスの走査

Indexer Reader を用いて Maven central リポジトリのインデックスを走査する方法は次のとおりです。

  1. インデックスを具体的に参照する ResourceHandler インタフェースを実装する
  2. IndexReader クラス (および ChunkReader クラス) を利用して、1 レコードずつ処理する

以降はその詳細になります。

ResourceHandler を実装してインデックスを取り扱う

Indexer Reader では、ローカルのファイルシステム上にあるインデックスもリモート (Web 上) にあるインデックスもどちらも取り扱うことができ、具体的には、ResourceHandler インタフェースの実装次第となります。

同インタフェースを見ると推測がつくとおり、ローカルのファイルシステム上のインデックスを参照したければ、ResourceHandler#locate(String) メソッドで返却する Resource オブジェクトの Resource#read() メソッドの戻り値 InputStream オブジェクトを、Files.newInputbbbStream(Path) メソッドを呼び出して得られたものにすればいいし、またリモートのインデックスを参照したければ素の HttpURLConnection を使うなり HttpClient や OkHttp などのライブラリを使うなどして HTTP レスポンスの InputStream を返却すればよいわけです。

ただ実際には、Maven central リポジトリのインデックスはそれなりの大きさがあるので (400 MB 超)、インデックスを走査しようとする都度むやみやたらに毎回リモートから取得するよりは、最新のインデックスを常にキャッシュするなどして無駄な HTTP 通信を避けた方が賢明に思えます。

なので、例えば こちらの実装 のように毎回 nexus-maven-repository-index.properties だけ先にダウンロードしておいて、キャッシュされているインデックスが最新と同一であればそれを利用し、なければリモートから取得してキャッシュしつつそれを利用する… といった実装にしておくのが好ましいと言えるでしょう。

IndexReader でインデックスを走査する

適切に ResourceHandler インタフェースを実装し終えたら、あとはその実装を用いて

  1. IndexReader オブジェクトを生成する
  2. その IndexerReader ならびに IndexerReader#iterator() で得られる ChunkReader をイテレーションする
  3. ChunkReader オブジェクトのイテレーションで得られる Map<String, String> オブジェクトを RecordExpander クラスを用いて Record オブジェクトに変換し、目的の処理を遂行する

という手順の処理を実装するだけです。これらの具体的な実装例は こちら になります。

まとめ

  • Maven central リポジトリでは、全アーティファクトのインデックスを週次更新で提供しているよ
  • 同インデックスを走査するには Indexer Reader を利用するのが便利だよ
  • インデックスを参照して走査する処理は、リモートのインデックスを毎回参照するのではなくキャッシュを活用した方がいいよ