Package org.sylfra.idea.plugins.revu.utils

Source Code of org.sylfra.idea.plugins.revu.utils.VcsFetcher$CacheKey

package org.sylfra.idea.plugins.revu.utils;

import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.diff.DiffProvider;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.vfs.VcsVirtualFile;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.sylfra.idea.plugins.revu.RevuBundle;
import org.sylfra.idea.plugins.revu.RevuFriendlyException;
import org.sylfra.idea.plugins.revu.RevuPlugin;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
* @author <a href="mailto:syllant@gmail.com">Sylvain FRANCOIS</a>
* @version $Id$
*/
public class VcsFetcher implements ApplicationComponent
{
  private final static Logger LOGGER = Logger.getInstance(VcsFetcher.class.getName());

  private final Map<CacheKey, VirtualFile> cache;

  public VcsFetcher()
  {
    cache = Collections.synchronizedMap(new HashMap<CacheKey, VirtualFile>());
  }

  public void initComponent()
  {
  }

  public void disposeComponent()
  {
    cache.clear();
  }

  @Nullable
  public void fetch(@NotNull Project project, @NotNull VirtualFile vFile, @NotNull String rev,
    @NotNull final IVcsFetchListener fetchListener)
  {
    VirtualFile result;
    final CacheKey key = new CacheKey(vFile, rev);

    synchronized (cache)
    {
      result = cache.get(key);
      if (result == null)
      {
        IVcsFetchListener listenerWrapper = new IVcsFetchListener()
        {
          public void fetchSucceeded(@NotNull VirtualFile vFile)
          {
            fetchListener.fetchSucceeded(vFile);
            cache.put(key, vFile);
          }

          public void fetchFailed(@NotNull RevuFriendlyException exception)
          {
            fetchListener.fetchFailed(exception);
          }
        };
        new FetchingFileTask(project, vFile, rev, listenerWrapper).queue();
      }
      else
      {
        fetchListener.fetchSucceeded(vFile);
      }
    }
  }

  @NotNull
  public String getComponentName()
  {
    return RevuPlugin.PLUGIN_NAME + "." + getClass().getSimpleName();
  }

  public static interface IVcsFetchListener
  {
    void fetchSucceeded(@NotNull VirtualFile vFile);
    void fetchFailed(@NotNull RevuFriendlyException exception);
  }

  private static final class CacheKey
  {
    private VirtualFile vFile;
    private String rev;

    private CacheKey(VirtualFile vFile, String rev)
    {
      this.vFile = vFile;
      this.rev = rev;
    }

    @Override
    public boolean equals(Object o)
    {
      if (this == o)
      {
        return true;
      }
      if (o == null || getClass() != o.getClass())
      {
        return false;
      }

      CacheKey cacheKey = (CacheKey) o;

      return !((!rev.equals(cacheKey.rev)) || (!vFile.equals(cacheKey.vFile)));
    }

    @Override
    public int hashCode()
    {
      return (31 * vFile.hashCode()) + rev.hashCode();
    }
  }

  private static class FetchingFileTask extends Task.Backgroundable
  {
    private final Project project;
    private final VirtualFile virtualFile;
    private final String revision;
    private final IVcsFetchListener fetchListener;

    public FetchingFileTask(Project project, VirtualFile vFile, String revision, IVcsFetchListener fetchListener)
    {
      super(project, RevuBundle.message("task.fetchingVcsFile.text",
        RevuVcsUtils.formatVcsFileRevision(vFile, revision)), false);

      this.project = project;
      this.virtualFile = vFile;
      this.revision = revision;
      this.fetchListener = fetchListener;
    }

    @Override
    public boolean shouldStartInBackground()
    {
      return false;
    }

    public void run(ProgressIndicator indicator)
    {
      indicator.setIndeterminate(true);
      VirtualFile result;
      try
      {
        result = fetchRevision(project, virtualFile, revision);
      }
      catch (RevuFriendlyException e)
      {
        fetchListener.fetchFailed(e);
        return;
      }

      fetchListener.fetchSucceeded(result);
    }

    @NotNull
    public VirtualFile fetchRevision(@NotNull Project project, @NotNull VirtualFile vFile, @NotNull String rev)
      throws RevuFriendlyException
    {
      DiffProvider diffProvider = RevuVcsUtils.getDiffProvider(project, vFile);
      if (diffProvider == null)
      {
        throw new RevuFriendlyException("Failed to get DiffProvider: " + vFile,
          RevuBundle.message("friendlyError.failedToFetchVcsFile.noVcs.details.text",
          vFile.getPath()));
      }

      AbstractVcs vcs = VcsUtil.getVcsFor(project, vFile);
      assert vcs != null;

      VcsRevisionNumber vcsRevisionNumber;
      try
      {
        vcsRevisionNumber = vcs.parseRevisionNumber(rev);
      }
      catch (VcsException e)
      {
        throw new RevuFriendlyException("Failed to parse VCS revision number: " + rev,
          RevuBundle.message("friendlyError.failedToFetchVcsFile.invalidRevision.details.text",
          vFile.getPath(), rev));
      }

      ContentRevision contentRevision = diffProvider.createFileContent(vcsRevisionNumber, vFile);
      String content = null;
      if (contentRevision != null)
      {
        try
        {
          if (LOGGER.isDebugEnabled())
          {
            LOGGER.debug("Fetching from VCS:" + contentRevision);
          }
          content = contentRevision.getContent();
        }
        catch (VcsException e)
        {
          throw new RevuFriendlyException("Error while retrieving VCS content: " + contentRevision,
            null, RevuBundle.message("friendlyError.failedToFetchVcsFile.vcsError.details.text",
            RevuBundle.message("general.vcsFileAndRev.text", vFile.getPath(), rev), e.getMessage()), e);
        }
      }

      if (content == null)
      {
        throw new RevuFriendlyException("VCS fetched content is null: ",
          RevuBundle.message("friendlyError.failedToFetchVcsFile.nullContent.details.text",
          vFile.getPath(), contentRevision));
      }

      return new VcsVirtualFile(contentRevision.getFile().getPath(), content.getBytes(),
        vcsRevisionNumber.asString(), vFile.getFileSystem());
    }
  }
}
TOP

Related Classes of org.sylfra.idea.plugins.revu.utils.VcsFetcher$CacheKey

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.