org.archicontribs.modelrepository.grafico.GraficoUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.archicontribs.modelrepository.grafico.GraficoUtils.java

Source

/**
 * This program and the accompanying materials
 * are made available under the terms of the License
 * which accompanies this distribution in the file LICENSE.txt
 */
package org.archicontribs.modelrepository.grafico;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URISyntaxException;

import org.eclipse.gef.commands.CommandStack;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jgit.api.AddCommand;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.CommitCommand;
import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.InitCommand;
import org.eclipse.jgit.api.PullCommand;
import org.eclipse.jgit.api.PullResult;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.api.RemoteAddCommand;
import org.eclipse.jgit.api.Status;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.eclipse.swt.widgets.Shell;

import com.archimatetool.editor.model.IEditorModelManager;
import com.archimatetool.model.IArchimateModel;

/**
 * Grafico and Git Utils
 * 
 * @author Phillip Beauvoir
 */
public class GraficoUtils {

    /**
     * Clone a model
     * @param localGitFolder
     * @param repoURL
     * @param userName
     * @param userPassword
     * @param monitor
     * @throws GitAPIException
     * @throws IOException
     */
    public static void cloneModel(File localGitFolder, String repoURL, String userName, String userPassword,
            ProgressMonitor monitor) throws GitAPIException, IOException {
        CloneCommand cloneCommand = Git.cloneRepository();
        cloneCommand.setDirectory(localGitFolder);
        cloneCommand.setURI(repoURL);
        cloneCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(userName, userPassword));
        cloneCommand.setProgressMonitor(monitor);

        try (Git git = cloneCommand.call()) {
            // Use the same line endings
            StoredConfig config = git.getRepository().getConfig();
            config.setString(ConfigConstants.CONFIG_CORE_SECTION, null, ConfigConstants.CONFIG_KEY_AUTOCRLF,
                    "true"); //$NON-NLS-1$
            config.save();
        }
    }

    /**
     * Load a model from a local Git folder
     * @param localGitFolder
     * @param shell
     * @return The model
     * @throws IOException
     */
    public static IArchimateModel loadModel(File localGitFolder, Shell shell) throws IOException {
        GraficoModelImporter importer = new GraficoModelImporter();
        IArchimateModel model = importer.importLocalGitRepositoryAsModel(localGitFolder);

        if (importer.getResolveStatus() != null) {
            ErrorDialog.openError(shell, Messages.GraficoUtils_0, Messages.GraficoUtils_1,
                    importer.getResolveStatus());

        } else {
            File tmpFile = getModelFileName(localGitFolder);
            model.setFile(tmpFile); // Add a file name used to locate the model

            // If we have it open, close and re-open to refresh changes
            IArchimateModel existingModel = locateModel(localGitFolder);
            if (existingModel != null) {
                // Set dirty state to non-dirty
                CommandStack stack = (CommandStack) existingModel.getAdapter(CommandStack.class);
                stack.flush();
                // Close it
                IEditorModelManager.INSTANCE.closeModel(existingModel);
            }

            IEditorModelManager.INSTANCE.openModel(model); // Open it
        }

        return model;
    }

    /**
     * Commit a model with any changes to local repo
     * @param model
     * @param localGitFolder
     * @param personIdent
     * @param commitMessage
     * @return 
     * @throws GitAPIException
     * @throws IOException
     */
    public static RevCommit commitModel(IArchimateModel model, File localGitFolder, PersonIdent personIdent,
            String commitMessage) throws GitAPIException, IOException {

        GraficoModelExporter exporter = new GraficoModelExporter();
        exporter.exportModelToLocalGitRepository(model, localGitFolder);

        try (Git git = Git.open(localGitFolder)) {
            Status status = git.status().call();

            // Nothing changed
            if (status.isClean()) {
                return null;
            }

            // Add modified files to index
            AddCommand addCommand = git.add();
            addCommand.addFilepattern("."); //$NON-NLS-1$
            addCommand.setUpdate(false);
            addCommand.call();

            // Add missing files to index
            for (String s : status.getMissing()) {
                git.rm().addFilepattern(s).call();
            }

            // Commit
            CommitCommand commitCommand = git.commit();
            commitCommand.setAuthor(personIdent);
            commitCommand.setMessage(commitMessage);
            return commitCommand.call();
        }
    }

    /**
     * Push to Remote
     * @param localGitFolder
     * @param userName
     * @param userPassword
     * @return 
     * @throws IOException
     * @throws GitAPIException
     */
    public static Iterable<PushResult> pushToRemote(File localGitFolder, String userName, String userPassword,
            ProgressMonitor monitor) throws IOException, GitAPIException {
        try (Git git = Git.open(localGitFolder)) {
            PushCommand pushCommand = git.push();
            pushCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(userName, userPassword));
            pushCommand.setProgressMonitor(monitor);
            return pushCommand.call();
        }
    }

    /**
     * Pull from Remote
     * @param localGitFolder
     * @param userName
     * @param userPassword
     * @return 
     * @throws IOException
     * @throws GitAPIException
     */
    public static PullResult pullFromRemote(File localGitFolder, String userName, String userPassword,
            ProgressMonitor monitor) throws IOException, GitAPIException {
        try (Git git = Git.open(localGitFolder)) {
            PullCommand pullCommand = git.pull();
            pullCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(userName, userPassword));
            pullCommand.setRebase(false); // Merge, not rebase
            pullCommand.setProgressMonitor(monitor);
            return pullCommand.call();
        }
    }

    /**
     * Fetch from Remote
     * @param localGitFolder
     * @param userName
     * @param userPassword
     * @throws IOException
     * @throws GitAPIException
     */
    public static FetchResult fetchFromRemote(File localGitFolder, String userName, String userPassword,
            ProgressMonitor monitor) throws IOException, GitAPIException {
        try (Git git = Git.open(localGitFolder)) {
            FetchCommand fetchCommand = git.fetch();
            fetchCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(userName, userPassword));
            fetchCommand.setProgressMonitor(monitor);
            return fetchCommand.call();
        }
    }

    /**
     * Get a local git folder name based on the repo's URL
     * @param repoURL
     * @return
     */
    public static String getLocalGitFolderName(String repoURL) {
        repoURL = repoURL.trim();

        int index = repoURL.lastIndexOf("/"); //$NON-NLS-1$
        if (index > 0 && index < repoURL.length() - 2) {
            repoURL = repoURL.substring(index + 1).toLowerCase();
        }

        index = repoURL.lastIndexOf(".git"); //$NON-NLS-1$
        if (index > 0 && index < repoURL.length() - 1) {
            repoURL = repoURL.substring(0, index);
        }

        return repoURL.replaceAll("[^a-zA-Z0-9-]", "_"); //$NON-NLS-1$ //$NON-NLS-2$
    }

    /**
     * Check if a folder contains a Git repository
     * @param folder
     * @return
     */
    public static boolean isGitRepository(File folder) {
        if (folder == null || !folder.exists() || !folder.isDirectory()) {
            return false;
        }

        // Name of the Git folder
        String GIT_FOLDER = ".git"; //$NON-NLS-1$

        File gitFolder = new File(folder, GIT_FOLDER);

        return gitFolder.exists() && gitFolder.isDirectory();
    }

    /**
     * @param localGitFolder
     * @return True if a model based on the local git folder name is loaded in the models tree
     */
    public static boolean isModelLoaded(File localGitFolder) {
        return IEditorModelManager.INSTANCE.isModelLoaded(getModelFileName(localGitFolder));
    }

    /**
     * Locate a model in the models tree based on its file location
     * @param localGitFolder
     * @return
     */
    public static IArchimateModel locateModel(File localGitFolder) {
        File tmpFileName = getModelFileName(localGitFolder);

        for (IArchimateModel model : IEditorModelManager.INSTANCE.getModels()) {
            if (tmpFileName.equals(model.getFile())) {
                return model;
            }
        }

        return null;
    }

    /**
     * Create a file name to attach to a model. Used to locate a model in the model tree
     * @param localGitFolder
     * @return
     */
    public static File getModelFileName(File localGitFolder) {
        return new File(localGitFolder, "/.git/temp.archimate"); //$NON-NLS-1$
    }

    /**
     * Create a new, local Git repository with name set to "origin"
     * @param localGitFolder
     * @param URL online URL
     * @return The Git object
     * @throws GitAPIException
     * @throws IOException
     * @throws URISyntaxException
     */
    public static Git createNewLocalGitRepository(File localGitFolder, String URL)
            throws GitAPIException, IOException, URISyntaxException {
        if (localGitFolder.exists() && localGitFolder.list().length > 0) {
            throw new IOException("Directory: " + localGitFolder + " is not empty."); //$NON-NLS-1$ //$NON-NLS-2$
        }

        InitCommand initCommand = Git.init();
        initCommand.setDirectory(localGitFolder);
        Git git = initCommand.call();

        RemoteAddCommand remoteAddCommand = git.remoteAdd();
        remoteAddCommand.setName("origin"); //$NON-NLS-1$
        remoteAddCommand.setUri(new URIish(URL));
        remoteAddCommand.call();

        return git;
    }

    /**
     * Return the URL of the Git repo, taken from local config file.
     * We assume that there is only one remote per repo, and its name is "origin"
     * @param localGitFolder
     * @return The URL or null if not found
     * @throws IOException
     */
    public static String getRepositoryURL(File localGitFolder) throws IOException {
        try (Git git = Git.open(localGitFolder)) {
            return git.getRepository().getConfig().getString("remote", "origin", "url"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        }
    }

    /**
     * Retune the contents of a file in the repo given its ref
     * Ref could be "HEAD" or "origin/master" for example
     * @param localGitFolder
     * @param path
     * @param ref
     * @return
     * @throws IOException
     */
    public static String getFileContents(File localGitFolder, String path, String ref) throws IOException {
        String str = ""; //$NON-NLS-1$

        try (Repository repository = Git.open(localGitFolder).getRepository()) {
            ObjectId lastCommitId = repository.resolve(ref);

            try (RevWalk revWalk = new RevWalk(repository)) {
                RevCommit commit = revWalk.parseCommit(lastCommitId);
                RevTree tree = commit.getTree();

                // now try to find a specific file
                try (TreeWalk treeWalk = new TreeWalk(repository)) {
                    treeWalk.addTree(tree);
                    treeWalk.setRecursive(true);
                    treeWalk.setFilter(PathFilter.create(path));

                    if (!treeWalk.next()) {
                        return Messages.GraficoUtils_2;
                    }

                    ObjectId objectId = treeWalk.getObjectId(0);
                    ObjectLoader loader = repository.open(objectId);

                    str = new String(loader.getBytes());
                }

                revWalk.dispose();
            }
        }

        return str;
    }

    /**
     * Get the file contents of a file in the working tree
     * @param localGitFolder
     * @param path
     * @return
     * @throws IOException
     */
    public static String getWorkingTreeFileContents(File localGitFolder, String path) throws IOException {
        String str = ""; //$NON-NLS-1$

        try (Git git = Git.open(localGitFolder)) {
            try (BufferedReader in = new BufferedReader(new FileReader(new File(localGitFolder, path)))) {
                String line;
                while ((line = in.readLine()) != null) {
                    str += line + "\n"; //$NON-NLS-1$
                }
            }
        }

        return str;
    }

}