再利用可能なソフトウェア部品(ライブラリ)を扱うときに、必ずつきまとう問題がバージョン管理です。バージョン管理といえば、CVSやSubversion等のソースコード・バージョン管理ツールが有名なため、ソースコードを管理する方に主眼が置かれがちです。しかし、再利用ソフトウェア部品は利用者がバイナリ形式(JAR形式ファイル)を扱うことになるので、ソースコードのバージョン管理では不十分です。
例えば、ロギング・ライブラリmylogging.jarという再利用ソフトウェア部品があったとします。幾度かバージョンアップした場合に、どのようにバージョン情報を持たせるのでしょうか。ファイル名にバージョン識別子を付加する方法が一つ考えられます。"mylogging-1.2.1.jar"というのが一例です。この方法の欠点は、バージョンが少しでも変わるとクラスパス設定を変更しなくてはならない点、バージョンアップによって使用できない組み合わせ(アプリケーションから呼び出していたクラス/メソッドが削除)の場合に、実行してみてNoSuchMethodlExceptionが出たり挙動が違っていることで初めて判明する点です。
そこで、バイナリ形式(JAR形式)におけるバージョン管理を扱う方法が必要となってきます。
Java 2 Standard Editionでは、Package Version Specificationというパッケージのバージョン管理に関するAPIが提供されています。
パッケージに関して管理する必要のあるバージョンには、次の種類があります。
仮想マシンのバージョンの情報として以下の項目が定義されています。
| 項目 | 内容 |
|---|---|
| java.vm.specification.version | 仕様バージョン |
| java.vm.specification.vendor | 仕様管理者 |
| java.vm.specification.name | 仕様名称 |
| java.vm.version | 実装バージョン |
| java.vm.vendor | 実装者 |
| java.vm.name | 実装名称 |
Java Runtimeのバージョン情報として以下の項目が定義されています。
| 項目 | 内容 |
|---|---|
| java.specification.version | 実行しているJavaの仕様バージョン |
| java.specification.name | 実行しているJavaの仕様名称 |
| java.specification.vendor | 実行しているJavaの仕様管理者 |
| java.version | 実行しているJavaのバージョン |
| java.vendor | 実行しているJavaの実装者 |
パッケージの仕様バージョンの情報として以下の項目が定義されています。
| 項目 | 内容 |
|---|---|
| Owner of the specification | 仕様の所有者(策定者や策定組織) |
| Name of the specificatin | 仕様の名称 |
| Version number | バージョン番号 |
パッケージの実装バージョンの情報として以下の項目が定義されています。
| 項目 | 内容 |
|---|---|
| Implementation Vendor | 実装者(組織) |
| Implementation Title | 実装の名称 |
| Implementation Version | バージョン番号 |
バージョン番号は、3つの数値から構成されます。
メジャー番号は、機能変更のような重大な変更があるとインクリメントします。マイナー番号は、互換性が保たれる小さな変更(基本的には拡張)があるとインクリメントします。マイクロ番号は、外部から見たインタフェースや振舞いが変更されずに内部的な変更のみの場合にインクリメントします。
パッケージやアプリケーションプログラムにおいて、前節で定義される各種バージョン情報を取得してバージョンの整合性をチェックするために、バージョン情報へのアクセス手段が必要になります。
仮想マシンのバージョン情報は、システム・プロパティに格納されているので、これを取得します。項目名がそのままプロパティ名となります。
Java Runtimeのバージョン情報は、システム・プロパティに格納されているので、これを取得します。項目名がそのままプロパティ名となります。
パッケージの仕様/実装バージョン情報へのアクセスは、Package APIを使用します。java.lang.Packageクラスのメソッドを使って情報を取得します。
| メソッド名 | 取得できる情報 |
|---|---|
| getName() | パッケージの名称 |
| getSpecificationTitle() | パッケージの仕様名称 |
| getSpecificationVersion() | パッケージのバージョン番号 |
| getSpecificationVendor() | パッケージの仕様所有者 |
| getImplementationTitle() | パッケージの実装名称 |
| getImplementationVersion() | パッケージの実装バージョン |
| getImplementationVendor() | パッケージの実装者 |
JAR形式で提供するソフトウェア部品は、JARファイル作成時にマニュフェストファイルにバージョン情報を記載します。
Manifest-version: 1.0 Name: jp/gr/java_conf/torutk/mylogging/ Specification-Title: Torutk's Logging Specification Specification-Version: 2.1 Specification-Vendor: Torutk Implementation-Title: Torutk's Logging Classes Implementation-Version: build78 Implementation-Vendor: Torutk
BeanShell 2.0b1.1 - by Pat Niemeyer (pat@pat.net)
bsh % log = new jp.gr.java_conf.torutk.mylogging.MyLog();
bsh % clazz = log.getClass();
bsh % print(clazz);
class jp.gr.java_conf.torutk.mylogging.MyLog
bsh % pkg = clazz.getPackage();
bsh % print(pkg);
package jp.gr.java_conf.torutk.mylogging, Torutk's Logging \
Specification, version 2.1
bsh % print(pkg.getName());
jp.gr.java_conf.torutk.mylogging
bsh % print(pkg.getSpecificationTitle());
Torutk's Logging Specification
bsh % print(pkg.getSpecificationVersion());
2.1
bsh % print(pkg.getSpecificationVendor());
Torutk
bsh % print(pkg.getImplementationTitle());
Torutk's Logging Classes
bsh % print(pkg.getImplementationVersion());
build78
bsh % print(pkg.getImplementationVendor());
Torutk
bsh %
java.lang.PackageクラスのisCompatibleWith(String)メソッドを使用したバージョン互換性のチェックが利用できます。このメソッドは、引数で指定したバージョン番号と、パッケージの仕様バージョン番号とを比較し、互換性有無を返却します。
例)仕様バージョン番号が"2.1"のとき、引数に指定したバージョン番号とその返却値
| 引数で指定した文字列 | 返却値 |
|---|---|
| 1.0 | true |
| 2.0 | true |
| 2.1 | true |
| 2.1.0 | true |
| 2.1.1 | false |
| 2.2 | false |
| 3.0 | false |