1 11 package org.eclipse.team.ui.synchronize; 12 13 import java.io.IOException ; 14 import java.util.ArrayList ; 15 import java.util.List ; 16 17 import org.eclipse.compare.structuremergeviewer.ICompareInput; 18 import org.eclipse.core.resources.mapping.*; 19 import org.eclipse.core.runtime.*; 20 import org.eclipse.core.runtime.jobs.Job; 21 import org.eclipse.jface.preference.PreferencePage; 22 import org.eclipse.jface.preference.PreferenceStore; 23 import org.eclipse.osgi.util.NLS; 24 import org.eclipse.swt.widgets.Shell; 25 import org.eclipse.team.core.mapping.*; 26 import org.eclipse.team.core.mapping.provider.*; 27 import org.eclipse.team.internal.core.subscribers.SubscriberDiffTreeEventHandler; 28 import org.eclipse.team.internal.ui.*; 29 import org.eclipse.team.internal.ui.mapping.ModelEnablementPreferencePage; 30 import org.eclipse.team.internal.ui.mapping.ModelSynchronizePage; 31 import org.eclipse.team.internal.ui.preferences.SyncViewerPreferencePage; 32 import org.eclipse.team.internal.ui.synchronize.*; 33 import org.eclipse.team.ui.TeamUI; 34 import org.eclipse.team.ui.mapping.*; 35 import org.eclipse.ui.*; 36 import org.eclipse.ui.part.IPageBookViewPage; 37 38 46 public class ModelSynchronizeParticipant extends 47 AbstractSynchronizeParticipant { 48 49 56 public static final String P_VISIBLE_MODEL_PROVIDER = TeamUIPlugin.ID + ".activeModelProvider"; 58 62 public static final String ALL_MODEL_PROVIDERS_VISIBLE = TeamUIPlugin.ID + ".activeModelProvider"; 64 68 public static final String PROP_ENABLED_MODEL_PROVIDERS = TeamUIPlugin.ID + ".ENABLED_MODEL_PROVIDERS"; 70 74 public static final String PROP_ACTIVE_SAVEABLE = TeamUIPlugin.ID + ".ACTIVE_SAVEABLE"; 76 80 public static final String PROP_DIRTY = TeamUIPlugin.ID + ".DIRTY"; 82 85 private static final String CTX_PARTICIPANT_SETTINGS = TeamUIPlugin.ID + ".MODEL_PARTICIPANT_SETTINGS"; 87 90 private static final String CTX_REFRESH_SCHEDULE_SETTINGS = TeamUIPlugin.ID + ".MODEL_PARTICIPANT_REFRESH_SCHEDULE"; 92 95 private static final String CTX_DESCRIPTION = TeamUIPlugin.ID + ".MODEL_PARTICIPANT_DESCRIPTION"; 97 100 private static final String CTX_PARTICIPANT_MAPPINGS = TeamUIPlugin.ID + ".MODEL_PARTICIPANT_MAPPINGS"; private static final String CTX_MODEL_PROVIDER_ID = "modelProviderId"; private static final String CTX_MODEL_PROVIDER_MAPPINGS = "mappings"; private static final String CTX_STARTUP_ACTION = "startupAction"; 105 private SynchronizationContext context; 106 private boolean mergingEnabled = true; 107 protected SubscriberRefreshSchedule refreshSchedule; 108 private String description; 109 private SaveableComparison activeSaveable; 110 private PreferenceStore preferences = new PreferenceStore() { 111 public void save() throws IOException { 112 } 114 }; 115 116 private IPropertyListener dirtyListener = new IPropertyListener() { 117 public void propertyChanged(Object source, int propId) { 118 if (source instanceof SaveableComparison && propId == SaveableComparison.PROP_DIRTY) { 119 SaveableComparison scm = (SaveableComparison) source; 120 boolean isDirty = scm.isDirty(); 121 firePropertyChange(ModelSynchronizeParticipant.this, PROP_DIRTY, Boolean.valueOf(!isDirty), Boolean.valueOf(isDirty)); 122 } 123 } 124 }; 125 126 132 public static ModelSynchronizeParticipant createParticipant(SynchronizationContext context, String name) { 133 return new ModelSynchronizeParticipant(context, name); 134 } 135 136 141 private ModelSynchronizeParticipant(SynchronizationContext context, String name) { 142 initializeContext(context); 143 try { 144 setInitializationData(TeamUI.getSynchronizeManager().getParticipantDescriptor("org.eclipse.team.ui.synchronization_context_synchronize_participant")); } catch (CoreException e) { 146 TeamUIPlugin.log(e); 147 } 148 setSecondaryId(Long.toString(System.currentTimeMillis())); 149 setName(name); 150 refreshSchedule = new SubscriberRefreshSchedule(createRefreshable()); 151 } 152 153 157 public ModelSynchronizeParticipant(SynchronizationContext context) { 158 initializeContext(context); 159 refreshSchedule = new SubscriberRefreshSchedule(createRefreshable()); 160 } 161 162 165 public ModelSynchronizeParticipant() { 166 } 167 168 171 public String getName() { 172 String name = super.getName(); 173 if (description == null) 174 description = Utils.getScopeDescription(getContext().getScope()); 175 return NLS.bind(TeamUIMessages.SubscriberParticipant_namePattern, new String [] { name, description }); 176 } 177 178 185 protected final String getShortName() { 186 return super.getName(); 187 } 188 189 192 protected void initializeConfiguration( 193 ISynchronizePageConfiguration configuration) { 194 if (isMergingEnabled()) { 195 configuration.addMenuGroup(ISynchronizePageConfiguration.P_TOOLBAR_MENU, ModelSynchronizeParticipantActionGroup.MERGE_ACTION_GROUP); 197 configuration.addActionContribution(createMergeActionGroup()); 198 } 199 configuration.setSupportedModes(ISynchronizePageConfiguration.ALL_MODES); 200 configuration.setMode(ISynchronizePageConfiguration.BOTH_MODE); 201 configuration.setProperty(ITeamContentProviderManager.P_SYNCHRONIZATION_CONTEXT, getContext()); 202 configuration.setProperty(ITeamContentProviderManager.P_SYNCHRONIZATION_SCOPE, getContext().getScope()); 203 if (getHandler() != null) 204 configuration.setProperty(StartupPreferencePage.STARTUP_PREFERENCES, preferences); 205 } 206 207 214 protected ModelSynchronizeParticipantActionGroup createMergeActionGroup() { 215 return new ModelSynchronizeParticipantActionGroup(); 216 } 217 218 221 public final IPageBookViewPage createPage( 222 ISynchronizePageConfiguration configuration) { 223 return new ModelSynchronizePage(configuration); 224 } 225 226 229 public void run(IWorkbenchPart part) { 230 refresh(part != null ? part.getSite() : null, context.getScope().getMappings()); 231 } 232 233 243 public final void refresh(IWorkbenchSite site, ResourceMapping[] mappings) { 244 IRefreshSubscriberListener listener = new RefreshUserNotificationPolicy(this); 245 internalRefresh(mappings, null, null, site, listener); 246 } 247 248 251 public void dispose() { 252 context.dispose(); 253 Job.getJobManager().cancel(this); 254 refreshSchedule.dispose(); 255 } 256 257 262 protected void initializeContext(SynchronizationContext context) { 263 this.context = context; 264 mergingEnabled = context instanceof IMergeContext; 265 SubscriberDiffTreeEventHandler handler = getHandler(); 266 if (handler != null) { 267 preferences.setDefault(StartupPreferencePage.PROP_STARTUP_ACTION, StartupPreferencePage.STARTUP_ACTION_NONE); 268 if (isSynchronizeOnStartup()) { 269 run(null); } else if (isPopulateOnStartup()) { 271 handler.initializeIfNeeded(); 272 } 273 } 274 } 275 276 private boolean isPopulateOnStartup() { 277 String pref = preferences.getString(StartupPreferencePage.PROP_STARTUP_ACTION); 278 return pref != null && pref.equals(StartupPreferencePage.STARTUP_ACTION_POPULATE); 279 } 280 281 private boolean isSynchronizeOnStartup() { 282 String pref = preferences.getString(StartupPreferencePage.PROP_STARTUP_ACTION); 283 return pref != null && pref.equals(StartupPreferencePage.STARTUP_ACTION_SYNCHRONIZE); 284 } 285 286 290 public ISynchronizationContext getContext() { 291 return context; 292 } 293 294 300 public ICompareInput asCompareInput(Object object) { 301 if (object instanceof ICompareInput) { 302 return (ICompareInput) object; 303 } 304 ISynchronizationCompareAdapter adapter = Utils.getCompareAdapter(object); 306 if (adapter != null) 307 return adapter.asCompareInput(getContext(), object); 308 return null; 309 } 310 311 318 public boolean hasCompareInputFor(Object object) { 319 ISynchronizationCompareAdapter adapter = Utils.getCompareAdapter(object); 321 if (adapter != null) 322 return adapter.hasCompareInput(getContext(), object); 323 return false; 324 } 325 326 332 public boolean isMergingEnabled() { 333 return mergingEnabled; 334 } 335 336 340 public void setMergingEnabled(boolean mergingEnabled) { 341 this.mergingEnabled = mergingEnabled; 342 } 343 344 private void internalRefresh(ResourceMapping[] mappings, String jobName, String taskName, IWorkbenchSite site, IRefreshSubscriberListener listener) { 345 if (jobName == null) 346 jobName = getShortTaskName(); 347 if (taskName == null) 348 taskName = getLongTaskName(mappings); 349 Job.getJobManager().cancel(this); 350 RefreshParticipantJob job = new RefreshModelParticipantJob(this, jobName, taskName, mappings, listener); 351 job.setUser(true); 352 Utils.schedule(job, site); 353 354 TeamUIPlugin.getPlugin().getPreferenceStore().setValue(IPreferenceIds.SYNCHRONIZING_DEFAULT_PARTICIPANT, getId()); 356 TeamUIPlugin.getPlugin().getPreferenceStore().setValue(IPreferenceIds.SYNCHRONIZING_DEFAULT_PARTICIPANT_SEC_ID, getSecondaryId()); 357 } 358 359 368 protected String getShortTaskName() { 369 return NLS.bind(TeamUIMessages.Participant_synchronizingDetails, getShortName()); 370 } 371 372 381 protected String getLongTaskName(ResourceMapping[] mappings) { 382 if (mappings == null) { 383 mappings = getContext().getScope().getMappings(); 385 } 386 int mappingCount = mappings.length; 387 if (mappingCount == getContext().getScope().getMappings().length) { 388 mappings = getContext().getScope().getInputMappings(); 390 mappingCount = mappings.length; 391 } 392 if (mappingCount == 1) { 393 return NLS.bind(TeamUIMessages.Participant_synchronizingMoreDetails, new String [] { getShortName(), Utils.getLabel(mappings[0]) }); 394 } 395 return NLS.bind(TeamUIMessages.Participant_synchronizingResources, new String [] { getShortName(), Integer.toString(mappingCount) }); 396 } 397 398 private IRefreshable createRefreshable() { 399 return new IRefreshable() { 400 401 public RefreshParticipantJob createJob(String interval) { 402 String jobName = NLS.bind(TeamUIMessages.RefreshSchedule_15, new String [] { ModelSynchronizeParticipant.this.getName(), interval }); 403 return new RefreshModelParticipantJob(ModelSynchronizeParticipant.this, 404 jobName, 405 jobName, 406 context.getScope().getMappings(), 407 new RefreshUserNotificationPolicy(ModelSynchronizeParticipant.this)); 408 } 409 public ISynchronizeParticipant getParticipant() { 410 return ModelSynchronizeParticipant.this; 411 } 412 public void setRefreshSchedule(SubscriberRefreshSchedule schedule) { 413 ModelSynchronizeParticipant.this.setRefreshSchedule(schedule); 414 } 415 public SubscriberRefreshSchedule getRefreshSchedule() { 416 return refreshSchedule; 417 } 418 419 }; 420 } 421 422 425 public Object getAdapter(Class adapter) { 426 if (adapter == IRefreshable.class && refreshSchedule != null) { 427 return refreshSchedule.getRefreshable(); 428 429 } 430 if (adapter == SubscriberRefreshSchedule.class) { 431 return refreshSchedule; 432 } 433 return super.getAdapter(adapter); 434 } 435 436 439 public void saveState(IMemento memento) { 440 super.saveState(memento); 441 IMemento settings = memento.createChild(CTX_PARTICIPANT_SETTINGS); 442 if (description != null) 443 settings.putString(CTX_DESCRIPTION, description); 444 refreshSchedule.saveState(settings.createChild(CTX_REFRESH_SCHEDULE_SETTINGS)); 445 saveMappings(settings); 446 settings.putString(CTX_STARTUP_ACTION, preferences.getString(StartupPreferencePage.PROP_STARTUP_ACTION)); 447 } 448 449 private void saveMappings(IMemento settings) { 450 ISynchronizationScope inputScope = getContext().getScope().asInputScope(); 451 ModelProvider[] providers = inputScope.getModelProviders(); 452 for (int i = 0; i < providers.length; i++) { 453 ModelProvider provider = providers[i]; 454 ISynchronizationCompareAdapter adapter = Utils.getCompareAdapter(provider); 455 if (adapter != null) { 456 IMemento child = settings.createChild(CTX_PARTICIPANT_MAPPINGS); 457 String id = provider.getDescriptor().getId(); 458 child.putString(CTX_MODEL_PROVIDER_ID, id); 459 adapter.save(inputScope.getMappings(id), child.createChild(CTX_MODEL_PROVIDER_MAPPINGS)); 460 } 461 } 462 } 463 464 467 public void init(String secondaryId, IMemento memento) throws PartInitException { 468 super.init(secondaryId, memento); 469 if(memento != null) { 470 IMemento settings = memento.getChild(CTX_PARTICIPANT_SETTINGS); 471 String startupAction = settings.getString(StartupPreferencePage.PROP_STARTUP_ACTION); 472 if (startupAction != null) 473 preferences.putValue(StartupPreferencePage.PROP_STARTUP_ACTION, startupAction); 474 ResourceMapping[] mappings = loadMappings(settings); 475 if (mappings.length == 0) 476 throw new PartInitException(NLS.bind(TeamUIMessages.ModelSynchronizeParticipant_0, getId())); 477 initializeContext(mappings); 478 if(settings != null) { 479 SubscriberRefreshSchedule schedule = SubscriberRefreshSchedule.init(settings.getChild(CTX_REFRESH_SCHEDULE_SETTINGS), createRefreshable()); 480 description = settings.getString(CTX_DESCRIPTION); 481 setRefreshSchedule(schedule); 482 if(schedule.isEnabled()) { 483 schedule.startJob(); 484 } 485 } 486 } 487 } 488 489 private ResourceMapping[] loadMappings(IMemento settings) throws PartInitException { 490 List result = new ArrayList (); 491 IMemento[] children = settings.getChildren(CTX_PARTICIPANT_MAPPINGS); 492 for (int i = 0; i < children.length; i++) { 493 IMemento memento = children[i]; 494 String id = memento.getString(CTX_MODEL_PROVIDER_ID); 495 if (id != null) { 496 IModelProviderDescriptor desc = ModelProvider.getModelProviderDescriptor(id); 497 try { 498 ModelProvider provider = desc.getModelProvider(); 499 ISynchronizationCompareAdapter adapter = Utils.getCompareAdapter(provider); 500 if (adapter != null) { 501 ResourceMapping[] mappings = adapter.restore(memento.getChild(CTX_MODEL_PROVIDER_MAPPINGS)); 502 for (int j = 0; j < mappings.length; j++) { 503 ResourceMapping mapping = mappings[j]; 504 result.add(mapping); 505 } 506 } 507 } catch (CoreException e) { 508 TeamUIPlugin.log(e); 509 } 510 } 511 } 512 return (ResourceMapping[]) result.toArray(new ResourceMapping[result.size()]); 513 } 514 515 private void initializeContext(ResourceMapping[] mappings) throws PartInitException { 516 try { 517 ISynchronizationScopeManager manager = createScopeManager(mappings); 518 MergeContext context = restoreContext(manager); 519 initializeContext(context); 520 } catch (CoreException e) { 521 TeamUIPlugin.log(e); 522 throw new PartInitException(e.getStatus()); 523 } 524 } 525 526 534 protected MergeContext restoreContext(ISynchronizationScopeManager manager) throws CoreException { 535 throw new PartInitException(NLS.bind(TeamUIMessages.ModelSynchronizeParticipant_1, getId())); 536 } 537 538 548 protected ISynchronizationScopeManager createScopeManager(ResourceMapping[] mappings) { 549 return new SynchronizationScopeManager(super.getName(), mappings, ResourceMappingContext.LOCAL_CONTEXT, true); 550 } 551 552 void setRefreshSchedule(SubscriberRefreshSchedule schedule) { 553 if (refreshSchedule != schedule) { 554 if (refreshSchedule != null) { 555 refreshSchedule.dispose(); 556 } 557 this.refreshSchedule = schedule; 558 } 559 firePropertyChange(this, AbstractSynchronizeParticipant.P_SCHEDULED, schedule, schedule); 561 } 562 563 570 public SaveableComparison getActiveSaveable() { 571 return activeSaveable; 572 } 573 574 578 public void setActiveSaveable(SaveableComparison activeSaveable) { 579 boolean wasDirty = false; 580 SaveableComparison oldModel = this.activeSaveable; 581 if (oldModel != null) { 582 oldModel.removePropertyListener(dirtyListener); 583 wasDirty = oldModel.isDirty(); 584 } 585 this.activeSaveable = activeSaveable; 586 firePropertyChange(this, PROP_ACTIVE_SAVEABLE, oldModel, activeSaveable); 587 boolean isDirty = false; 588 if (activeSaveable != null) { 589 activeSaveable.addPropertyListener(dirtyListener); 590 isDirty = activeSaveable.isDirty(); 591 } 592 if (isDirty != wasDirty) 593 firePropertyChange(this, PROP_DIRTY, Boolean.valueOf(wasDirty), Boolean.valueOf(isDirty)); 594 } 595 596 606 public boolean checkForBufferChange(Shell shell, ISynchronizationCompareInput input, boolean cancelAllowed, IProgressMonitor monitor) throws CoreException { 607 SaveableComparison currentBuffer = getActiveSaveable(); 608 SaveableComparison targetBuffer = input.getSaveable(); 609 if (monitor == null) 610 monitor = new NullProgressMonitor(); 611 try { 612 ModelParticipantAction.handleTargetSaveableChange(shell, targetBuffer, currentBuffer, cancelAllowed, Policy.subMonitorFor(monitor, 10)); 613 } catch (InterruptedException e) { 614 return false; 615 } 616 setActiveSaveable(targetBuffer); 617 return true; 618 } 619 620 626 public ModelProvider[] getEnabledModelProviders() { 627 return getContext().getScope().getModelProviders(); 628 } 629 630 633 public PreferencePage[] getPreferencePages() { 634 List pages = new ArrayList (); 635 SyncViewerPreferencePage syncViewerPreferencePage = new SyncViewerPreferencePage(); 636 syncViewerPreferencePage.setIncludeDefaultLayout(false); 637 pages.add(syncViewerPreferencePage); 638 pages.add(new ModelEnablementPreferencePage()); 639 ITeamContentProviderDescriptor[] descriptors = TeamUI.getTeamContentProviderManager().getDescriptors(); 640 for (int i = 0; i < descriptors.length; i++) { 641 ITeamContentProviderDescriptor descriptor = descriptors[i]; 642 if (isIncluded(descriptor)) { 643 try { 644 PreferencePage page = (PreferencePage)descriptor.createPreferencePage(); 645 if (page != null) { 646 pages.add(page); 647 } 648 } catch (CoreException e) { 649 TeamUIPlugin.log(e); 650 } 651 } 652 } 653 if (getHandler() != null) { 654 pages.add(new StartupPreferencePage(preferences)); 655 } 656 return (PreferencePage[]) pages.toArray(new PreferencePage[pages.size()]); 657 } 658 659 private boolean isIncluded(ITeamContentProviderDescriptor descriptor) { 660 ModelProvider[] providers = getEnabledModelProviders(); 661 for (int i = 0; i < providers.length; i++) { 662 ModelProvider provider = providers[i]; 663 if (provider.getId().equals(descriptor.getModelProviderId())) { 664 return true; 665 } 666 } 667 return false; 668 } 669 670 private SubscriberDiffTreeEventHandler getHandler() { 671 return (SubscriberDiffTreeEventHandler)Utils.getAdapter(context, SubscriberDiffTreeEventHandler.class); 672 } 673 674 } 675 | Popular Tags |