リソース変更のトラッキング

リソース・プラグインには、 変更の関連パーティーをリソースに通知するイベント・メカニズムがあります。ユーザー・プラグインが実行中にリソース・ツリーへの変更をトラッキングする必要がある場合には、 ワークスペースに IResourceChangeListener を登録することができます。ユーザーのリスナーは、 変更を記述する IResourceChangeEvent オブジェクトによって変更が通知されます。

リソース変更処理

リソースへの変更をトラッキングするには、リソース変更リスナーをワークスペースに登録する必要があります。

IResourceChangeListener listener = new MyResourceChangeReporter();
ResourcesPlugin.getWorkspace().addResourceChangeListener(
      listener, IResourceChangeEvent.POST_CHANGE);

ユーザーのリスナーは、ワークスペース・リソースに変更が行われた後で通知されます。 リソースを変更するリソース API メソッドは、文書化された振る舞いの一部として、これらのイベントを起動します。 リソース API メソッドに対するメソッド・コメントは、 そのメソッドがリソース変更イベントを起動するかどうかを明示しています。 例えば、以下のコメントが IFile.setContents() コメントに含まれています。

   This method changes resources; these changes will be reported in a subsequent
   resource change event, including an indication that this file's content have
   been changed.

リソースを作成、削除、または変更するメソッドは、通常これらのイベントを起動します。リソースの読み取りを行い、書き込みしないメソッドは、通常これらのイベントを起動しません。

バッチ変更およびリソース・デルタ

同時に複数のリソースを変更する必要がある場合には、リソース変更 API 呼び出しをバッチで行うことができます。 これによって、リソース変更イベントが 1 つだけ、すべての変更に送信されます。操作をバッチで実行するには、IWorkspace.run(実行可能コードおよびモニター) を使用します。リソース変更イベントは、 指定された実行可能コードの終了時に、登録済みリスナーにだけ送信されます。実行可能コードで作成されたその他すべての (ネストされた) Runnable は、 親バッチ操作の一部として扱われ、これらの実行可能コードの中で変更されたリソースは、親のリソース変更通知に表示されます。

多数の小さな変更をブロードキャストすることによって発生するオーバーヘッドを制限できる場合は、 変更をバッチ処理にする必要があります。 バッチ処理の使用ができないと、 リソース変更通知および自動ビルドによって、システムに負荷がかかりすぎることがあります。

リソース変更イベントは、ワークスペースで発生した特定の変更 (または一連の変更) を記述します。 このイベントには、変更の実質的な 影響を記述するリソース・デルタが含まれています。例えば、リソースを追加して、その後複数の変更のバッチ中にそのリソースを削除すると、そのリソースはデルタに表示されません。

リソース・デルタはワークスペース・ルートにルートされたツリーとして構造化されています。リソース・デルタ・ツリーは、以下のタイプの変更を記述します。

リソース・デルタ・ツリーを横断するには、IResourceDeltaVisitor インターフェースをインプリメントするか、 または IResource.getAffectedChildren を使用して明示的にツリーを横断します。リソース・デルタ・ビジターは、 リソース・デルタによって呼び出される訪問 メソッドをインプリメントします。これは、このメソッドがツリー内のそれぞれの変更を列挙しているためです。

注:  リソース・セッション・プロパティー、またはリソースの永続的プロパティーに加えられた変更は、リソース・デルタ内で識別されません。

リソース変更イベント

リソース変更イベントは、1 つの変更 (またはバッチ化された複数の変更) がワークスペースに加えられるごとに送信されます。また、リソース変更イベントは、ある特定のワークスペース操作に対して送信されます。 以下のテーブルは、リソース変更イベントの型、およびそれらイベントが報告されるタイミングの要約です。

イベントの型

説明

PRE_CLOSE

プロジェクトを閉じることをリスナーに通知します。このイベントは、プロジェクトを閉じる前に、 プロジェクトのメモリー内の表記 (すなわちセッション・プロパティー) から必要な情報を抽出および保管するために使用できます。 (プロジェクトを閉じると、メモリー内の表記は破棄されます。) ワークスペースは、このイベント中はロックされます (更新可能なリソースはありません)。このイベントには、閉じている途中のプロジェクトが含まれています。

PRE_DELETE

プロジェクトが削除されることをリスナーに通知します。このイベントは、 プロジェクトに関連する保管された任意の状態をユーザー・プラグインのディレクトリーから削除するなどの終結処理の実行に使用できます。  ワークスペースは、このイベント中はロックされます (更新可能なリソースはありません)。このイベントには、削除されているプロジェクトが含まれています。

PRE_AUTOBUILD

自動ビルドが発生すると、リスナーに通知します。 このイベントは、 自動ビルドが実際に使用可能でない場合でも、 プラットフォームが自動ビルドを発生させる必要があることを検出すると、ブロードキャストされます。  ワークスペースはこのイベント中はロックされません (リソースは更新可能です)。 このイベントには、 最後の POST_CHANGE イベントが報告されてから発生した変更を記述するリソース・デルタが含まれています。

POST_AUTOBUILD

自動ビルドが発生すると、リスナーに通知します。このイベントは、自動ビルドが実際に使用可能でない場合も、 プラットフォームが自動ビルドを実行すると、ブロードキャストされます。  ワークスペースはこのイベント中はロックされません (リソースは更新可能です)。このイベントには、 最後の POST_CHANGE イベントが報告されてから発生した変更を記述するリソース・デルタが含まれています。

POST_CHANGE

最後の POST_CHANGE イベントが報告されてからワークスペースに発生した一連の変更を記述します。 リソース変更 API が個々に、またはワークスペース変更のバッチ・セットで使用された後に起動されます。 任意の PRE_AUTOBUILD 通知または POST_AUTOBUILD 通知が終了後も起動されます。このイベントには、 最後の POST_CHANGE イベント以降の実質的な変更を記述するリソース・デルタが含まれています。  ワークスペースは、このイベント中はロックされます (更新可能なリソースはありません)。

リソース変更リスナーのインプリメント

以下の例では、コンソール・ベースのリソース変更リスナーをインプリメントします。リソース変更リスナーは、 特定のイベントの型に対して登録され、これらのイベントの情報はコンソールに出力されます。

IResourceChangeListener listener = new MyResourceChangeReporter();
ResourcesPlugin.getWorkspace().addResourceChangeListener(listener,
      IResourceChangeEvent.PRE_CLOSE
      | IResourceChangeEvent.PRE_DELETE
      | IResourceChangeEvent.PRE_AUTO_BUILD
      | IResourceChangeEvent.POST_AUTO_BUILD
      | IResourceChangeEvent.POST_CHANGE);

リスナーはそれぞれのイベント型を検査して、変更されたリソースの情報および発生した変更の種類を報告します。  この例は、リソース・イベントのすべての型を処理する汎用リスナーを示すために設計されていますが、 一般的なリスナーは 1 つのイベントの型に対して登録されます。

POST_CHANGE のインプリメンテーションは、リソース・デルタ内の変更を訪問するために使用できる他のクラスを使用します。

import org.eclipse.resources.*;import org.eclipse.runtime.*;
public class MyResourceChangeReporter implements IResourceChangeListener {
      public void resourceChanged(IResourceChangeEvent event) {
         IResource res = event.getResource();
         switch (event.getType()) {
            case IResourceChangeEvent.PRE_CLOSE:
               System.out.print("Project ");
               System.out.print(res.getFullPath());
               System.out.println(" is about to close.");
               break;
            case IResourceChangeEvent.PRE_DELETE:
               System.out.print("Project ");
               System.out.print(res.getFullPath());
               System.out.println(" is about to be deleted.");
               break;
            case IResourceChangeEvent.POST_CHANGE:
               System.out.println("Resources have changed.");
               event.getDelta().accept(new DeltaPrinter());
               break;
            case IResourceChangeEvent.PRE_AUTO_BUILD:
               System.out.println("Auto build about to run.");
               event.getDelta().accept(new DeltaPrinter());
               break;
            case IResourceChangeEvent.POST_AUTO_BUILD:
               System.out.println("Auto build complete.");
               event.getDelta().accept(new DeltaPrinter());
               break;
         }
      }
   }

DeltaPrinter クラスは、リソース・デルタに質問する IResourceDeltaVisitor インターフェースをインプリメントします。 visit() メソッドは、リソース・デルタのそれぞれのリソース変更ごとに呼び出されます。 ビジターは、戻り値を使用して、子リソースのデルタを訪問すべきかどうかを示します。

class DeltaPrinter implements IResourceDeltaVisitor {
      public boolean visit(IResourceDelta delta) {
         IResource res = delta.getResource();
         switch (delta.getKind()) {
            case IResourceDelta.ADDED:
      System.out.print("Resource ");
               System.out.print(res.getFullPath());
               System.out.println(" was added.");
               break;
            case IResourceDelta.REMOVED"
      System.out.print("Resource ");
               System.out.print(res.getFullPath());
               System.out.println(" was removed.");
               break;
case IResourceDelta.CHANGED:
      System.out.print("Resource ");
               System.out.print(res.getFullPath());
      System.out.println(" has changed.");
               break;
         }
         return true; // visit the children
      }
   }

詳しい情報は、提供されているリソース・デルタから取得できます。以下のコードの断片は、 リソース変更を詳しく記述するために、IResourceDelta.CHANGED の事例をインプリメントする方法を示しています。

   ...
case IResourceDelta.CHANGED:
      System.out.print("Resource ");
      System.out.print(delta.getFullPath());
      System.out.println(" has changed.");
      int flags = delta.getFlags();
      if ((flags & IResourceDelta.CONTENT) != 0) {
            System.out.println("--> Content Change");
      }
      if ((flags & IResourceDelta.REPLACED) != 0) {
            System.out.println("--> Content Replaced");
      }
      if ((flags & IResourceDelta.MARKERS) != 0) {
            System.out.println("--> Marker Change");
            IMarkerDelta[] markers = delta.getMarkerDeltas();
            // if interested in markers, check these deltas
      }
               break;
   ...

リソース・デルタ、ビジター、およびマーカー・デルタについての詳細な説明については、IResourceDeltaIResourceDeltaVisitor、および IMarkerDelta の API 仕様を参照してください。

注:  リソース変更リスナーは、ユーザー・プラグインが活動化されている間のリソースに発生した変更をトラッキングする際に役立ちます。 ユーザー・プラグインが、始動コードの間にリソース変更リスナーを登録する場合には、 ユーザー・プラグインの活動化の前に多数のリソース変更イベントが起動される場合があります。 ユーザー・プラグインによって受信される最初のリソース変更イベントに含まれるリソース・デルタには、 ユーザー・プラグインが最後に活動化されてから行われたすべての変更は含まれていません。ユーザー・プラグインの活動化と活動化の間に行われた変更をトラッキングする必要がある場合には、 ワークスペースの保管用に提供されているサポートを使用する必要があります。これは『ワークスペース保管処理への参加』で説明されています。

Copyright IBM Corporation and others 2000, 2003.