KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > ui > operations > RemoteCompareOperation


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.team.internal.ccvs.ui.operations;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.HashSet JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Set JavaDoc;
18
19 import org.eclipse.compare.CompareUI;
20 import org.eclipse.core.runtime.*;
21 import org.eclipse.osgi.util.NLS;
22 import org.eclipse.swt.widgets.Display;
23 import org.eclipse.team.core.TeamException;
24 import org.eclipse.team.internal.ccvs.core.*;
25 import org.eclipse.team.internal.ccvs.core.client.*;
26 import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
27 import org.eclipse.team.internal.ccvs.core.client.listeners.RDiffSummaryListener;
28 import org.eclipse.team.internal.ccvs.core.resources.*;
29 import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
30 import org.eclipse.team.internal.ccvs.ui.*;
31 import org.eclipse.team.internal.ccvs.ui.Policy;
32 import org.eclipse.team.internal.ui.TeamUIPlugin;
33 import org.eclipse.ui.IWorkbenchPage;
34 import org.eclipse.ui.IWorkbenchPart;
35
36 /**
37  * Compare the two versions of given remote folders obtained from the two tags specified.
38  */

39 public class RemoteCompareOperation extends RemoteOperation {
40     
41     private CompareTreeBuilder builder;
42     private CVSTag left, right;
43     
44     /**
45      * Helper class for builder and comparing the resource trees
46      */

47     public static class CompareTreeBuilder implements RDiffSummaryListener.IFileDiffListener {
48         private ICVSRepositoryLocation location;
49         private RemoteFolderTree leftTree, rightTree;
50         private CVSTag left, right;
51
52         public CompareTreeBuilder(ICVSRepositoryLocation location, CVSTag left, CVSTag right) {
53             this.left = left;
54             this.right = right;
55             this.location = location;
56             reset();
57         }
58         
59         public RemoteFolderTree getLeftTree() {
60             return leftTree;
61         }
62         public RemoteFolderTree getRightTree() {
63             return rightTree;
64         }
65         
66         /**
67          * Reset the builder to prepare for a new build
68          */

69         public void reset() {
70             leftTree = new RemoteFolderTree(null, location, ICVSRemoteFolder.REPOSITORY_ROOT_FOLDER_NAME, left);
71             leftTree.setChildren(new ICVSRemoteResource[0]);
72             rightTree = new RemoteFolderTree(null, location, ICVSRemoteFolder.REPOSITORY_ROOT_FOLDER_NAME, right);
73             rightTree.setChildren(new ICVSRemoteResource[0]);
74         }
75         
76         /**
77          * Cache the contents for the files that are about to be compares
78          * @throws CVSException
79          */

80         public void cacheContents(IProgressMonitor monitor) throws CVSException {
81             String JavaDoc[] overlappingFilePaths = getOverlappingFilePaths();
82             if (overlappingFilePaths.length > 0) {
83                 monitor.beginTask(null, 100);
84                 fetchFileContents(leftTree, overlappingFilePaths, Policy.subMonitorFor(monitor, 50));
85                 fetchFileContents(rightTree, overlappingFilePaths, Policy.subMonitorFor(monitor, 50));
86                 monitor.done();
87             }
88         }
89         
90         /**
91          * Open the comparison in a compare editor
92          */

93         public void openCompareEditor(final IWorkbenchPage page, final String JavaDoc title, final String JavaDoc toolTip) {
94             if (leftTree == null || rightTree == null) return;
95             Display.getDefault().asyncExec(new Runnable JavaDoc() {
96                 public void run() {
97                     CompareUI.openCompareEditorOnPage(
98                         new CVSCompareEditorInput(title, toolTip, new ResourceEditionNode(leftTree), new ResourceEditionNode(rightTree)), page);
99                 }
100             });
101         }
102         
103         /**
104          * Add the predecessor to the left tree and the remote to the right tree.
105          * @param predecessor
106          * @param remote
107          */

108         public void addToTrees(ICVSRemoteFile predecessor, ICVSRemoteFile remote) {
109             if (remote != null) {
110                 try {
111                     Path filePath = new Path(null, remote.getRepositoryRelativePath());
112                     addFile(rightTree, right, filePath, remote.getRevision());
113                     getFolder(leftTree, left, filePath.removeLastSegments(1), Path.EMPTY);
114                 } catch (TeamException e) {
115                     CVSUIPlugin.log(e);
116                 }
117             }
118             if (predecessor != null) {
119                 try {
120                     Path filePath = new Path(null, predecessor.getRepositoryRelativePath());
121                     addFile(leftTree, left, filePath, predecessor.getRevision());
122                     getFolder(rightTree, right, filePath.removeLastSegments(1), Path.EMPTY);
123                 } catch (TeamException e) {
124                     CVSUIPlugin.log(e);
125                 }
126             }
127         }
128         
129         private void addFile(RemoteFolderTree tree, CVSTag tag, Path filePath, String JavaDoc revision) throws CVSException {
130             RemoteFolderTree parent = (RemoteFolderTree)getFolder(tree, tag, filePath.removeLastSegments(1), Path.EMPTY);
131             String JavaDoc name = filePath.lastSegment();
132             ICVSRemoteFile file = new RemoteFile(parent, 0, name, revision, null, getTag(revision, tag));
133             addChild(parent, file);
134         }
135         
136         private CVSTag getTag(String JavaDoc revision, CVSTag tag) {
137             if (tag == null) {
138                 tag = new CVSTag(revision, CVSTag.VERSION);
139             }
140             return tag;
141         }
142
143         /*
144          * Get the folder at the given path in the given tree, creating any missing folders as needed.
145          */

146         private ICVSRemoteFolder getFolder(RemoteFolderTree tree, CVSTag tag, IPath remoteFolderPath, IPath parentPath) throws CVSException {
147             if (remoteFolderPath.segmentCount() == 0) return tree;
148             String JavaDoc name = remoteFolderPath.segment(0);
149             ICVSResource child;
150             IPath childPath = parentPath.append(name);
151             if (tree.childExists(name)) {
152                 child = tree.getChild(name);
153             } else {
154                 child = new RemoteFolderTree(tree, tree.getRepository(), childPath.toString(), tag);
155                 ((RemoteFolderTree)child).setChildren(new ICVSRemoteResource[0]);
156                 addChild(tree, (ICVSRemoteResource)child);
157             }
158             return getFolder((RemoteFolderTree)child, tag, remoteFolderPath.removeFirstSegments(1), childPath);
159         }
160
161         private void addChild(RemoteFolderTree tree, ICVSRemoteResource resource) {
162             ICVSRemoteResource[] children = tree.getChildren();
163             ICVSRemoteResource[] newChildren;
164             if (children == null) {
165                 newChildren = new ICVSRemoteResource[] { resource };
166             } else {
167                 newChildren = new ICVSRemoteResource[children.length + 1];
168                 System.arraycopy(children, 0, newChildren, 0, children.length);
169                 newChildren[children.length] = resource;
170             }
171             tree.setChildren(newChildren);
172         }
173         
174         /* (non-Javadoc)
175          * @see org.eclipse.team.internal.ccvs.core.client.listeners.RDiffSummaryListener.IFileDiffListener#fileDiff(java.lang.String, java.lang.String, java.lang.String)
176          */

177         public void fileDiff(String JavaDoc remoteFilePath, String JavaDoc leftRevision, String JavaDoc rightRevision) {
178             try {
179                 addFile(rightTree, right, new Path(null, remoteFilePath), rightRevision);
180             } catch (CVSException e) {
181                 CVSUIPlugin.log(e);
182             }
183             try {
184                 addFile(leftTree, left, new Path(null, remoteFilePath), leftRevision);
185             } catch (CVSException e) {
186                 CVSUIPlugin.log(e);
187             }
188         }
189
190         /* (non-Javadoc)
191          * @see org.eclipse.team.internal.ccvs.core.client.listeners.RDiffSummaryListener.IFileDiffListener#newFile(java.lang.String, java.lang.String)
192          */

193         public void newFile(String JavaDoc remoteFilePath, String JavaDoc rightRevision) {
194             try {
195                 addFile(rightTree, right, new Path(null, remoteFilePath), rightRevision);
196             } catch (CVSException e) {
197                 CVSUIPlugin.log(e);
198             }
199         }
200
201         /* (non-Javadoc)
202          * @see org.eclipse.team.internal.ccvs.core.client.listeners.RDiffSummaryListener.IFileDiffListener#deletedFile(java.lang.String)
203          */

204         public void deletedFile(String JavaDoc remoteFilePath, String JavaDoc leftRevision) {
205             // The leftRevision may be null in which case the tag is used
206
try {
207                 addFile(leftTree, left, new Path(null, remoteFilePath), leftRevision);
208             } catch (CVSException e) {
209                 CVSUIPlugin.log(e);
210             }
211         }
212
213         /* (non-Javadoc)
214          * @see org.eclipse.team.internal.ccvs.core.client.listeners.RDiffSummaryListener.IFileDiffListener#directory(java.lang.String)
215          */

216         public void directory(String JavaDoc remoteFolderPath) {
217             try {
218                 getFolder(leftTree, left, new Path(null, remoteFolderPath), Path.EMPTY);
219             } catch (CVSException e) {
220                 CVSUIPlugin.log(e);
221             }
222             try {
223                 getFolder(rightTree, right, new Path(null, remoteFolderPath), Path.EMPTY);
224             } catch (CVSException e) {
225                 CVSUIPlugin.log(e);
226             }
227         }
228         
229         private String JavaDoc[] getOverlappingFilePaths() {
230             String JavaDoc[] leftFiles = getFilePaths(leftTree);
231             String JavaDoc[] rightFiles = getFilePaths(rightTree);
232             Set JavaDoc set = new HashSet JavaDoc();
233             for (int i = 0; i < rightFiles.length; i++) {
234                 String JavaDoc rightFile = rightFiles[i];
235                 for (int j = 0; j < leftFiles.length; j++) {
236                     String JavaDoc leftFile = leftFiles[j];
237                     if (leftFile.equals(rightFile)) {
238                         set.add(leftFile);
239                     }
240                 }
241             }
242             return (String JavaDoc[]) set.toArray(new String JavaDoc[set.size()]);
243         }
244
245         private void fetchFileContents(RemoteFolderTree tree, String JavaDoc[] overlappingFilePaths, IProgressMonitor monitor) throws CVSException {
246             FileContentCachingService.fetchFileContents(tree, overlappingFilePaths, monitor);
247         }
248
249         private String JavaDoc[] getFilePaths(RemoteFolderTree tree) {
250             ICVSRemoteResource[] children = tree.getChildren();
251             List JavaDoc result = new ArrayList JavaDoc();
252             for (int i = 0; i < children.length; i++) {
253                 ICVSRemoteResource resource = children[i];
254                 if (resource.isContainer()) {
255                     result.addAll(Arrays.asList(getFilePaths((RemoteFolderTree)resource)));
256                 } else {
257                     result.add(resource.getRepositoryRelativePath());
258                 }
259             }
260             return (String JavaDoc[]) result.toArray(new String JavaDoc[result.size()]);
261         }
262     }
263     
264     public static CVSTag getTag(ICVSRemoteResource resource) throws CVSException {
265         CVSTag tag = null;
266         try {
267             if (resource.isContainer()) {
268                 tag = ((ICVSRemoteFolder)resource).getTag();
269             } else {
270                 ICVSRemoteFile file = (ICVSRemoteFile)resource;
271                 String JavaDoc revision = file.getRevision();
272                 if (revision.equals(ResourceSyncInfo.ADDED_REVISION)) {
273                     ResourceSyncInfo info =file.getSyncInfo();
274                     if (info != null) tag = info.getTag();
275                 } else {
276                     tag = new CVSTag(revision, CVSTag.VERSION);
277                 }
278             }
279         } catch (TeamException e) {
280             throw CVSException.wrapException(e);
281         }
282         if (tag == null) tag = CVSTag.DEFAULT;
283         return tag;
284     }
285     
286     public static RemoteCompareOperation create(IWorkbenchPart part, ICVSRemoteResource remoteResource, CVSTag tag) throws CVSException {
287         CVSTag tag0 = getTag(remoteResource);
288         CVSTag tag1 = tag;
289         if (tag0.getType() == CVSTag.DATE && tag1.getType() == CVSTag.DATE) {
290             if (tag0.asDate().after(tag1.asDate())) {
291                 tag = tag0;
292                 remoteResource = remoteResource.forTag(tag1);
293             }
294         }
295         return new RemoteCompareOperation(part, remoteResource, tag);
296     }
297     
298     /**
299      * Compare two versions of the given remote resource.
300      * @param shell
301      * @param remoteResource the resource whose tags are being compared
302      * @param left the earlier tag (not null)
303      * @param right the later tag (not null)
304      */

305     protected RemoteCompareOperation(IWorkbenchPart part, ICVSRemoteResource remoteResource, CVSTag tag) {
306         super(part, new ICVSRemoteResource[] {remoteResource});
307         Assert.isNotNull(tag);
308         this.right = tag;
309         try {
310             this.left = getTag(remoteResource);
311         } catch (CVSException e) {
312             // This shouldn't happen but log it just in case
313
CVSProviderPlugin.log(e);
314         }
315         if (this.left == null) {
316             this.left = CVSTag.DEFAULT;
317         }
318         builder = new CompareTreeBuilder(remoteResource.getRepository(), left, right);
319     }
320
321     /*
322      * This command only supports the use of a single resource
323      */

324     private ICVSRemoteResource getRemoteResource() {
325         return getRemoteResources()[0];
326     }
327     
328     /* (non-Javadoc)
329      * @see org.eclipse.team.internal.ccvs.ui.operations.CVSOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
330      */

331     protected void execute(IProgressMonitor monitor) throws CVSException {
332         boolean fetchContents = CVSUIPlugin.getPlugin().getPluginPreferences().getBoolean(ICVSUIConstants.PREF_CONSIDER_CONTENTS);
333         monitor.beginTask(getTaskName(), 50 + (fetchContents ? 100 : 0));
334         try {
335             ICVSRemoteResource resource = getRemoteResource();
336             IStatus status = buildTrees(resource, Policy.subMonitorFor(monitor, 50));
337             if (status.isOK() && fetchContents) {
338                 builder.cacheContents(Policy.subMonitorFor(monitor, 100));
339             }
340             collectStatus(status);
341             openCompareEditor(builder);
342         } finally {
343             monitor.done();
344         }
345     }
346
347     /**
348      * This method is here to allow subclasses to override
349      */

350     protected void openCompareEditor(CompareTreeBuilder builder) {
351         builder.openCompareEditor(getTargetPage(), null, null);
352     }
353
354     /*
355      * Build the two trees uses the reponses from "cvs rdiff -s ...".
356      */

357     private IStatus buildTrees(ICVSRemoteResource resource, IProgressMonitor monitor) throws CVSException {
358         // Initialize the resulting trees
359
builder.reset();
360         Command.QuietOption oldOption= CVSProviderPlugin.getPlugin().getQuietness();
361         Session session = new Session(resource.getRepository(), builder.getLeftTree(), false);
362         try {
363             monitor.beginTask(getTaskName(), 100);
364             CVSProviderPlugin.getPlugin().setQuietness(Command.VERBOSE);
365             session.open(Policy.subMonitorFor(monitor, 10));
366             IStatus status = Command.RDIFF.execute(session,
367                     Command.NO_GLOBAL_OPTIONS,
368                     getLocalOptions(),
369                     new ICVSResource[] { resource },
370                     new RDiffSummaryListener(builder),
371                     Policy.subMonitorFor(monitor, 90));
372             return status;
373         } finally {
374             try {
375                 session.close();
376             } finally {
377                 CVSProviderPlugin.getPlugin().setQuietness(oldOption);
378             }
379             monitor.done();
380         }
381     }
382
383     private LocalOption[] getLocalOptions() {
384         return new LocalOption[] {RDiff.SUMMARY, RDiff.makeTagOption(left), RDiff.makeTagOption(right)};
385     }
386
387     /* (non-Javadoc)
388      * @see org.eclipse.team.internal.ccvs.ui.operations.CVSOperation#getTaskName()
389      */

390     protected String JavaDoc getTaskName() {
391         return NLS.bind(CVSUIMessages.RemoteCompareOperation_0, (new Object JavaDoc[] {left.getName(), right.getName(), getRemoteResource().getRepositoryRelativePath()}));
392     }
393     
394     protected IWorkbenchPage getTargetPage() {
395         return TeamUIPlugin.getActivePage();
396     }
397 }
398
Popular Tags