| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> |
| <html> |
| <head> |
| |
| <meta name="copyright" content="Copyright (c) IBM Corporation and others 2000, 2005. This page is made available under license. For full details see the LEGAL in the documentation book that contains this page." > |
| |
| <meta content="text/html; charset=ISO-8859-1" |
| http-equiv="Content-Type"> |
| <meta content="text/css" http-equiv="Content-Style-Type"> |
| <link type="text/css" charset="ISO-8859-1" href="../book.css" |
| rel="STYLESHEET"> |
| <title>Synchronization Support</title> |
| <link href="../book.css" type="text/css" rel="stylesheet"> |
| </head> |
| <body style="background-color: rgb(255, 255, 255);"> |
| <h2>Synchronization Support</h2> |
| <p>Eclipse includes APIs for managing and displaying synchronization state |
| between workspace resources and resources in another location. We refer to a |
| resource outside of the workspace as a variant. Synchronizing is the act of |
| displaying the changes between resources in different locations and optionally |
| allowing the user to affect the synchronization state by performing an action. |
| The synchronize APIs are orthogonal to the RepositoryProvider APIs and can be |
| used without a repository provider. The purpose of the synchronization API is |
| to ease the task of implementing different ways of presenting the synchronization |
| state of resources. As such, the API requires a means to query the synchronization |
| state of resources but does not require a means to affect the state. The means |
| of affecting the state is left to the implementer (although the UI does provide |
| hooks for adding provider specific menu items to menus).</p> |
| <h3>Terminology </h3> |
| <p>Before the synchronization API is described, it is helpful to |
| present some of the terminology and concepts that apply when discussing |
| workspace synchronization.</p> |
| <blockquote> |
| <p><em>Resource Variant</em>: A local resource that is mapped to a resource |
| that exists at another location can be referred to as a variant of that resource. |
| That is, the resources are usually very similar but may differ slightly (either |
| due to modifications to the local resource or changes made the remote copy |
| by other users). We take a local workspace centric view of this, referring |
| to the local copy as the resource and any remote copy as resource variants.</p> |
| <p><em>Synchronize</em>: We refer to synchronize as the action of displaying |
| to the user the differences between resource variants. Synchronizing doesn't |
| affect the state of the variants, but instead provides a view to help the |
| user understand the differences between different sets of variants. It is |
| common however to allow users to affect the states of the variants (e.g. allowing |
| to check-in, or revert) while synchronizing.</p> |
| <p><em>Two-way vs. Three-way Synchronization</em>: There are two basic types |
| of synchronization state determination: two-way and three-way. A two-way comparison |
| only considers the local resource and a single resource variant, referred |
| to as the remote resource variant. This type of comparison can only show the |
| differences between the two resources but cannot offer hints as to how the |
| changes interrelate. Most code repository systems support a three-way comparison |
| for synchronization state determination. This type of comparison involves |
| the local resource, a remote resource variant and a base resource variant. |
| The base resource variant represents a common ancestor for the local and remote |
| resources. This allows for more sophisticated synchronization states that |
| indicate the direction of the change.<br> |
| </p> |
| <p>Table 1: The synchronization states<br> |
| </p> |
| <table style="text-align: left; width: 90%;" border="1" |
| cellspacing="2" cellpadding="2"> |
| <tbody> |
| <tr> |
| <td style="vertical-align: top;"><span |
| style="font-weight: bold;">Two-Way</span></td> |
| <td style="vertical-align: top;"><span |
| style="font-weight: bold;">Three-Way</span></td> |
| </tr> |
| <tr> |
| <td style="vertical-align: top;">Changed<br> |
| Deleted<br> |
| Added</td> |
| <td style="vertical-align: top;">Outgoing Change<br> |
| Incoming Change<br> |
| Outgoing Deletion<br> |
| Incoming Deletion<br> |
| Outgoing Addition<br> |
| Incoming Addition<br> |
| Conflicting Change<br> |
| Conflicting Deletion<br> |
| Conflicting Addition</td> |
| </tr> |
| </tbody> |
| </table> |
| </blockquote> |
| <h3>The Basics - SyncInfo</h3> |
| <p> |
| The classes in the <a |
| href="../reference/api/org/eclipse/team/core/synchronize/package-summary.html">org.eclipse.team.core.synchronize</a> |
| are used to describe the synchronization state. The most important |
| class is <a |
| href="../reference/api/org/eclipse/team/core/synchronize/SyncInfo.html">SyncInfo</a> |
| because it is the class that actually defines the synchronization |
| state. It can be used as follows: |
| </p> |
| <pre><span style="color: rgb(68, 68, 204);">SyncInfo info = getSyncInfo(resource); // this is a simulated method of obtaining the sync info for a resource<br>int changekind = info.getKind();<br>if(info.getResourceComparator().isThreeWay()) {<br> if((changeKind & SyncInfo.DIRECTION_MASK) == SyncInfo.INCOMING) {<br> // do something<br> }<br>} else if(changeKind == SyncInfo.CHANGE) {<br> // do something else<br>}</span></pre> |
| <p> |
| The SyncInfo class provides both the two-way and three-way comparison algorithms, |
| a client must provide the resources and a class that can compare the resources |
| (<a |
| href="../reference/api/org/eclipse/team/core/variants/IResourceVariantComparator.html">IResourceVariantComparator</a>). |
| Here is an example variant comparator: |
| </p> |
| <pre style="color: rgb(68, 68, 204);">public class TimestampVariantComparator implements IResourceVariantComparator { <br> protected boolean compare(IResourceVariant e1, IResourceVariant e2) {<br> if(e1.isContainer()) {<br> if(e2.isContainer()) {<br> return true;<br> }<br> return false;<br> }<br> if(e1 instanceof MyResourceVariant && e2 instanceof MyResourceVariant) {<br> MyResourceVariant myE1 = (MyResourceVariant)e1; <br> MyResourceVariant myE2 = (MyResourceVariant)e2; <br> return myE1.getTimestamp().equals(myE2.getTimestamp());<br> }<br> return false;<br> }<br> protected boolean compare(IResource e1, IResourceVariant e2) {<br> <br> }<br> public boolean isThreeWay() {<br> return true;<br> }<br>}<br><br>SyncInfo info = new SyncInfo(resource, variant1, variant2, new TimestampComparator());<br>info.init(); // calculate the sync info</pre> |
| <p>This package also contains collections specifically designed to contain |
| SyncInfo and filters that can be applied to SyncInfo instances. |
| </p> |
| <h3>Managing the synchronization state</h3> |
| <p> |
| As we have seen in the examples above, <a |
| href="../reference/api/org/eclipse/team/core/synchronize/SyncInfo.html">SyncInfo |
| </a>and |
| <a |
| href="../reference/api/org/eclipse/team/core/variants/IResourceVariantComparator.html">IResourceVariantComparator</a> |
| classes provide access to the |
| synchronization state of resources. But what we haven't seen yet is how |
| the state is managed. A <a |
| href="../reference/api/org/eclipse/team/core/subscribers/Subscriber.html">Subscriber</a> |
| provides access to the synchronization state between the resources in |
| the local workspace and a set of resource variants for these resources |
| using either a two-way or three-way comparison, depending on the nature |
| of the subscriber. A subscriber provides the following capabilities: |
| </p> |
| |
| <ul> |
| <li><span style="font-weight: bold;">local workspace traversal</span>: a subscriber |
| supports the traversal of the local workspace resources that are <em>supervised</em> |
| by the subscriber. As such, the subscriber has a set of <em>root</em> resources |
| that define the workspace subtrees under the subscriber's control, as well |
| as a <em>members</em> method that returns the supervised members of a workspace |
| resource. This traversal differs from the usual workspace resource traversal |
| in that the resources being traversed may include resources that do not exist |
| locally, either because they have been deleted by the user locally or created |
| by a 3rd party. <br> |
| </li> |
| <li><span style="font-weight: bold;">resource synchronization state determination</span>: |
| For supervised resources, the subscriber provides access to the synchronization |
| state of the resource, including access to the variants of the resource. For |
| each supervised resource, the subscriber provides a <em>SyncInfo</em> object |
| that contains the synchronization state and the <em>variants</em> used to |
| determine the state.The subscriber also provides an <em>IResourceVariantComparator</em> |
| which determines whether two-way or three-way comparison is to be used and |
| provides the logic used by the SyncInfo to comparing resource variants when |
| determining the synchronization state. <br> |
| </li> |
| <li><span style="font-weight: bold;">refresh of synchronization state and change |
| notification</span>: Clients can react to changes that happen to local resources |
| by listening to the Core resource deltas. When a local resource is changed, |
| the synchronization state of the resource can then be re-obtained from the |
| subscriber. However, clients must explicitly query the server to know if there |
| are changes to the resource variants. For subscribers, this process is broken |
| up into two parts. A client can explicitly <em>refresh</em> a subscriber. |
| In response the subscriber will obtain the latest state of the resource variants |
| from the remote location and fire <em>synchronization state change</em> events |
| for any resource variants that have changed. The change notification is separate |
| from the refresh since there may be other operations that contact the remote |
| location and obtain the latest remote state. </li> |
| </ul> |
| <p> The APIs do not not define how a Subscriber is created, this is left to the |
| specific implementations. For example the CVS plug-in creates a Subscriber when |
| a merge is performed, another for a comparison, and another when synchronizing |
| the local workspace with the current branch. </p> |
| <p> |
| So let's revisit our first example of using SyncInfo and see how a |
| Subscriber could be used to access SyncInfo.</p> |
| |
| <pre><span style="color: rgb(68, 68, 204);">// Create a file system subscriber and specify that the<br>// subscriber will synchronize with the provided file system location<br>Subscriber subscriber = new FileSystemSubscriber("c:\temp\repo");<br><br>// Allow the subscriber to refresh its state<br>subscriber.refresh(subscriber.roots(), IResource.DEPTH_INFINITE, monitor);<br><br>// Collect all the synchronization states and print<br>IResource[] children = subscriber.roots();<br>for(int i=0; i < children.length; i++) {<br> printSyncState(children[i]);<br>}<br><br>...<br><br>void printSyncState(Subscriber subscriber, IResource resource) {<br> System.out.println(subscriber.getSyncInfo(resource).toString());<br></span><span |
| style="color: rgb(68, 68, 204);"><span style="color: rgb(68, 68, 204);"> IResource[] children = subscriber.members(resource);<br> for(int i=0; i < children.length; i++) {<br> IResource child = children[i];<br> if(! child.exists()) {<br> System.out.println(resource.getFullPath() + " doesn't exist in the workspace");<br> }<br> printSyncState(subscriber, children[i]);<br> }<br>}<br></span></span></pre> |
| <p> |
| The important point to remember is that the Subscriber knows about |
| resources that do not exist in the workspace and non-existing resources |
| can be returned from the <a |
| href="../reference/api/org/eclipse/team/core/subscribers/Subscriber.html#members(org.eclipse.core.resources.IResource)">Subscriber#members()</a> |
| and <a |
| href="../reference/api/org/eclipse/team/core/synchronize/SyncInfo.html#getLocal()">SyncInfo#getLocal()</a>. |
| </p> |
| <h3>Displaying the synchronizations state in the UI</h3> |
| <p> |
| We could spend more time explaining how to manage synchronization state |
| but instead let's see how to actually get the state shown to the user. |
| A <a |
| href="../reference/api/org/eclipse/team/ui/synchronize/ISynchronizeParticipant.html">ISynchronizeParticipant |
| </a>is the user interface component that displays synchronization state |
| and allows the user to affect its state. The Synchronize View displays |
| synchronize participants, but it is also possible to show these in |
| dialogs and wizards. In order to provide support for users to show any |
| type of synchronization state to the user, even those not based on |
| SyncInfo and Subscribers, a participant is a very generic component.</p> |
| <p> |
| There is also an extension point called <a |
| href="../reference/extension-points/org_eclipse_team_ui_synchronizeWizards.html">org.eclipse.team.ui.synchronizeWizards</a> |
| to add a synchronization creation wizard. This will put your wizard in |
| the global synchronize action and in the Synchronize View, so that |
| users can easily create a synchronization of your type. |
| </p> |
| <p> |
| However, if you have implemented a Subscriber you can benefit from a |
| concrete participant called <a |
| href="../reference/api/org/eclipse/team/ui/synchronize/SubscriberParticipant.html">SubscriberParticipant |
| </a>which will provide |
| the following functionality: |
| </p> |
| |
| <ul> |
| <li>Collects SyncInfo from a Subscriber in the background.</li> |
| <li>Listens to changes in the workspace and those found when a |
| Subscriber is refreshed and keeps the synchronization state updated |
| dynamically.</li> |
| <li>Provides the user interface that support modes for filtering the |
| changes, and layouts.</li> |
| <li>Support scheduling a refresh with the Subscriber so that the |
| synchronization states are kept up-to-date.</li> |
| <li>Supports refreshing a Subscriber in the background.</li> |
| <li>Supports navigation of the changes and showing the differences |
| between the files.</li> |
| <li>Supports configuration of the actions, toolbars, and decorators |
| by subclasses.<br> |
| </li> |
| </ul> |
| <p>The best way to explain these concepts are to see them used in the context |
| of a simple example. Go to the <a |
| href="team_synchronize_localhistory_example.htm">local history synchronization</a> |
| example to see how all of these pieces can be used together. Or if you want |
| pointers on how to use the more advanced APIs, go to <a |
| href="team_synchronize_beyond_basics.htm">Beyond The Basics</a>.<br> |
| </p> |
| |
| </body> |
| </html> |