private SubscriberChangeEvent[] handleRemovedRoot(IResource removedRoot) {
    // Determine if any of the roots of the compare are affected
    List removals = new ArrayList(resources.length);
    for (int j = 0; j < resources.length; j++) {
      IResource root = resources[j];
      if (removedRoot.getFullPath().isPrefixOf(root.getFullPath())) {
        // The root is no longer managed by CVS
        removals.add(root);
        try {
          tree.flushVariants(root, IResource.DEPTH_INFINITE);
        } catch (TeamException e) {
          CVSProviderPlugin.log(e);
        }
      }
    }
    if (removals.isEmpty()) {
      return new SubscriberChangeEvent[0];
    }

    // Adjust the roots of the subscriber
    List newRoots = new ArrayList(resources.length);
    newRoots.addAll(Arrays.asList(resources));
    newRoots.removeAll(removals);
    resources = (IResource[]) newRoots.toArray(new IResource[newRoots.size()]);

    // Create the deltas for the removals
    SubscriberChangeEvent[] deltas = new SubscriberChangeEvent[removals.size()];
    for (int i = 0; i < deltas.length; i++) {
      deltas[i] =
          new SubscriberChangeEvent(
              this, ISubscriberChangeEvent.ROOT_REMOVED, (IResource) removals.get(i));
    }
    return deltas;
  }
 /*
  * Determine if the resource is a descendant of an orphaned subtree.
  * If it is, purge the CVS folders of the subtree.
  */
 private void handleOrphanedSubtree(IResource resource) {
   try {
     if (!CVSWorkspaceRoot.isSharedWithCVS(resource)) return;
     ICVSFolder folder;
     if (resource.getType() == IResource.FILE) {
       folder = CVSWorkspaceRoot.getCVSFolderFor(resource.getParent());
     } else {
       folder = CVSWorkspaceRoot.getCVSFolderFor((IContainer) resource);
     }
     handleOrphanedSubtree(folder);
   } catch (CVSException e) {
     CVSProviderPlugin.log(e);
   }
 }
  /* (non-Javadoc)
   * @see org.eclipse.team.core.subscribers.ITeamResourceChangeListener#teamResourceChanged(org.eclipse.team.core.subscribers.TeamDelta[])
   */
  public void subscriberResourceChanged(ISubscriberChangeEvent[] deltas) {
    List outgoingDeltas = new ArrayList(deltas.length);
    for (int i = 0; i < deltas.length; i++) {
      ISubscriberChangeEvent delta = deltas[i];
      if ((delta.getFlags() & ISubscriberChangeEvent.ROOT_REMOVED) != 0) {
        IResource resource = delta.getResource();
        outgoingDeltas.addAll(Arrays.asList(handleRemovedRoot(resource)));
      } else if ((delta.getFlags() & ISubscriberChangeEvent.SYNC_CHANGED) != 0) {
        IResource resource = delta.getResource();
        try {
          if (isSupervised(resource)) {
            outgoingDeltas.add(new SubscriberChangeEvent(this, delta.getFlags(), resource));
          }
        } catch (TeamException e) {
          // Log and ignore
          CVSProviderPlugin.log(e);
        }
      }
    }

    fireTeamResourceChange(
        (SubscriberChangeEvent[])
            outgoingDeltas.toArray(new SubscriberChangeEvent[outgoingDeltas.size()]));
  }
  /**
   * The action is enabled for the appropriate resources. This method checks that:
   *
   * <ol>
   *   <li>there is no overlap between a selected file and folder (overlapping folders is allowed
   *       because of logical vs. physical mapping problem in views)
   *   <li>the state of the resources match the conditions provided by:
   *       <ul>
   *         <li>isEnabledForIgnoredResources()
   *         <li>isEnabledForManagedResources()
   *         <li>isEnabledForUnManagedResources() (i.e. not ignored and not managed)
   *       </ul>
   * </ol>
   *
   * @see TeamAction#isEnabled()
   */
  public boolean isEnabled() {

    // allow the super to decide enablement. if the super doesn't know it will return false.
    boolean enabled = super.isEnabled();
    if (enabled) return true;

    // invoke the inherited method so that overlaps are maintained
    IResource[] resources = getSelectedResourcesWithOverlap();

    // disable if no resources are selected
    if (resources.length == 0) return false;

    // disable properly for single resource enablement
    if (!isEnabledForMultipleResources() && resources.length != 1) return false;

    // validate enabled for each resource in the selection
    List folderPaths = new ArrayList();
    List filePaths = new ArrayList();
    for (int i = 0; i < resources.length; i++) {
      IResource resource = resources[i];

      // only enable for accessible resources
      if (resource.getType() == IResource.PROJECT) {
        if (!resource.isAccessible()) return false;
      }

      // no CVS actions are enabled if the selection contains a linked resource
      if (CVSWorkspaceRoot.isLinkedResource(resource)) return false;

      // only enable for resources in a project shared with CVS
      if (RepositoryProvider.getProvider(resource.getProject(), CVSProviderPlugin.getTypeId())
          == null) {
        return false;
      }

      // collect files and folders separately to check for overlap later
      IPath resourceFullPath = resource.getFullPath();
      if (resource.getType() == IResource.FILE) {
        filePaths.add(resourceFullPath);
      } else {
        folderPaths.add(resourceFullPath);
      }

      // ensure that resource management state matches what the action requires
      ICVSResource cvsResource = getCVSResourceFor(resource);
      try {
        if (!isEnabledForCVSResource(cvsResource)) {
          return false;
        }
      } catch (CVSException e) {
        if (!isEnabledForException(e)) return false;
      }
    }
    // Ensure that there is no overlap between files and folders
    // NOTE: folder overlap must be allowed because of logical vs. physical
    if (!folderPaths.isEmpty()) {
      for (Iterator fileIter = filePaths.iterator(); fileIter.hasNext(); ) {
        IPath resourcePath = (IPath) fileIter.next();
        for (Iterator it = folderPaths.iterator(); it.hasNext(); ) {
          IPath folderPath = (IPath) it.next();
          if (folderPath.isPrefixOf(resourcePath)) {
            return false;
          }
        }
      }
    }
    return true;
  }
 public void dispose() {
   CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber().removeListener(this);
   tree.dispose();
 }
 private void initialize() {
   CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber().addListener(this);
 }