[先頭の項目] [前の項目] [次の項目] [最後の項目]

第 13 章

サービスプロバイダインタフェースの概要

サービスとは何か

サービスとは、アプリケーションプログラムで JavaTM Sound API の実装を使用すると自動的に利用可能になるサウンド処理機能をまとめて表現したものです。サービスを構成するのは、オーディオデータと MIDI データの読み込み、書き込み、ミキシング、処理、変換の各作業を行うオブジェクト群です。Java Sound API の実装では、通常は、基本サービスセットが提供されていますが、さらに、API に新しい機構が組み込まれて、サードパーティ開発者 (または実装自体のベンダー) を対象にした新しいサウンドサービスの開発もサポートされています。これらの新規サービスを、既存の導入済み実装に「プラグイン」のかたちで組み込むと、新規リリースとしなくても機能を拡張することができます。Java Sound API アーキテクチャは、サードパーティサービスをシステムに統合する方法として、アプリケーションプログラムのサードパーティサービスへのインタフェースを「ビルトイン (組み込み)」サービスへのインタフェースと同じにしました。時として、javax.sound.sampled パッケージや javax.sound.midi パッケージを使用するアプリケーション開発者たちは、サードパーティサービスを使用していることに気づかないこともあります。

サードパーティのサンプリングオーディオサービスの例として、次のようなものが挙げられます。

サードパーティの MIDI サービスは、次のようなものです。

サービスの動作

javax.sound.sampled パッケージおよび javax.sound.midi パッケージは、アプリケーションにサウンドサービスを付加したいと考えているアプリケーション開発者に必要な機能を提供するものです。この 2 つのパッケージはサウンドサービスの「消費者 (コンシューマ)」を対象に、オーディオ、MIDI の両サービスに関する情報を取得、制御、およびアクセスに必要なインタフェースを提供します。 また、Java Sound API は、サウンドサービスの「提供者 (プロバイダ)」を対象に、抽象クラスを定義するための javax.sound.sampled.spi パッケージと javax.sound.midi.spi パッケージの 2 つを提供しています。

新しいサウンドパッケージの開発者は、SPI パッケージの中の、使用するクラスの具象サブクラスを実装します。 これらの具象サブクラスは、新サービスのサポートに必要な任意のサブクラスと一緒に含まれているサービスの説明つきで、JavaTM Archive (JAR) アーカイブファイルに置かれます。 この JAR ファイルがユーザの CLASSPATH にインストールされると、実行システムは、自動的に新サービスを利用可能にして、JavaTM プラットフォームの実行システムの機能性を拡張します。

新しいサービスは、インストールされた後は、その前にインストールされていた他のサービスと同様にアクセスできます。サービスの消費者は、新サービス情報と新サービス自体の複数のインスタンスを取得できます。そのためには、AudioSystem クラスと MidiSystem クラスのメソッド群 (前者は javax.sound.sampled パッケージ、後者は javax.sound.midi パッケージに収録) を呼び出して、新サービス情報と、新規または既存のサービスクラス自体を戻します。アプリケーションプログラムはインストールされたサービスを利用するために、SPI パッケージ内のクラス (およびそのサブクラス) を直接参照する必要はなく、またすべきでもありません。

たとえば、Acme Software, Inc. という仮想のサービスプロバイダが、アプリケーションプログラムで新しい形式のサウンドファイル (ただし、オーディオデータは標準のデータ形式) を読み込むパッケージを提供できないかと考えたとします。SPI クラス AudioFileReader は、たとえば AcmeAudioFileReader というクラスにサブクラス化できます。新しいサブクラスで、Acme は AudioFileReader に定義されているすべてのメソッドの実装を提供します。この場合のメソッドは、getAudioFileFormatgetAudioInputStream の 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 つの新しいサービスにより構成されるものとします。

たとえば /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 つの異なるサービスプロバイダが同じタイプのサウンドファイルの読み込みをサポートする場合があります。このような場合、システムは任意にいずれかのプロバイダを選択します。選択するプロバイダをユーザが決める場合には、そのプロバイダのみをインストールします。



[先頭の項目] [前の項目] [次の項目] [最後の項目]

Copyright © 2000, Sun Microsystems Inc. All rights reserved.