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.
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
in order to make use of a
to manage workspace synchronization state. Subclasses of this class must do
- create a
instance to manage the local workspace synchronization state.
- create an instance of a
subclass to provide remote tree refresh.
- The class FileSystemRemoteTree was defined for this
- implement a method to create the resource variant handles used to
calculate the synchronization state.
- 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
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
translates these change events into the proper format to be sent to listeners
registered with the subscriber.
makes use of Core scheduling rules and locks to ensure thread safety and provide
change notification batching.
is a subclass of
that is tailored to the
It must be overridden by clients to provide the mechanism for fetching the remote
state from the server.
is discussed in more detail in the next example.
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
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.
As was mentioned in the previous example, the
is a subclass of
that provides local workspace synchronization using a
that provide the behavior for traversing and refreshing the remote resource
variants and, for subscribers that support three-way comparisons, the base
- An implementation of
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
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
is a concrete implementation of
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
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
are provided that persist bytes across workbench invocations (
or cached the bytes only for the current session (
However, building a subscriber on top of an existing workspace synchronization
infrastructure will typically require the implementation of
subclasses that interface with the underlying synchronizer. For example the
makes use of a byte store implementation that stores the remote bytes in the
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.