注:バージョン5.0の場合、新規コンストラクタの |
サービスとは、アプリケーション・プログラムでJava Sound APIの実装を使用すると自動的に利用可能になるサウンド処理機能の総称です。サービスを構成するのは、オーディオ・データとMIDIデータの読み込み、書き込み、ミキシング、処理、変換の各作業を行うオブジェクト群です。Java Sound APIの実装では、通常は、基本サービス・セットが提供されていますが、さらに、APIに新しいメカニズムも組み込まれて、サード・パーティ開発者(または実装自体のベンダー)を対象にした新しいサウンド・サービスの開発もサポートされています。これらの新しいサービスを、既存の導入済み実装に「プラグイン」の形で組み込むと、新規リリースとしなくても機能を拡張することができます。Java Sound APIアーキテクチャは、サード・パーティ・サービスをシステムに統合する方法として、アプリケーション・プログラムのサード・パーティ・サービスへのインタフェースを「ビルトイン(組み込み)」サービスへのインタフェースと同じにしました。場合によっては、javax.sound.sampled
パッケージやjavax.sound.midi
パッケージを使用するアプリケーション開発者が、サード・パーティ・サービスを使用していることに気づかないこともあります。
サード・パーティのサンプリング・オーディオ・サービスの例として、次のようなものが挙げられます。
javax.sound.sampled
パッケージおよびjavax.sound.midi
パッケージは、アプリケーション・プログラムにサウンド・サービスを付加することを考えているアプリケーション開発者に必要な機能を提供するものです。この2つのパッケージはサウンド・サービスの消費者(コンシューマ)を対象に、オーディオ、MIDIの両サービスに関する情報の取得、制御、およびアクセスに必要なインタフェースを提供します。また、Java Sound APIは、サウンド・サービスの提供者(プロバイダ)を対象に、抽象クラスを定義するための2つのパッケージであるjavax.sound.sampled.spi
とjavax.sound.midi.spi
を提供しています。
新しいサウンド・パッケージの開発者は、SPIパッケージの中の、使用するクラスの具象サブクラスを実装します。これらのサブクラスと、新しいサービスのサポートに必要な任意のクラスは、含まれているサービスの説明とともに、Java Archive (JAR)アーカイブ・ファイルに置かれます。このJARファイルがユーザーのCLASSPATH
にインストールされると、実行システムは、自動的に新しいサービスを利用可能にして、Javaプラットフォームの実行システムの機能性を拡張します。
インストールされた新しいサービスには、すでにインストールされている他のサービスと同様にアクセスできます。サービスの消費者は、新しいサービスに関する情報、または新しいサービス・クラス自体のインスタンスを取得することができます。そのためには、AudioSystem
クラスとMidiSystem
クラスのメソッド群(前者はjavax.sound.sampled
パッケージ、後者はjavax.sound.midi
パッケージに収録)を呼び出して、新しいサービスに関する情報、あるいは新規または既存のサービス・クラス自体のインスタンスを戻します。アプリケーション・プログラムはインストールされたサービスを利用するために、SPIパッケージ内のクラス(およびそのサブクラス)を直接参照する必要はないので、直接参照すべきではありません。
たとえば、Acme Software, Inc. という架空のサービス・プロバイダが、アプリケーション・プログラムで新しい形式のサウンド・ファイル(ただし、オーディオ・データは標準のデータ形式)を読み込むパッケージを提供できないかと考えたとします。SPIクラスAudioFileReader
は、たとえばAcmeAudioFileReader
というクラスにサブクラス化できます。新しいサブクラスで、AcmeはAudioFileReader
に定義されているすべてのメソッドの実装を提供します。この場合は、getAudioFileFormat
とgetAudioInputStream
の2つのメソッド(引数バリアント付き)だけです。次に、アプリケーション・プログラムが読み込もうとしたサウンド・ファイルがAcmeのファイル形式だった場合は、javax.sound.sampled
内のAudioSystem
クラスのメソッドを呼び出してファイルとそのファイル情報にアクセスします。AudioSystem.getAudioInputStream
メソッドとAudioSystem.getAudioFileFormat
メソッドは、オーディオ・ストリームを読み込む標準APIを提供します。AcmeAudioFileReader
クラスがインストールされている場合は、このインタフェースは拡張され、新しいファイル・タイプを透過的にサポートします。アプリケーション開発者は、新しく登録したSPIクラスに直接アクセスする必要はありません。AudioSystem
オブジェクトのメソッドが、インストールされているAcmeAudioFileReader
クラスについてのクエリーを渡します。
これらの「ファクトリ」クラスを持つことの利点は何でしょうか。また、新しく提供されるサービスへの直接アクセスをアプリケーション開発者に許可しない理由は何でしょうか。直接アクセスも可能性としては考えられますが、オブジェクトにサービスの管理とインスタンス化をすべてパススルーするゲートキーパー・システムが備わっているため、アプリケーション開発者は、インストールされている各サービスについて知る必要がありません。アプリケーション開発者は、自覚することさえなく、自分にとって使用価値のあるサービスのみを使用します。同時に、このアーキテクチャにより、サービス・プロバイダはパッケージ内の利用可能なリソースを効率的に管理することができます。
新しいサウンド・サービスの使用は、多くの場合、アプリケーション・プログラムからは見えません。たとえば、アプリケーション開発者がファイルからオーディオのストリームで読み込む場合を考えます。thePathName
によりオーディオ入力ファイルを識別すると仮定すると、プログラムは次のようになります。
File theInFile = new File(thePathName); AudioInputStream theInStream = AudioSystem.getAudioInputStream(theInFile);バックグラウンドで、
AudioSystem
は、ファイルを読み込むことができるインストール・サービスを判別し、そのサービスに対して、データをAudioInputStream
オブジェクトとして提供するよう要請します。開発者は、入力オーディオ・ファイルが新しいファイル形式(Acme形式など)になっていて、インストールされているサード・パーティ・サービスでサポートされていることを知る必要も気にする必要もありません。プログラムは、最初にAudioSystem
オブジェクトを介してストリームにアクセスします。その後、ストリームとプロパティには常にAudioInputStream
のメソッドを介してアクセスします。これらはどちらもjavax.sound.sampled
APIの標準オブジェクトであり、新しいファイル形式に必要な特別な処理は、完全に隠されています。
サービス・プロバイダは新しいサービスを特別な形式のJARファイルで提供します。このファイルは、JavaランタイムがJARファイルを検索するユーザーのシステム上のディレクトリにインストールされます。JARファイルはアーカイブ・ファイルで、各ファイルにはアーカイブ内で階層ディレクトリ構造に編成されているファイル・セットが含まれます。これらのアーカイブに保存されるクラス・ファイルの準備方法の詳細については、第14章と第15章のオーディオ・パッケージとMIDI SPIパッケージの仕様を参照してください。ここでは、JARファイルの作成プロセスの概要を説明します。
新しいサービスに使用するJARファイルには、そのJARファイルでサポートされる各サービス用のクラス・ファイルが含まれていなければなりません。Javaプラットフォームの規約に従い、各クラス・ファイルは新しく定義されたクラスの名前を持ちます。この新しく定義されたクラスは、サービス・プロバイダの抽象クラスのうちのいずれかの具象サブクラスです。JARファイルには、新しいサービスの実装に必要なサポート・クラスも含める必要があります。また、実行システムのサービス・プロバイダ・メカニズムで新しいサービスの位置を特定できるようにするため、JARファイルには、定義されている新しいサブクラスにSPIクラス名をマップする特殊ファイル(次に説明)も含める必要があります。
前述の例の続きで、Acme Software, Inc. は新しいサンプリング・オーディオ・サービスのパッケージを配布しているとします。このパッケージは、次の2つの新しいサービスにより構成されるものとします。
AudioFileReader
のサブクラスであるAcmeAudioFileReader
クラス(前の説明を参照)AudioFileWriter
のサブクラスであり、Acmeの新しい形式のサウンド・ファイルを書き込むAcmeAudioFileWriter
クラス/devel
という名前のディレクトリの下にサブディレクトリ群を作成し、そこに新しいクラス・ファイルを置きます。新しいクラスを参照できるパス名を使用して編成する必要があります。
com/acme/AcmeAudioFileReader.class com/acme/AcmeAudioFileWriter.classさらに、サブクラス化されている新しい各SPIクラス用に、
META-INF/services
という特別な名前のディレクトリにマッピング・ファイルを作成します。このファイル名はサブクラス化されているSPIクラスの名前で、ファイルには、そのSPI抽象クラスの新しいサブクラスの名前が含まれています。
次の内容で構成される
META-INF/services/javax.sound.sampled.spi.AudioFileReader
ファイルを作成します。
# Providers of sound file-reading services # (a comment line begins with a pound sign) com.acme.AcmeAudioFileReader
および、次の内容で構成される
META-INF/services/javax.sound.sampled.spi.AudioFileWriter,
ファイルを作成します。
# Providers of sound file-writing services com.acme.AcmeAudioFileWriter
ここで、任意のディレクトリから、次のコマンド行によりjar
を実行します。
jar cvf acme.jar -C /devel .
-C
オプションにより、jar
はコマンドが実行されたディレクトリを使用しないで、/devel
ディレクトリを使用します。最後の引数のピリオドは、そのディレクトリ(/devel
)のすべての内容をアーカイブするようjar
に指示します。ただし、ディレクトリそのものはアーカイブしません。
これにより、次の内容のacme.jar
ファイルが作成されます。
com/acme/AcmeAudioFileReader.class com/acme/AcmeAudioFileWriter.class META-INF/services/javax.sound.sampled.spi.AudioFileReader META-INF/services/javax.sound.sampled.spi.AudioFileWriter META-INF/Manifest.mf
jar
ユーティリティ自体により生成されるManifest.mf,
ファイルは、アーカイブに含まれるすべてのファイルのリストです。
アプリケーション・プログラムから新しいサービスにアクセスしようとするエンド・ユーザー(またはシステム管理者)は、インストールを簡単に行うことができます。ユーザーは提供されたJARファイルをCLASSPATH
内のディレクトリに置きます。実行されるとすぐに、Java ランタイムは必要に応じて参照クラスを検出します。
同じサービスに複数のプロバイダをインストールするのは誤りではありません。たとえば、2つの異なるサービス・プロバイダが同じタイプのサウンド・ファイルの読込みをサポートする場合があります。このような場合、システムはいずれかのプロバイダを任意に選択します。選択するプロバイダをユーザーが決める場合は、そのプロバイダのみをインストールします。