org.jahia.services.templates.SourceControlFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.jahia.services.templates.SourceControlFactory.java

Source

/**
 * ==========================================================================================
 * =                   JAHIA'S DUAL LICENSING - IMPORTANT INFORMATION                       =
 * ==========================================================================================
 *
 *                                 http://www.jahia.com
 *
 *     Copyright (C) 2002-2017 Jahia Solutions Group SA. All rights reserved.
 *
 *     THIS FILE IS AVAILABLE UNDER TWO DIFFERENT LICENSES:
 *     1/GPL OR 2/JSEL
 *
 *     1/ GPL
 *     ==================================================================================
 *
 *     IF YOU DECIDE TO CHOOSE THE GPL LICENSE, YOU MUST COMPLY WITH THE FOLLOWING TERMS:
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *     2/ JSEL - Commercial and Supported Versions of the program
 *     ===================================================================================
 *
 *     IF YOU DECIDE TO CHOOSE THE JSEL LICENSE, YOU MUST COMPLY WITH THE FOLLOWING TERMS:
 *
 *     Alternatively, commercial and supported versions of the program - also known as
 *     Enterprise Distributions - must be used in accordance with the terms and conditions
 *     contained in a separate written agreement between you and Jahia Solutions Group SA.
 *
 *     If you are unsure which license is appropriate for your use,
 *     please contact the sales department at sales@jahia.com.
 */
package org.jahia.services.templates;

import java.io.File;
import java.io.IOException;
import java.util.*;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.io.FileUtils;
import org.jahia.utils.StringOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Source control management central factory class responsible for checking out a remote SCM repository content and instantiating
 * {@link SourceControlManagement} helpers for SCM operations on module's sources.
 */
public class SourceControlFactory {

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

    private Map<String, String> sourceControlExecutables;

    private List<String> ignoredFiles;

    public List<String> getIgnoredFiles() {
        return ignoredFiles;
    }

    public void setIgnoredFiles(List<String> ignoredFiles) {
        this.ignoredFiles = ignoredFiles;
    }

    /**
     * Performs checkout of the remote SCM content into the provided working directory.
     * 
     * @param workingDir
     *            working directory to perform checkout into
     * @param scmURI
     *            the remote SCM repository URL
     * @param branchOrTag
     *            the name of the remote branch or tag if any
     * @return an instance of the {@link SourceControlManagement} helper for the checked out content
     * @throws IOException
     *             in case of communication errors
     */
    public SourceControlManagement checkoutRepository(File workingDir, String scmURI, String branchOrTag,
            boolean initRepository) throws IOException {
        SourceControlManagement scm = getSCM(scmURI);
        if (scm != null) {
            String scmUrl = getScmURL(scmURI);
            if (initRepository) {
                addIgnore(workingDir);
                scm.sendToSCM(workingDir, scmUrl);
            } else {
                scm.getFromSCM(workingDir, scmUrl, branchOrTag);
            }
        }
        return scm;
    }

    private void addIgnore(File path) throws IOException {
        File ignore = new File(path, ".gitignore");
        List<String> lines;
        if (ignore.exists()) {
            lines = FileUtils.readLines(ignore, "UTF-8");
        } else {
            lines = new ArrayList<>();
        }
        for (String ignoredFile : ignoredFiles) {
            if (!lines.contains(ignoredFile)) {
                lines.add(ignoredFile);
            }
        }
        FileUtils.writeLines(ignore, "UTF-8", lines);
    }

    /**
     * List all available tags on distant repository
     * @param scmURI the remote SCM repository URI (of the trunk for SVN)
     * @return a map tag/uri
     * @throws IOException
     */
    public Map<String, String> listTags(String scmURI) throws IOException {
        SourceControlManagement scm = getSCM(scmURI);
        if (scm != null) {
            String scmUrl = getScmURL(scmURI);
            return scm.getTagInfos(scmUrl);
        }
        return null;
    }

    /**
     * List all available branches on distant repository
     * @param scmURI the remote SCM repository URI (of the trunk for SVN)
     * @return a map tag/uri
     * @throws IOException
     */
    public Map<String, String> listBranches(String scmURI) throws IOException {
        SourceControlManagement scm = getSCM(scmURI);
        if (scm != null) {
            String scmUrl = getScmURL(scmURI);
            return scm.getBranchInfos(scmUrl);
        }
        return null;
    }

    private SourceControlManagement getSCM(String scmURI) throws IOException {
        SourceControlManagement scm = null;
        if (scmURI.startsWith("scm:")) {
            String scmProvider = scmURI.substring(4, scmURI.indexOf(":", 4));
            if (scmProvider.equals("git") && sourceControlExecutables.containsKey("git")) {
                scm = new GitSourceControlManagement(sourceControlExecutables.get("git"));
            } else if (scmProvider.equals("svn") && sourceControlExecutables.containsKey("svn")) {
                scm = new SvnSourceControlManagement(sourceControlExecutables.get("svn"));
            } else {
                throw new IOException("Unknown repository type");
            }
        }
        return scm;
    }

    private String getScmURL(String scmURI) {
        return scmURI.substring(scmURI.indexOf(":", 4) + 1);
    }

    /**
     * Returns a registry of executables (paths to the SCM executables) by SCM type.
     * 
     * @return a registry of executables (paths to the SCM executables) by SCM type
     */
    public Map<String, String> getSourceControlExecutables() {
        return sourceControlExecutables;
    }

    /**
     * Returns an instance of the {@link SourceControlManagement} helper for the specified working directory.
     * 
     * @param workingDir
     *            the working directory to get SCM helper for
     * @return an instance of the {@link SourceControlManagement} helper for the specified working directory
     * @throws IOException
     *             in case of I/O errors
     */
    public SourceControlManagement getSourceControlManagement(File workingDir) throws IOException {
        SourceControlManagement scm = null;
        File dir = workingDir;
        do {
            if (new File(dir, ".git").exists()) {
                if (!sourceControlExecutables.containsKey("git")) {
                    // no git SCM provider found
                    break;
                }
                scm = new GitSourceControlManagement(sourceControlExecutables.get("git"));
            } else if (new File(dir, ".svn").exists()) {
                if (!sourceControlExecutables.containsKey("svn")) {
                    // no SVN SCM provider found
                    break;
                }
                scm = new SvnSourceControlManagement(sourceControlExecutables.get("svn"));
            } else {
                dir = dir.getParentFile();
            }
        } while (scm == null && dir != null);

        if (scm != null) {
            scm.initWithWorkingDirectory(workingDir);
        }
        return scm;
    }

    /**
     * Returns a set of supported SCM types.
     * 
     * @return a set of supported SCM types
     */
    public Set<String> getSupportedSourceControls() {
        return sourceControlExecutables.keySet();
    }

    /**
     * Sets the executables for various SCM providers.
     * 
     * @param sourceControlExecutables
     *            a map with paths to SCM executables by SCM type
     */
    public void setSourceControlExecutables(Map<String, String> sourceControlExecutables) {
        this.sourceControlExecutables = new HashMap<String, String>();
        for (Map.Entry<String, String> entry : sourceControlExecutables.entrySet()) {
            try {
                DefaultExecutor executor = new DefaultExecutor();
                executor.setStreamHandler(
                        new PumpStreamHandler(new StringOutputStream(), new StringOutputStream()));
                executor.execute(new CommandLine(entry.getValue()), System.getenv());
            } catch (ExecuteException e) {
                // ignore this one as the command always returns error code 1
            } catch (IOException e) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Unable to execute the " + entry.getKey() + " SCM executable: " + entry.getValue()
                            + ". The SCM provider will be disabled. Cause: " + e.getMessage(), e);
                } else {
                    logger.info("Cannot find a valid " + entry.getKey() + " SCM executable at: " + entry.getValue()
                            + ". The SCM provider will be skipped.");
                }
                continue;
            }
            this.sourceControlExecutables.put(entry.getKey(), entry.getValue());
        }
    }
}