Ressourcenänderungen im Stapelbetrieb vornehmen

Wenn Sie Ressourcen im Arbeitsbereich ändern müssen, so muss beachtet werden, dass andere Plug-ins möglicherweise mit den gleichen Ressource arbeiten könnten. Die Ressourcen-API bietet eine leistungsfähige Methode, um Plug-ins über Änderungen im Arbeitsbereich auf dem neuesten Stand zu halten, und um sicherzustellen, dass nicht mehrere Plug-ins gleichzeitig dieselbe Ressource ändern. Wenn möglich, sollten die Arbeitsbereichänderungen Ihres Plug-ins in Arbeitseinheiten innerhalb von ausführbaren Arbeitsbereichfunktionen zusammengefasst werden. Durch diese ausführbaren Funktionen wird die durch Änderungen generierte Menge von Änderungshinweisen reduziert. Außerdem bieten Sie Ihnen die Möglichkeit zu deklarieren, welcher Teil des Arbeitsbereichs geändert werden soll. Hierdurch kann verhindert werden kann, dass andere Plug-ins den gleichen Teil des Arbeitsbereichs ändern.

Das Protokoll für IWorkspaceRunnable ist recht einfach strukturiert. Eine ausführbare Arbeitsbereichfunktion ähnelt einer Operation mit langer Laufzeit oder einem Plattform-Job. Die eigentliche Arbeit wird innerhalb der Methode run geleistet, und der Fortschritt wird an IProgressMonitor berichtet. Code, der den Arbeitsbereich bearbeitet, wird innerhalb der Methode run ausgeführt.

IWorkspaceRunnable myRunnable = 
new IWorkspaceRunnable() {
		public void run(IProgressMonitor monitor) throws CoreException {
			//do the actual work in here
			...
		}
}

Zum Zeitpunkt der Codeausführung benachrichtigt das Plug-in den Arbeitsbereich, den Code in seinem Auftrag auszuführen. Auf diese Art kann der Arbeitsbereich alle nötigen Änderungsereignisse generieren und sicherstellen, dass zwei Plug-ins nicht gleichzeitig dieselbe Ressource ändern. (Auch wenn Ihr Plug-in für Arbeitsbereichsänderungen keine Hintergrund-Jobs oder das Gerüst für gemeinsamen Zugriff verwendet, kann es sein, dass andere Plug-ins so verfahren.)

Regeln und Sperren planen

Das Protokoll IWorkspace wird verwendet, um eine ausführbare Arbeitsbereichfunktion auszuführen. Die empfohlene Methode ist die Verwendung der Langform der Methode run, die eine Regel für die Zeitplanung bereitstellt und bestimmt, auf welche ArtRessourcenänderungsereignisse übertragen werden.

Wenn bei der Ausführung einer ausführbaren Arbeitsbereichfunktion eine Regel für die Zeitplanung angegeben wird, kann der Arbeitsbereich feststellen, ob es einen Konflikt zwischen den Ressourcenänderungen und den Arbeitsbereichsänderungen geben wird, die in anderen Threads ausgeführt werden. (Eine Übersicht der Regeln für die Zeitplanung und das Protokoll ISchedulingRule finden Sie unter Regeln für die Zeitplanung.) Glücklicherweise enthält das Protokoll IResource das Protokoll für ISchedulingRule, wodurch eine Ressource häufig als Regel für die Zeitplanung für sich selbst verwendet werden kann.

Code kann diesen Punkt verdeutlichen und mögliche Verwirrung vermeiden. Angenommen, Ihr Projekt soll mehrere Ressourcen in einem bestimmten Projekt ändern. Es kann das Projekt selbst als Regel für die Zeitplanung bei der Durchführung der Änderungen verwenden. Der folgende Code-Ausschnitt führt die zuvor erstellte ausführbare Arbeitsbereichfunktion aus:

IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.run(myRunnable, myProject, IWorkspace.AVOID_UPDATE, null);

Zunächst wird die ausführbare Funktion an den Arbeitsbereich übergeben, und anschließend das Projekt, das der Code bearbeitet. Hierdurch wird der Arbeitsbereich darüber informiert, dass alle Änderungen der ausführbaren Funktion auf myProject beschränkt sind. Sollten andere Threads versuchen, myProject zu ändern, so werden sie gesperrt, bis diese ausführbare Funktion bis zum Ende ausgeführt wurde. Ebenso wird dieser Aufruf gesperrt, wenn zur Zeit ein anderer Thread myProject ändert. Indem Sie angeben, welcher Teil der Ressourcenbaumstruktur durch die ausführbare Funktion geändert wird, ermöglichen Sie es anderen Threads, mit der Änderung anderer Bereiche des Arbeitsbereiches fortzufahren. Es ist wichtig, dass Sie sicherstellen, dass Ihre Ressourcenregel den in der ausführbaren Funktion ausgeführten Arbeitsschritten entspricht. Jeder Versuch, auf eine Ressource außerhalb des Bereichs der Regel für die Zeitplanung zuzugreifen, löst eine Ausnahmebedingung aus.

Der dritte Parameter der Methode run bestimmt, ob im Umfang dieses Aufrufs regelmäßige Ressourcenänderungsereignisse im Broadcastbetrieb übertragen werden sollen. Die Verwendung von IWorkspace.AVOID_UPDATE weist die Plattform an, während der Ausführung der ausführbaren Funktion alle Ressourcenänderungsereignisse zu unterdrücken und am Ende der Änderungen ein Ereignis im Broadcastbetrieb zu übertragen. In diesem Aufruf werden alle anderen innerhalb der ausführbaren Funktion erstellten ausführbaren Funktionen als Teil der übergeordneten Stapelverarbeitungsoperation angesehen. Die in diesen ausführbaren Funktionen durchgeführten Ressourcenänderungen erscheinen in den übergeordneten Benachrichtigungen über Ressourcenänderungen.

Factory für Ressourcenregeln

Im vorangehenden Beispiel wird angenommen, dass der Code innerhalb der ausführbaren Funktion nur Ressourcen in einem bestimmten Projekt ändert. Hierdurch ist es sehr leicht, eine Regel für die Zeitplanung für diese ausführbare Funktion anzugeben. In der Praxis kann es schwieriger sein zu berechnen, welche Teile des Arbeitsbereichs von einer bestimmten Änderung betroffen sind. Wenn beispielsweise eine Ressource von einem Projekt zu einem anderen verlagert wird, so sind beide Projekte betroffen. IResourceRuleFactory kann verwendet werden, um für bestimmte Arten von Ressourcenänderungen geeignete Ressourcenregeln zu berechnen. Der Arbeitsbereich selbst stellt eine Factory für Ressourcenregeln zur Verfügung.

IWorkspace workspace = ResourcesPlugin.getWorkspace();
IResourceRuleFactory ruleFactory = workspace.getRuleFactory();

Die Factory liefert Regeln, die für viele Arten von Operationen geeignet sind. Wenn Ihre ausführbare Funktion eine Ressource von einer Position zu einer anderen verlagert, kann sie eine für diese Operation geeignete Regel erstellen.

ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource);
workspace.run(myRunnable, movingRule, IWorkspace.AVOID_UPDATE, null);

Eine Liste der verfügbaren Regeln finden Sie in der Javadoc-Datei für IResourceRuleFactory. Das Ressourcen-Plug-in verwendet diese Regeln selbst, um die meisten Ressourcenoperationen zu implementieren. Um zu verstehen, wie diese Regelmethoden funktionieren, hilft es, den Code zu untersuchen, der auf sie verweist.

Mehrere Regeln können über MultiRule kombiniert werden.

ISchedulingRule movingRule = ruleFactory.moveResource(sourceResource, destinationResource);
ISchedulingRule modifyRule = ruleFactory.modifyResource(destinationResource);
workspace.run(myRunnable, MultiRule.combine(movingRule, modifyRule), IWorkspace.AVOID_UPDATE, null);

Regeln ignorieren

Die Kurzform der Methode run in IWorkspace ist ebenfalls verfügbar. Sie wird aus Gründen der Abwärtskompatibilität aufbewahrt. Die Kurzform enthält weder eine Regel noch eine Aktualisierungsmarkierung.

workspace.run(myRunnable, null);

hat den selben Effekt wie der Aufruf von

workspace.run(myRunnable, workspace.getRoot(), IWorkspace.AVOID_UPDATE, null);

Wenn das Stammverzeichnis des Arbeitsbereichs als Regel für die Zeitplanung angegeben wird, so bleibt der gesamte Arbeitsbereich gesperrt, bis die ausführbare Funktion bis zum Ende ausgeführt wurde. Dies ist die konservativste Art, eine Aktualisierung des Arbeitsbereichs durchzuführen, die allerdings die Ansätze anderer Plug-ins bezüglich gleichzeitigen Zugriffs außer Acht lässt.