Synchronisationsunterstützung

Eine Neuheit in Eclipse 3.0 sind APIs, die den Synchronisierungsstatus zwischen Arbeitsbereichressourcen und Ressourcen an einer anderen Position verwalten und darstellen. Eine Ressource außerhalb des Arbeitsbereichs wird als Variante bezeichnet. Synchronisierung ist die Darstellung der Änderungen zwischen Ressourcen in unterschiedlichen Positionen und optional die Möglichkeit, den Synchronisierungsstatus durch eine Aktion des Benutzers zu beeinflussen. Die Synchronisierungs-APIs stehen rechtwinklig zu RepositoryProvider-APIs und können ohne einen Repository-Provider verwendet werden. Synchronisierungs-APIs sollen die Implementierung verschiedener Darstellungsarten für die Synchronisierungsstatuswerte von Ressourcen erleichtern. Daher benötigt die API einen Weg, um den Synchronisierungsstatus der Ressource abzufragen, nicht aber, um diesen Status auch zu beeinflussen. Wie der Status beeinflusst wird, liegt im Ermessen des Implementierers (die Benutzerschnittstelle stellt allerdings Hooks zur Verfügung, über die provider-spezifische Menüpunkte zu Menüs hinzugefügt werden können).

Terminologie

Bevor die Synchronisierungs-API beschrieben wird, ist es sicherlich sinnvoll, zunächst die Terminologie und Konzepte einzuführen, die bei der Erläuterung der Arbeitsbereichsynchronisierung verwendet werden.

Ressourcenvariante: Eine lokale Ressource, für die eine Zuordnung zu einer Ressource an einer anderen Position besteht, kann als Variante dieser Ressource bezeichnet werden. Die Ressourcen sind sich zwar in der Regel sehr ähnlich, können sich aber geringfügig unterscheiden (aufgrund von Änderungen an entweder der lokalen Ressource oder an der fernen Kopie durch andere Benutzer). Die hier verwendete Betrachtungsweise geht vom lokalen Arbeitsbereich aus, daher wird die lokale Kopie als Ressource, die ferne Kopie als Ressourcenvariante bezeichnet.

Synchronisieren: Als synchronisieren wird der Vorgang bezeichnet, bei dem einem Benutzer die Unterschiede zwischen Ressourcenvarianten dargestellt werden. Eine Synchronisierung beeinflusst den Status der Varianten nicht, sondern bietet lediglich eine Sicht, damit der Benutzer die Unterschiede zwischen unterschiedlichen Variantengruppen verstehen kann. Häufig wird den Benutzern allerdings auch die Möglichkeit geboten, die Statuswerte der Varianten bei der Synchronisierung zu beeinflussen (z.B. freizugeben oder zurückzusetzen).

Zweifach- oder Dreifachsynchronisierung: Es gibt zwei Grundarten, um den Synchronisierungsstatus zu bestimmen: zweifach und dreifach. Ein Zweifachvergleich zieht nur die lokale Ressource und eine einzige Ressourcenvariante in Betracht, wobei letztere als ferne Ressourcenvariante bezeichnet wird. Diese Art des Vergleichs kann lediglich die Unterschiede zwischen zwei Ressourcen aufweisen. Sie kann keinerlei Hinweis darauf liefern, wie die Änderungen zusammenhängen. Die meisten Code-Repositorysysteme unterstützen einen Dreifachvergleich für die Bestimmung des Synchronisierungsstatus. Diese Art des Vergleichs greift auf die lokale Ressource, eine ferne Ressourcenvariante und eine Basisressourcenvariante zu. Die Basisressourcenvariante stellt einen gemeinsamen Vorfahren sowohl der lokalen als auch der fernen Ressource dar. Dies ermöglicht ausgereiftere Synchronisierungsstatuswerte, aus denen sich die Richtung der Änderung ablesen lässt.

Tabelle 1: Synchronisierungsstatuswerte

Zweifach Dreifach
Geändert
Gelöscht
Hinzugefügt
Abgehende Änderung
Eingehende Änderung
Abgehende Löschung
Eingehende Löschung
Abgehende Hinzufügung
Eingehende Hinzufügung
Konflikt bei Änderung
Konflikt bei Löschung
Konflikt bei Hinzufügung

Grundlegende Informationen - SyncInfo

Die Klassen in org.eclipse.team.core.synchronize werden für die Beschreibung des Synchronisierungsstatus verwendet. Die wichtigste Klasse ist SyncInfo, da dies auch die Klasse ist, die den Synchronisierungsstatus definiert. Sie kann folgendermaßen verwendet werden:

SyncInfo info = getSyncInfo(resource); // this is a simulated method of obtaining the sync info for a resource
int changekind = info.getKind();
if(info.getResourceComparator().isThreeWay()) {
if((changeKind & SyncInfo.DIRECTION_MASK) == SyncInfo.INCOMING) {
// do something
}
} else if(changeKind == SyncInfo.CHANGE) {
// do something else
}

Die Klasse SyncInfo bietet Algorithmen sowohl für Zweifach- als auch für Dreifachvergleiche. Ein Client muss die Ressourcen zur Verfügung stellen, sowie eine Klasse, die die Ressource vergleichen kann (IResourceVariantComparator). Das Folgende ist ein Beispiel für einen Variantenvergleichsoperator:

public class TimestampVariantComparator implements IResourceVariantComparator {	
protected boolean compare(IResourceVariant e1, IResourceVariant e2) {
if(e1.isContainer()) {
if(e2.isContainer()) {
return true;
}
return false;
}
if(e1 instanceof MyResourceVariant && e2 instanceof MyResourceVariant) {
MyResourceVariant myE1 = (MyResourceVariant)e1;
MyResourceVariant myE2 = (MyResourceVariant)e2;
return myE1.getTimestamp().equals(myE2.getTimestamp());
}
return false;
}
protected boolean compare(IResource e1, IResourceVariant e2) {

}
public boolean isThreeWay() {
return true;
}
}

SyncInfo info = new SyncInfo(resource, variant1, variant2, new TimestampComparator());
info.init(); // calculate the sync info

Dieses Paket enthält auch Objektgruppen, die speziell dafür entworfen wurden, SyncInfo zu enthalten, sowie Filter, die auf Exemplare von SyncInfo angewendet werden können.

Den Synchronisierungsstatus verwalten

In den voranstehenden Beispielen wurde dargestellt, dass die Klassen SyncInfo und IResourceVariantComparator Zugriff auf den Synchronisierungsstatus von Ressourcen bieten. Eine Statusverwaltung hat bisher nicht stattgefunden. Ein Subskribent bietet Zugriff auf den Synchronisierungsstatus zwischen Ressourcen im lokalen Arbeitsbereich und einer Gruppe von Ressourcenvarianten für diese Ressourcen. Hierbei wird, je nach Art des Subskribenten, ein Zwei- oder Dreifachvergleich verwendet. Ein Subskribent bietet die folgenden Fähigkeiten:

Die APIs definieren nicht die Art, wie ein Subskribent erstellt wird. Dies ist Aufgabe der jeweiligen Implementierungen. Das CVS-Plug-in erstellt einen Subskribenten beispielsweise bei der Ausführung einer Zusammenführung, einen anderen für einen Vergleich und noch einen weiteren, wenn der lokale Arbeitsbereich mit der aktuellen Verzweigung synchronisiert wird.

Im folgenden Ausschnitt wird dargestellt, wie im ersten Beispiel ein Subskribent verwendet werden könnte, um auf SyncInfo zuzugreifen.

// Create a file system subscriber and specify that the
// subscriber will synchronize with the provided file system location
Subscriber subscriber = new FileSystemSubscriber("c:\temp\repo");

// Allow the subscriber to refresh its state
subscriber.refresh(subscriber.roots(), IResource.DEPTH_INFINITE, monitor);

// Collect all the synchronization states and print
IResource[] children = subscriber.roots();
for (int i = 0; i < children.length; i++) {
printSyncState(children[i]);
}

...

void printSyncState(Subscriber subscriber, IResource resource) {
System.out.println(subscriber.getSyncInfo(resource).toString());
IResource[] children = subscriber.members(resource);
for (int i = 0; i < children.length; i++) {
IResource child = children[i];
if(! child.exists()) {
System.out.println(resource.getFullPath() + " doesn't exist in the workspace");
}
printSyncState(subscriber, children[i]);
}
}

Es darf nicht vergessen werden, dass der Subskribent Informationen über Ressourcen hält, die sich nicht im Arbeitsbereich befinden, und dass nicht existierende Ressourcen von Subscriber#members() und SyncInfo#getLocal() zurückgegeben werden können.

Synchronisierungsstatus in der Benutzerschnittstelle darstellen

Anstatt noch weitere Details über die Verwaltung des Synchronisierungsstatus zu erläutern, soll nun endlich dargestellt werden, wie der Status dem Benutzer angezeigt werden kann. Ein ISynchronizeParticipant ist die Komponente der Benutzerschnittstelle, die den Synchronisierungsstatus anzeigt und über die der Benutzer den Status beeinflussen kann. Die Sicht 'Synchronisieren' zeigt Teilnehmer an der Synchronisierung an. Sie können allerdings auch in Dialogen und Assistenten dargestellt werden. Ein Teilnehmer ist eine sehr generische Komponente, über die Benutzern jede Art von Synchronisierungsstatus angezeigt werden kann, selbst diejenigen, die nicht auf SyncInfo oder Subskribenten basieren.

Es gibt auch einen Erweiterungspunkt namens org.eclipse.team.ui.synchronizeWizards, über den ein Synchronisierungsassistent hinzugefügt werden kann. Der neue Assistent wird hierbei in die globale Synchronisierungsaktion in der Sicht 'Synchronisieren' eingebunden, so dass Benutzer leicht eine Synchronisierung des neuen Typs erstellen können.

Wenn Sie allerdings bereits einen Subskribenten implementiert haben, können Sie einen konkreten Teilnehmer namens SubscriberParticipant nutzen, der die folgende Funktionalität bietet:

Diese Konzepte werden am besten im Kontext eines einfachen Beispiels erläutert. Ein Beispiel für die gleichzeitige Verwendung all dieser Elemente finden Sie unter Synchronisierung des lokalen Protokolls. Informationen über die Verwendung differenzierterer APIs finden Sie unter Informationen für Fortgeschrittene.