KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > core > ChangeTracker


1 /*******************************************************************************
2  * Copyright (c) 2005, 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.core;
12
13 import java.util.*;
14
15 import org.eclipse.core.resources.*;
16 import org.eclipse.core.runtime.CoreException;
17 import org.eclipse.core.runtime.IAdaptable;
18 import org.eclipse.team.core.RepositoryProvider;
19 import org.eclipse.team.core.RepositoryProviderType;
20 import org.eclipse.team.internal.core.subscribers.ActiveChangeSet;
21 import org.eclipse.team.internal.core.subscribers.ActiveChangeSetManager;
22
23 /**
24  * Track changes to plugin projects so that changes to any of the manifest files
25  * will be grouped together for the purposes of committing.
26  *
27  * @since 3.2
28  */

29 public abstract class ChangeTracker implements IResourceChangeListener, IRepositoryProviderListener {
30
31     private Map trackedProjects = new HashMap(); // Map IProject->SubscriberChanegSetCollector
32
private boolean disposed;
33     
34     /**
35      * Create a change tracker
36      */

37     public ChangeTracker() {
38         super();
39     }
40
41     /**
42      * Start tracking changes. This registers listeners with the workspace
43      * and team.
44      */

45     public void start() {
46         ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
47         RepositoryProviderManager.getInstance().addListener(this);
48         IProject[] allProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
49         for (int i = 0; i < allProjects.length; i++) {
50             IProject project = allProjects[i];
51             if (isProjectOfInterest(project))
52                 trackProject(project);
53         }
54     }
55
56     /**
57      * Remove any listeners for this tracker. Subclasses
58      * may extend this method but must call this method if they do.
59      */

60     public void dispose() {
61         disposed = true;
62         ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
63         RepositoryProviderManager.getInstance().removeListener(this);
64     }
65     
66     /**
67      * Handle a resource change event.
68      * Update the set of projects for which we can track changes
69      * by listening for project changes and project description changes.
70      * @param event the change event
71      */

72     public void resourceChanged(IResourceChangeEvent event) {
73         if (disposed) return;
74         IResourceDelta delta = event.getDelta();
75         IResourceDelta[] projectDeltas = delta.getAffectedChildren(IResourceDelta.ADDED | IResourceDelta.CHANGED | IResourceDelta.REMOVED);
76         for (int i = 0; i < projectDeltas.length; i++) {
77             IResourceDelta projectDelta = projectDeltas[i];
78             IResource resource = projectDelta.getResource();
79             if (resource.getType() == IResource.PROJECT) {
80                 IProject project = (IProject)resource;
81                 if (isProjectOfInterest(project)) {
82                     if (isProjectTracked(project)) {
83                         IResource[] resources = getProjectChanges(project, projectDelta);
84                         if (resources.length > 0)
85                             handleChanges(project, resources);
86                     } else {
87                         trackProject(project);
88                     }
89                 } else {
90                     stopTrackingProject(project);
91                 }
92             }
93         }
94     }
95
96     private IResource[] getProjectChanges(IProject project, IResourceDelta projectDelta) {
97         final List result = new ArrayList();
98         try {
99             projectDelta.accept(new IResourceDeltaVisitor() {
100                 public boolean visit(IResourceDelta delta) throws CoreException {
101                     if (isResourceOfInterest(delta.getResource()) & isChangeOfInterest(delta)) {
102                         result.add(delta.getResource());
103                     }
104                     return true;
105                 }
106             });
107         } catch (CoreException e) {
108             TeamPlugin.log(e);
109         }
110         return (IResource[]) result.toArray(new IResource[result.size()]);
111     }
112
113     /**
114      * Return whether the given delta represents a change of interest.
115      * @param delta the delta
116      * @return whether the given delta represents a change of interest
117      */

118     protected boolean isChangeOfInterest(IResourceDelta delta) {
119         return (delta.getKind() & (IResourceDelta.ADDED | IResourceDelta.REMOVED | IResourceDelta.CHANGED)) > 0;
120     }
121
122     /**
123      * Stop tracking changes for the given project. Subclasses
124      * may extend but must call this method.
125      * @param project the project
126      */

127     protected void stopTrackingProject(IProject project) {
128         trackedProjects.remove(project);
129     }
130
131     /**
132      * Return whether the given project is being tracked.
133      * @param project the project
134      * @return whether the given project is being tracked
135      */

136     protected final boolean isProjectTracked(IProject project) {
137         return trackedProjects.containsKey(project);
138     }
139
140     /**
141      * Return whether the given project is of interest to this
142      * tracker. By default, <code>true</code> is returned if the
143      * project is accessible. Subclasses may extend but should
144      * still check for project accessibility either by calling
145      * {@link IResource#isAccessible()} or by invoking the
146      * overridden method.
147      * @param project the project
148      * @return whether the given project is of interest to this
149      * tracker
150      */

151     protected boolean isProjectOfInterest(IProject project) {
152         return project.isAccessible();
153     }
154
155     /**
156      * When a project is shared, start tracking it if it is of interest.
157      * @param provider the repository provider
158      */

159     public void providerMapped(RepositoryProvider provider) {
160         if (disposed) return;
161         if (isProjectOfInterest(provider.getProject())) {
162             trackProject(provider.getProject());
163         }
164     }
165
166     /**
167      * When a project is no longer shared, stop tracking the project.
168      * @param project the project
169      */

170     public void providerUnmapped(IProject project) {
171         if (disposed) return;
172         stopTrackingProject(project);
173     }
174
175     /**
176      * Return whether the given resource is of interest to the tracker.
177      * @param resource the resource
178      * @return whether the given resource is of interest to the tracker
179      */

180     protected abstract boolean isResourceOfInterest(IResource resource);
181
182     /**
183      * The given resources of interest have changed in the given project.
184      * @param project the project
185      * @param resources the resources
186      */

187     protected abstract void handleChanges(IProject project, IResource[] resources);
188
189     /**
190      * Resources of interest in the given project have changed but the
191      * specific changes are not known. Implementors must search the project for
192      * changes of interest.
193      * @param project the project
194      */

195     protected abstract void handleProjectChange(IProject project);
196
197     /**
198      * Track the given project if it has a change set collector. If the project
199      * does not have a collector, the project is not tracked.
200      * @param project the project
201      * @return whether the project is being tracked
202      */

203     protected final boolean trackProject(IProject project) {
204         if (RepositoryProvider.isShared(project)) {
205             try {
206                 String JavaDoc currentId = project.getPersistentProperty(TeamPlugin.PROVIDER_PROP_KEY);
207                 if (currentId != null) {
208                     RepositoryProviderType type = RepositoryProviderType.getProviderType(currentId);
209                     if (type != null) {
210                         ActiveChangeSetManager collector = getCollector(type);
211                         if (collector != null) {
212                             trackedProjects.put(project, collector);
213                             // Ensure that an appropriate change set exists if needed
214
// We can do this here because we know that the number of files
215
// to test is small.
216
projectTracked(project);
217                             return true;
218                         }
219                     }
220                 }
221             } catch (CoreException e) {
222                 TeamPlugin.log(e);
223             }
224         }
225         return false;
226     }
227
228     private ActiveChangeSetManager getCollector(RepositoryProviderType type) {
229         if (type instanceof IAdaptable) {
230             IAdaptable adaptable = (IAdaptable) type;
231             Object JavaDoc o = adaptable.getAdapter(ActiveChangeSetManager.class);
232             if (o instanceof ActiveChangeSetManager) {
233                 return (ActiveChangeSetManager) o;
234             }
235         }
236         return null;
237     }
238
239     /**
240      * Callback made from {@link #trackProject(IProject)} when a project is tracked.
241      * By default, {@link #handleProjectChange(IProject)} is called by subclasses may override.
242      * @param project the project
243      */

244     protected void projectTracked(IProject project) {
245         handleProjectChange(project);
246     }
247     
248     /**
249      * Group the given modified file into a change set with the given name.
250      * @param project the project
251      * @param name the unique name used to identify the change set
252      * @param files the change files to be grouped
253      * @throws CoreException
254      */

255     protected void groupAsSet(IProject project, String JavaDoc name, IFile[] files) throws CoreException {
256         ActiveChangeSetManager collector = getCollector(project);
257         if (collector != null) {
258             ActiveChangeSet set = collector.getSet(name);
259             if (set == null) {
260                 set = collector.createSet(name, files);
261                 set.setUserCreated(false);
262                 collector.add(set);
263             } else {
264                 set.setUserCreated(false);
265                 set.add(files);
266             }
267         }
268     }
269
270     private ActiveChangeSetManager getCollector(IProject project) {
271         return (ActiveChangeSetManager)trackedProjects.get(project);
272     }
273     
274     /**
275      * Return whether the given file is modified with respect to the
276      * repository provider associated with the file's project.
277      * @param file the file
278      * @return whether the given file is modified
279      * @throws CoreException
280      */

281     protected boolean isModified(IFile file) throws CoreException {
282         ActiveChangeSetManager collector = getCollector(file.getProject());
283         if (collector != null)
284             return collector.isModified(file);
285         return false;
286     }
287
288 }
289
Popular Tags