KickJava   Java API By Example, From Geeks To Geeks.

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


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.lang.reflect.InvocationTargetException JavaDoc;
14 import java.util.ArrayList JavaDoc;
15 import java.util.Arrays JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Map JavaDoc;
20 import java.util.Set JavaDoc;
21
22 import org.eclipse.core.resources.IProject;
23 import org.eclipse.core.resources.IResource;
24 import org.eclipse.core.resources.mapping.*;
25 import org.eclipse.core.runtime.*;
26 import org.eclipse.core.runtime.jobs.ISchedulingRule;
27 import org.eclipse.jface.action.IAction;
28 import org.eclipse.team.core.RepositoryProvider;
29 import org.eclipse.team.core.TeamException;
30 import org.eclipse.team.core.mapping.ISynchronizationScope;
31 import org.eclipse.team.core.mapping.ISynchronizationScopeManager;
32 import org.eclipse.team.core.mapping.provider.SynchronizationScopeManager;
33 import org.eclipse.team.internal.ccvs.core.*;
34 import org.eclipse.team.internal.ccvs.core.client.Command;
35 import org.eclipse.team.internal.ccvs.core.client.Session;
36 import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
37 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
38 import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
39 import org.eclipse.team.internal.ccvs.ui.Policy;
40 import org.eclipse.team.internal.ui.mapping.BuildScopeOperation;
41 import org.eclipse.ui.IWorkbenchPart;
42
43 /**
44  * Performs a cvs operation on multiple repository providers
45  */

46 public abstract class RepositoryProviderOperation extends CVSOperation {
47
48     /**
49      * Flag to indicate whether models are to be consulted when building
50      * the scope. This is provided for testing purposes and is not expected
51      * to be used otherwise.
52      */

53     public static boolean consultModelsWhenBuildingScope = true;
54     
55     private ISynchronizationScopeManager manager;
56     private final ResourceMapping[] selectedMappings;
57     
58     /**
59      * Interface that is available to sublcasses which identifies
60      * the depth for various resources. The files will be included
61      * in whichever group (deep or shallow) has resources.
62      */

63     public interface ICVSTraversal {
64         IResource[] getShallowResources();
65         IResource[] getDeepResources();
66         IResource[] getNontraversedFolders();
67     }
68     
69     /*
70      * A map entry for a provider that divides the traversals to be performed by depth.
71      * There are really only
72      */

73     private static class TraversalMapEntry implements ICVSTraversal {
74         // The provider for this entry
75
RepositoryProvider provider;
76         // Files are always shallow
77
List JavaDoc files = new ArrayList JavaDoc();
78         // Not sure what to do with zero depth folders but we'll record them
79
List JavaDoc zeroFolders = new ArrayList JavaDoc();
80         // Non-recursive folder (-l)
81
List JavaDoc shallowFolders = new ArrayList JavaDoc();
82         // Recursive folders (-R)
83
List JavaDoc deepFolders = new ArrayList JavaDoc();
84         public TraversalMapEntry(RepositoryProvider provider) {
85             this.provider = provider;
86         }
87         /**
88          * Add the resources from the traversals to the entry
89          * @param traversals the traversals
90          */

91         public void add(ResourceTraversal[] traversals) {
92             for (int i = 0; i < traversals.length; i++) {
93                 ResourceTraversal traversal = traversals[i];
94                 add(traversal);
95             }
96         }
97         /**
98          * Add the resources from the traversal to the entry
99          * @param traversal the traversal
100          */

101         public void add(ResourceTraversal traversal) {
102             IResource[] resources = traversal.getResources();
103             for (int i = 0; i < resources.length; i++) {
104                 IResource resource = resources[i];
105                 if (resource.getProject().equals(provider.getProject())) {
106                     if (resource.getType() == IResource.FILE) {
107                         files.add(resource);
108                     } else {
109                         switch (traversal.getDepth()) {
110                         case IResource.DEPTH_ZERO:
111                             zeroFolders.add(resource);
112                             break;
113                         case IResource.DEPTH_ONE:
114                             shallowFolders.add(resource);
115                             break;
116                         case IResource.DEPTH_INFINITE:
117                             deepFolders.add(resource);
118                             break;
119                         default:
120                             deepFolders.add(resource);
121                         }
122                     }
123                 }
124             }
125         }
126         /**
127          * Return the resources that can be included in a shallow operation.
128          * Include files with the shallow resources if there are shallow folders
129          * or if there are no shallow or deep folders.
130          * @return the resources that can be included in a shallow operation
131          */

132         public IResource[] getShallowResources() {
133             if (shallowFolders.isEmpty() && deepFolders.isEmpty() && !files.isEmpty()) {
134                 return (IResource[]) files.toArray(new IResource[files.size()]);
135             }
136             if (!shallowFolders.isEmpty()) {
137                 if (files.isEmpty()) {
138                     return (IResource[]) shallowFolders.toArray(new IResource[shallowFolders.size()]);
139                 }
140                 List JavaDoc result = new ArrayList JavaDoc();
141                 result.addAll(shallowFolders);
142                 result.addAll(files);
143                 return (IResource[]) result.toArray(new IResource[result.size()]);
144             }
145             return new IResource[0];
146         }
147         /**
148          * Return the resources to be included in a deep operation.
149          * If there are no shallow folders, this will include any files.
150          * @return
151          */

152         public IResource[] getDeepResources() {
153             if (deepFolders.isEmpty())
154                 return new IResource[0];
155             if (!shallowFolders.isEmpty())
156                 return (IResource[]) deepFolders.toArray(new IResource[deepFolders.size()]);
157             List JavaDoc result = new ArrayList JavaDoc();
158             result.addAll(deepFolders);
159             result.addAll(files);
160             return (IResource[]) result.toArray(new IResource[result.size()]);
161         }
162         /**
163          * Return the folders that are depth zero
164          */

165         public IResource[] getNontraversedFolders() {
166             return (IResource[]) zeroFolders.toArray(new IResource[zeroFolders.size()]);
167         }
168     }
169
170     
171     /**
172      * Convert the provided resources to one or more resource mappers
173      * that traverse the elements deeply. The model element of the resource
174      * mappers will be an IStructuredSelection.
175      * @param resources the resources
176      * @return a resource mappers that traverses the resources
177      */

178     public static ResourceMapping[] asResourceMappers(final IResource[] resources) {
179         return asResourceMappers(resources, IResource.DEPTH_INFINITE);
180     }
181     
182     /**
183      * Convert the provided resources to one or more resource mappers
184      * that traverse the elements deeply. The model element of the resource
185      * mappers will be an IStructuredSelection.
186      * @param resources the resources
187      * @return a resource mappers that traverses the resources
188      */

189     public static ResourceMapping[] asResourceMappers(final IResource[] resources, int depth) {
190         return WorkspaceResourceMapper.asResourceMappers(resources, depth);
191     }
192     
193     public RepositoryProviderOperation(IWorkbenchPart part, final IResource[] resources) {
194         this(part, asResourceMappers(resources));
195     }
196
197     public RepositoryProviderOperation(IWorkbenchPart part, ResourceMapping[] selectedMappings) {
198         super(part);
199         this.selectedMappings = selectedMappings;
200     }
201
202     /* (non-Javadoc)
203      * @see org.eclipse.team.internal.ccvs.ui.operations.CVSOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
204      */

205     public void execute(IProgressMonitor monitor) throws CVSException, InterruptedException JavaDoc {
206         try {
207             monitor.beginTask(null, 100);
208             buildScope(monitor);
209             Map JavaDoc table = getProviderTraversalMapping(Policy.subMonitorFor(monitor, 30));
210             execute(table, Policy.subMonitorFor(monitor, 30));
211         } catch (CoreException e) {
212             throw CVSException.wrapException(e);
213         } finally {
214             monitor.done();
215         }
216     }
217     
218     protected void endOperation() throws CVSException {
219         if (manager != null) {
220             manager.dispose();
221             manager = null;
222         }
223         super.endOperation();
224     }
225
226     public ISynchronizationScope buildScope(IProgressMonitor monitor) throws InterruptedException JavaDoc, CVSException {
227         if (manager == null) {
228             manager = createScopeManager(consultModelsWhenBuildingScope && consultModelsForMappings());
229             BuildScopeOperation op = new BuildScopeOperation(getPart(), manager);
230             try {
231                 op.run(monitor);
232             } catch (InvocationTargetException JavaDoc e) {
233                 throw CVSException.wrapException(e);
234             }
235         }
236         return manager.getScope();
237     }
238
239     /**
240      * Create the scope manager to be used by this operation.
241      * @param consultModels whether models should be consulted to include additional mappings
242      * @return a scope manager
243      */

244     protected SynchronizationScopeManager createScopeManager(boolean consultModels) {
245         return new SynchronizationScopeManager(getJobName(), getSelectedMappings(), getResourceMappingContext(), consultModels);
246     }
247
248     private void execute(Map JavaDoc providerTraversal, IProgressMonitor monitor) throws CVSException, InterruptedException JavaDoc {
249         Set JavaDoc keySet = providerTraversal.keySet();
250         monitor.beginTask(null, keySet.size() * 1000);
251         Iterator JavaDoc iterator = keySet.iterator();
252         while (iterator.hasNext()) {
253             CVSTeamProvider provider = (CVSTeamProvider)iterator.next();
254             monitor.setTaskName(getTaskName(provider));
255             TraversalMapEntry entry = (TraversalMapEntry)providerTraversal.get(provider);
256             execute(provider, entry, Policy.subMonitorFor(monitor, 1000));
257         }
258     }
259
260     /**
261      * Execute the operation on the given set of traversals
262      * @param provider
263      * @param entry
264      * @param subMonitor
265      * @throws CVSException
266      * @throws InterruptedException
267      */

268     protected void execute(CVSTeamProvider provider, ICVSTraversal entry, IProgressMonitor monitor) throws CVSException, InterruptedException JavaDoc {
269         IResource[] deepResources = entry.getDeepResources();
270         IResource[] shallowResources = entry.getShallowResources();
271         IResource[] nontraversedFolders = entry.getNontraversedFolders();
272         try {
273             monitor.beginTask(getTaskName(provider), (deepResources.length > 0 ? 100 : 0) + (shallowResources.length > 0 ? 100 : 0) + (nontraversedFolders.length > 0 ? 10 : 0));
274             if (deepResources.length == 0 && shallowResources.length == 0 && nontraversedFolders.length == 0)
275                 return;
276             final ISchedulingRule rule = getSchedulingRule(provider);
277             try {
278                 Platform.getJobManager().beginRule(rule, monitor);
279                 if (deepResources.length > 0)
280                     execute(provider, deepResources, true /* recurse */, Policy.subMonitorFor(monitor, 100));
281                 if (shallowResources.length > 0)
282                     execute(provider, shallowResources, false /* recurse */, Policy.subMonitorFor(monitor, 100));
283                 if (nontraversedFolders.length > 0) {
284                     handleNontraversedFolders(provider, nontraversedFolders, Policy.subMonitorFor(monitor, 10));
285                 }
286             } finally {
287                 Platform.getJobManager().endRule(rule);
288             }
289         } finally {
290             monitor.done();
291         }
292     }
293     
294     /**
295      * Handle any non-traversed (depth-zero) folders that were in the logical modle that primed this operation.
296      * @param provider the repository provider associated with the project containing the folders
297      * @param nontraversedFolders the folders
298      * @param monitor a progress monitor
299      */

300     protected void handleNontraversedFolders(CVSTeamProvider provider, IResource[] nontraversedFolders, IProgressMonitor monitor) throws CVSException {
301         // Default is do nothing
302
}
303
304     /**
305      * Return the taskname to be shown in the progress monitor while operating
306      * on the given provider.
307      * @param provider the provider being processed
308      * @return the taskname to be shown in the progress monitor
309      */

310     protected abstract String JavaDoc getTaskName(CVSTeamProvider provider);
311
312     /**
313      * Retgurn the scheduling rule to be obtained before work
314      * begins on the given provider. By default, it is the provider's project.
315      * This can be changed by subclasses.
316      * @param provider
317      * @return
318      */

319     protected ISchedulingRule getSchedulingRule(CVSTeamProvider provider) {
320         return provider.getProject();
321     }
322
323     /*
324      * Helper method. Return a Map mapping provider to a list of resources
325      * shared with that provider.
326      */

327     private Map JavaDoc getProviderTraversalMapping(IProgressMonitor monitor) throws CoreException {
328         Map JavaDoc result = new HashMap JavaDoc();
329         ResourceMapping[] mappings = getScope().getMappings();
330         for (int j = 0; j < mappings.length; j++) {
331             ResourceMapping mapping = mappings[j];
332             IProject[] projects = mapping.getProjects();
333             ResourceTraversal[] traversals = getScope().getTraversals(mapping);
334             for (int k = 0; k < projects.length; k++) {
335                 IProject project = projects[k];
336                 RepositoryProvider provider = RepositoryProvider.getProvider(project, CVSProviderPlugin.getTypeId());
337                 if (provider != null) {
338                     TraversalMapEntry entry = (TraversalMapEntry)result.get(provider);
339                     if (entry == null) {
340                         entry = new TraversalMapEntry(provider);
341                         result.put(provider, entry);
342                     }
343                     entry.add(traversals);
344                 }
345             }
346         }
347         return result;
348     }
349
350     /**
351      * Return the resource mapping context that is to be usd by this operation.
352      * By defautl, <code>null</code> is returned but subclasses may override
353      * to provide a specific context.
354      * @return the resource mapping context for this operaton
355      */

356     protected ResourceMappingContext getResourceMappingContext() {
357         return ResourceMappingContext.LOCAL_CONTEXT;
358     }
359
360     /**
361      * Execute the operation on the resources for the given provider.
362      * @param provider the provider for the project that contains the resources
363      * @param resources the resources to be operated on
364      * @param recurse whether the operation is deep or shallow
365      * @param monitor a progress monitor
366      * @throws CVSException
367      * @throws InterruptedException
368      */

369     protected abstract void execute(CVSTeamProvider provider, IResource[] resources, boolean recurse, IProgressMonitor monitor) throws CVSException, InterruptedException JavaDoc;
370
371     /**
372      * Return the local options for this operation including the
373      * option to provide the requested traversal.
374      * @param recurse deep or shallow
375      * @return the local options for the operation
376      */

377     protected LocalOption[] getLocalOptions(boolean recurse) {
378         if (!recurse) {
379             return new LocalOption[] { Command.DO_NOT_RECURSE };
380         }
381         return Command.NO_LOCAL_OPTIONS;
382     }
383     
384     protected ICVSResource[] getCVSArguments(IResource[] resources) {
385         ICVSResource[] cvsResources = new ICVSResource[resources.length];
386         for (int i = 0; i < cvsResources.length; i++) {
387             cvsResources[i] = CVSWorkspaceRoot.getCVSResourceFor(resources[i]);
388         }
389         return cvsResources;
390     }
391     
392     /*
393      * Get the arguments to be passed to a commit or update
394      */

395     protected String JavaDoc[] getStringArguments(IResource[] resources) throws CVSException {
396         List JavaDoc arguments = new ArrayList JavaDoc(resources.length);
397         for (int i=0;i<resources.length;i++) {
398             IPath cvsPath = resources[i].getFullPath().removeFirstSegments(1);
399             if (cvsPath.segmentCount() == 0) {
400                 arguments.add(Session.CURRENT_LOCAL_FOLDER);
401             } else {
402                 arguments.add(cvsPath.toString());
403             }
404         }
405         return (String JavaDoc[])arguments.toArray(new String JavaDoc[arguments.size()]);
406     }
407     
408     protected ICVSRepositoryLocation getRemoteLocation(CVSTeamProvider provider) throws CVSException {
409         CVSWorkspaceRoot workspaceRoot = provider.getCVSWorkspaceRoot();
410         return workspaceRoot.getRemoteLocation();
411     }
412     
413     protected ICVSFolder getLocalRoot(CVSTeamProvider provider) throws CVSException {
414         CVSWorkspaceRoot workspaceRoot = provider.getCVSWorkspaceRoot();
415         return workspaceRoot.getLocalRoot();
416     }
417
418     /**
419      * Update the workspace subscriber for an update operation performed on the
420      * given resources. After an update, the remote tree is flushed in order
421      * to ensure that stale incoming additions are removed. This need only
422      * be done for folders. At the time of writting, all update operations
423      * are deep so the flush is deep as well.
424      * @param provider the provider (projedct) for all the given resources
425      * @param resources the resources that were updated
426      * @param recurse
427      * @param monitor a progress monitor
428      */

429     protected void updateWorkspaceSubscriber(CVSTeamProvider provider, ICVSResource[] resources, boolean recurse, IProgressMonitor monitor) {
430         CVSWorkspaceSubscriber s = CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber();
431         monitor.beginTask(null, 100 * resources.length);
432         for (int i = 0; i < resources.length; i++) {
433             ICVSResource resource = resources[i];
434             if (resource.isFolder()) {
435                 try {
436                     s.updateRemote(provider, (ICVSFolder)resource, recurse, Policy.subMonitorFor(monitor, 100));
437                 } catch (TeamException e) {
438                     // Just log the error and continue
439
CVSUIPlugin.log(e);
440                 }
441             } else {
442                 monitor.worked(100);
443             }
444         }
445     }
446     
447     /* (non-Javadoc)
448      * @see org.eclipse.team.ui.TeamOperation#isKeepOneProgressServiceEntry()
449      */

450     public boolean isKeepOneProgressServiceEntry() {
451         // Keep the last repository provider operation in the progress service
452
return true;
453     }
454     
455     /* (non-Javadoc)
456      * @see org.eclipse.team.ui.TeamOperation#getGotoAction()
457      */

458     protected IAction getGotoAction() {
459         return getShowConsoleAction();
460     }
461     
462     /**
463      * Return the root resources for all the traversals of this operation.
464      * Tis method may only be invoked after {@link #buildScope(IProgressMonitor) }.
465      * @return the root resources for all the traversals of this operation
466      * @throws CoreException
467      */

468     protected IResource[] getTraversalRoots() {
469         List JavaDoc result = new ArrayList JavaDoc();
470         ResourceTraversal[] traversals = getTraversals();
471         for (int i = 0; i < traversals.length; i++) {
472             ResourceTraversal traversal = traversals[i];
473             result.addAll(Arrays.asList(traversal.getResources()));
474         }
475         return (IResource[]) result.toArray(new IResource[result.size()]);
476     }
477     
478     /**
479      * Return the traversals that will be used by this operation.
480      * This method can only be called after {@link #buildScope(IProgressMonitor) }.
481      * @return the traversals that will be used by this operation
482      * @throws CoreException
483      */

484     public ResourceTraversal[] getTraversals() {
485         return getScope().getTraversals();
486     }
487     
488     public boolean consultModelsForMappings() {
489         return true;
490     }
491
492     public ResourceMapping[] getSelectedMappings() {
493         return selectedMappings;
494     }
495
496     public ISynchronizationScope getScope() {
497         return manager.getScope();
498     }
499
500     public ISynchronizationScopeManager getScopeManager() {
501         return manager;
502     }
503 }
504
Popular Tags