1 11 package org.eclipse.team.internal.core.subscribers; 12 13 import java.util.ArrayList ; 14 import java.util.List ; 15 16 import org.eclipse.core.resources.IResource; 17 import org.eclipse.core.resources.IWorkspaceRunnable; 18 import org.eclipse.core.resources.mapping.ResourceMapping; 19 import org.eclipse.core.resources.mapping.ResourceTraversal; 20 import org.eclipse.core.runtime.*; 21 import org.eclipse.core.runtime.jobs.IJobChangeEvent; 22 import org.eclipse.core.runtime.jobs.Job; 23 import org.eclipse.osgi.util.NLS; 24 import org.eclipse.team.core.ITeamStatus; 25 import org.eclipse.team.core.TeamException; 26 import org.eclipse.team.core.mapping.ISynchronizationScope; 27 import org.eclipse.team.core.mapping.ISynchronizationScopeChangeListener; 28 import org.eclipse.team.core.subscribers.Subscriber; 29 import org.eclipse.team.internal.core.*; 30 31 38 public abstract class SubscriberEventHandler extends BackgroundEventHandler { 39 40 private List resultCache = new ArrayList (); 42 43 private boolean started = false; 44 private boolean initializing = true; 45 46 private IProgressMonitor progressGroup; 47 48 private int ticks; 49 50 private final Subscriber subscriber; 51 private ISynchronizationScope scope; 52 53 private ISynchronizationScopeChangeListener scopeChangeListener; 54 55 58 class SubscriberEvent extends ResourceEvent{ 59 static final int REMOVAL = 1; 60 static final int CHANGE = 2; 61 static final int INITIALIZE = 3; 62 63 SubscriberEvent(IResource resource, int type, int depth) { 64 super(resource, type, depth); 65 } 66 protected String getTypeString() { 67 switch (getType()) { 68 case REMOVAL : 69 return "REMOVAL"; case CHANGE : 71 return "CHANGE"; case INITIALIZE : 73 return "INITIALIZE"; default : 75 return "INVALID"; } 77 } 78 public ResourceTraversal asTraversal() { 79 return new ResourceTraversal(new IResource[] { getResource() }, getDepth(), IResource.NONE); 80 } 81 } 82 83 89 public SubscriberEventHandler(Subscriber subscriber, ISynchronizationScope scope) { 90 super( 91 NLS.bind(Messages.SubscriberEventHandler_jobName, new String [] { subscriber.getName() }), 92 NLS.bind(Messages.SubscriberEventHandler_errors, new String [] { subscriber.getName() })); 93 this.subscriber = subscriber; 94 this.scope = scope; 95 scopeChangeListener = new ISynchronizationScopeChangeListener() { 96 public void scopeChanged(ISynchronizationScope scope, 97 ResourceMapping[] newMappings, 98 ResourceTraversal[] newTraversals) { 99 reset(new ResourceTraversal[0], scope.getTraversals()); 100 } 101 }; 102 this.scope.addScopeChangeListener(scopeChangeListener); 103 } 104 105 110 protected synchronized void reset(ResourceTraversal[] oldTraversals, ResourceTraversal[] newTraversals) { 111 reset(newTraversals, SubscriberEvent.CHANGE); 112 } 113 114 118 public synchronized void start() { 119 started = true; 122 ResourceTraversal[] traversals = scope.getTraversals(); 123 reset(traversals, SubscriberEvent.INITIALIZE); 124 initializing = false; 125 } 126 127 protected synchronized void queueEvent(Event event, boolean front) { 128 if (started) { 130 super.queueEvent(event, front); 131 } 132 } 133 136 public void schedule() { 137 Job job = getEventHandlerJob(); 138 if (job.getState() == Job.NONE) { 139 if(progressGroup != null) { 140 job.setSystem(false); 141 job.setProgressGroup(progressGroup, ticks); 142 } else { 143 job.setSystem(isSystemJob()); 144 } 145 } 146 getEventHandlerJob().schedule(); 147 } 148 149 protected boolean isSystemJob() { 150 return !initializing; 151 } 152 153 154 157 protected void jobDone(IJobChangeEvent event) { 158 super.jobDone(event); 159 progressGroup = null; 160 } 161 162 168 public void change(IResource resource, int depth) { 169 queueEvent(new SubscriberEvent(resource, SubscriberEvent.CHANGE, depth), false); 170 } 171 172 177 public void remove(IResource resource) { 178 queueEvent( 179 new SubscriberEvent(resource, SubscriberEvent.REMOVAL, IResource.DEPTH_INFINITE), false); 180 } 181 182 186 private void collect( 187 IResource resource, 188 int depth, 189 IProgressMonitor monitor) { 190 191 Policy.checkCanceled(monitor); 192 193 handlePreemptiveEvents(monitor); 195 196 if (resource.getType() != IResource.FILE 197 && depth != IResource.DEPTH_ZERO) { 198 try { 199 IResource[] members = 200 getSubscriber().members(resource); 201 for (int i = 0; i < members.length; i++) { 202 collect( 203 members[i], 204 depth == IResource.DEPTH_INFINITE 205 ? IResource.DEPTH_INFINITE 206 : IResource.DEPTH_ZERO, 207 monitor); 208 } 209 } catch (TeamException e) { 210 if (resource.getProject().isAccessible()) 213 handleException(e, resource, ITeamStatus.SYNC_INFO_SET_ERROR, NLS.bind(Messages.SubscriberEventHandler_8, new String [] { resource.getFullPath().toString(), e.getMessage() })); 214 } 215 } 216 217 monitor.subTask(NLS.bind(Messages.SubscriberEventHandler_2, new String [] { resource.getFullPath().toString() })); 218 try { 219 handleChange(resource); 220 handlePendingDispatch(monitor); 221 } catch (CoreException e) { 222 handleException(e, resource, ITeamStatus.RESOURCE_SYNC_INFO_ERROR, NLS.bind(Messages.SubscriberEventHandler_9, new String [] { resource.getFullPath().toString(), e.getMessage() })); 223 } 224 monitor.worked(1); 225 } 226 227 231 protected Subscriber getSubscriber() { 232 return subscriber; 233 } 234 235 240 protected abstract void handleChange(IResource resource) throws CoreException; 241 242 protected void handlePendingDispatch(IProgressMonitor monitor) { 243 if (isReadyForDispatch(false )) { 244 try { 245 dispatchEvents(Policy.subMonitorFor(monitor, 5)); 246 } catch (TeamException e) { 247 handleException(e, null, ITeamStatus.SYNC_INFO_SET_ERROR, e.getMessage()); 248 } 249 } 250 } 251 252 258 protected void handleException(CoreException e, IResource resource, int code, String message) { 259 handleException(e); 260 } 261 262 269 protected abstract void collectAll( 270 IResource resource, 271 int depth, 272 IProgressMonitor monitor); 273 274 279 protected abstract void dispatchEvents(SubscriberEvent[] events, IProgressMonitor monitor); 280 281 287 protected void reset(ResourceTraversal[] traversals, int type) { 288 for (int i = 0; i < traversals.length; i++) { 289 ResourceTraversal traversal = traversals[i]; 290 IResource[] resources = traversal.getResources(); 291 for (int j = 0; j < resources.length; j++) { 292 queueEvent(new SubscriberEvent(resources[j], type, traversal.getDepth()), false); 293 } 294 } 295 } 296 297 protected void processEvent(Event event, IProgressMonitor monitor) { 298 try { 299 int type = event.getType(); 302 switch (type) { 303 case BackgroundEventHandler.RUNNABLE_EVENT : 304 executeRunnable(event, monitor); 305 break; 306 case SubscriberEvent.REMOVAL : 307 queueDispatchEvent(event); 308 break; 309 case SubscriberEvent.CHANGE : 310 collect( 311 event.getResource(), 312 ((ResourceEvent)event).getDepth(), 313 monitor); 314 break; 315 case SubscriberEvent.INITIALIZE : 316 monitor.subTask(NLS.bind(Messages.SubscriberEventHandler_2, new String [] { event.getResource().getFullPath().toString() })); 317 collectAll( 318 event.getResource(), 319 ((ResourceEvent)event).getDepth(), 320 Policy.subMonitorFor(monitor, 64)); 321 break; 322 } 323 } catch (OperationCanceledException e) { 324 handleCancel(e); 327 } catch (RuntimeException e) { 328 if (event.getType() == BackgroundEventHandler.RUNNABLE_EVENT ) { 330 handleException(new TeamException(Messages.SubscriberEventHandler_10, e)); 331 } else { 332 handleException(new TeamException(Messages.SubscriberEventHandler_10, e), event.getResource(), ITeamStatus.SYNC_INFO_SET_ERROR, NLS.bind(Messages.SubscriberEventHandler_11, new String [] { event.getResource().getFullPath().toString(), e.getMessage() })); 333 } 334 } 335 } 336 337 341 protected void queueDispatchEvent(Event event) { 342 resultCache.add(event); 343 } 344 345 349 protected void handleCancel(OperationCanceledException e) { 350 resultCache.clear(); 351 } 352 353 356 private void executeRunnable(Event event, IProgressMonitor monitor) { 357 try { 358 dispatchEvents(Policy.subMonitorFor(monitor, 1)); 360 } catch (TeamException e) { 361 handleException(e, null, ITeamStatus.SYNC_INFO_SET_ERROR, e.getMessage()); 362 } 363 try { 364 ((RunnableEvent)event).run(Policy.subMonitorFor(monitor, 1)); 365 } catch (CoreException e) { 366 handleException(e, null, ITeamStatus.SYNC_INFO_SET_ERROR, e.getMessage()); 367 } 368 } 369 370 373 protected boolean doDispatchEvents(IProgressMonitor monitor) { 374 if (!resultCache.isEmpty()) { 375 dispatchEvents((SubscriberEvent[]) resultCache.toArray(new SubscriberEvent[resultCache.size()]), monitor); 376 resultCache.clear(); 377 return true; 378 } 379 return false; 380 } 381 382 386 public void run(IWorkspaceRunnable runnable, boolean frontOnQueue) { 387 queueEvent(new RunnableEvent(runnable, frontOnQueue), frontOnQueue); 388 } 389 390 public void setProgressGroupHint(IProgressMonitor progressGroup, int ticks) { 391 this.progressGroup = progressGroup; 392 this.ticks = ticks; 393 } 394 395 protected void handlePreemptiveEvents(IProgressMonitor monitor) { 396 Event event = peek(); 397 if (event instanceof RunnableEvent && ((RunnableEvent)event).isPreemtive()) { 398 executeRunnable(nextElement(), monitor); 399 } 400 } 401 402 407 protected ISynchronizationScope getScope() { 408 return scope; 409 } 410 411 414 public void shutdown() { 415 super.shutdown(); 416 scope.removeScopeChangeListener(scopeChangeListener); 417 } 418 } 419 | Popular Tags |