Location-Independent Access to Resources

  • 概要
  • リソース、名前、およびコンテキスト
  • システムリソース
  • 非システムリソース
  • リソース名
  • Using methods of java.lang.Normal Resource
  • Resource Names
  • Using Methods of the java.lang.Non-System Resources

  • With the Unified Resource
  • Using Methods ofjava.lang.ClassLoader
  • Security
  • Examples

概要

リソースとはプログラムがプログラムコードの位置から独立してアクセスしたいデータ(イメージ、オーディオ、テキストなど)である。 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 の形式である。 shortNameextension は両方とも Java 識別子でなければならない。

リソースの名前は Javimplementation とは無関係で、特にパス区切り文字は常にスラッシュ (/) である。 しかし、Java の実装は、リソースの内容が実際のリソースを含むファイル、データベース、またはその他のオブジェクトにどのようにマッピングされるかの詳細を制御します。 ClassLoader クラスによって実装されたメソッドはこの解釈を行います。

システムリソース

システムリソースは、システムに組み込まれているか、ホスト実装によって、たとえばローカルファイルシステムなどに保持されているリソースです。 プログラムはClassLoaderメソッドgetSystemResourcegetSystemResourceAsStreamを使用してシステムリソースにアクセスします。

たとえば、特定の実装でシステムリソースを見つけるには、CLASSPATHのエントリを検索する必要があるかもしれません。 ClassLoader メソッドは、CLASSPATH 内の各ディレクトリ、ZIP ファイル、または JAR ファイルのエントリを検索してリソース・ファイルを見つけ、見つかった場合は InputStream またはリソース名を返します。 見つからなかった場合、メソッドは null を返します。 リソースは、クラスファイルがロードされた場所とは異なる CLASSPATH のエントリで見つかるかもしれません。

非システムリソース

クラスロードにおける getResource の実装は、ClassLoaderクラスの詳細によって決まります。 たとえば、AppletClassLoader:

  • 最初にシステム リソースとしてリソースを見つけようとし、見つからない場合は、
  • この CODEBASE にすでにロードされているアーカイブ (JAR ファイル) 内のリソースを検索し、見つからない場合は
  • CODEBASE を使用してリソースを見つけようとします (これはリモート サイトへの問い合わせになる可能性があります)。

すべてのクラス ローダーは、クラス ファイルの検索に類似した方法で、システム リソースとして最初にリソースを検索します。 この検索ルールでは、任意のリソースをローカルに上書きすることができます。

リソース名

クラスによって使用されるリソースの名前の一般的な規約は、クラスのパッケージの完全修飾名を使用しますが、すべてのピリオド (.) をスラッシュ (/) に変換して、name.extension 形式のリソース名を追加することです。 これをサポートし、システム・クラス (getClassLoader は null を返す) の詳細を簡単に処理するために、クラス ClassClassLoader の適切なメソッドを呼び出す 2 つの便利なメソッドを提供します。

絶対名は、その開始 “/” を取り除かれ、リソースを見つけるために適切なClassLoaderメソッドに、それ以上の変更なしに渡されます。

Using Methods of java.lang.Class

Class クラスはリソースをロードするためのいくつかのメソッドを実装しています。

getResource()メソッドはリソースの URL を返します。 URL (およびその表現) は、実装と JVM に固有です (つまり、あるランタイム・インスタンスで得られた URL は、別のインスタンスでは動作しないかもしれません)。 そのプロトコルは通常、リソースをロードするClassLoaderに固有である。

クライアント コードがリソースのコンテンツを InputStream として読み取りたい場合、URL に openStream() メソッドを適用することができます。 これは、getResourceAsStream()ClassClassLoader に追加することを正当化できるほど一般的です。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() を呼び出すと、ImageProducerAudioClipInputStream などのオブジェクトが返されます。

getResourceAsStream メソッドは、指定したリソースに対する InputStream またはリソースが見つからなければ null を返します。 リソースが見つからない場合は、リソースへのURLを返すか、NULLを返します。 URL を指定して java.net.URL.getContent() を呼び出すと、ImageProducerAudioClipInputStream などのオブジェクトが返されます。

セキュリティ

getResource() は情報へのアクセスを提供するので、十分に定義され根拠のあるセキュリティ規則を持っている必要があります。 セキュリティの考慮により、リソースがあるセキュリティコンテキストで可視化されない場合、getResource()メソッドはリソースが全く存在しないかのように失敗 (null を返す) し、これは存在攻撃に対処します。

非システムのクラスローダーによって検出されるリソースに関して、指定されたセキュリティ問題や制限はありません。AppletClassLoader は、個別に、または JAR ファイルを通してグループとして、ソースロケーションから読み込まれる情報へのアクセスを提供します。したがって、AppletClassLoadergetResource() を通して 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 オブジェクトを取得します。

コメントを残す

メールアドレスが公開されることはありません。