Location-Independent Access to Resources
- 概要
- リソース、名前、およびコンテキスト
- システムリソース
- 非システムリソース
- リソース名
- Using methods of java.lang.Normal Resource
- Resource Names
- With the Unified Resource
- Using Methods ofjava.lang.ClassLoader
- Security
- Examples
Using Methods of the java.lang.Non-System Resources
概要
リソースとはプログラムがプログラムコードの位置から独立してアクセスしたいデータ(イメージ、オーディオ、テキストなど)である。 Java プログラムは、リソースにアクセスするために 2 つのメカニズムを使用できます。 アプレットは、Applet.getCodeBase()
を使用してアプレット コードのベース URL を取得し、ベース URL を相対パスで拡張して、たとえば Applet.getAudioClip(url)
で目的のリソースをロードします。 アプリケーションは、System.getProperty("user.home")
や System.getProperty("java.home")
などの “well-known location” を使用し、次に “/lib/resource” を追加し、そのファイルを開きます。
Class
および ClassLoader
クラス内のメソッドは、リソースを配置する場所に依存しない方法を提供します。 たとえば、次のリソースを検索できます。
- A applet loaded from the Internet using multiple HTTPconnections.
- A applet loaded using JAR files.
- A Java Bean loaded or installed in the CLASSPATH.
- A “library” installed in the CLASSPATH.
これらの方法は、ローカルなリソース検索を特にサポートするものではありません。
リソース、名前、およびコンテキスト
リソースは、スラッシュ (/) で区切られた一連のサブストリングと、リソース名からなる文字列で識別されます。 リソース名は shortName
または shortName.extension
の形式である。 shortName
と extension
は両方とも Java 識別子でなければならない。
リソースの名前は Javimplementation とは無関係で、特にパス区切り文字は常にスラッシュ (/) である。 しかし、Java の実装は、リソースの内容が実際のリソースを含むファイル、データベース、またはその他のオブジェクトにどのようにマッピングされるかの詳細を制御します。 ClassLoader
クラスによって実装されたメソッドはこの解釈を行います。
システムリソース
システムリソースは、システムに組み込まれているか、ホスト実装によって、たとえばローカルファイルシステムなどに保持されているリソースです。 プログラムはClassLoader
メソッドgetSystemResource
とgetSystemResourceAsStream
を使用してシステムリソースにアクセスします。
たとえば、特定の実装でシステムリソースを見つけるには、CLASSPATHのエントリを検索する必要があるかもしれません。 ClassLoader
メソッドは、CLASSPATH 内の各ディレクトリ、ZIP ファイル、または JAR ファイルのエントリを検索してリソース・ファイルを見つけ、見つかった場合は InputStream
またはリソース名を返します。 見つからなかった場合、メソッドは null を返します。 リソースは、クラスファイルがロードされた場所とは異なる CLASSPATH のエントリで見つかるかもしれません。
非システムリソース
クラスロードにおける getResource
の実装は、ClassLoader
クラスの詳細によって決まります。 たとえば、AppletClassLoader
:
- 最初にシステム リソースとしてリソースを見つけようとし、見つからない場合は、
- この CODEBASE にすでにロードされているアーカイブ (JAR ファイル) 内のリソースを検索し、見つからない場合は
- CODEBASE を使用してリソースを見つけようとします (これはリモート サイトへの問い合わせになる可能性があります)。
すべてのクラス ローダーは、クラス ファイルの検索に類似した方法で、システム リソースとして最初にリソースを検索します。 この検索ルールでは、任意のリソースをローカルに上書きすることができます。
リソース名
クラスによって使用されるリソースの名前の一般的な規約は、クラスのパッケージの完全修飾名を使用しますが、すべてのピリオド (.) をスラッシュ (/) に変換して、name.extension
形式のリソース名を追加することです。 これをサポートし、システム・クラス (getClassLoader
は null を返す) の詳細を簡単に処理するために、クラス Class
は ClassLoader
の適切なメソッドを呼び出す 2 つの便利なメソッドを提供します。
絶対名は、その開始 “/” を取り除かれ、リソースを見つけるために適切なClassLoader
メソッドに、それ以上の変更なしに渡されます。
Using Methods of java.lang.Class
Class
クラスはリソースをロードするためのいくつかのメソッドを実装しています。
getResource()
メソッドはリソースの URL を返します。 URL (およびその表現) は、実装と JVM に固有です (つまり、あるランタイム・インスタンスで得られた URL は、別のインスタンスでは動作しないかもしれません)。 そのプロトコルは通常、リソースをロードするClassLoader
に固有である。
クライアント コードがリソースのコンテンツを InputStream
として読み取りたい場合、URL に openStream()
メソッドを適用することができます。 これは、getResourceAsStream()
を Class
と ClassLoader
に追加することを正当化できるほど一般的です。getResourceAsStream()
は、getResource().openStream()
の呼び出しと同じですが、getResourceAsStream()
は IO 例外をキャッチして、空の InputStream
を返します。
クライアント コードは、URL の java.net.URL.getContent()
メソッドを適用してオブジェクトとしてのリソースのコンテンツを要求することも可能です。 これは、リソースに画像のデータが含まれている場合などに便利です。
getResource
および getResourceAsStream
メソッドは、指定された名前のリソースを検索します。 指定された名前のリソースが見つからなければ null を返します。 与えられたクラスに関連付けられたリソースを検索するルールは、そのクラスのClassLoaderによって実装されます。 リソース名が “/” で始まる場合、それはそのまま使用されます。そうでない場合、すべてのピリオド (.) をスラッシュ (/) に変換した後、パッケージ名が先頭に追加されます。
public InputStream getResourceAsStream(String name) { name = resolveName(name); ClassLoader cl = getClassLoader(); if (cl==null) { return ClassLoader.getSystemResourceAsStream(name); // A system class. } return cl.getResourceAsStream(name);}public java.net.URL getResource(String name) { name = resolveName(name); ClassLoader cl = getClassLoader(); if (cl==null) { return ClassLoader.getSystemResource(name); // A system class. } return cl.getResource(name);}
resolveName
メソッドは、名前が絶対でなければパッケージ名のプレフィックスを追加し、名前が絶対なら最初の “/” は除去されます。
private String resolveName(String name) { if (name == null) { return name; } if (!name.startsWith("/")) { Class c = this; while (c.isArray()) { c = c.getComponentType(); } String baseName = c.getName(); int index = baseName.lastIndexOf('.'); if (index != -1) { name = baseName.substring(0, index).replace('.', '/') + "/" + name; } } else { name = name.substring(1); } return name;}
Using Methods of java.lang.ClassLoader
ClassLoader
クラスには、リソースにアクセスするためのメソッドが2組あります。 1つのセットは、リソースに対するInputStream
を返します。 もう 1 つのセットは URL を返します。 InputStream
を返すメソッドは使いやすく、多くのニーズを満たしますが、URLを返すメソッドは Image や AudioClip のようなより複雑な情報へのアクセスを提供します。
ClassLoader
は、クラスを管理する方法と同様に、リソースを変更します。 ClassLoader
は、リソースの名前をそのコンテンツにマッピングする方法を制御します。 ClassLoader
はまた、システムクラスと同様にシステムリソースにアクセスするためのメソッドを提供します。 Class
クラスは、ClassLoader
メソッドに機能を委譲するいくつかの便利なメソッドを提供します。
多くの Java プログラムは、I18N (localization) API を通して間接的にこれらのメソッドにアクセスするでしょう。 他のものは、Class
のメソッドを通じてアクセスします。 ClassLoader
のメソッドは、与えられた文字列を絶対/相対変換を適用せずにリソースの名前として使用します (クラス内のメソッドを参照)。
システムリソースとは、ホスト側の実装で直接扱われるリソースのことです。 例えば、CLASSPATH に配置されるかもしれません。
リソースの名前は “/” で区切られた識別子のシーケンスです。 Class
クラスは、リソースにアクセスするための便利なメソッドを提供します。メソッドは、パッケージ名の前にリソースの短い名前を付けるという慣習を実装しています。
リソースは、InputStream
または URL としてアクセスできます。 リソース名は任意のシステムリソースです。
getSystemResource
メソッドは、指定された名前のシステムリソースを見つけます。 リソースが見つからない場合は、リソースへの URL または null を返します。 URL を指定して java.net.URL.getContent()
を呼び出すと、ImageProducer
、AudioClip
、InputStream
などのオブジェクトが返されます。
getResourceAsStream
メソッドは、指定したリソースに対する InputStream
またはリソースが見つからなければ null を返します。 リソースが見つからない場合は、リソースへのURLを返すか、NULLを返します。 URL を指定して java.net.URL.getContent()
を呼び出すと、ImageProducer
、AudioClip
、InputStream
などのオブジェクトが返されます。
セキュリティ
getResource()
は情報へのアクセスを提供するので、十分に定義され根拠のあるセキュリティ規則を持っている必要があります。 セキュリティの考慮により、リソースがあるセキュリティコンテキストで可視化されない場合、getResource()
メソッドはリソースが全く存在しないかのように失敗 (null を返す) し、これは存在攻撃に対処します。
非システムのクラスローダーによって検出されるリソースに関して、指定されたセキュリティ問題や制限はありません。AppletClassLoader
は、個別に、または JAR ファイルを通してグループとして、ソースロケーションから読み込まれる情報へのアクセスを提供します。したがって、AppletClassLoader
は getResource()
を通して URL を処理する場合、同じ checkConnect()
規則を適用する必要があります。 CLASSPATH には、ディレクトリと JAR ファイルを含めることができます。 JAR ファイルは意図的に作成されるため、ディレクトリのように適当に作成するのとは意味が異なります。 特に、ディレクトリから情報を取得することについては、JAR ファイルから取得するよりも厳格です。
リソースがディレクトリにある場合、
-
getResource()
呼び出しは、対応するファイルをユーザーに見せるかどうかを判断するのに、File.exists()
を使用します。 リソースが JAR ファイルの場合:-
getResource()
の呼び出しは、呼び出しがシステムまたは非システム クラスのどちらから行われたかにかかわらず、すべてのファイルに対して成功します。 -
getResourceAsStream()
呼び出しは .class 以外のリソースで成功し、対応する URL ではjava.net.URL.getContent()
も成功します。
例
このセクションでは、クライアントコードの例を 2 つ示します。 最初の例は、「絶対リソース」名と従来のメカニズムを使用して
Class
オブジェクトを取得します。package pkg;import java.io.IOException;import java.io.InputStream;import java.io.PrintStream;class Test { private static final String absName = "/pkg/mumble.baf"; public static void test1() { Class c=null; try { c = Class.forName("pkg.Test"); } catch (Exception ex) { // This should not happen. } InputStream s = c.getResourceAsStream(absName); // do something with it. } public void test2() { InputStream s = this.getClass().getResourceAsStream(absName); // do something with it. }}
この例は、「相対リソース」名と
-experimental
フラグによってコンパイラから利用できるメカニズムを使用して、Class
オブジェクトを取得します。 -