Package org.eclipse.egit.core.internal.util

Source Code of org.eclipse.egit.core.internal.util.ResourceUtil

/*******************************************************************************
* Copyright (C) 2011, Jens Baumgart <jens.baumgart@sap.com>
* Copyright (C) 2012, 2013 Robin Stocker <robin@nibor.org>
* Copyright (C) 2012, 2013 Laurent Goubet <laurent.goubet@obeo.fr>
* Copyright (C) 2012, Gunnar Wagenknecht <gunnar@wagenknecht.org>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.egit.core.internal.util;

import java.io.ByteArrayInputStream;
import java.net.URI;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.mapping.IModelProviderDescriptor;
import org.eclipse.core.resources.mapping.ModelProvider;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.resources.mapping.ResourceMappingContext;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.egit.core.Activator;
import org.eclipse.egit.core.GitProvider;
import org.eclipse.egit.core.RepositoryCache;
import org.eclipse.egit.core.internal.CoreText;
import org.eclipse.egit.core.internal.indexdiff.IndexDiffCacheEntry;
import org.eclipse.egit.core.internal.indexdiff.IndexDiffData;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.team.core.RepositoryProvider;

/**
* Resource utilities
*
*/
public class ResourceUtil {

  /**
   * Return the corresponding resource if it exists and has the Git repository
   * provider.
   * <p>
   * The returned file will be relative to the most nested non-closed
   * Git-managed project.
   *
   * @param location
   *            the path to check
   * @return the resources, or null
   */
  public static IResource getResourceForLocation(IPath location) {
    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
    URI uri = URIUtil.toURI(location);
    IFile file = getFileForLocationURI(root, uri);
    if (file != null)
      return file;
    return getContainerForLocationURI(root, uri);
  }

  /**
   * Return the corresponding file if it exists and has the Git repository
   * provider.
   * <p>
   * The returned file will be relative to the most nested non-closed
   * Git-managed project.
   *
   * @param location
   * @return the file, or null
   */
  public static IFile getFileForLocation(IPath location) {
    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
    URI uri = URIUtil.toURI(location);
    return getFileForLocationURI(root, uri);
  }

  /**
   * Return the corresponding container if it exists and has the Git
   * repository provider.
   * <p>
   * The returned container will be relative to the most nested non-closed
   * Git-managed project.
   *
   * @param location
   * @return the container, or null
   */
  public static IContainer getContainerForLocation(IPath location) {
    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
    URI uri = URIUtil.toURI(location);
    return getContainerForLocationURI(root, uri);
  }

  /**
   * Get the {@link IFile} corresponding to the arguments if it exists and has
   * the Git repository provider.
   * <p>
   * The returned file will be relative to the most nested non-closed
   * Git-managed project.
   *
   * @param repository
   *            the repository of the file
   * @param repoRelativePath
   *            the repository-relative path of the file to search for
   * @return the IFile corresponding to this path, or null
   */
  public static IFile getFileForLocation(Repository repository,
      String repoRelativePath) {
    IPath path = new Path(repository.getWorkTree().getAbsolutePath()).append(repoRelativePath);
    return getFileForLocation(path);
  }

  /**
   * Get the {@link IContainer} corresponding to the arguments, using
   * {@link IWorkspaceRoot#getContainerForLocation(org.eclipse.core.runtime.IPath)}
   * .
   *
   * @param repository
   *            the repository
   * @param repoRelativePath
   *            the repository-relative path of the container to search for
   * @return the IContainer corresponding to this path, or null
   */
  public static IContainer getContainerForLocation(Repository repository,
      String repoRelativePath) {
    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
    IPath path = new Path(repository.getWorkTree().getAbsolutePath()).append(repoRelativePath);
    return root.getContainerForLocation(path);
  }

  /**
   * The method splits the given resources by their repository. For each
   * occurring repository a list is built containing the repository relative
   * paths of the related resources.
   * <p>
   * When one of the passed resources corresponds to the working directory,
   * <code>""</code> will be returned as part of the collection.
   *
   * @param resources
   * @return a map containing a list of repository relative paths for each
   *         occurring repository
   */
  public static Map<Repository, Collection<String>> splitResourcesByRepository(
      Collection<IResource> resources) {
    Map<Repository, Collection<String>> result = new HashMap<Repository, Collection<String>>();
    for (IResource resource : resources) {
      RepositoryMapping repositoryMapping = RepositoryMapping
          .getMapping(resource);
      if (repositoryMapping == null)
        continue;
      String path = repositoryMapping.getRepoRelativePath(resource);
      addPathToMap(repositoryMapping.getRepository(), path, result);
    }
    return result;
  }

  /**
   * @see #splitResourcesByRepository(Collection)
   * @param resources
   * @return a map containing a list of repository relative paths for each
   *         occurring repository
   */
  public static Map<Repository, Collection<String>> splitResourcesByRepository(
      IResource[] resources) {
    return splitResourcesByRepository(Arrays.asList(resources));
  }

  /**
   * The method splits the given paths by their repository. For each occurring
   * repository a list is built containing the repository relative paths of
   * the related resources.
   * <p>
   * When one of the passed paths corresponds to the working directory,
   * <code>""</code> will be returned as part of the collection.
   *
   * @param paths
   * @return a map containing a list of repository relative paths for each
   *         occurring repository
   */
  public static Map<Repository, Collection<String>> splitPathsByRepository(
      Collection<IPath> paths) {
    RepositoryCache repositoryCache = Activator.getDefault()
        .getRepositoryCache();
    Map<Repository, Collection<String>> result = new HashMap<Repository, Collection<String>>();
    for (IPath path : paths) {
      Repository repository = repositoryCache.getRepository(path);
      if (repository != null) {
        IPath repoPath = new Path(repository.getWorkTree()
            .getAbsolutePath());
        IPath repoRelativePath = path.makeRelativeTo(repoPath);
        addPathToMap(repository, repoRelativePath.toString(), result);
      }
    }
    return result;
  }

  /**
   * Determine if given resource is imported into workspace or not
   *
   * @param resource
   * @return {@code true} when given resource is not imported into workspace,
   *         {@code false} otherwise
   */
  public static boolean isNonWorkspace(IResource resource) {
    return resource.getLocation() == null;
  }

  private static IFile getFileForLocationURI(IWorkspaceRoot root, URI uri) {
    IFile[] files = root.findFilesForLocationURI(uri);
    return getExistingMappedResourceWithShortestPath(files);
  }

  private static IContainer getContainerForLocationURI(IWorkspaceRoot root,
      URI uri) {
    IContainer[] containers = root.findContainersForLocationURI(uri);
    return getExistingMappedResourceWithShortestPath(containers);
  }

  private static <T extends IResource> T getExistingMappedResourceWithShortestPath(
      T[] resources) {
    int shortestPathSegmentCount = Integer.MAX_VALUE;
    T shortestPath = null;
    for (T resource : resources) {
      if (!resource.exists())
        continue;
      RepositoryProvider provider = RepositoryProvider.getProvider(
          resource.getProject(), GitProvider.ID);
      if (provider == null)
        continue;
      IPath fullPath = resource.getFullPath();
      int segmentCount = fullPath.segmentCount();
      if (segmentCount < shortestPathSegmentCount) {
        shortestPath = resource;
        shortestPathSegmentCount = segmentCount;
      }
    }
    return shortestPath;
  }

  private static void addPathToMap(Repository repository,
      String path, Map<Repository, Collection<String>> result) {
    if (path != null) {
      Collection<String> resourcesList = result.get(repository);
      if (resourcesList == null) {
        resourcesList = new ArrayList<String>();
        result.put(repository, resourcesList);
      }
      resourcesList.add(path);
    }
  }

  /**
   * This will query all model providers for those that are enabled on the
   * given resource and list all mappings available for that resource.
   *
   * @param resource
   *            The resource for which we need the associated resource
   *            mappings.
   * @param context
   *            Context from which remote content could be retrieved.
   * @return All mappings available for that file.
   */
  public static ResourceMapping[] getResourceMappings(IResource resource,
      ResourceMappingContext context) {
    final IModelProviderDescriptor[] modelDescriptors = ModelProvider
        .getModelProviderDescriptors();

    final Set<ResourceMapping> mappings = new LinkedHashSet<ResourceMapping>();
    for (IModelProviderDescriptor candidate : modelDescriptors) {
      try {
        final IResource[] resources = candidate
            .getMatchingResources(new IResource[] { resource, });
        if (resources.length > 0) {
          // get mappings from model provider if there are matching resources
          final ModelProvider model = candidate.getModelProvider();
          final ResourceMapping[] modelMappings = model.getMappings(
              resource, context, new NullProgressMonitor());
          for (ResourceMapping mapping : modelMappings)
            mappings.add(mapping);
        }
      } catch (CoreException e) {
        Activator.logError(e.getMessage(), e);
      }
    }
    return mappings.toArray(new ResourceMapping[mappings.size()]);
  }

  /**
   * Save local history.
   *
   * @param repository
   */
  public static void saveLocalHistory(Repository repository) {
    IndexDiffCacheEntry indexDiffCacheEntry = org.eclipse.egit.core.Activator
        .getDefault().getIndexDiffCache()
        .getIndexDiffCacheEntry(repository);
    IndexDiffData indexDiffData = indexDiffCacheEntry.getIndexDiff();
    if (indexDiffData != null) {
      Collection<IResource> changedResources = indexDiffData
          .getChangedResources();
      if (changedResources != null) {
        for (IResource changedResource : changedResources) {
          if (changedResource instanceof IFile
              && changedResource.exists()) {
            try {
              ResourceUtil.saveLocalHistory(changedResource);
            } catch (CoreException e) {
              // Ignore error. Failure to save local history must
              // not interfere with the operation.
              Activator
                  .logError(
                      MessageFormat
                          .format(CoreText.ResourceUtil_SaveLocalHistoryFailed,
                              changedResource), e);
            }
          }
        }
      }
    }
  }

  private static void saveLocalHistory(IResource resource)
      throws CoreException {
    if (!resource.isSynchronized(IResource.DEPTH_ZERO))
      resource.refreshLocal(IResource.DEPTH_ZERO, null);
    // Dummy update to force save for local history.
    ((IFile) resource).appendContents(
        new ByteArrayInputStream(new byte[0]), IResource.KEEP_HISTORY,
        null);
  }
}
TOP

Related Classes of org.eclipse.egit.core.internal.util.ResourceUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.