W tej sekcji objaśniono, jak od podstaw przeprowadzić implementację
subskrybenta. Informacje te są przydatne, gdy planuje się obsługę synchronizacji, ale nie istnieje jeszcze mechanizm
zarządzania stanem synchronizacji. Zilustrowano tutaj sposób użycia pewnych
funkcji API przeznaczonych do obsługi stanu synchronizacji w przypadku braku
istniejącej infrastruktury synchronizacji.
W pozostałej części tego przykładu użyty zostanie działający przykład. Kod źródłowy można znaleźć w pakiecie dostawcy systemu plików dla modułu dodatkowego org.eclipse.team.examples.filesystem. Odpowiedni projekt należy pobrać z repozytorium CVS i używać go jako odniesienia podczas lektury tego kursu.
Na potrzeby tego pierwszego przykładu przyjęto, że infrastruktura do obsługi stanu synchronizacji lokalnego obszaru roboczego nie istnieje. Podczas implementowania subskrybenta od podstaw można użyć pewnych dodatkowych funkcji API udostępnianych w module dodatkowym org.eclipse.team.core. Pakiet org.eclipse.team.core.variants zawiera dwie podklasy klasy Subscriber, których można użyć do uproszczenia implementacji. Pierwsza z nich to klasa ResourceVariantTreeSubscriber, która zostanie omówiona przy okazji drugiego przykładu poniżej. Druga to podklasa pierwszej klasy o nazwie ThreeWaySubscriber. Ta implementacja subskrybenta oferuje kilka użytecznych klas na potrzeby zarządzania stanem synchronizacji lokalnego obszaru roboczego. W razie braku jakiejkolwiek infrastruktury implementacja ta stanowi dobry punkt wyjścia.
Proces implementowania subskrybenta od podstaw zostanie zilustrowany za pomocą przykładu systemu plików dostępnego w module dodatkowym org.eclipse.team.examples.filesystem. W poniższym opisie zamieszczono tylko minimalne fragmenty kodu, ponieważ jest on dostępny w repozytorium CVS platformy Eclipse. Chociaż przykład systemu plików nie jest z technicznego punktu widzenia trójkierunkowym subskrybentem, z powodzeniem wykorzystuje on tę infrastrukturę. Moduły dodatkowe FTP i WebDAV zostały również zbudowane przy użyciu tej infrastruktury.
Na potrzeby przykładu systemu plików zdefiniowano już implementację klasy RepositoryProvider, która wiąże projekt lokalny z położeniem w systemie plików, w którym znajduje się kopia lustrzana treści lokalnej. Klasa FileSystemSubscriber została utworzona jako podklasa klasy ThreeWaySubscriber, co pozwala użyć klasy ThreeWaySynchronizer do zarządzania stanem synchronizacji obszaru roboczego. Podklasy tej klasy muszą wykonywać następujące czynności:
Oprócz zaimplementowania subskrybenta zmodyfikowano także operacje get i put dla dostawcy systemu plików, aby aktualizowały stan synchronizacji w klasie ThreeWaySynchronizer. Operacje te zostały zaimplementowane w klasie org.eclipse.team.examples.filesystem.FileSystemOperations.
Klasa ThreeWaySynchronizer zarządza stanem synchronizacji lokalnego obszaru roboczego ze zdalnym położeniem. Buforuje ona i utrwala lokalne, podstawowe i zdalne znaczniki, co pozwala efektywnie obliczać stan synchronizacji zasobu. Ponadto wyzwala ona wysyłanie powiadomień o zmianach do wszystkich zarejestrowanych funkcji nasłuchiwania. Klasa ThreeWaySubscriber tłumaczy te zdarzenia zmian na format odpowiedni do wysłania do funkcji nasłuchiwania zarejestrowanych z subskrybentem.
Do zapewnienia bezpieczeństwa wątków oraz umożliwienia wsadowego wysyłania powiadomień o zmianach klasa ThreeWaySynchronizer używa reguł planowania i blokad klasy Core.
Klasa ThreeWayRemoteTree to podklasa klasy ResourceVariantTree zmodyfikowanej na potrzeby klasy ThreeWaySubscriber. Klasa ta musi zostać przesłonięta przez klientów w celu udostępnienia mechanizmu pobierania stanu zdalnego z serwera. Klasa ResourceVariantTree została bardziej szczegółowo opisana w następnym przykładzie.
Funkcja CachedResourceVariant jest częściową implementacją interfejsu IResourceVariant, który przechowuje w pamięci podręcznej pobraną treść przez pewien czas (obecnie przez 1 godzinę). Jest to przydatne, ponieważ w krótkim czasie może nastąpić kilka operacji uzyskania dostępu do tej samej treści (na przykład w celu określenia stanu synchronizacji i wyświetlenia treści w edytorze porównawczym). Podklasy muszą w dalszym ciągu udostępniać unikalny identyfikator treści wraz z tablicą bajtową, która może być utrwalona w celu odtworzenia uchwytu wariantu zasobu.
Wielu dostawców repozytoriów może już mieć mechanizm zarządzania swoim stanem synchronizacji (na przykład gdy istnieją w ich przypadku moduły dodatkowe). Klasa ResourceVariantTreeSubscriber i jej klasy pokrewne pozwalają wykorzystać istniejącą infrastrukturę synchronizacji. Jest to na przykład nadklasa wszystkich subskrybentów CVS.
Jak wspomniano w poprzednim przykładzie, klasa ThreeWaySubscriber jest podklasą klasy ResourceVariantTreeSubscriber, która oferuje synchronizację lokalnego obszaru roboczego przy użyciu klasy ThreeWaySynchronizer. Podklasy klasy ResourceVariantTreeSubscriber muszą udostępniać:
Podklasy klasy ResourceVariantTree (lub klasy AbstractResourceVariantTree), które definiują zachowanie podczas przechodzenia przez zdalne warianty zasobów i ich odświeżania, a także udostępniają podstawowe warianty zasobów w przypadku subskrybentów obsługujących synchronizację trójkierunkową.
Inne możliwości subskrybenta są implementowane przy użyciu poniższych narzędzi.
Obiekt ResourceVariantTree jest konkretną implementacją interfejsu IResourceVariantTree, która zapewnia:
Podklasy muszą implementować:
Dostępne są konkretne implementacje klasy ResourceVariantByteStore, które zapewniają utrwalanie bajtów między wywołaniami środowiska roboczego (PersistantResourceVariantByteStore) lub zapisują w pamięci podręcznej wyłącznie bajty dla bieżącej sesji (SessionResourceVariantByteStore). Budowanie subskrybenta przy użyciu istniejącej infrastruktury synchronizacji obszaru roboczego będzie zwykle wymagało implementacji podklas ResourceVariantByteStore, które komunikują się z programem synchronizującym. Na przykład klasa ThreeWayRemoteTree używa implementacji składnicy bajtów, która zapisuje zdalne bajty w klasie ThreeWaySynchronizer.
Tworzenie uchwytów wariantu zasobu dla tego przykładu różni się od poprzedniego przykładu tylko tym, że uchwyty są żądane z instancji drzewa wariantów zasobów, a nie z subskrybenta.