com.mangosolutions.rcloud.rawgist.repository.git.ReadGistOperation.java Source code

Java tutorial

Introduction

Here is the source code for com.mangosolutions.rcloud.rawgist.repository.git.ReadGistOperation.java

Source

/*******************************************************************************
* Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com]
*
* SPDX-License-Identifier:   MIT
*
*******************************************************************************/
package com.mangosolutions.rcloud.rawgist.repository.git;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

import javax.activation.MimetypesFileTypeMap;

import org.ajoberstar.grgit.Grgit;
import org.ajoberstar.grgit.operation.OpenOp;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.FilenameUtils;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.StringUtils;

import com.mangosolutions.rcloud.rawgist.model.FileContent;
import com.mangosolutions.rcloud.rawgist.model.GistHistory;
import com.mangosolutions.rcloud.rawgist.model.GistIdentity;
import com.mangosolutions.rcloud.rawgist.model.GistResponse;
import com.mangosolutions.rcloud.rawgist.repository.GistCommentRepository;
import com.mangosolutions.rcloud.rawgist.repository.GistError;
import com.mangosolutions.rcloud.rawgist.repository.GistErrorCode;
import com.mangosolutions.rcloud.rawgist.repository.GistRepositoryError;

public class ReadGistOperation implements Callable<GistResponse> {

    private static final Logger logger = LoggerFactory.getLogger(ReadGistOperation.class);

    public static final String REF_HEAD_MASTER = "refs/heads/master";

    private GistCommentRepository commentRepository;

    private MetadataStore metadataStore;

    private HistoryCache historyCache = new HistoryCache() {

        @Override
        public List<GistHistory> load(String commitId) {
            return new LinkedList<>();
        }

        @Override
        public List<GistHistory> save(String commitId, List<GistHistory> history) {
            return history;
        }

    };

    private FileContentCache fileContentCache = new FileContentCache() {

        @Override
        public FileContent load(String contentId, String path) {
            return null;
        }

        @Override
        public FileContent save(String contentId, String path, FileContent content) {
            return content;
        }

    };
    private RepositoryLayout layout;

    private UserDetails user;

    private String gistId;

    private String commitId = null;

    public ReadGistOperation(RepositoryLayout layout, String gistId, String commitId, UserDetails user) {
        this.layout = layout;
        this.gistId = gistId;
        this.commitId = commitId;
        this.user = user;
    }

    public ReadGistOperation(File repositoryFolder, String gistId, String commitId, UserDetails user) {
        this(new RepositoryLayout(repositoryFolder), gistId, commitId, user);
    }

    public ReadGistOperation(RepositoryLayout layout, String gistId, UserDetails user) {
        this(layout, gistId, null, user);

    }

    public ReadGistOperation(File repositoryFolder, String gistId, UserDetails user) {
        this(new RepositoryLayout(repositoryFolder), gistId, user);
    }

    @Override
    public GistResponse call() {
        OpenOp openOp = new OpenOp();
        openOp.setDir(layout.getBareFolder());
        try (Grgit git = openOp.call()) {

            return this.readGist(git);
        }
    }

    protected GistResponse readGist(Grgit git) {
        try {
            Repository repository = git.getRepository().getJgit().getRepository();
            RevCommit revCommit = resolveCommit(repository);
            GistResponse response = new GistResponse();

            Map<String, FileContent> fileContent = Collections.emptyMap();
            List<GistHistory> history = Collections.emptyList();
            if (revCommit != null) {
                fileContent = getFileContent(repository, revCommit);
                history = getHistory(git, revCommit);
            }
            response.setFiles(fileContent);
            response.setComments(this.commentRepository.getComments(user).size());
            response.setHistory(history);
            applyMetadata(response);
            return response;
        } catch (IOException e) {
            GistError error = new GistError(GistErrorCode.ERR_GIST_CONTENT_NOT_READABLE,
                    "Could not read content of gist {}", gistId);
            logger.error(error.getFormattedMessage() + " with path {}", this.layout.getRootFolder(), e);
            throw new GistRepositoryError(error, e);
        }
    }

    private Map<String, FileContent> getFileContent(Repository repository, RevCommit commit)
            throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException {
        Map<String, FileContent> fileContent = new LinkedHashMap<String, FileContent>();
        RevTree tree = commit.getTree();
        try (TreeWalk treeWalk = new TreeWalk(repository)) {
            treeWalk.addTree(tree);
            treeWalk.setRecursive(true);
            treeWalk.setPostOrderTraversal(false);

            while (treeWalk.next()) {

                FileContent content = readContent(repository, treeWalk);
                fileContent.put(content.getFilename(), content);
            }
        }
        return fileContent;
    }

    private RevCommit resolveCommit(Repository repository) throws IOException {
        try (RevWalk revWalk = new RevWalk(repository)) {
            if (StringUtils.isEmpty(commitId)) {
                Ref head = repository.exactRef(REF_HEAD_MASTER);
                if (head != null) {
                    return revWalk.parseCommit(head.getObjectId());
                }
                return null;
            } else {
                return revWalk.parseCommit(ObjectId.fromString(this.commitId));
            }
        }
    }

    private FileContent readContent(Repository repository, TreeWalk treeWalk) {

        ObjectId objectId = treeWalk.getObjectId(0);
        String fileName = treeWalk.getPathString();
        FileContent content = fileContentCache.load(objectId.getName(), fileName);
        if (content == null) {
            content = new FileContent();
            try {
                content.setFilename(fileName);
                ObjectLoader loader = repository.open(objectId);

                content.setContent(new String(loader.getBytes(), Charsets.UTF_8));
                content.setSize(loader.getSize());
                content.setTruncated(false);
                String language = FilenameUtils.getExtension(fileName);
                if (!GitGistRepository.B64_BINARY_EXTENSION.equals(language) && !StringUtils.isEmpty(language)) {
                    content.setLanguage(language);
                }
                content.setType(MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(fileName));
                fileContentCache.save(objectId.getName(), fileName, content);
            } catch (IOException e) {
                GistError error = new GistError(GistErrorCode.ERR_GIST_CONTENT_NOT_READABLE,
                        "Could not read content of {} for gist {}", fileName, gistId);
                logger.error(error.getFormattedMessage() + " with path {}", this.layout.getRootFolder(), e);
                throw new GistRepositoryError(error, e);
            }
        }
        return content;
    }

    private void applyMetadata(GistResponse response) {

        GistMetadata metadata = this.getMetadata();
        response.setId(metadata.getId());
        response.setDescription(metadata.getDescription());
        response.setDescription(metadata.getDescription());
        response.setCreatedAt(metadata.getCreatedAt());
        response.setUpdatedAt(metadata.getUpdatedAt());
        response.setPublic(metadata.isPublic());
        if (!StringUtils.isEmpty(metadata.getOwner())) {
            GistIdentity owner = new GistIdentity();
            owner.setLogin(metadata.getOwner());
            response.setOwner(owner);
            response.setUser(owner);
        }
        response.setForkOf(metadata.getForkOf());
        response.addAdditionalProperties(metadata.getAdditionalProperties());
    }

    public GistMetadata getMetadata() {
        return metadataStore.load(layout.getMetadataFile());
    }

    private List<GistHistory> getHistory(Grgit git, RevCommit commit) {
        GitHistoryOperation historyOperation = new GitHistoryOperation(git, commit.getName());
        historyOperation.setHistoryCache(historyCache);
        return historyOperation.call();
    }

    public UserDetails getUser() {
        return user;
    }

    public void setUser(UserDetails user) {
        this.user = user;
    }

    public GistCommentRepository getCommentRepository() {
        return commentRepository;
    }

    public void setCommentRepository(GistCommentRepository commentRepository) {
        this.commentRepository = commentRepository;
    }

    public RepositoryLayout getLayout() {
        return layout;
    }

    public void setLayout(RepositoryLayout layout) {
        this.layout = layout;
    }

    public void setMetadataStore(MetadataStore metadataStore) {
        this.metadataStore = metadataStore;
    }

    public MetadataStore getMetadataStore() {
        return this.metadataStore;
    }

    public void setHistorycache(HistoryCache historyStore) {
        this.historyCache = historyStore;
    }

    public String getGistId() {
        return gistId;
    }

    public void setGistId(String gistId) {
        this.gistId = gistId;
    }

    public String getCommitId() {
        return commitId;
    }

    public void setCommitId(String commitId) {
        this.commitId = commitId;
    }

    public void setFileContentCache(FileContentCache fileContentCache) {
        this.fileContentCache = fileContentCache;
    }

}