## Beyond the Basics

If you plan on providing synchronization support and don't have an existing mechanism for managing synchronization state, this section explains how to implementing a Subscriber from scratch. This means that there is no existing synchronization infrastructure and illustrates how to use some API that is provided to maintain the synchronization state.

For the remainder of this example we will make use of a running example. The source code can be found in the file system provider package of the org.eclipse.team.examples.filesystem plug-in. You should check the project out from the CVS repository and use as a reference while you are reading this tutorial.

### Implementing a Subscriber From Scratch

This first example assumes that there is no existing infrastructure for maintaining the synchronization state of the local workspace. When implementing a subscriber from scratch, you can make use of some additional API provided in the org.eclipse.team.core plug-in. The org.eclipse.team.core.variants package contains two subclasses of Subscriber which can be used to simplify implementation. The first is ResourceVariantTreeSubscriber which will be discussed in the second example below. The second is a subclass of the first: ThreeWaySubscriber. This subscriber implementation provides several helpful classes for managing the synchronization state of a local workspace. If you do not have any existing infrastructure, this is a good place to start.

Implementing a subscriber from scratch will be illustrated using the file system example available in the org.eclipse.team.examples.filesystem plug-in. The code in the following description is kept to a minimum since it is available from the Eclipse CVS repository. Although not technically a three-way subscriber, the file system example can still make good use of this infrastructure. The FTP and WebDAV plug-ins also are built using this infrastructure.

### ThreeWaySubscriber

For the file system example, we already had an implementation of a RepositoryProvider that associated a local project with a file system location where the local contents were mirrored. FileSystemSubscriber was created as a subclass of ThreeWaySubscriber in order to make use of a ThreeWaySynchronizer to manage workspace synchronization state. Subclasses of this class must do the following:

- create a ThreeWaySynchronizer instance to manage the local workspace synchronization state.
- create an instance of a ThreeWayRemoteTree subclass to provide remote tree refresh.
  - The class FileSystemRemoteTree was defined for this purpose
- implement a method to create the resource variant handles used to calculate the synchronization state.
  - The class FileSystemResourceVariant (a subclass of CachedResourceVariant) was defined for this
- implement the roots method
  - The roots for the subscriber are all the projects mapped to the FileSystemProvider. Callbacks were added to FileSystemProvider in order to allow the FileSystemSubscriber to generate change events when projects are mapped and unmapped.

In addition to the subscriber implementation, the get and put operations for the file system provider were modified to update the synchronization state in the ThreeWaySynchronizer. The operations are implemented in the class org.eclipse.team.examples.filesystem.FileSystemOperations.

### ThreeWaySynchronizer

ThreeWaySynchronizer manages the synchronization state between the local workspace and a remote location. It caches and persists the local, base and remote timestamps in order to support the efficient calculation of the synchronization state of a resource. It also fires change notifications to any registered listeners. The ThreeWaySubscriber translates these change events into the proper format to be sent to listeners registered with the subscriber.

The ThreeWaySynchronizer makes use of Core scheduling rules and locks to ensure thread safety and provide change notification batching.

### ThreeWayRemoteTree

A ThreeWayRemoteTree is a subclass of ResourceVariantTree that is tailored to the ThreeWaySubscriber. It must be overridden by clients to provide the mechanism for fetching the remote state from the server. ResourceVariantTree is discussed in more detail in the next example.

### CachedResourceVariant

A CachedResourceVariant is a partial implementation of IResourceVariant that caches any fetched contents for a period of time (currently 1 hour). This is helpful since the contents may be accessed several times in a short period of time (for example, to determine the synchronization state and display the contents in a compare editor). Subclasses must still provide the unique content identifier along with the byte array that can be persisted in order to recreate the resource variant handle.

### Building on Top of Existing Workspace Synchronization

Many repository providers may already have a mechanism for managing their synchronization state (e.g. if they have existing plug-ins). The ResourceVariantTreeSubscriber and its related classes provide the ability to build on top of an existing synchronization infrastructure. For example, this is the superclass of all of the CVS subscribers.

#### ResourceVariantTreeSubscriber

As was mentioned in the previous example, the ThreeWaySubscriber is a subclass of ResourceVariantTreeSubscriber that provides local workspace synchronization using a ThreeWaySynchronizer. Subclasses of ResourceVariantTreeSubscriber must provide:

- Subclasses of ResourceVariantTree (or AbstractResourceVariantTree) that provide the behavior for traversing and refreshing the remote resource variants and, for subscribers that support three-way comparisons, the base resource variants.

- An implementation of IResourceVariantComparator that performs the two-way or three-way comparison for a local resource and its base and remote resource variants.It is common to also provide a subclass of SyncInfo in order to customize the synchronization state determination algorithm.
- An implementation of the roots method for providing the roots of the subscriber and an implementation of the isSupervised method for determining what resources are supervised by the subscriber.

The other capabilities of the subscriber are implemented using these facilities.

#### ResourceVariantTree

ResourceVariantTree is a concrete implementation of IResourceVariantTree that provides the following:

- traversal of the resource variant tree
- logic to merge the previous resource variant tree state with the current fetched state.
- caching of the resource variant tree using a ResourceVariantByteStore.

The following must be implemented by subclasses:

- creation of resource variant handles from the cached bytes that represent a resource variant
- fetching of the current remote state from the server
- creation of the byte store instance used to cache the bytes that uniquely identify a resource variant

Concrete implementations of ResourceVariantByteStore are provided that persist bytes across workbench invocations (PersistantResourceVariantByteStore) or cached the bytes only for the current session (SessionResourceVariantByteStore). However, building a subscriber on top of an existing workspace synchronization infrastructure will typically require the implementation of ResourceVariantByteStore subclasses that interface with the underlying synchronizer. For example the ThreeWayRemoteTree makes use of a byte store implementation that stores the remote bytes in the ThreeWaySynchronizer.

The creation of resource variant handles for this example does not differ from the previous example except that the handles are requested from a resource variant tree instance instead of the subscriber.