Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Valenta2004-03-03 18:21:34 +0000
committerMichael Valenta2004-03-03 18:21:34 +0000
commitbb660189c1ef356aa97a8960e78ae6714f4101c5 (patch)
treeb5432d5456812607e4e02382780a12f623d1abf6
parent6011408d6ed3c619bf48cc50cfd21c10c4c3ea5b (diff)
downloadeclipse.platform.team-bb660189c1ef356aa97a8960e78ae6714f4101c5.tar.gz
eclipse.platform.team-bb660189c1ef356aa97a8960e78ae6714f4101c5.tar.xz
eclipse.platform.team-bb660189c1ef356aa97a8960e78ae6714f4101c5.zip
Refactoring of subscribers and resource variants
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/Subscriber.java2
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/package.html3
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/SyncInfo.java1
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/SyncInfoFilter.java1
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/package.html57
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/AbstractResourceVariantTree.java (renamed from bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/AbstractResourceVariantTree.java)5
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/CachedResourceVariant.java (renamed from bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/CachedResourceVariant.java)2
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/IResourceVariant.java (renamed from bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/IResourceVariant.java)12
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/IResourceVariantComparator.java (renamed from bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/IResourceVariantComparator.java)6
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/IResourceVariantTree.java (renamed from bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/IResourceVariantTree.java)3
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ISynchronizerChangeListener.java26
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/PersistantResourceVariantByteStore.java (renamed from bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/PersistantResourceVariantByteStore.java)4
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ResourceVariantByteStore.java (renamed from bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantByteStore.java)2
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ResourceVariantTree.java (renamed from bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTree.java)11
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ResourceVariantTreeSubscriber.java (renamed from bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTreeSubscriber.java)3
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/SessionResourceVariantByteStore.java (renamed from bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SessionResourceVariantByteStore.java)2
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWayRemoteTree.java89
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWayResourceComparator.java88
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWaySubscriber.java165
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWaySynchronizer.java515
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/package.html56
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/ResourceVariantCache.java2
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/ResourceVariantCacheEntry.java2
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties2
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/BatchingLock.java309
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/ContentComparator.java2
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/DescendantResourceVariantByteStore.java (renamed from bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/DescendantResourceVariantByteStore.java)5
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SyncByteConverter.java152
-rw-r--r--bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/ThreeWayBaseTree.java113
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSCompareSubscriber.java4
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java6
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSyncInfo.java1
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSRevisionNumberCompareCriteria.java4
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncInfo.java3
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java6
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSWorkspaceSubscriber.java8
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteResource.java9
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSBaseResourceVariantTree.java2
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSDescendantResourceVariantByteStore.java8
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSResourceVariantTree.java10
-rw-r--r--bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/MultiTagResourceVariantTree.java2
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSCompareRevisionsInput.java2
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/ResourceEditionNode.java2
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/ReconcileProjectOperation.java2
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/CVSSubscriberAction.java1
-rw-r--r--bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/SafeUpdateAction.java1
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/Utils.java2
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/synchronize/RemoteResourceTypedElement.java2
-rw-r--r--bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoModelElement.java1
-rw-r--r--examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/FileSystemProvider.java45
-rw-r--r--examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/FileSystemSubscriber.java70
-rw-r--r--examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/subscriber/FileSystemRemoteTree.java62
-rw-r--r--examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/subscriber/FileSystemResourceVariant.java134
-rw-r--r--examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/subscriber/FileSystemSubscriber.java115
-rw-r--r--tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/RemoteResourceTest.java2
55 files changed, 1976 insertions, 168 deletions
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/Subscriber.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/Subscriber.java
index acafd2105..260fca9d9 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/Subscriber.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/Subscriber.java
@@ -21,9 +21,9 @@ import org.eclipse.core.runtime.Platform;
import org.eclipse.team.core.ITeamStatus;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.TeamStatus;
-import org.eclipse.team.core.synchronize.IResourceVariantComparator;
import org.eclipse.team.core.synchronize.SyncInfo;
import org.eclipse.team.core.synchronize.SyncInfoSet;
+import org.eclipse.team.core.variants.IResourceVariantComparator;
import org.eclipse.team.internal.core.Policy;
import org.eclipse.team.internal.core.TeamPlugin;
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/package.html b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/package.html
index e590138cb..585699428 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/package.html
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/package.html
@@ -56,6 +56,7 @@ SyncInfoFilter (e.g. to select groupings such as incoming-changes or
conflicts). Even when filtered, the collector still maintains a set of
all out-of-sync resources from the subscriber in order to provide
statistics on the number of pre and post filtered out-of-sync resources.</p>
-<p>FilteredSyncInfoCollector: should be generalized</p>
+<p>FilteredSyncInfoCollector is used to populate an output sync info set
+with the contents of an input set that match a particular filter.</p>
</body>
</html>
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/SyncInfo.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/SyncInfo.java
index 625c755bf..543d925b8 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/SyncInfo.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/SyncInfo.java
@@ -13,6 +13,7 @@ package org.eclipse.team.core.synchronize;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.team.core.TeamException;
+import org.eclipse.team.core.variants.*;
import org.eclipse.team.internal.core.Assert;
import org.eclipse.team.internal.core.Policy;
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/SyncInfoFilter.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/SyncInfoFilter.java
index caa89b17e..be3827c4a 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/SyncInfoFilter.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/SyncInfoFilter.java
@@ -12,6 +12,7 @@ package org.eclipse.team.core.synchronize;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.variants.*;
import org.eclipse.team.internal.core.subscribers.*;
/**
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/package.html b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/package.html
index c21ea5545..25d39ad6b 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/package.html
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/package.html
@@ -9,47 +9,26 @@
<body>
Application programming interfaces for managing synchronization state.
<h2>Package Specification</h2>
-<p>This package specifies the API for managing the synchronization
-state between the local workspace resources and a corresponding
-variants of those resources. The classes in this package can be used by
-Subscribers (see the org.eclipse.team.core.subscribers package) or
-others. The classes are roughly divided into three categories: <br>
-</p>
+<p>This package specifies the API for managing the synchronization state between
+ the local workspace resources and a corresponding variants of those resources.
+ The classes in this package can be used by Subscribers (see the org.eclipse.team.core.subscribers
+ package) or others. The classes are roughly divided into three categories: </p>
<ul>
- <li>describing the synchronization state of a single resource, <br>
- </li>
- <li>describing the synchronization state of a collection of
-resources, and <br>
- </li>
- <li>notifying interested parties of changes in the synchronization
-state.</li>
+ <li>describing the synchronization state of a one or more resources,</li>
+ <li>notifying interested parties of changes in the synchronization state.</li>
+ <li>filtering a set of resource based on a sync state criteria</li>
</ul>
-<h3>Describing the synchronization state of a single resource</h3>
-<p>The following classes are provided in order to map a local resource
-to its corresponding variant resource and, for the case of a three-way
-compare, base resource.</p>
+<h3>Describing the synchronization state of resources</h3>
+<p>The following classes are provided to accumulate (and possibly filter) the
+ synchronization state of one or more resources.</p>
<ul>
- <li>SyncInfo: node which maps a local resource to a corresponding
-variant resource (and a base resource for three-way compare) and
-descibes the synchronization state of those resources (e.g. in-sync or
-incoming-change).</li>
- <li>IResourceVariant: interface used by SyncInfo to access
-information about a variant resource, such as it's name, its type (file
-or container) and its contents.</li>
- <li>IResourceVariantComparator: interface used by SyncInfo to
-indicate whether the comparison to be used is two-way or three-way and
-to compare either a local resource with a remote resource or, in the
-case of a three-way compare, two remote resources.</li>
-</ul>
-<h3>Describing the synchronization state of a collection of resources</h3>
-<p>The following classes are provided to accumulate multiple SyncInfo
-and to filter the accumulated set based on some selection criteria.</p>
-<ul>
- <li>SyncInfoSet: a set which contains the out-of-sync SyncInfo for
-multiple local resources.</li>
- <li>SyncInfoTree: a specialized set optimized for hierarchical
-resource based access (e.g. to obtain all out-of-sync children of a
-particular local resource).</li>
+ <li>SyncInfo: node which maps a local resource to a corresponding variant resource
+ (and a base resource for three-way compare) and descibes the synchronization
+ state of those resources (e.g. in-sync or incoming-change).</li>
+ <li>SyncInfoSet: a set which contains the out-of-sync SyncInfo for multiple
+ local resources.</li>
+ <li>SyncInfoTree: a specialized set optimized for hierarchical resource based
+ access (e.g. to obtain all out-of-sync children of a particular local resource).</li>
</ul>
<h3>Notifying interested parties of sync info set changes</h3>
<p>Interested parties can register with a SyncInfoSet in order to
@@ -64,7 +43,7 @@ SyncInfoSet</li>
generated by SyncInfoTree which includes notification of resource
subtree aditions and removals.</li>
</ul>
-<h3>Additional classes</h3>
+<h3>Sync info filtering</h3>
<p>There are also some additional classes provided to help manage
SyncInfoSets</p>
<ul>
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/AbstractResourceVariantTree.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/AbstractResourceVariantTree.java
index 09a9e5387..688de3ac8 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/AbstractResourceVariantTree.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/AbstractResourceVariantTree.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.team.internal.core.subscribers.caches;
+package org.eclipse.team.core.variants;
import java.util.ArrayList;
import java.util.Arrays;
@@ -28,7 +28,6 @@ import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.IResourceVariant;
import org.eclipse.team.internal.core.Assert;
import org.eclipse.team.internal.core.Policy;
@@ -77,7 +76,7 @@ public abstract class AbstractResourceVariantTree implements IResourceVariantTre
* Helper method invoked from <code>refresh(IResource[], int, IProgressMonitor monitor)</code>
* for each resource. The default implementation performs the following steps:
* <ol>
- * <li>obtaine the scheduling rule for the resource
+ * <li>obtain the scheduling rule for the resource
* as returned from <code>getSchedulingRule(IResource)</code>.
* <li>get the resource variant handle corresponding to the local resource by calling
* <code>getRemoteTree</code>.
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/CachedResourceVariant.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/CachedResourceVariant.java
index 57c8a538d..b51dd1e3f 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/CachedResourceVariant.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/CachedResourceVariant.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.team.core.synchronize;
+package org.eclipse.team.core.variants;
import java.io.InputStream;
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/IResourceVariant.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/IResourceVariant.java
index 9b1039cbe..76204f61a 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/IResourceVariant.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/IResourceVariant.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.team.core.synchronize;
+package org.eclipse.team.core.variants;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -19,7 +19,7 @@ import org.eclipse.team.core.TeamException;
* to provide access to the base and remote resources that correspond to
* a local resource.
*
- * @see SyncInfo
+ * @see org.eclipse.team.core.synchronize.SyncInfo
* @since 3.0
*/
public interface IResourceVariant {
@@ -63,6 +63,14 @@ public interface IResourceVariant {
public String getContentIdentifier();
/**
+ * Return an array of bytes that can be used to uniquely identify this
+ * resource variant when compared to other resource variants and could
+ * also potentially be used to recreate a resource variant handle.
+ * @return the bytes that uniquely identify this resource variant
+ */
+ public byte[] asBytes();
+
+ /**
* Returns whether the remote resource is equal to the provided object.
* @param object the object to be compared
* @return whether the object is equal to the remote resource
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/IResourceVariantComparator.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/IResourceVariantComparator.java
index 58673c628..aba626bb7 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/synchronize/IResourceVariantComparator.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/IResourceVariantComparator.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.team.core.synchronize;
+package org.eclipse.team.core.variants;
import org.eclipse.core.resources.IResource;
@@ -20,8 +20,8 @@ import org.eclipse.core.resources.IResource;
* size or file timestamps as comparison criterias whereas a CVS workspace subscriber would
* use file revision numbers.
*
- * @see SyncInfo
- * @see Subscriber
+ * @see org.eclipse.team.core.synchronize.SyncInfo
+ * @see org.eclipse.team.core.subscribers.Subscriber
* @since 3.0
*/
public interface IResourceVariantComparator {
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/IResourceVariantTree.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/IResourceVariantTree.java
index 3270c0048..ff383c6f0 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/IResourceVariantTree.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/IResourceVariantTree.java
@@ -8,11 +8,10 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.team.internal.core.subscribers.caches;
+package org.eclipse.team.core.variants;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.IResourceVariant;
/**
* A handle that provides access to locally cached resource variants that
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ISynchronizerChangeListener.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ISynchronizerChangeListener.java
new file mode 100644
index 000000000..746b7868c
--- /dev/null
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ISynchronizerChangeListener.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.core.variants;
+
+import org.eclipse.core.resources.IResource;
+
+/**
+ * Listener that can receive notification from a <code>ThreeWaySynchronizer</code>
+ * when the synchronization state of one or more resources has changed.
+ */
+public interface ISynchronizerChangeListener {
+
+ /**
+ * Notification of synchronization state changes for the given resources.
+ * @param resources the resources whose synchronization state has changed
+ */
+ public void syncStateChanged(IResource[] resources);
+}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/PersistantResourceVariantByteStore.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/PersistantResourceVariantByteStore.java
index 4c0f94356..318a41af7 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/PersistantResourceVariantByteStore.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/PersistantResourceVariantByteStore.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.team.internal.core.subscribers.caches;
+package org.eclipse.team.core.variants;
import java.util.ArrayList;
import java.util.List;
@@ -24,7 +24,7 @@ import org.eclipse.team.internal.core.Assert;
* the <code>org.eclipse.core.resources.ISynchronizer</code> so that
* the tree is cached accross workbench invocations.
* <p>
- * This class is not intended to be subclassed by clients
+ * This class is not intended to be subclassed by clients.
*
* @since 3.0
*/
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantByteStore.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ResourceVariantByteStore.java
index 8d2d8e8e5..495fceefc 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantByteStore.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ResourceVariantByteStore.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.team.internal.core.subscribers.caches;
+package org.eclipse.team.core.variants;
import org.eclipse.core.resources.IResource;
import org.eclipse.team.core.TeamException;
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTree.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ResourceVariantTree.java
index 177a9d2ad..619de1ab1 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTree.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ResourceVariantTree.java
@@ -8,11 +8,10 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.team.internal.core.subscribers.caches;
+package org.eclipse.team.core.variants;
import org.eclipse.core.resources.IResource;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.IResourceVariant;
/**
* Provides caching for a {@link AbstractResourceVariantTree} using a
@@ -84,10 +83,14 @@ public abstract class ResourceVariantTree extends AbstractResourceVariantTree {
/**
* Get the bytes to be stored in the <code>ResourceVariantByteStore</code>
- * from the given resource variant.
+ * from the given resource variant. By default, the <code>IResourceVariant#asBytes()</code>
+ * method is used to get the bytes.
* @param local the local resource
* @param remote the corresponding resource variant handle
* @return the bytes for the resource variant.
*/
- protected abstract byte[] getBytes(IResource local, IResourceVariant remote) throws TeamException;
+ protected byte[] getBytes(IResource local, IResourceVariant remote) throws TeamException {
+ if (remote == null) return null;
+ return remote.asBytes();
+ }
}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTreeSubscriber.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ResourceVariantTreeSubscriber.java
index e4ec78c08..73e5dac87 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/ResourceVariantTreeSubscriber.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ResourceVariantTreeSubscriber.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.team.internal.core.subscribers.caches;
+package org.eclipse.team.core.variants;
import java.util.ArrayList;
import java.util.Arrays;
@@ -29,7 +29,6 @@ import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.TeamStatus;
import org.eclipse.team.core.subscribers.Subscriber;
import org.eclipse.team.core.subscribers.SubscriberChangeEvent;
-import org.eclipse.team.core.synchronize.IResourceVariant;
import org.eclipse.team.core.synchronize.SyncInfo;
import org.eclipse.team.internal.core.Policy;
import org.eclipse.team.internal.core.TeamPlugin;
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SessionResourceVariantByteStore.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/SessionResourceVariantByteStore.java
index 4aa20c7b2..d49e46c9e 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/SessionResourceVariantByteStore.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/SessionResourceVariantByteStore.java
@@ -8,7 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.team.internal.core.subscribers.caches;
+package org.eclipse.team.core.variants;
import java.util.*;
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWayRemoteTree.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWayRemoteTree.java
new file mode 100644
index 000000000..35d75081b
--- /dev/null
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWayRemoteTree.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.core.variants;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.team.core.TeamException;
+
+/**
+ * A resource variant tree that caches and obtains its bytes from the remote slot
+ * in a three-way synchronizer. Clients must subclass to provide remote recource
+ * variant refresh functionality.
+ *
+ * @see ThreeWaySubscriber
+ *
+ * @since 3.0
+ */
+public abstract class ThreeWayRemoteTree extends ResourceVariantTree {
+
+ private ThreeWaySubscriber subscriber;
+
+ /*
+ * A resource variant byte store that accesses the remote bytes
+ * from a three-way synchronizer. Both access and modification
+ * are supported.
+ */
+ static class RemoteResourceVariantByteStore extends ResourceVariantByteStore {
+ private ThreeWaySynchronizer synchronizer;
+ public RemoteResourceVariantByteStore(ThreeWaySynchronizer synchronizer) {
+ this.synchronizer = synchronizer;
+ }
+ public void dispose() {
+ // Nothing to do as contents are owned by the TargetSynchronizer
+ }
+ public byte[] getBytes(IResource resource) throws TeamException {
+ return getSynchronizer().getRemoteBytes(resource);
+ }
+ public boolean setBytes(IResource resource, byte[] bytes) throws TeamException {
+ return getSynchronizer().setRemoteBytes(resource, bytes);
+ }
+ public boolean flushBytes(IResource resource, int depth) throws TeamException {
+ // This method is invoked when the remote bytes are stale and should be removed
+ // This is handled by the ThreeWaySynchronizer so nothing needs to be done here.
+ return false;
+ }
+ public boolean isVariantKnown(IResource resource) throws TeamException {
+ return getSynchronizer().hasSyncBytes(resource);
+ }
+ public boolean deleteBytes(IResource resource) throws TeamException {
+ return getSynchronizer().removeRemoteBytes(resource);
+ }
+ public IResource[] members(IResource resource) throws TeamException {
+ return synchronizer.members(resource);
+ }
+ private ThreeWaySynchronizer getSynchronizer() {
+ return synchronizer;
+ }
+ }
+
+ public ThreeWayRemoteTree(ThreeWaySubscriber subscriber) {
+ super(new RemoteResourceVariantByteStore(subscriber.getSynchronizer()));
+ this.subscriber = subscriber;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree#roots()
+ */
+ public IResource[] roots() {
+ return getSubscriber().roots();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree#getResourceVariant(org.eclipse.core.resources.IResource)
+ */
+ public IResourceVariant getResourceVariant(IResource resource) throws TeamException {
+ return getSubscriber().getResourceVariant(resource, getByteStore().getBytes(resource));
+ }
+
+ protected ThreeWaySubscriber getSubscriber() {
+ return subscriber;
+ }
+}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWayResourceComparator.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWayResourceComparator.java
new file mode 100644
index 000000000..b152f44e8
--- /dev/null
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWayResourceComparator.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.core.variants;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.internal.core.TeamPlugin;
+
+/**
+ * A resource comparator that uses the <code>ThreeWaySynchronizer</code>
+ * to compare local resources to their resource variants.
+ */
+public class ThreeWayResourceComparator implements IResourceVariantComparator {
+
+ private ThreeWaySynchronizer synchronizer;
+
+ /**
+ * Create a three-way resource comparator that uses the <code>ThreeWaySynchronizer</code>
+ * to compare a local resource to a resource variant.
+ * @param synchronizer
+ */
+ public ThreeWayResourceComparator(ThreeWaySynchronizer synchronizer) {
+ this.synchronizer = synchronizer;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.IResourceVariantComparator#compare(org.eclipse.core.resources.IResource, org.eclipse.team.core.variants.IResourceVariant)
+ */
+ public boolean compare(IResource local, IResourceVariant remote) {
+ // First, ensure the resources are the same gender
+ if ((local.getType() == IResource.FILE) == remote.isContainer()) {
+ return false;
+ }
+ try {
+ // If the file is locally modified, it cannot be in sync
+ if (local.getType() == IResource.FILE && getSynchronizer().isLocallyModified(local)) {
+ return false;
+ }
+ // If there is no base, the local cannopt match the remote
+ if (getSynchronizer().getBaseBytes(local) == null) return false;
+ // Otherwise, assume they are the same if the remote equals the base
+ return equals(getSynchronizer().getBaseBytes(local), getBytes(remote));
+ } catch (TeamException e) {
+ TeamPlugin.log(e);
+ return false;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.IResourceVariantComparator#compare(org.eclipse.team.core.variants.IResourceVariant, org.eclipse.team.core.variants.IResourceVariant)
+ */
+ public boolean compare(IResourceVariant base, IResourceVariant remote) {
+ byte[] bytes1 = getBytes(base);
+ byte[] bytes2 = getBytes(remote);
+ return equals(bytes1, bytes2);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.IResourceVariantComparator#isThreeWay()
+ */
+ public boolean isThreeWay() {
+ return true;
+ }
+
+ private ThreeWaySynchronizer getSynchronizer() {
+ return synchronizer;
+ }
+
+ private byte[] getBytes(IResourceVariant remote) {
+ return remote.asBytes();
+ }
+
+ private boolean equals(byte[] syncBytes, byte[] oldBytes) {
+ if (syncBytes.length != oldBytes.length) return false;
+ for (int i = 0; i < oldBytes.length; i++) {
+ if (oldBytes[i] != syncBytes[i]) return false;
+ }
+ return true;
+ }
+}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWaySubscriber.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWaySubscriber.java
new file mode 100644
index 000000000..66812d594
--- /dev/null
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWaySubscriber.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.core.variants;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.team.core.Team;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.core.subscribers.ISubscriberChangeEvent;
+import org.eclipse.team.core.subscribers.SubscriberChangeEvent;
+import org.eclipse.team.internal.core.TeamPlugin;
+import org.eclipse.team.internal.core.subscribers.ThreeWayBaseTree;
+
+/**
+ * A resource variant tree subscriber whose trees use an underlying
+ * <code>ThreeWaySycnrhonizer</code> to store and manage the
+ * synchronization state for the local workspace.
+ */
+public abstract class ThreeWaySubscriber extends ResourceVariantTreeSubscriber implements ISynchronizerChangeListener {
+
+ private ThreeWayResourceComparator comparator;
+ private ThreeWayBaseTree baseTree;
+ private ThreeWayRemoteTree remoteTree;
+ private ThreeWaySynchronizer synchronizer;
+
+ /**
+ * Create a three-way subscriber that uses the given synchronizer
+ * to manage the synchronization state of local resoures
+ * and their variants
+ * @param synchronizer the three-way synchronizer for this subscriber
+ */
+ protected ThreeWaySubscriber(ThreeWaySynchronizer synchronizer) {
+ this.synchronizer = synchronizer;
+ baseTree = new ThreeWayBaseTree(this);
+ getSynchronizer().addListener(this);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.ResourceVariantTreeSubscriber#getBaseTree()
+ */
+ protected final IResourceVariantTree getBaseTree() {
+ return baseTree;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.ResourceVariantTreeSubscriber#getRemoteTree()
+ */
+ protected final IResourceVariantTree getRemoteTree() {
+ if (remoteTree == null) {
+ remoteTree = createRemoteTree();
+ }
+ return remoteTree;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.subscribers.Subscriber#getResourceComparator()
+ */
+ public final IResourceVariantComparator getResourceComparator() {
+ if (comparator == null) {
+ comparator = new ThreeWayResourceComparator(this.getSynchronizer());
+ }
+ return comparator;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.target.subscriber.ISynchronizerChangeListener#syncStateChanged(org.eclipse.core.resources.IResource[])
+ */
+ public void syncStateChanged(IResource[] resources) {
+ fireTeamResourceChange(SubscriberChangeEvent.asSyncChangedDeltas(this, resources));
+ }
+
+ /**
+ * Returns <code>false</code> for resources that are not children
+ * of a subscriber root, are ignored by the subscriber's synchronizer
+ * or are ignored by the <code>Team.ignoreHist(IResource)</code>. Returns
+ * <code>true</code> otherwise.
+ * @see org.eclipse.team.core.subscribers.Subscriber#isSupervised(IResource)
+ */
+ public boolean isSupervised(IResource resource) throws TeamException {
+ if (!isChildOfRoot(resource)) return false;
+ if (getSynchronizer().isIgnored(resource)) return false;
+ if (Team.isIgnoredHint(resource)) return false;
+ return true;
+ }
+
+ /**
+ * Return the three-way sychronizer of this subscriber.
+ * @return the three-way sychronizer of this subscriber.
+ */
+ public ThreeWaySynchronizer getSynchronizer() {
+ return synchronizer;
+ }
+
+ /**
+ * Create the resource variant for the given loicla resource from the
+ * given bytes. The bytes are those that were prviously returned
+ * from a call to <code>IResourceVariant#asBytes()</code>.
+ * @param resource the local resource
+ * @param bytes the bytes that identify a variant of the resource
+ * @return the resouce variant handle recreated from the bytes
+ * @throws TeamException
+ */
+ public abstract IResourceVariant getResourceVariant(IResource resource, byte[] bytes) throws TeamException;
+
+ /**
+ * Create the three-way remote tree which provides access to the
+ * remote bytes in the three-way synchronizer. This method is invoked
+ * once when the remote tree is first accessed. The returned object is
+ * cached and reused on subsequent accesses.
+ * @return the remote tree
+ */
+ protected abstract ThreeWayRemoteTree createRemoteTree();
+
+ /**
+ * Convenience method that can be used by subclasses to notify listeners
+ * when a root is added or removed from the subscriber. The added
+ * parameter should be <code>true</code> if the root was added and <code>false</code>
+ * if it was removed.
+ * @param resource the added or removed root
+ * @param added <code>true</code> if the root was added and <code>false</code>
+ * if it was removed.
+ */
+ protected void handleRootChanged(IResource resource, boolean added) {
+ if (added) {
+ rootAdded(resource);
+ } else {
+ rootRemoved(resource);
+ }
+ }
+
+ private void rootAdded(IResource resource) {
+ SubscriberChangeEvent delta = new SubscriberChangeEvent(this, ISubscriberChangeEvent.ROOT_ADDED, resource);
+ fireTeamResourceChange(new SubscriberChangeEvent[] { delta });
+ }
+
+ private void rootRemoved(IResource resource) {
+ try {
+ getSynchronizer().flush(resource, IResource.DEPTH_INFINITE);
+ } catch (TeamException e) {
+ TeamPlugin.log(e);
+ }
+ SubscriberChangeEvent delta = new SubscriberChangeEvent(this, ISubscriberChangeEvent.ROOT_REMOVED, resource);
+ fireTeamResourceChange(new SubscriberChangeEvent[] { delta });
+ }
+
+ private boolean isChildOfRoot(IResource resource) {
+ IResource[] roots = roots();
+ IPath fullPath = resource.getFullPath();
+ for (int i = 0; i < roots.length; i++) {
+ IResource root = roots[i];
+ if (root.getFullPath().isPrefixOf(fullPath)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWaySynchronizer.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWaySynchronizer.java
new file mode 100644
index 000000000..7574ad436
--- /dev/null
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/ThreeWaySynchronizer.java
@@ -0,0 +1,515 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.core.variants;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.jobs.ILock;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.internal.core.Assert;
+import org.eclipse.team.internal.core.Policy;
+import org.eclipse.team.internal.core.subscribers.BatchingLock;
+import org.eclipse.team.internal.core.subscribers.SyncByteConverter;
+import org.eclipse.team.internal.core.subscribers.BatchingLock.IFlushOperation;
+import org.eclipse.team.internal.core.subscribers.BatchingLock.ThreadInfo;
+
+/**
+ * This class manages the synchronization between local resources and their
+ * corresponding resource variants. It provides the following:
+ * <ul>
+ * <li>Three way synchronization (set base, set remote, ignored)
+ * <li>Resource traversal (members)
+ * <li>Change events and event batching (run)
+ * <li>Thread-safety
+ * </ul>
+ */
+public class ThreeWaySynchronizer implements IFlushOperation {
+
+ private static final byte[] IGNORED_BYTES = "i".getBytes(); //$NON-NLS-1$
+
+ private ILock lock = Platform.getJobManager().newLock();
+ private BatchingLock batchingLock = new BatchingLock();
+ private ResourceVariantByteStore cache;
+ private Set listeners = new HashSet();
+
+ /**
+ * Create a three-way synchronizer that uses a persistant
+ * byte store with the given qualified name as its unique
+ * identifier.
+ * @param name the unique identifier for the persistant store
+ */
+ public ThreeWaySynchronizer(QualifiedName name) {
+ this(new PersistantResourceVariantByteStore(name));
+ }
+
+ /**
+ * Create a three-way synchronizer that uses the given byte store
+ * as its underlying byte cache.
+ * @param store the byte store this synchronizer uses to cache its bytes
+ */
+ public ThreeWaySynchronizer(ResourceVariantByteStore store) {
+ cache = store;
+ }
+
+ /**
+ * Adds a listener to this synchronizer. Listeners will be notified
+ * when the synchronization state of a resource changes. Listeners
+ * are not notified when files are modified locally. Clients can
+ * make use of the <code>IResource</code> delta mechanism if they
+ * need to know about local modifications.
+ * Has no effect if an identical listener is already registered.
+ * <p>
+ * Team resource change listeners are informed about state changes
+ * that affect the resources supervised by this subscriber.</p>
+ *
+ * @param listener a synchronizer change listener
+ */
+ public void addListener(ISynchronizerChangeListener listener) {
+ synchronized (listeners) {
+ listeners.add(listener);
+ }
+ }
+
+ /**
+ * Removes a listener previously registered with this synchronizer.
+ * Has no affect if an identical listener is not registered.
+ *
+ * @param listener a synchronizer change listener
+ */
+ public void removeListener(ISynchronizerChangeListener listener) {
+ synchronized (listeners) {
+ listeners.remove(listener);
+ }
+ }
+
+ /**
+ * Return the base bytes that are cached for the given resource
+ * or <code>null</code> if no base is cached. The returned bytes
+ * should uniquely identify the resource variant that is the base
+ * for the given local resource.
+ *
+ * @param resource the resource
+ * @return the base bytes cached with the resource or <code>null</code>
+ * @throws TeamException
+ */
+ public byte[] getBaseBytes(IResource resource) throws TeamException {
+ try {
+ beginOperation();
+ byte[] syncBytes = internalGetSyncBytes(resource);
+ if (syncBytes == null) return null;
+ byte[] baseBytes = getSlot(syncBytes, 1);
+ if (baseBytes == null || baseBytes.length == 0) return null;
+ return baseBytes;
+ } finally {
+ endOperation();
+ }
+ }
+
+ /**
+ * Set the base bytes for the given resource. The provided bytes
+ * should encode enough information to uniquely identify
+ * (and possibly recreate) the resource variant that is the base
+ * for the given local resource. In essence, setting the base
+ * bytes is equivalent to marking the file as in-sync. As such,
+ * setting the base bytes will also set the remote bytes and mark
+ * the file as clean (i.e. having no outgoing changes).
+ *
+ * @param resource the resource
+ * @param baseBytes the base bytes that identify the base resource variant
+ * @throws TeamException
+ */
+ public void setBaseBytes(IResource resource, byte[] baseBytes) throws TeamException {
+ Assert.isNotNull(baseBytes);
+ ISchedulingRule rule = null;
+ try {
+ rule = beginBatching(resource, null);
+ try {
+ beginOperation();
+ String base = new String(baseBytes);
+ String[] slots = new String[] {
+ new Long(resource.getModificationStamp()).toString(),
+ base,
+ base
+ };
+ byte[] syncBytes = toBytes(slots);
+ internalSetSyncBytes(resource, syncBytes);
+ batchingLock.resourceChanged(resource);
+ } finally {
+ endOperation();
+ }
+ } finally {
+ if (rule != null) endBatching(rule, null);
+ }
+ }
+
+ /**
+ * Return whether the local resource has been modified since the last time
+ * the base bytes were set. This method will return <code>false</code>
+ * for ignored resources and <code>true</code> for non-existant resources
+ * that have base bytes cached.
+ * @param resource the resource
+ * @return <code>true</code> if the resource has been modified since the
+ * last time the base bytes were set.
+ * @throws TeamException
+ */
+ public boolean isLocallyModified(IResource resource) throws TeamException {
+ return ((internalGetSyncBytes(resource) == null && ! isIgnored(resource)) ||
+ (getLocalTimestamp(resource) != resource.getModificationStamp()) ||
+ (getBaseBytes(resource) != null && !resource.exists()));
+ }
+
+ /**
+ * Return the remote bytes that are cached for the given resource
+ * or <code>null</code> if no remote is cached. The returned bytes
+ * should uniquely identify the resource variant that is the remote
+ * for the given local resource.
+ *
+ * @param resource the resource
+ * @return the remote bytes cached with the resource or <code>null</code>
+ * @throws TeamException
+ */
+ public byte[] getRemoteBytes(IResource resource) throws TeamException {
+ try {
+ beginOperation();
+ byte[] syncBytes = internalGetSyncBytes(resource);
+ if (syncBytes == null) return null;
+ byte[] remoteBytes = getSlot(syncBytes, 2);
+ if (remoteBytes == null || remoteBytes.length == 0) return null;
+ return remoteBytes;
+ } finally {
+ endOperation();
+ }
+ }
+
+ /**
+ * Set the remote bytes for the given resource. The provided bytes
+ * should encode enough information to uniquely identify
+ * (and possibly recreate) the resource variant that is the remote
+ * for the given local resource. If the remote for a resource
+ * no longer exists, <code>removeRemoteBytes(IResource)</code>
+ * should be called.
+ *
+ * @param resource the resource
+ * @param remoteBytes the base bytes that identify the remote resource variant
+ * @return <code>true</code> if the remote bytes changed as a result of the set
+ * @throws TeamException
+ */
+ public boolean setRemoteBytes(IResource resource, byte[] remoteBytes) throws TeamException {
+ Assert.isNotNull(remoteBytes);
+ ISchedulingRule rule = null;
+ try {
+ rule = beginBatching(resource, null);
+ try {
+ beginOperation();
+ byte[] syncBytes = internalGetSyncBytes(resource);
+ if (syncBytes == null) {
+ String[] slots = new String[] {
+ "", //$NON-NLS-1$
+ "", //$NON-NLS-1$
+ new String(remoteBytes)
+ };
+ syncBytes = toBytes(slots);
+ } else {
+ byte[] currentRemote = getSlot(syncBytes, 2);
+ if (equals(remoteBytes, currentRemote)) return false;
+ syncBytes = setSlot(syncBytes, 2, remoteBytes);
+ }
+ internalSetSyncBytes(resource, syncBytes);
+ batchingLock.resourceChanged(resource);
+ return true;
+ } finally {
+ endOperation();
+ }
+ } finally {
+ if (rule != null) endBatching(rule, null);
+ }
+ }
+
+ /**
+ * Remove the remote bytes associated with the resource. This is typically
+ * done when the corresponding remote resource variant no longer exists.
+ * @param resource the resource
+ * @return <code>true</code> if the remote bytes changed as a result of the removal
+ * @throws TeamException
+ */
+ public boolean removeRemoteBytes(IResource resource) throws TeamException {
+ ISchedulingRule rule = null;
+ try {
+ rule = beginBatching(resource, null);
+ try {
+ beginOperation();
+ byte[] syncBytes = internalGetSyncBytes(resource);
+ if (syncBytes != null) {
+ String currentRemote = new String(getSlot(syncBytes, 2));
+ if (currentRemote.length() == 0) return false;
+ syncBytes = setSlot(syncBytes, 2, new byte[0]);
+ internalSetSyncBytes(resource, syncBytes);
+ batchingLock.resourceChanged(resource);
+ return true;
+ }
+ return false;
+ } finally {
+ endOperation();
+ }
+ } finally {
+ if (rule != null) endBatching(rule, null);
+ }
+ }
+
+ /**
+ * Return whether the given resource has sync bytes in the synchronizer.
+ * @param resource the local resource
+ * @return whether there are sync bytes cached for the local resources.
+ */
+ public boolean hasSyncBytes(IResource resource) throws TeamException {
+ return internalGetSyncBytes(resource) != null;
+ }
+
+ /**
+ * Returns whether the resource has been marked as ignored
+ * using <code>setIgnored(IResource)</code>.
+ * @param resource the resource
+ * @return <code>true</code> if the resource is ignored.
+ * @throws TeamException
+ */
+ public boolean isIgnored(IResource resource) throws TeamException {
+ byte[] bytes = cache.getBytes(resource);
+ return (bytes != null && equals(bytes, IGNORED_BYTES));
+ }
+
+ /**
+ * Mark the resource as being ignored. Ignored resources
+ * are not returned by the <code>members</code> method,
+ * are never dirty (see <code>isLocallyModified</code>) and
+ * do not have base or remote bytes cahced for them.
+ * @param resource the resource to be ignored
+ * @throws TeamException
+ */
+ public void setIgnored(IResource resource) throws TeamException {
+ internalSetSyncBytes(resource, IGNORED_BYTES);
+ }
+
+ /**
+ * Return the members of the local resource that either have sync bytes
+ * or exist locally and are not ignored.
+ * @param resource the local resource
+ * @return the children of the local resource that have cached sync bytes
+ * or are not ignored
+ * @throws TeamException
+ */
+ public IResource[] members(IResource resource) throws TeamException {
+ if (resource.getType() == IResource.FILE) {
+ return new IResource[0];
+ }
+ try {
+ Set potentialChildren = new HashSet();
+ IContainer container = (IContainer)resource;
+ potentialChildren.addAll(Arrays.asList(container.members()));
+ potentialChildren.addAll(Arrays.asList(cache.members(resource)));
+ List result = new ArrayList();
+ for (Iterator iter = potentialChildren.iterator(); iter.hasNext();) {
+ IResource child = (IResource) iter.next();
+ if (child.exists() || hasSyncBytes(child)) {
+ result.add(child);
+ }
+ }
+ return (IResource[]) result.toArray(new IResource[result.size()]);
+ } catch (CoreException e) {
+ throw TeamException.asTeamException(e);
+ }
+ }
+
+ /**
+ * Flush any cached bytes for the given resource to the depth specified.
+ * @param resource the resource
+ * @param depth the depth of the flush (one of <code>IResource.DEPTH_ZERO</code>,
+ * <code>IResource.DEPTH_ONE</code>, or <code>IResource.DEPTH_INFINITE</code>)
+ * @throws TeamException
+ */
+ public void flush(IResource resource, int depth) throws TeamException {
+ ISchedulingRule rule = null;
+ try {
+ rule = beginBatching(resource, null);
+ try {
+ beginOperation();
+ if (cache.flushBytes(resource, depth)) {
+ batchingLock.resourceChanged(resource);
+ }
+ } finally {
+ endOperation();
+ }
+ } finally {
+ if (rule != null) endBatching(rule, null);
+ }
+ }
+
+ /**
+ * Perform multiple sync state modifications and fire only a single change notification
+ * at the end.
+ * @param resourceRule the scheduling rule that encompasses all modifications
+ * @param runnable the runnable that performs the sync state modifications
+ * @param monitor a progress monitor
+ * @throws TeamException
+ */
+ public void run(ISchedulingRule resourceRule, IWorkspaceRunnable runnable, IProgressMonitor monitor) throws TeamException {
+ monitor = Policy.monitorFor(monitor);
+ monitor.beginTask(null, 100);
+ ISchedulingRule rule = beginBatching(resourceRule, Policy.subMonitorFor(monitor, 10));
+ try {
+ runnable.run(Policy.subMonitorFor(monitor, 80));
+ } catch (CoreException e) {
+ throw TeamException.asTeamException(e);
+ } finally {
+ if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 10));
+ monitor.done();
+ }
+ }
+
+ /* (non-Javadoc)
+ *
+ * Callback which is invoked when the batching resource lock is released
+ * or when a flush is requested (see beginBatching(IResource)).
+ *
+ * @see org.eclipse.team.internal.ftp.deployment.BatchingLock.IFlushOperation#flush(org.eclipse.team.internal.ftp.deployment.BatchingLock.ThreadInfo, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void flush(ThreadInfo info, IProgressMonitor monitor) throws TeamException {
+ if (info != null && !info.isEmpty()) {
+ broadcastSyncChanges(info.getChangedResources());
+ }
+ }
+
+ private void broadcastSyncChanges(final IResource[] resources) {
+ ISynchronizerChangeListener[] allListeners;
+ // Copy the listener list so we're not calling client code while synchronized
+ synchronized(listeners) {
+ allListeners = (ISynchronizerChangeListener[]) listeners.toArray(new ISynchronizerChangeListener[listeners.size()]);
+ }
+ // Notify the listeners safely so all will receive notification
+ for (int i = 0; i < allListeners.length; i++) {
+ final ISynchronizerChangeListener listener = allListeners[i];
+ Platform.run(new ISafeRunnable() {
+ public void handleException(Throwable exception) {
+ // don't log the exception....it is already being logged in Platform#run
+ }
+ public void run() throws Exception {
+ listener.syncStateChanged(resources);
+
+ }
+ });
+ }
+ }
+
+ /*
+ * Return the cached sync bytes for the given resource.
+ * The value <code>null</code> is returned if there is no
+ * cached bytes or if the resource is ignored.
+ */
+ private byte[] internalGetSyncBytes(IResource resource) throws TeamException {
+ byte[] bytes = cache.getBytes(resource);
+ if (bytes != null && equals(bytes, IGNORED_BYTES)) return null;
+ return bytes;
+ }
+
+ /*
+ * Set the cached sync bytes
+ */
+ private boolean internalSetSyncBytes(IResource resource, byte[] syncBytes) throws TeamException {
+ return cache.setBytes(resource, syncBytes);
+ }
+
+ private byte[] getSlot(byte[] syncBytes, int i) {
+ return SyncByteConverter.getSlot(syncBytes, i, false);
+ }
+
+ private byte[] setSlot(byte[] syncBytes, int i, byte[] insertBytes) throws TeamException {
+ return SyncByteConverter.setSlot(syncBytes, i, insertBytes);
+ }
+
+ private byte[] toBytes(String[] slots) {
+ return SyncByteConverter.toBytes(slots);
+ }
+
+ private long getLocalTimestamp(IResource resource) throws TeamException {
+ try {
+ beginOperation();
+ byte[] syncBytes = internalGetSyncBytes(resource);
+ if (syncBytes == null) return 0;
+ byte[] bytes = getSlot(syncBytes, 0);
+ if (bytes == null || bytes.length == 0) return 0;
+ return Long.parseLong(new String(bytes));
+ } finally {
+ endOperation();
+ }
+ }
+
+ private boolean equals(byte[] syncBytes, byte[] oldBytes) {
+ if (syncBytes.length != oldBytes.length) return false;
+ for (int i = 0; i < oldBytes.length; i++) {
+ if (oldBytes[i] != syncBytes[i]) return false;
+ }
+ return true;
+ }
+
+ /*
+ * Begin an access to the internal data structures of the synchronizer
+ */
+ private void beginOperation() {
+ // Do not try to acquire the lock if the resources tree is locked
+ // The reason for this is that during the resource delta phase (i.e. when the tree is locked)
+ // the workspace lock is held. If we obtain our lock, there is
+ // a chance of dealock. It is OK if we don't as we are still protected
+ // by scheduling rules and the workspace lock.
+ if (ResourcesPlugin.getWorkspace().isTreeLocked()) return;
+ lock.acquire();
+ }
+
+ /*
+ * End an access to the internal data structures of the synchronizer
+ */
+ private void endOperation() {
+ // See beginOperation() for a description of why the lock is not obtained when the tree is locked
+ if (ResourcesPlugin.getWorkspace().isTreeLocked()) return;
+ lock.release();
+ }
+
+ /*
+ * Begins a batch of operations in order to batch event changes.
+ * The provided scheduling rule indicates the resources
+ * that the resources affected by the operation while the returned scheduling rule
+ * is the rule obtained by the lock. It may differ from the provided rule.
+ */
+ private ISchedulingRule beginBatching(ISchedulingRule resourceRule, IProgressMonitor monitor) {
+ return batchingLock.acquire(resourceRule, this /* IFlushOperation */, monitor);
+ }
+
+ /*
+ * Ends a batch of operations. The provided rule must be the one that was returned
+ * by the corresponding call to beginBatching.
+ */
+ private void endBatching(ISchedulingRule rule, IProgressMonitor monitor) throws TeamException {
+ batchingLock.release(rule, monitor);
+ }
+}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/package.html b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/package.html
new file mode 100644
index 000000000..d895da483
--- /dev/null
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/variants/package.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta content="text/html; charset=iso-8859-1"
+ http-equiv="Content-Type">
+ <meta content="IBM" name="Author">
+ <title>Package-level Javadoc</title>
+</head>
+<body>
+Application programming interfaces for accessing and managing resource variants.
+<h2>Package Specification</h2>
+<p>This package specifies the API for accessing and managing variants for local
+ workspace resources. The classes in this package can be used by Subscribers
+ (see the org.eclipse.team.core.subscribers package) or others. The classes are
+ roughly divided into three categories: <br>
+</p>
+<h3>Access to Resource Variants</h3>
+<p>The following interfaces define the API required for subscribers to access
+ and manage variants of local resources.</p>
+<ul>
+ <li>IResourceVariant: provides access to information about a variant resource,
+ such as it's name, its type (file or container) and its contents.</li>
+ <li>IResourceVariantComparator: supports the comparison of a local resource
+ with a variant or the comparison of two variants (if three-way comparison
+ is supported).</li>
+ <li>IResourceVariantTree: provides access to a tree of locally cached resource
+ variants along with API to refresh the cached variants.</li>
+</ul>
+<h3>Implementing Resource Variants</h3>
+<p>Several classes are available that provide partial, extandable implementations
+ of the above mentioned interfaces.</p>
+<ul>
+ <li>CachedResourceVariant: an IResourceVariant implementation that supports
+ the caching of the contents of the variant. Subclasses must override to provide
+ fecthing of contents.</li>
+ <li>AbstractResourceVariantTree: an IResourceVariantTree that contains logic
+ for performing a refresh of the cached resource variants. The caching mechanism
+ is delegated to subclasses as is the fetching of the resource variants.</li>
+ <li>ResourceVariantTree: An AbstractResourceVariantTree that uses a ResourceVariantByteStore
+ to cache the resource variants. Subclasses must still provide the fecthing
+ of the remote state.</li>
+ <li>ResourceVariantByteStore: An abstract class that defines the API required
+ for caching resource variants as byte arrays.</li>
+ <li>PersistantResourceVariantByteStore: a ResourceVariantByteStore that persists
+ the bytes accross workbench invocations.</li>
+ <li>SessionResourceVariantByteStore: a ResourceVariantByteStore that caches
+ the bytes in a session store and does not persist them.</li>
+</ul>
+<h3>Implementing Subscribers</h3>
+<p>The ResourceVariantTreeSubscriber class is a partial subscriber implementation
+ that makes use of the IResourceVariantTree interface to provide the remote and
+ base resesource management.</p>
+<h3>&nbsp;</h3>
+<p>&nbsp;</p>
+</body>
+</html>
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/ResourceVariantCache.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/ResourceVariantCache.java
index cda7872e2..98b924671 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/ResourceVariantCache.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/ResourceVariantCache.java
@@ -22,7 +22,7 @@ import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.jobs.ILock;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.CachedResourceVariant;
+import org.eclipse.team.core.variants.CachedResourceVariant;
/**
* This class implements a caching facility that can be used by TeamProviders to cache contents
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/ResourceVariantCacheEntry.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/ResourceVariantCacheEntry.java
index 860028151..d139a6ef1 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/ResourceVariantCacheEntry.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/ResourceVariantCacheEntry.java
@@ -16,7 +16,7 @@ import java.util.Date;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.ILock;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.CachedResourceVariant;
+import org.eclipse.team.core.variants.CachedResourceVariant;
/**
* This class provides the implementation for the ICacheEntry
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties
index 55fef4983..8e89babab 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties
@@ -125,3 +125,5 @@ CachedResourceVariant.0=There is no cached contents for resource {0}.
SyncInfoTree.0=Sync info is missing for resource {0}.
ResourceVariantTreeSubscriber.1=Errors occurred during refresh of {0}
ResourceVariantTreeSubscriber.2=An error occurred refreshing {0}: {1}
+SyncByteConverter.1=Malformed sync byte format detected in {0}
+BatchingLock.11=An error occurred while flushing batched changes
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/BatchingLock.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/BatchingLock.java
new file mode 100644
index 000000000..d12ae0930
--- /dev/null
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/BatchingLock.java
@@ -0,0 +1,309 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.internal.core.subscribers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.MultiRule;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.internal.core.Assert;
+import org.eclipse.team.internal.core.Policy;
+import org.eclipse.team.internal.core.TeamPlugin;
+
+/**
+ * Provides a per-thread nested locking mechanism. A thread can acquire a
+ * lock on a specific resource by calling acquire(). Subsequently, acquire() can be called
+ * multiple times on the resource or any of its children from within the same thread
+ * without blocking. Other threads that try
+ * and acquire the lock on those same resources will be blocked until the first
+ * thread releases all it's nested locks.
+ * <p>
+ * The locking is managed by the platform via scheduling rules. This class simply
+ * provides the nesting mechnism in order to allow the client to determine when
+ * the lock for the thread has been released. Therefore, this lock will block if
+ * another thread already locks the same resource.</p>
+ */
+public class BatchingLock {
+
+ private final static boolean DEBUG = false;
+
+ // This is a placeholder rule used to indicate that no scheduling rule is needed
+ /* internal use only */ static final ISchedulingRule NULL_SCHEDULING_RULE= new ISchedulingRule() {
+ public boolean contains(ISchedulingRule rule) {
+ return false;
+ }
+ public boolean isConflicting(ISchedulingRule rule) {
+ return false;
+ }
+ };
+
+ public class ThreadInfo {
+ private Set changedResources = new HashSet();
+ private IFlushOperation operation;
+ private List rules = new ArrayList();
+ public ThreadInfo(IFlushOperation operation) {
+ this.operation = operation;
+ }
+ /**
+ * Push a scheduling rule onto the stack for this thread and
+ * acquire the rule if it is not the workspace root.
+ * @param resource
+ */
+ public ISchedulingRule pushRule(ISchedulingRule resource, IProgressMonitor monitor) {
+ // The scheduling rule is either the project or the resource's parent
+ ISchedulingRule rule = getRuleForResoure(resource);
+ if (rule != NULL_SCHEDULING_RULE) {
+ try {
+ Platform.getJobManager().beginRule(rule, monitor);
+ } catch (OperationCanceledException e) {
+ // The begin was cancelled.
+ // Free the scheduling rule and throw the cancel
+ // so the clients of ReentrantLock don't need to
+ // do an endRule when the operation is cancelled.
+ Platform.getJobManager().endRule(rule);
+ throw e;
+ }
+ }
+ addRule(rule);
+ return rule;
+ }
+ /**
+ * Pop the scheduling rule from the stack and release it if it
+ * is not the workspace root. Flush any changed sync info to
+ * disk if necessary. A flush is necessary if the stack is empty
+ * or if the top-most non-null scheduling rule was popped as a result
+ * of this operation.
+ * @param monitor
+ * @throws CVSException
+ */
+ public void popRule(ISchedulingRule rule, IProgressMonitor monitor) throws TeamException {
+ try {
+ if (isFlushRequired()) {
+ flush(monitor);
+ }
+ } finally {
+ ISchedulingRule stackedRule = removeRule();
+ if (rule == null) {
+ rule = NULL_SCHEDULING_RULE;
+ }
+ Assert.isTrue(stackedRule.equals(rule), "end for resource '" + rule + "' does not match stacked rule '" + stackedRule + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ if (rule != NULL_SCHEDULING_RULE) {
+ Platform.getJobManager().endRule(rule);
+ }
+ }
+ }
+ private ISchedulingRule getRuleForResoure(ISchedulingRule resourceRule) {
+ ISchedulingRule rule;
+ if (resourceRule instanceof IResource) {
+ IResource resource = (IResource)resourceRule;
+ if (resource.getType() == IResource.ROOT) {
+ // Never lock the whole workspace
+ rule = NULL_SCHEDULING_RULE;
+ } else if (resource.getType() == IResource.PROJECT) {
+ rule = resource;
+ } else {
+ rule = resource.getParent();
+ }
+ } else if (resourceRule instanceof MultiRule) {
+ // Create a MultiRule for all projects from the given rule
+ ISchedulingRule[] rules = ((MultiRule)resourceRule).getChildren();
+ Set projects = new HashSet();
+ for (int i = 0; i < rules.length; i++) {
+ ISchedulingRule childRule = rules[i];
+ if (childRule instanceof IResource) {
+ projects.add(((IResource)childRule).getProject());
+ }
+ }
+ if (projects.isEmpty()) {
+ rule = NULL_SCHEDULING_RULE;
+ } else if (projects.size() == 1) {
+ rule = (ISchedulingRule)projects.iterator().next();
+ } else {
+ rule = new MultiRule((ISchedulingRule[]) projects.toArray(new ISchedulingRule[projects.size()]));
+ }
+ } else {
+ // Rule is not associated with resources so ignore it
+ rule = NULL_SCHEDULING_RULE;
+ }
+ return rule;
+ }
+ /**
+ * Return <code>true</code> if we are still nested in
+ * an acquire for this thread.
+ *
+ * @return
+ */
+ public boolean isNested() {
+ return !rules.isEmpty();
+ }
+ public void addChangedResource(IResource resource) {
+ changedResources.add(resource);
+ }
+ public boolean isEmpty() {
+ return changedResources.isEmpty();
+ }
+ public IResource[] getChangedResources() {
+ return (IResource[]) changedResources.toArray(new IResource[changedResources.size()]);
+ }
+ public void flush(IProgressMonitor monitor) throws TeamException {
+ try {
+ operation.flush(this, monitor);
+ } catch (OutOfMemoryError e) {
+ throw e;
+ } catch (Error e) {
+ handleAbortedFlush(e);
+ throw e;
+ } catch (RuntimeException e) {
+ handleAbortedFlush(e);
+ throw e;
+ }
+ changedResources.clear();
+ }
+ private boolean isFlushRequired() {
+ return rules.size() == 1 || remainingRulesAreNull();
+ }
+ /*
+ * Return true if all but the last rule in the stack is null
+ */
+ private boolean remainingRulesAreNull() {
+ for (int i = 0; i < rules.size() - 1; i++) {
+ ISchedulingRule rule = (ISchedulingRule) rules.get(i);
+ if (rule != NULL_SCHEDULING_RULE) {
+ return false;
+ }
+ }
+ return true;
+ }
+ private void handleAbortedFlush(Throwable t) {
+ TeamPlugin.log(IStatus.ERROR, Policy.bind("BatchingLock.11"), t); //$NON-NLS-1$
+ }
+ private void addRule(ISchedulingRule rule) {
+ rules.add(rule);
+ }
+ private ISchedulingRule removeRule() {
+ return (ISchedulingRule)rules.remove(rules.size() - 1);
+ }
+ public boolean ruleContains(IResource resource) {
+ for (Iterator iter = rules.iterator(); iter.hasNext();) {
+ ISchedulingRule rule = (ISchedulingRule) iter.next();
+ if (rule != NULL_SCHEDULING_RULE && rule.contains(resource)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ public interface IFlushOperation {
+ public void flush(ThreadInfo info, IProgressMonitor monitor) throws TeamException;
+ }
+
+ private Map infos = new HashMap();
+
+ private ThreadInfo getThreadInfo() {
+ Thread thisThread = Thread.currentThread();
+ synchronized (infos) {
+ ThreadInfo info = (ThreadInfo)infos.get(thisThread);
+ return info;
+ }
+ }
+
+ private ThreadInfo getThreadInfo(IResource resource) {
+ synchronized (infos) {
+ for (Iterator iter = infos.values().iterator(); iter.hasNext();) {
+ ThreadInfo info = (ThreadInfo) iter.next();
+ if (info.ruleContains(resource)) {
+ return info;
+ }
+ }
+ return null;
+ }
+ }
+
+ public ISchedulingRule acquire(ISchedulingRule resourceRule, IFlushOperation operation, IProgressMonitor monitor) {
+ ThreadInfo info = getThreadInfo();
+ boolean added = false;
+ synchronized (infos) {
+ if (info == null) {
+ info = new ThreadInfo(operation);
+ Thread thisThread = Thread.currentThread();
+ infos.put(thisThread, info);
+ added = true;
+ if(DEBUG) System.out.println("[" + thisThread.getName() + "] acquired batching lock on " + resourceRule); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ try {
+ return info.pushRule(resourceRule, monitor);
+ } catch (OperationCanceledException e) {
+ // The operation was cancelled.
+ // If this is the outermost acquire then remove the info that was just added
+ if (added) {
+ synchronized (infos) {
+ infos.remove(Thread.currentThread());
+ }
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Release the lock held on any resources by this thread. The provided rule must
+ * be identical to the rule returned by the corresponding acquire(). If the rule
+ * for the release is non-null and all remaining rules held by the lock are null,
+ * the the flush operation provided in the acquire method will be executed.
+ */
+ public void release(ISchedulingRule rule, IProgressMonitor monitor) throws TeamException {
+ ThreadInfo info = getThreadInfo();
+ Assert.isNotNull(info, "Unmatched acquire/release."); //$NON-NLS-1$
+ Assert.isTrue(info.isNested(), "Unmatched acquire/release."); //$NON-NLS-1$
+ info.popRule(rule, monitor);
+ synchronized (infos) {
+ if (!info.isNested()) {
+ Thread thisThread = Thread.currentThread();
+ if(DEBUG) System.out.println("[" + thisThread.getName() + "] released batching lock"); //$NON-NLS-1$ //$NON-NLS-2$
+ infos.remove(thisThread);
+ }
+ }
+ }
+
+ public void resourceChanged(IResource resource) {
+ ThreadInfo info = getThreadInfo();
+ Assert.isNotNull(info, "Folder changed outside of resource lock"); //$NON-NLS-1$
+ info.addChangedResource(resource);
+ }
+
+ /**
+ * Flush any changes accumulated by the lock so far.
+ */
+ public void flush(IProgressMonitor monitor) throws TeamException {
+ ThreadInfo info = getThreadInfo();
+ Assert.isNotNull(info, "Flush requested outside of resource lock"); //$NON-NLS-1$
+ info.flush(monitor);
+ }
+
+ public boolean isWithinActiveOperationScope(IResource resource) {
+ synchronized (infos) {
+ return getThreadInfo(resource) != null;
+ }
+ }
+}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/ContentComparator.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/ContentComparator.java
index 44922f9fa..381785790 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/ContentComparator.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/ContentComparator.java
@@ -15,7 +15,7 @@ import java.io.*;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.*;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.IResourceVariant;
+import org.eclipse.team.core.variants.IResourceVariant;
import org.eclipse.team.internal.core.Policy;
import org.eclipse.team.internal.core.TeamPlugin;
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/DescendantResourceVariantByteStore.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/DescendantResourceVariantByteStore.java
index 0e3e6a79e..77cb91d1f 100644
--- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/caches/DescendantResourceVariantByteStore.java
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/DescendantResourceVariantByteStore.java
@@ -8,13 +8,14 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-package org.eclipse.team.internal.core.subscribers.caches;
+package org.eclipse.team.internal.core.subscribers;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.resources.IResource;
import org.eclipse.team.core.TeamException;
+import org.eclipse.team.core.variants.*;
/**
* A <code>ResourceVariantByteStore</code> that optimizes the memory footprint
@@ -44,7 +45,7 @@ public abstract class DescendantResourceVariantByteStore extends ResourceVariant
/**
* This method will dispose the remote cache but not the base cache.
- * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore#dispose()
+ * @see org.eclipse.team.core.variants.ResourceVariantByteStore#dispose()
*/
public void dispose() {
remoteStore.dispose();
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SyncByteConverter.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SyncByteConverter.java
new file mode 100644
index 000000000..1fe2c5b26
--- /dev/null
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/SyncByteConverter.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.internal.core.subscribers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.internal.core.Policy;
+
+/**
+ * Utility for managing slash separated sync information fields.
+ */
+public class SyncByteConverter {
+
+ protected static final byte SEPARATOR_BYTE = (byte)'/';
+
+ public static String[] parseIntoSubstrings(String string, String delimiter) {
+ List result = new ArrayList();
+ int start = 0;
+ int index = string.indexOf(delimiter);
+ String next;
+ while (index != -1) {
+ next = string.substring(start, index);
+ result.add(next);
+ start = index + 1;
+ index = string.indexOf(delimiter, start);
+ }
+ if (start >= string.length()) {
+ next = "";//$NON-NLS-1$
+ } else {
+ next = string.substring(start);
+ }
+ result.add(next);
+ return (String[]) result.toArray(new String[result.size()]);
+ }
+
+ /**
+ * Method setSlot.
+ * @param syncBytes
+ * @param i
+ * @param b
+ * @return byte[]
+ */
+ public static byte[] setSlot(byte[] syncBytes, int slot, byte[] newBytes) throws TeamException {
+ int start = startOfSlot(syncBytes, slot);
+ if (start == -1) {
+ throw new TeamException(Policy.bind("SyncByteConverter.1", new String(syncBytes))); //$NON-NLS-1$
+ }
+ int end = startOfSlot(syncBytes, slot + 1);
+ int totalLength = start + 1 + newBytes.length;
+ if (end != -1) {
+ totalLength += syncBytes.length - end;
+ }
+ byte[] result = new byte[totalLength];
+ System.arraycopy(syncBytes, 0, result, 0, start + 1);
+ System.arraycopy(newBytes, 0, result, start + 1, newBytes.length);
+ if (end != -1) {
+ System.arraycopy(syncBytes, end, result, start + 1 + newBytes.length, syncBytes.length - end);
+ }
+ return result;
+ }
+
+ /**
+ * Method startOfSlot returns the index of the slash that occurs before the
+ * given slot index. The provided index should be >= 1 which assumes that
+ * slot zero occurs before the first slash.
+ *
+ * @param syncBytes
+ * @param i
+ * @return int
+ */
+ private static int startOfSlot(byte[] syncBytes, int slot) {
+ int count = 0;
+ for (int j = 0; j < syncBytes.length; j++) {
+ if (syncBytes[j] == SEPARATOR_BYTE) {
+ count++;
+ if (count == slot) return j;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Return the offset the the Nth delimeter from the given start index.
+ * @param bytes
+ * @param delimiter
+ * @param start
+ * @param n
+ * @return int
+ */
+ private static int getOffsetOfDelimeter(byte[] bytes, byte delimiter, int start, int n) {
+ int count = 0;
+ for (int i = start; i < bytes.length; i++) {
+ if (bytes[i] == delimiter) count++;
+ if (count == n) return i;
+ }
+ // the Nth delimeter was not found
+ return -1;
+ }
+
+ /**
+ * Method getBytesForSlot.
+ * @param syncBytes
+ * @param SEPARATOR_BYTE
+ * @param i
+ * @param b
+ * @return byte[]
+ */
+ public static byte[] getSlot(byte[] bytes, int index, boolean includeRest) {
+ // Find the starting index
+ byte delimiter = SEPARATOR_BYTE;
+ int start;
+ if (index == 0) {
+ // make start -1 so that end determination will start at offset 0.
+ start = -1;
+ } else {
+ start = getOffsetOfDelimeter(bytes, delimiter, 0, index);
+ if (start == -1) return null;
+ }
+ // Find the ending index
+ int end = getOffsetOfDelimeter(bytes, delimiter, start + 1, 1);
+ // Calculate the length
+ int length;
+ if (end == -1 || includeRest) {
+ length = bytes.length - start - 1;
+ } else {
+ length = end - start - 1;
+ }
+ byte[] result = new byte[length];
+ System.arraycopy(bytes, start + 1, result, 0, length);
+ return result;
+ }
+
+ public static byte[] toBytes(String[] slots) {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < slots.length; i++) {
+ String string = slots[i];
+ buffer.append(string);
+ buffer.append(new String(new byte[] {SyncByteConverter.SEPARATOR_BYTE }));
+ }
+ return buffer.toString().getBytes();
+ }
+}
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/ThreeWayBaseTree.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/ThreeWayBaseTree.java
new file mode 100644
index 000000000..0a3b5c200
--- /dev/null
+++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/subscribers/ThreeWayBaseTree.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.internal.core.subscribers;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.core.variants.IResourceVariant;
+import org.eclipse.team.core.variants.ResourceVariantByteStore;
+import org.eclipse.team.core.variants.ResourceVariantTree;
+import org.eclipse.team.core.variants.ThreeWaySubscriber;
+
+/**
+ * Allow access to the base resource variants but do not support refresh
+ * or modification.
+ */
+public final class ThreeWayBaseTree extends ResourceVariantTree {
+
+ private ThreeWaySubscriber subscriber;
+
+ /*
+ * A resource variant byte store that accesses the base bytes from a three-way
+ * synchronizer. The modification methods are disabled as the base should
+ * only be modified in the synchronizer directly.
+ */
+ static class BaseResourceVariantByteStore extends ResourceVariantByteStore {
+ private ThreeWaySubscriber subscriber;
+ public BaseResourceVariantByteStore(ThreeWaySubscriber subscriber) {
+ this.subscriber = subscriber;
+ }
+ public void dispose() {
+ // Nothing to do
+ }
+ public byte[] getBytes(IResource resource) throws TeamException {
+ return subscriber.getSynchronizer().getBaseBytes(resource);
+ }
+ public boolean setBytes(IResource resource, byte[] bytes) throws TeamException {
+ // Base bytes are set directly in the synchronizer
+ return false;
+ }
+ public boolean flushBytes(IResource resource, int depth) throws TeamException {
+ // Base bytes are flushed directly in the synchronizer
+ return false;
+ }
+ public boolean deleteBytes(IResource resource) throws TeamException {
+ // Base bytes are deleted directly in the synchronizer
+ return false;
+ }
+ public IResource[] members(IResource resource) throws TeamException {
+ return subscriber.getSynchronizer().members(resource);
+ }
+ }
+
+ /**
+ * Create a base resource variant tree that accesses the base bytes
+ * from a three-way synchronizer.
+ * @param subscriber the three-way subscriber
+ */
+ public ThreeWayBaseTree(ThreeWaySubscriber subscriber) {
+ super(new BaseResourceVariantByteStore(subscriber));
+ this.subscriber = subscriber;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.core.subscribers.caches.AbstractResourceVariantTree#refresh(org.eclipse.core.resources.IResource[], int, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IResource[] refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException {
+ return new IResource[0];
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.core.subscribers.caches.AbstractResourceVariantTree#fetchMembers(org.eclipse.team.core.synchronize.IResourceVariant, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected IResourceVariant[] fetchMembers(IResourceVariant variant, IProgressMonitor progress) throws TeamException {
+ // Refresh not supported
+ return new IResourceVariant[0];
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.core.subscribers.caches.AbstractResourceVariantTree#fetchVariant(org.eclipse.core.resources.IResource, int, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected IResourceVariant fetchVariant(IResource resource, int depth, IProgressMonitor monitor) throws TeamException {
+ // Refresh not supported
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree#roots()
+ */
+ public IResource[] roots() {
+ return getSubscriber().roots();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree#getResourceVariant(org.eclipse.core.resources.IResource)
+ */
+ public IResourceVariant getResourceVariant(IResource resource) throws TeamException {
+ return getSubscriber().getResourceVariant(resource, getByteStore().getBytes(resource));
+ }
+
+ private ThreeWaySubscriber getSubscriber() {
+ return subscriber;
+ }
+
+}
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSCompareSubscriber.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSCompareSubscriber.java
index 8806e07b3..6b127b7f5 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSCompareSubscriber.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSCompareSubscriber.java
@@ -23,10 +23,10 @@ import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.subscribers.ISubscriberChangeEvent;
import org.eclipse.team.core.subscribers.ISubscriberChangeListener;
import org.eclipse.team.core.subscribers.SubscriberChangeEvent;
+import org.eclipse.team.core.variants.IResourceVariantTree;
+import org.eclipse.team.core.variants.SessionResourceVariantByteStore;
import org.eclipse.team.internal.ccvs.core.syncinfo.CVSResourceVariantTree;
import org.eclipse.team.internal.ccvs.core.syncinfo.MultiTagResourceVariantTree;
-import org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree;
-import org.eclipse.team.internal.core.subscribers.caches.SessionResourceVariantByteStore;
/**
* This subscriber is used when comparing the local workspace with its
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java
index 2d8cd74b7..cefb2e5b4 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java
@@ -30,16 +30,16 @@ import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.subscribers.ISubscriberChangeEvent;
import org.eclipse.team.core.subscribers.ISubscriberChangeListener;
import org.eclipse.team.core.subscribers.SubscriberChangeEvent;
-import org.eclipse.team.core.synchronize.IResourceVariant;
import org.eclipse.team.core.synchronize.SyncInfo;
import org.eclipse.team.core.synchronize.SyncInfoFilter;
+import org.eclipse.team.core.variants.IResourceVariant;
+import org.eclipse.team.core.variants.IResourceVariantTree;
+import org.eclipse.team.core.variants.PersistantResourceVariantByteStore;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.resources.RemoteFile;
import org.eclipse.team.internal.ccvs.core.syncinfo.CVSResourceVariantTree;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
import org.eclipse.team.internal.ccvs.core.util.Util;
-import org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree;
-import org.eclipse.team.internal.core.subscribers.caches.PersistantResourceVariantByteStore;
/**
* A CVSMergeSubscriber is responsible for maintaining the remote trees for a merge into
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSyncInfo.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSyncInfo.java
index b4a4d0feb..ac35b0126 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSyncInfo.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSMergeSyncInfo.java
@@ -11,6 +11,7 @@ import org.eclipse.core.runtime.*;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.subscribers.*;
import org.eclipse.team.core.synchronize.*;
+import org.eclipse.team.core.variants.*;
/**
* @author JLemieux
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSRevisionNumberCompareCriteria.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSRevisionNumberCompareCriteria.java
index 23ef83af0..8b3be7c1f 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSRevisionNumberCompareCriteria.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSRevisionNumberCompareCriteria.java
@@ -12,8 +12,8 @@ package org.eclipse.team.internal.ccvs.core;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
-import org.eclipse.team.core.synchronize.IResourceVariant;
-import org.eclipse.team.core.synchronize.IResourceVariantComparator;
+import org.eclipse.team.core.variants.IResourceVariant;
+import org.eclipse.team.core.variants.IResourceVariantComparator;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncInfo.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncInfo.java
index a603c7950..e60495132 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncInfo.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncInfo.java
@@ -17,12 +17,13 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.subscribers.*;
import org.eclipse.team.core.synchronize.*;
+import org.eclipse.team.core.variants.*;
+import org.eclipse.team.core.variants.ResourceVariantTreeSubscriber;
import org.eclipse.team.internal.ccvs.core.client.Update;
import org.eclipse.team.internal.ccvs.core.resources.*;
import org.eclipse.team.internal.ccvs.core.syncinfo.*;
import org.eclipse.team.internal.ccvs.core.util.Assert;
import org.eclipse.team.internal.ccvs.core.Policy;
-import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTreeSubscriber;
/**
* CVSSyncInfo
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java
index 1cbbca7a5..49f978fde 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSSyncTreeSubscriber.java
@@ -20,11 +20,11 @@ import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.subscribers.Subscriber;
-import org.eclipse.team.core.synchronize.IResourceVariant;
-import org.eclipse.team.core.synchronize.IResourceVariantComparator;
import org.eclipse.team.core.synchronize.SyncInfo;
+import org.eclipse.team.core.variants.IResourceVariant;
+import org.eclipse.team.core.variants.IResourceVariantComparator;
+import org.eclipse.team.core.variants.ResourceVariantTreeSubscriber;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
-import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTreeSubscriber;
/**
* This class provides common funtionality for three way sychronizing
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSWorkspaceSubscriber.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSWorkspaceSubscriber.java
index e37643afe..3523b562b 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSWorkspaceSubscriber.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSWorkspaceSubscriber.java
@@ -30,18 +30,18 @@ import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.TeamStatus;
import org.eclipse.team.core.subscribers.ISubscriberChangeEvent;
import org.eclipse.team.core.subscribers.SubscriberChangeEvent;
-import org.eclipse.team.core.synchronize.IResourceVariant;
import org.eclipse.team.core.synchronize.SyncInfo;
import org.eclipse.team.core.synchronize.SyncInfoSet;
+import org.eclipse.team.core.variants.IResourceVariant;
+import org.eclipse.team.core.variants.IResourceVariantTree;
+import org.eclipse.team.core.variants.PersistantResourceVariantByteStore;
+import org.eclipse.team.core.variants.ResourceVariantByteStore;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.resources.EclipseSynchronizer;
import org.eclipse.team.internal.ccvs.core.syncinfo.CVSBaseResourceVariantTree;
import org.eclipse.team.internal.ccvs.core.syncinfo.CVSDescendantResourceVariantByteStore;
import org.eclipse.team.internal.ccvs.core.syncinfo.CVSResourceVariantTree;
import org.eclipse.team.internal.ccvs.core.util.ResourceStateChangeListeners;
-import org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree;
-import org.eclipse.team.internal.core.subscribers.caches.PersistantResourceVariantByteStore;
-import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore;
import org.eclipse.team.internal.ccvs.core.Policy;
/**
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteResource.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteResource.java
index 52bc6999c..44449357b 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteResource.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteResource.java
@@ -14,7 +14,7 @@ package org.eclipse.team.internal.ccvs.core.resources;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.*;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.CachedResourceVariant;
+import org.eclipse.team.core.variants.CachedResourceVariant;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.Update;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
@@ -226,4 +226,11 @@ public abstract class RemoteResource extends CachedResourceVariant implements IC
protected String getCacheId() {
return CVSProviderPlugin.ID;
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.IResourceVariant#asBytes()
+ */
+ public byte[] asBytes() {
+ return getSyncBytes();
+ }
}
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSBaseResourceVariantTree.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSBaseResourceVariantTree.java
index 0484285cc..475227759 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSBaseResourceVariantTree.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSBaseResourceVariantTree.java
@@ -13,7 +13,7 @@ package org.eclipse.team.internal.ccvs.core.syncinfo;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore;
+import org.eclipse.team.core.variants.ResourceVariantByteStore;
import org.eclipse.team.internal.ccvs.core.resources.EclipseSynchronizer;
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSDescendantResourceVariantByteStore.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSDescendantResourceVariantByteStore.java
index 469a65835..9fc5c06f3 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSDescendantResourceVariantByteStore.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSDescendantResourceVariantByteStore.java
@@ -18,8 +18,12 @@ import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.internal.core.subscribers.caches.*;
-import org.eclipse.team.internal.ccvs.core.*;
+import org.eclipse.team.core.variants.PersistantResourceVariantByteStore;
+import org.eclipse.team.core.variants.ResourceVariantByteStore;
+import org.eclipse.team.internal.ccvs.core.CVSException;
+import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
+import org.eclipse.team.internal.ccvs.core.Policy;
+import org.eclipse.team.internal.core.subscribers.DescendantResourceVariantByteStore;
/**
* CVS sycnrhonization cache that ignores stale remote bytes
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSResourceVariantTree.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSResourceVariantTree.java
index 786b73cc1..34b1cec3c 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSResourceVariantTree.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/CVSResourceVariantTree.java
@@ -21,7 +21,10 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.IResourceVariant;
+import org.eclipse.team.core.variants.IResourceVariant;
+import org.eclipse.team.core.variants.PersistantResourceVariantByteStore;
+import org.eclipse.team.core.variants.ResourceVariantByteStore;
+import org.eclipse.team.core.variants.ResourceVariantTree;
import org.eclipse.team.internal.ccvs.core.CVSException;
import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
import org.eclipse.team.internal.ccvs.core.CVSSyncTreeSubscriber;
@@ -33,9 +36,6 @@ import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.resources.RemoteFile;
import org.eclipse.team.internal.ccvs.core.resources.RemoteFolder;
import org.eclipse.team.internal.ccvs.core.resources.RemoteResource;
-import org.eclipse.team.internal.core.subscribers.caches.PersistantResourceVariantByteStore;
-import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore;
-import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTree;
/**
* CVS Specific refresh operation
@@ -64,7 +64,7 @@ public class CVSResourceVariantTree extends ResourceVariantTree {
*/
protected byte[] getBytes(IResource local, IResourceVariant remote) throws TeamException {
if (remote != null) {
- return ((RemoteResource)remote).getSyncBytes();
+ return super.getBytes(local, remote);
} else {
if (local.getType() == IResource.FOLDER) {
// If there is no remote, use the local sync for the folder
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/MultiTagResourceVariantTree.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/MultiTagResourceVariantTree.java
index 2006dad07..d78017c57 100644
--- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/MultiTagResourceVariantTree.java
+++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/MultiTagResourceVariantTree.java
@@ -15,9 +15,9 @@ import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
+import org.eclipse.team.core.variants.ResourceVariantByteStore;
import org.eclipse.team.internal.ccvs.core.CVSTag;
import org.eclipse.team.internal.ccvs.core.util.Assert;
-import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantByteStore;
/**
* A CVS resource variant tree that associates a different tag with each root project.
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSCompareRevisionsInput.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSCompareRevisionsInput.java
index 085dd4e3a..915bf0b16 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSCompareRevisionsInput.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/CVSCompareRevisionsInput.java
@@ -27,7 +27,7 @@ import org.eclipse.jface.viewers.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.IResourceVariant;
+import org.eclipse.team.core.variants.IResourceVariant;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.Command;
import org.eclipse.team.internal.ccvs.core.client.Update;
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/ResourceEditionNode.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/ResourceEditionNode.java
index 977288b4c..0b8fede68 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/ResourceEditionNode.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/ResourceEditionNode.java
@@ -22,7 +22,7 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.graphics.Image;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.IResourceVariant;
+import org.eclipse.team.core.variants.IResourceVariant;
import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource;
/**
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/ReconcileProjectOperation.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/ReconcileProjectOperation.java
index 376208d7a..557cb03ed 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/ReconcileProjectOperation.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/operations/ReconcileProjectOperation.java
@@ -17,7 +17,7 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.IResourceVariant;
+import org.eclipse.team.core.variants.IResourceVariant;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
import org.eclipse.team.internal.ccvs.ui.Policy;
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/CVSSubscriberAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/CVSSubscriberAction.java
index 24e58168c..6463d0876 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/CVSSubscriberAction.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/CVSSubscriberAction.java
@@ -20,6 +20,7 @@ import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.synchronize.*;
+import org.eclipse.team.core.variants.*;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.PruneFolderVisitor;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
diff --git a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/SafeUpdateAction.java b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/SafeUpdateAction.java
index 895175342..2a7d63f16 100644
--- a/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/SafeUpdateAction.java
+++ b/bundles/org.eclipse.team.cvs.ui/src/org/eclipse/team/internal/ccvs/ui/subscriber/SafeUpdateAction.java
@@ -21,6 +21,7 @@ import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.synchronize.*;
import org.eclipse.team.core.synchronize.FastSyncInfoFilter.*;
+import org.eclipse.team.core.variants.*;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/Utils.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/Utils.java
index 83e5bafb6..3a2a29329 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/Utils.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/Utils.java
@@ -38,8 +38,8 @@ import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.IResourceVariant;
import org.eclipse.team.core.synchronize.SyncInfo;
+import org.eclipse.team.core.variants.IResourceVariant;
import org.eclipse.team.ui.TeamImages;
import org.eclipse.team.ui.synchronize.subscriber.SubscriberParticipant;
import org.eclipse.team.ui.synchronize.viewers.SynchronizeModelElement;
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/synchronize/RemoteResourceTypedElement.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/synchronize/RemoteResourceTypedElement.java
index edfb92c13..912f874d5 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/synchronize/RemoteResourceTypedElement.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/synchronize/RemoteResourceTypedElement.java
@@ -17,7 +17,7 @@ import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.*;
import org.eclipse.swt.graphics.Image;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.IResourceVariant;
+import org.eclipse.team.core.variants.IResourceVariant;
/**
* RemoteResourceTypedElement
diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoModelElement.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoModelElement.java
index 57e445795..3763b09b1 100644
--- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoModelElement.java
+++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/synchronize/viewers/SyncInfoModelElement.java
@@ -17,6 +17,7 @@ import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.synchronize.*;
+import org.eclipse.team.core.variants.*;
import org.eclipse.team.internal.ui.Policy;
import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
import org.eclipse.team.internal.ui.synchronize.RemoteResourceTypedElement;
diff --git a/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/FileSystemProvider.java b/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/FileSystemProvider.java
index 60f64c48b..597776599 100644
--- a/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/FileSystemProvider.java
+++ b/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/FileSystemProvider.java
@@ -13,12 +13,16 @@ package org.eclipse.team.examples.filesystem;
import java.io.File;
import org.eclipse.core.resources.IFileModificationValidator;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
+import org.eclipse.team.core.variants.IResourceVariant;
+import org.eclipse.team.examples.filesystem.subscriber.FileSystemResourceVariant;
+import org.eclipse.team.examples.filesystem.subscriber.FileSystemSubscriber;
/**
* This example illustrates how to create a concrete implementation of a <code>RepositoryProvider</code>
@@ -71,6 +75,7 @@ public class FileSystemProvider extends RepositoryProvider {
* @see org.eclipse.team.core.RepositoryProvider#configureProject()
*/
public void configureProject() throws CoreException {
+ FileSystemSubscriber.getInstance().handleRootChanged(getProject(), true /* added */);
}
/**
@@ -82,6 +87,7 @@ public class FileSystemProvider extends RepositoryProvider {
public void deconfigure() throws CoreException {
// Clear the persistant property containing the location
getProject().setPersistentProperty(FILESYSTEM_REPO_LOC, null);
+ FileSystemSubscriber.getInstance().handleRootChanged(getProject(), false /* removed */);
}
/**
@@ -162,4 +168,43 @@ public class FileSystemProvider extends RepositoryProvider {
return new FileModificationValidator(this);
}
+ /**
+ * Return the resource variant for the local resource using the bytes to
+ * identify the variant.
+ * @param resource the resource
+ * @param bytes the bytes that identify the resource variant
+ * @return the resource variant handle
+ */
+ public IResourceVariant getResourceVariant(IResource resource, byte[] bytes) {
+ File file = getFile(resource);
+ if (file == null) return null;
+ return new FileSystemResourceVariant(file, bytes);
+ }
+
+ /**
+ * Return the resource variant for the local resource.
+ * @param resource the resource
+ * @return the resource variant
+ */
+ public IResourceVariant getResourceVariant(IResource resource) {
+ File file = getFile(resource);
+ if (file == null) return null;
+ return new FileSystemResourceVariant(file);
+ }
+
+ /**
+ * Return the <code>java.io.File</code> that the given resource maps to.
+ * Return <code>null</code> if the resource is not a child of this provider's
+ * project.
+ * @param resource the resource
+ * @return the file that the resource maps to.
+ */
+ public java.io.File getFile(IResource resource) {
+ if (resource.getProject().equals(getProject())) {
+ IPath rootdir = getRoot();
+ return new File(rootdir.append(resource.getProjectRelativePath()).toOSString());
+ }
+ return null;
+ }
+
}
diff --git a/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/FileSystemSubscriber.java b/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/FileSystemSubscriber.java
deleted file mode 100644
index 81de667bb..000000000
--- a/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/FileSystemSubscriber.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.team.examples.filesystem;
-
-import org.eclipse.core.resources.IResource;
-import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.IResourceVariantComparator;
-import org.eclipse.team.internal.core.subscribers.caches.IResourceVariantTree;
-import org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTreeSubscriber;
-
-public class FileSystemSubscriber extends ResourceVariantTreeSubscriber {
-
- /* (non-Javadoc)
- * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTreeSubscriber#getBaseTree()
- */
- protected IResourceVariantTree getBaseTree() {
- // TODO Auto-generated method stub
- return null;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.team.internal.core.subscribers.caches.ResourceVariantTreeSubscriber#getRemoteTree()
- */
- protected IResourceVariantTree getRemoteTree() {
- // TODO Auto-generated method stub
- return null;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.team.core.subscribers.Subscriber#getName()
- */
- public String getName() {
- // TODO Auto-generated method stub
- return null;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.team.core.subscribers.Subscriber#isSupervised(org.eclipse.core.resources.IResource)
- */
- public boolean isSupervised(IResource resource) throws TeamException {
- // TODO Auto-generated method stub
- return false;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.team.core.subscribers.Subscriber#roots()
- */
- public IResource[] roots() {
- // TODO Auto-generated method stub
- return null;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.team.core.subscribers.Subscriber#getResourceComparator()
- */
- public IResourceVariantComparator getResourceComparator() {
- // TODO Auto-generated method stub
- return null;
- }
-
-
-}
diff --git a/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/subscriber/FileSystemRemoteTree.java b/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/subscriber/FileSystemRemoteTree.java
new file mode 100644
index 000000000..65f87d805
--- /dev/null
+++ b/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/subscriber/FileSystemRemoteTree.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.examples.filesystem.subscriber;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.RepositoryProvider;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.core.variants.IResourceVariant;
+import org.eclipse.team.core.variants.ThreeWayRemoteTree;
+import org.eclipse.team.examples.filesystem.FileSystemPlugin;
+import org.eclipse.team.examples.filesystem.FileSystemProvider;
+
+/**
+ * The file sytem three-way remote resource varant tree taht provides
+ * the ability to traverse the file system for the creation of resource variants.
+ */
+public class FileSystemRemoteTree extends ThreeWayRemoteTree {
+
+ /**
+ * Create the file syetm remote resource variant tree
+ * @param subscriber the file system subscriber
+ */
+ public FileSystemRemoteTree(FileSystemSubscriber subscriber) {
+ super(subscriber);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.AbstractResourceVariantTree#fetchMembers(org.eclipse.team.core.variants.IResourceVariant, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected IResourceVariant[] fetchMembers(IResourceVariant variant, IProgressMonitor progress) throws TeamException {
+ if (variant.isContainer()) {
+ java.io.File[] members = ((FileSystemResourceVariant)variant).members();
+ FileSystemResourceVariant[] result = new FileSystemResourceVariant[members.length];
+ for (int i = 0; i < members.length; i++) {
+ result[i] = new FileSystemResourceVariant(members[i]);
+ }
+ return result;
+ } else {
+ return new IResourceVariant[0];
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.AbstractResourceVariantTree#fetchVariant(org.eclipse.core.resources.IResource, int, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected IResourceVariant fetchVariant(IResource resource, int depth, IProgressMonitor monitor) throws TeamException {
+ RepositoryProvider provider = RepositoryProvider.getProvider(resource.getProject(), FileSystemPlugin.PROVIDER_ID);
+ if (provider != null) {
+ return ((FileSystemProvider)provider).getResourceVariant(resource);
+ }
+ return null;
+ }
+}
diff --git a/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/subscriber/FileSystemResourceVariant.java b/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/subscriber/FileSystemResourceVariant.java
new file mode 100644
index 000000000..630b73ee5
--- /dev/null
+++ b/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/subscriber/FileSystemResourceVariant.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.examples.filesystem.subscriber;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Date;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.core.variants.CachedResourceVariant;
+import org.eclipse.team.examples.filesystem.FileSystemPlugin;
+
+/**
+ * A file system resource variant. Although not strictly necessary, this
+ * class extends <code>CachedResourceVariant</code> which will
+ * cache the contents of the resource variant.
+ */
+public class FileSystemResourceVariant extends CachedResourceVariant {
+
+ private java.io.File ioFile;
+ private byte[] bytes;
+
+ /**
+ * Create a resource variant for the given file. The bytes will
+ * be calculated when they are accessed.
+ * @param file the file
+ */
+ public FileSystemResourceVariant(java.io.File file) {
+ this.ioFile = file;
+ }
+
+ /**
+ * Create a resource variant for the given file and sync bytes.
+ * @param file the file
+ * @param bytes the timestamp bytes
+ */
+ public FileSystemResourceVariant(java.io.File file, byte[] bytes) {
+ this.ioFile = file;
+ this.bytes = bytes;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.CachedResourceVariant#fetchContents(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected void fetchContents(IProgressMonitor monitor) throws TeamException {
+ try {
+ setContents(new BufferedInputStream(new FileInputStream(ioFile)), monitor);
+ } catch (FileNotFoundException e) {
+ throw new TeamException("Failed to fetch contents for " + getFilePath(), e);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.CachedResourceVariant#getCachePath()
+ */
+ protected String getCachePath() {
+ // append the timestamp to the file path to give each variant a unique path
+ return getFilePath() + " " + ioFile.lastModified();
+ }
+
+ private String getFilePath() {
+ try {
+ return ioFile.getCanonicalPath();
+ } catch (IOException e) {
+ // Failed for some reason. Try the absolute path.
+ FileSystemPlugin.log(new Status(IStatus.ERROR, FileSystemPlugin.ID, 0,
+ "Failed to obtain canonical path for " + ioFile.getAbsolutePath(), e));
+ return ioFile.getAbsolutePath();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.CachedResourceVariant#getCacheId()
+ */
+ protected String getCacheId() {
+ return FileSystemPlugin.ID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.IResourceVariant#getName()
+ */
+ public String getName() {
+ return ioFile.getName();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.IResourceVariant#isContainer()
+ */
+ public boolean isContainer() {
+ return ioFile.isDirectory();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.IResourceVariant#getContentIdentifier()
+ */
+ public String getContentIdentifier() {
+ // Use the modification timestamp as the content identifier
+ return new Date(ioFile.lastModified()).toString();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.IResourceVariant#asBytes()
+ */
+ public byte[] asBytes() {
+ if (bytes == null) {
+ // For simplicity, convert the timestamp to it's string representation.
+ // A more optimal storage format would be the 8 bytes that make up the long.
+ bytes = Long.toString(ioFile.lastModified()).getBytes();
+ }
+ return bytes;
+ }
+
+ /**
+ * Return the files contained by the file of this resource variant.
+ * @return the files contained by the file of this resource variant.
+ */
+ public File[] members() {
+ return ioFile.listFiles();
+ }
+}
diff --git a/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/subscriber/FileSystemSubscriber.java b/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/subscriber/FileSystemSubscriber.java
new file mode 100644
index 000000000..fc0880b46
--- /dev/null
+++ b/examples/org.eclipse.team.examples.filesystem/src/org/eclipse/team/examples/filesystem/subscriber/FileSystemSubscriber.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.team.examples.filesystem.subscriber;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.team.core.RepositoryProvider;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.core.variants.IResourceVariant;
+import org.eclipse.team.core.variants.ThreeWayRemoteTree;
+import org.eclipse.team.core.variants.ThreeWaySubscriber;
+import org.eclipse.team.core.variants.ThreeWaySynchronizer;
+import org.eclipse.team.examples.filesystem.FileSystemPlugin;
+import org.eclipse.team.examples.filesystem.FileSystemProvider;
+
+/**
+ * This is an example file system subscriber that overrides
+ * ThreeWaySubscriber. It uses a repository
+ * provider (<code>FileSystemProvider</code>) to determine and
+ * manage the roots and to create resource variants. It also makes
+ * use of a file system specific remote tree (<code>FileSystemRemoteTree</code>)
+ * for provided the remote tree access and refresh.
+ *
+ * @see ThreeWaySubscriber
+ * @see ThreeWaySynchronizer
+ * @see FileSystemProvider
+ * @see FileSystemRemoteTree
+ */
+public class FileSystemSubscriber extends ThreeWaySubscriber {
+
+ private static FileSystemSubscriber instance;
+
+ /**
+ * Return the file system subscriber singleton.
+ * @return the file system subscriber singleton.
+ */
+ public static synchronized FileSystemSubscriber getInstance() {
+ if (instance == null) {
+ instance = new FileSystemSubscriber();
+ }
+ return instance;
+ }
+
+ /**
+ * Create the file system subscriber.
+ */
+ private FileSystemSubscriber() {
+ super(new ThreeWaySynchronizer(new QualifiedName(FileSystemPlugin.ID, "workpsace-sync"))); //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.ThreeWaySubscriber#getResourceVariant(org.eclipse.core.resources.IResource, byte[])
+ */
+ public IResourceVariant getResourceVariant(IResource resource, byte[] bytes) throws TeamException {
+ RepositoryProvider provider = RepositoryProvider.getProvider(resource.getProject(), FileSystemPlugin.PROVIDER_ID);
+ if (provider != null) {
+ return ((FileSystemProvider)provider).getResourceVariant(resource, bytes);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.ThreeWaySubscriber#createRemoteTree()
+ */
+ protected ThreeWayRemoteTree createRemoteTree() {
+ return new FileSystemRemoteTree(this);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.subscribers.Subscriber#getName()
+ */
+ public String getName() {
+ return "File System Example";
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.subscribers.Subscriber#roots()
+ */
+ public IResource[] roots() {
+ List result = new ArrayList();
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ for (int i = 0; i < projects.length; i++) {
+ IProject project = projects[i];
+ if(project.isAccessible()) {
+ RepositoryProvider provider = RepositoryProvider.getProvider(project, FileSystemPlugin.PROVIDER_ID);
+ if(provider != null) {
+ result.add(project);
+ }
+ }
+ }
+ return (IProject[]) result.toArray(new IProject[result.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.team.core.variants.ThreeWaySubscriber#handleRootChanged(org.eclipse.core.resources.IResource, boolean)
+ */
+ public void handleRootChanged(IResource resource, boolean added) {
+ // Override to allow FileSystemProvider to signal the addition and removal of roots
+ super.handleRootChanged(resource, added);
+ }
+
+}
diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/RemoteResourceTest.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/RemoteResourceTest.java
index eef4fa51e..425187f62 100644
--- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/RemoteResourceTest.java
+++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/RemoteResourceTest.java
@@ -19,7 +19,7 @@ import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.team.core.TeamException;
-import org.eclipse.team.core.synchronize.IResourceVariant;
+import org.eclipse.team.core.variants.IResourceVariant;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.resources.*;
import org.eclipse.team.internal.ccvs.ui.operations.CheckoutToRemoteFolderOperation;

Back to the top