ワークスペースのリソースを変更する必要がある場合は、他のプラグインも同じリソースで作動していることを考慮する必要があります。リソース API には、ワークスペースの変更をプラグインに継続的に通知し、複数のプラグインが同じリソースを同時に変更しないようにする堅固な仕組みがあります。 可能な場合は、ワークスペースに対するプラグインの変更が、ワークスペース実行可能コード内の作業単位にバッチされます。 この実行可能コードは、変更によって生成される変更通知の量を減らすのに役立ちます。また、この実行可能コードを使用すると、ワークスペースのどの部分を変更するかを宣言できるため、他のプラグインがワークスペースの同じ部分を変更しないようにすることができます。
IWorkspaceRunnable のプロトコルは、とても簡単です。 ワークスペース実行可能コードは、長期に渡る運用またはプラットフォーム・ジョブと似ています。実際の処理は、実行メソッド内で行われ、 指定された IProgressMonitor に進行状況が報告されます。ワークスペースを操作するコードは、実行メソッド内で実行されます。
IWorkspaceRunnable myRunnable = new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { //do the actual work in here ... } }
コードを実行する場合、プラグインは、ワークスペースに、代わりにコードを実行するよう通知します。この場合、ワークスペースは、必要な変更イベントを生成し、2 つのプラグインが同じリソースを同時に変更しないようにします。(ご使用のプラグインが、ワークスペースを変更する場合にバックグラウンド・ジョブおよび並行フレームワークを使用しない場合でも、他のプラグインは使用することがあります。)
IWorkspace プロトコルは、ワークスペース実行可能コードを実行する場合に使用されます。 スケジュール・ルールを提供し、リソース変更イベントがブロードキャストされる方法を指定する長い形式の実行メソッドを使用することをお勧めします。
ワークスペース実行可能コードの実行時にスケジュール・ルールを指定すると、リソースの変更が他のスレッドで発生したワークスペースの変更と競合していないかどうかをワークスペースで判別できます。 (スケジュール・ルールの概要と ISchedulingRule プロトコルについては、『スケジュール・ルール』を参照してください。) 都合の良いことに、IResource プロトコルには、ISchedulingRule のプロトコルが含まれています。つまり、通常、リソースを、リソース自体に対するスケジュール・ルールとして使用することができます。
混乱しましたか?コードを見ると、このことが分かります。 プラグインが、特定のプロジェクトの一連のリソースを変更できると仮定します。 プラグインは、変更する場合のスケジュール・ルールとしてプロジェクト自体を使用できます。 以下のコードの断片は、以前に作成したワークスペース実行可能コードを実行します。
IWorkspace workspace = ResourcesPlugin.getWorkspace(); workspace.run(myRunnable, myProject, IWorkspace.AVOID_UPDATE, null);
実行可能コードは、ワークスペースに渡された後、コードが操作するプロジェクトに渡されます。これにより、実行可能コード内のすべての変更が myProject に制限されていることが、ワークスペースに通知されます。他のスレッドによる myProject の変更に対する要求は、この実行可能コードが完了するまでブロックされます。 同様に、他のスレッドがすでに myProject を変更している場合、この呼び出しはブロックします。 リソース・ツリーのどの部分を実行可能コードで変更するかを指定すると、他のスレッドは、ワークスペースの他の部分への変更を継続できます。 リソース・ルールが、実行可能コード内で実行される処理と一致している必要があります。 スケジュール・ルールの範囲外のリソースにアクセスしようとすると、例外がトリガーされます。
実行メソッドに対する 3 番目のパラメーターは、この呼び出しの範囲時に定期的なリソース変更イベントをブロードキャストする必要があるかどうかを指定します。 IWorkspace.AVOID_UPDATE を使用すると、プラットフォームは、実行可能コードの実行中にリソース変更イベントを抑制し、変更の終了時にイベントをブロードキャストするよう通知されます。 この呼び出しの間に、実行可能コードで作成された他の実行可能コードは、親バッチ操作の一部として扱われます。 これらの実行可能コード内で行われたリソース変更は、親のリソース変更通知に表示されます。
上記の例では、実行可能コード内のコードは、特定のプロジェクトのリソースのみを変更したと想定しています。 これにより、実行可能コードのスケジュール・ルールを簡単に指定できます。 実際は、ワークスペースのどの部分が特定の変更の影響を受けるのかを計算するのは困難です。 例えば、リソースをあるプロジェクトから別のプロジェクトに移動すると、両方のプロジェクトが影響を受けます。IResourceRuleFactory を使用すると、特定の種類のリソース変更に対する適切なリソース・ルールを計算するのに役立ちます。リソース・ルール・ファクトリーは、ワークスペース自体から取得できます。
IWorkspace workspace = ResourcesPlugin.getWorkspace(); IResourceRuleFactory ruleFactory = workspace.getRuleFactory();
ファクトリーは、さまざまな種類の操作に適切なルールを提供できます。 実行可能コードは、リソースをあるロケーションから別のロケーションに移動する場合、この操作に適切なルールを取得できます。
ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource); workspace.run(myRunnable, movingRule, IWorkspace.AVOID_UPDATE, null);
使用可能なルールのリストについては、IResourceRuleFactory の Javadoc を参照してください。リソース・プラグインは、このルール自体を使用して、ほとんどのリソース操作をインプリメントします。 このルール・メソッドを参照するコードをブラウズすると、ルール・メソッドが実際にどのように使用されているかを示すことができます。
MultiRule を使用して、複数のルールを結合することができます。
ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource); ISchedulingRule modifyRule = ruleFactory.modifyResource(destinationResource); workspace.run(myRunnable, MultiRule.combine(movingRule, modifyRule), IWorkspace.AVOID_UPDATE, null);
IWorkspace の実行メソッドの簡易書式も使用することができます。簡易書式は、後方互換性のために保存されています。 簡易書式には、ルールや更新フラグは含まれていません。
workspace.run(myRunnable, null);
上記は、以下を呼び出した場合と同じです。
workspace.run(myRunnable, workspace.getRoot(), IWorkspace.AVOID_UPDATE, null);
ワークスペース・ルートをスケジュール・ルールとして指定すると、実行可能コードが完了するまで、ワークスペース全体がロックされます。この方法はワークスペースを更新する最も保守的な方法ですが、他の並行性を意識したプラグインに対して実行しやすい方法ではありません。