リソースおよびローカル・ファイル・システム

プラットフォームが実行中でリソース・プラグインがアクティブの場合には、 ワークスペースは、インスタンス IWorkspace によって表されます。このインスタンスは、それが含むリソースにアクセスするプロトコルを提供します。IWorkspace インスタンスは、 ローカル・ファイル・システム内の関連付けられたファイルおよびディレクトリーの集合を表します。 ユーザーは、ワークスペースにリソース・プラグイン・クラス (org.eclipse.core.resources に定義されている) からアクセスできます。

   IWorkspace workspace = ResourcesPlugin.getWorkspace();

リソース・プラグインが実行中でない場合には、ワークスペースは、単にローカル・ファイル・システム内に存在するだけで、 ユーザーによって標準ファイルをベースにするツールで表示または操作されます。 リソース・プラグイン API の説明の際に、ディスク上でワークスペースがどのように表されているかを説明します。

ディスクにあるサンプル・ツリー

プラットフォーム SDK のインストール時に、ユーザーが選択したディレクトリーにファイルが unzip されています。 このディレクトリーは、プラットフォーム・ルート・ディレクトリーと呼ばれています。特に、このディレクトリーは、プラグイン・ディレクトリーを含むディレクトリーです。プラットフォーム・ルート・ディレクトリーの中に、 プラットフォームによって作成および操作されるリソースの保持に使用する workspace ディレクトリーがあります。ユーザーの workspace ディレクトリーには、 ワークスペースに存在するそれぞれのプロジェクトごとに別々のサブディレクトリーがあります。これらのサブディレクトリー内には、各プロジェクトに含まれているフォルダーおよびファイルがあります。

本書の例における SDK が c:¥MySDK にインストールされている場合には、c:¥MySDK¥workspace ディレクトリーの中に、 ワークスペースのプロジェクト、MyWeb および MyServlet から名前を取ったサブディレクトリーがあります。これらのサブディレクトリーは、プロジェクトの内容ディレクトリーと呼ばれています。 内容ディレクトリーは、ユーザーがプロジェクトを作成する時にプラットフォームによって作成されます。

それぞれのディレクトリーの中には、プロジェクト内のファイルおよびフォルダーがあります。 これらのファイルおよびフォルダーは、ワークスペースのリソース・ツリー内とまったく同じ方法でレイアウトされています。 すべてのファイル名は同じであり、ファイルの内容は、ファイル・システムまたはワークスペースのどちらからアクセスしても 同じです。 違いは、後で説明する .project ファイルのみです。

   C:¥MySDK¥workspace  (workspace root)
      .metadata¥ (platform metadata directory)
      MyWeb¥ (project content directory for MyWeb)
	 .project
         index.html
         images¥
            logo.png
      MyServlet¥ (project content directory for MyServlet)
	 .project
         src¥
            main.java
         bin¥
            main.class

プラットフォームには、プラットフォームの内部情報を保持するための特別な .metadata ディレクトリーがあります。 ワークスペースの .metadata ディレクトリーは、"ブラック・ボックス"として扱われます。 プロジェクトの参照またはリソースのプロパティーなどのワークスペース構造に関する重要な情報は、 ワークスペースのメタデータ部分に保管され、 プラットフォームの API を使用するツールのみでアクセスする必要があります。  これらのファイルは汎用ファイル・システム API を使用して編集または操作できません。

さらに、各プロジェクトには独自の .project ファイルがあり、これにはプロジェクトに関するメタデータが保持されます。  基本的に、このファイルはプロジェクトの IProjectDescription にある情報のディスク上の等価物です。  

ワークスペース・ディレクトリー内のフォルダーとファイルは、.metadata ディレクトリーと .project ファイルを除いて、 他のツールで処理できます。  ファイルとフォルダーは、テキスト・エディターおよびファイル・システム・ユーティリティーなどの統合されていないツールによる操作が可能です。  唯一の問題は、ワークベンチの内部と外部の両方でこれらのファイルを編集するときに、ユーザーの注意が必要であることです。  (これは、ユーザーが 2 つのスタンドアロン・ツールを使用してファイルを編集するときと同じです。)  ワークベンチは、 ファイル・システム内の実際の状態と、リソースのワークスペース・ビューを調整するためのリフレッシュ操作を提供し、ファイル・システムの状態に基づきワークスペースを定期的にリフレッシュします。

コード形式のサンプル・ツリー

リソース API によって、ユーザーは、このリソース・ツリーをコードで操作できます。以下は、リソース API を簡単に理解するためのいくつかの断片的なコードです。 リソース API は、org.eclipse.core.resources 内の一連のインターフェースで定義されています。IProjectIFolder、および IFile などのすべてのリソース・タイプに対して、 インターフェースが存在します。広範囲な共通プロトコルは、 IResource に定義されます。org.eclipse.core.runtime インターフェース IPath も使用します。 このインターフェースは、リソースまたはファイル・システム・パスなどのセグメント化されたパスを表しています。

リソースの操作は、 java.io.File の使用によるファイルの操作によく似ています。 API はハンドルに基づいています。  getProjectgetFolder のような API を使用するとき、リソースにハンドルが返されます。  ハンドルで何かを試みようとするまで、ハンドル自体が存在することについて保証や要件はありません。   リソースが存在していなければならない場合、exists メソッドを使用し、そのことを確実にしてください。    

プラグインからワークスペースをナビゲートするには、最初に IWorkspaceRoot を取得する必要があります。 これはワークスペースのトップレベルのリソース階層です。

   IWorkspaceRoot myWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot();

ワークスペース・ルートを一度取得すると、ワークスペース内のプロジェクトをアクセスできます。

   IProject myWebProject = myWorkspaceRoot.getProject("MyWeb");
   // open if necessary
   if (myWebProject.exists() && !myWebProject.isOpen())
      myWebProject.open(null);

プロジェクトを操作するには、そのプロジェクトを開く必要があります。プロジェクトのオープンは、 ディスクからプロジェクトの構造を読み取り、 プロジェクトのリソース・ツリーのメモリー内のオブジェクト表記を作成します。 プロジェクトのオープンは明示的な操作です。 これは、それぞれのオープン・プロジェクトがリソース・ツリーを内部に表示するためにメモリーを消費し、 オープン・プロジェクトが、場合によっては非常に長いものとなる各種のリソース・ライフ・サイクル・イベント (ビルドなど) に参加するためです。  一般的に、クローズされたプロジェクトはアクセスできず、 リソースがまだそのファイル・システムに存在していても、空で表示されます。

これらのリソース・サンプルの多くが、リソースを操作するときに null パラメーターを渡していることに注意してください。 多くのリソース操作は、進行報告およびユーザー・キャンセルを確実に行うために複雑になる可能性があります。 ユーザーのコードにユーザー・インターフェースが含まれている場合、 通常 IProgressMonitor を渡します。 このモニターによって、リソース・プラグインはリソースの操作時に進行を報告し、 ユーザーは必要であれば操作をキャンセルできます。  ここでは単に、進行をモニターしないことを示す NULL を渡します。

オープン・プロジェクトができると、フォルダーとファイルへのアクセスと、追加のフォルダーとファイルの作成が可能になります。  以下の例では、ワークスペースの外にあるファイルのコンテンツからファイル・リソースを作成します。

   IFolder imagesFolder = myWebProject.getFolder("images");
   if (imagesFolder.exists()) {
      // create a new file
      IFile newLogo = imagesFolder.getFile("newLogo.png");
      FileInputStream fileStream = new FileInputStream(
         "c:/MyOtherData/newLogo.png");
      newLogo.create(fileStream, false, null);
      // create closes the file stream, so no worries.
   }

上の例では、最初の行がイメージ・フォルダーへのハンドルを取得します。 フォルダーの作業を行う前に、そのフォルダーの存在を検査する必要があります。 同様に、newLogo ファイルを取得する場合、 最終行でそのファイルを作成するまで、ハンドルは実際のファイルを表しません。 この例では、ファイルの作成は、ファイルに logo.png の内容を取り込むことで行います。

以下のコードの断片は、直前の例と同様です。ただし、newLogo ファイルを、 その内容から新規に作成するのではなく、オリジナルのロゴからコピーします。

   IFile logo = imagesFolder.getFile("logo.png");
   if (logo.exists()) {
      IPath newLogoPath = new Path("newLogo.png");
      logo.copy(newLogoPath, false, null);
      IFile newLogo = imagesFolder.getFile("newLogo.png");
      ...
   }

最後に、他のイメージ・フォルダーを作成し、新規に作成したファイルをそのフォルダーに移動します。 移動に伴って、そのファイルを名前変更します。

   ...
   IFolder newImagesFolder = myWebProject.getFolder("newimages");
   newImagesFolder.create(false, true, null);
   IPath renamedPath = newImagesFolder.getFullPath().append("renamedLogo.png");
   newLogo.move(renamedPath, false, null);
   IFile renamedLogo = newImagesFolder.getFile("renamedLogo.png");

リソース API メソッドの多くには、ローカル・ファイル・システム内の対応するファイルと同期がとれていないリソースを、 それでも更新するかどうかを指定する、force ブール値フラグが組み込まれています。 詳しくは、IResource を参照してください。  また、IResource.isSynchronized を使用して、 特定のリソースがファイル・システムと同期しているかどうかを判別することができます。 

ディスク・ロケーションへのリソースのマッピング

サンプル・リソース・ツリーでは、すべてのプロジェクトの内容ディレクトリーが、 プラットフォームのルート・ディレクトリーの下にある workspace ディレクトリーに存在することを前提にしていました (C:¥MySDK¥workspace)。 これはプロジェクトのデフォルト構成です。 ただし、 プロジェクトの内容ディレクトリーは、おそらく異なるディスク・ドライブ上に存在する、 ファイル・システム内の任意のディレクトリーに再マップできます。

他のプロジェクトとは独立したプロジェクトのロケーションをマップする機能によって、 ユーザーは、そのプロジェクトおよびプロジェクト・チームにとって適切な場所に、プロジェクトの内容を保管できます。 プロジェクトの内容ディレクトリーは、"オープン状態"として扱う必要があります。 つまりユーザーは、ワークベンチおよびプラグインを使用して、またはファイル・システム・ベースのツールおよびエディターを直接使用して、リソースの作成、変更、および削除が行えます。

リソース・パス名は、完全ファイル・システム・パスではありません。 リソース・パスは常に、プロジェクトのロケーション (通常は workspace ディレクトリー) に基づいています。 リソースの完全ファイル・システム・パスを調べるには、 IResource.getLocation でそのロケーションを 照会しなければなりません。  ただし、ロケーションを変更するために IProjectDescription.setLocation を 使用することはできません。 これは、このメソッドがデータ構造の単なる setter でしかないためです。    

逆に、ファイル・システム・パスが指定された、対応するリソース・オブジェクトを取得したい場合、 IWorkspaceRoot.getFileForLocation または IWorkspaceRoot.getContainerForLocation を使用できます。

リソース API およびファイル・システム

リソース API を使用してユーザー・ワークスペースのリソース・ツリーを変更する場合には、 ユーザー・リソース・オブジェクトが更新されるだけでなく、ファイルがファイル・システム内で変更されます。 一方、プラットフォームの API の外部で発生するリソース・ファイルへの変更についてはどうなるでしょう。

リソースへの外部変更は、リソース・プラグインによって検出されるまで、 ワークスペースおよびリソース・オブジェクト内には反映されません。 また、リソース・プラグインは、特定の固有オペレーティング・システムごとに適切なメカニズムを使用して、ファイル・システム内の外部変更を発見します。 さらに、クライアントは、リソース API を使用して、ユーザーが介入することなく、ワークスペースおよびリソース・オブジェクトを、 静的にローカル・ファイル・システムと調整することができます。 また、ユーザーは、ワークベンチのリソース・ナビゲーター・ビューで、常に明示的に最新表示を強制できます。

リソース API の中の多数のメソッドには、ファイル・システムと同期がとれていないリソースを処理する方法を指定する、 強制パラメーターが含まれています。 それぞれのメソッドごとの API 参照は、このパラメーターに関する特定情報を提供します。API の追加メソッドによって、IResource.refreshLocal(int depth、IProgressMonitor monitor) などのファイル・システム・リフレッシュを、方針に基づいてコントロールできます。正しい使用法およびコストについて詳しくは、IResource を参照してください。

外部ファイル・システムの状態に基づいてワークスペースを定期的に最新表示する独自のメカニズムを指定するプラグインは、org.eclipse.core.resources.refreshProviders 拡張ポイントを使用します。 詳しくは、『プロバイダーの更新』を参照してください。