All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kuali.maven.plugins.jenkins.helper.JenkinsHelper Maven / Gradle / Ivy

/**
 * Copyright 2011-2011 The Kuali Foundation
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.opensource.org/licenses/ecl2.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.kuali.maven.plugins.jenkins.helper;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.StringUtils;
import org.kuali.maven.common.Extractor;
import org.kuali.maven.common.PropertiesUtils;
import org.kuali.maven.common.ResourceUtils;
import org.kuali.maven.plugins.jenkins.BaseMojo;
import org.kuali.maven.plugins.jenkins.CliMojo;
import org.kuali.maven.plugins.jenkins.Command;
import org.kuali.maven.plugins.jenkins.DeleteJobMojo;
import org.kuali.maven.plugins.jenkins.DeleteJobsMojo;
import org.kuali.maven.plugins.jenkins.GenJobMojo;
import org.kuali.maven.plugins.jenkins.GenJobsMojo;
import org.kuali.maven.plugins.jenkins.GetJobMojo;
import org.kuali.maven.plugins.jenkins.GetJobsMojo;
import org.kuali.maven.plugins.jenkins.PushJobsMojo;
import org.kuali.maven.plugins.jenkins.RunJobCommand;
import org.kuali.maven.plugins.jenkins.RunJobMojo;
import org.kuali.maven.plugins.jenkins.RunJobsMojo;
import org.kuali.maven.plugins.jenkins.SimpleJobCommand;
import org.kuali.maven.plugins.jenkins.context.GAV;
import org.kuali.maven.plugins.jenkins.context.JenkinsException;
import org.kuali.maven.plugins.jenkins.context.ProcessContext;
import org.kuali.maven.plugins.jenkins.context.ProcessResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JenkinsHelper {

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

    public static final String XML_EXTENSION = ".xml";
    public static final int SUCCESS_CODE = 0;
    public static final int NO_SUCH_COMMAND = 255;
    public static final String SERVER_ARG = "-s";
    public static final String NONE = "NONE";
    public static final String DASH = "-";
    public static final String FS = System.getProperty("file.separator");

    Extractor extractor = new Extractor();
    PropertiesUtils propertiesUtils = new PropertiesUtils();
    ResourceUtils resourceUtils = new ResourceUtils();
    JavaHelper javaHelper = new JavaHelper();
    CommandHelper cmdHelper = new CommandHelper();

    protected List getNamesList(String csvNames, List names) {
        if (!Helper.isEmpty(names)) {
            return names;
        } else {
            return Helper.splitAndTrimCSVToList(csvNames);
        }
    }

    protected List getJobNames(BaseMojo mojo, String csvNames, List names) {
        List namesList = getNamesList(csvNames, names);
        List newNames = new ArrayList();
        for (String name : namesList) {
            String newName = getJobName(mojo, name);
            newNames.add(newName);
        }
        return newNames;
    }

    public void execute(GetJobMojo mojo) {
        List jobNames = getJobNames(mojo, mojo.getName(), null);
        List commands = createGetJobCommands(mojo, mojo.getCmd(), jobNames);
        executeCli(mojo, commands);
    }

    public void execute(GetJobsMojo mojo) {
        List jobNames = getJobNames(mojo, mojo.getNames(), mojo.getNameList());
        List commands = createGetJobCommands(mojo, mojo.getCmd(), jobNames);
        executeCli(mojo, commands);
    }

    protected List createGetJobCommands(BaseMojo mojo, String cmd, List jobNames) {
        List commands = new ArrayList();
        for (String jobName : jobNames) {
            Command command = createGetJobCommand(mojo, cmd, jobName);
            commands.add(command);
        }
        return commands;
    }

    protected Command createGetJobCommand(BaseMojo mojo, String cmd, String jobName) {
        String filename = mojo.getWorkingDir() + FS + jobName + XML_EXTENSION;
        String[] args = { cmd, jobName };
        Command command = new Command();
        command.setArgs(Arrays.asList(args));
        command.setStdout(new File(filename));
        return command;
    }

    protected GAV getGav(Properties properties) {
        String groupId = properties.getProperty("jenkins.cli.groupId");
        String artifactId = properties.getProperty("jenkins.cli.artifactId");
        String version = properties.getProperty("jenkins.cli.version");
        if (Helper.anyAreBlank(groupId, artifactId, version)) {
            return null;
        }
        GAV gav = new GAV();
        gav.setVersion(version);
        gav.setArtifactId(artifactId);
        gav.setGroupId(groupId);
        return gav;
    }

    protected GAV getGav(Artifact artifact) {
        GAV gav = new GAV();
        gav.setGroupId(artifact.getGroupId());
        gav.setArtifactId(artifact.getArtifactId());
        gav.setVersion(artifact.getVersion());
        return gav;
    }

    protected GAV getGav(MavenProject project) {
        try {
            String location = "classpath:org/kuali/maven/plugins/jenkins/jenkins-cli.properties";
            Properties internal = propertiesUtils.getProperties(location);
            GAV internalGAV = getGav(internal);
            GAV overrideGAV = getGav(project.getProperties());

            GAV gav = internalGAV;
            if (overrideGAV != null && !internalGAV.equals(overrideGAV)) {
                logger.info("Jenkins CLI override: [internal=" + internalGAV + ", override=" + overrideGAV + "]");
                gav = overrideGAV;
            }
            return gav;
        } catch (IOException e) {
            throw new JenkinsException(e);
        }

    }

    protected File getJenkinsJar(MavenProject project, List pluginArtifacts) {
        GAV gav = getGav(project);
        File jar = getJar(gav, pluginArtifacts);
        if (jar == null) {
            throw new JenkinsException("Unable to locate jenkins-cli.jar");
        } else {
            return jar;
        }
    }

    protected File getJar(GAV gav, List artifacts) {
        for (Artifact artifact : artifacts) {
            if (equals(artifact, gav)) {
                return artifact.getFile();
            }
        }
        return null;
    }

    protected boolean equals(Artifact artifact, GAV gav) {
        GAV artifactGav = getGav(artifact);
        return artifactGav.equals(gav);
    }

    protected List getFiles(File workingDir) {
        if (!workingDir.exists()) {
            return new ArrayList();
        }
        FileFilter filter = new XmlFileFilter();
        File[] files = workingDir.listFiles(filter);
        return Arrays.asList(files);
    }

    protected void pushJobs(BaseMojo mojo, String cmd) {
        try {
            List commands = getCommands(mojo.getWorkingDir(), cmd);
            executeCli(mojo, commands);
        } catch (IOException e) {
            throw new JenkinsException(e);
        }

    }

    protected List getCommands(File workingDir, String cmd) throws IOException {
        List files = getFiles(workingDir);
        List commands = new ArrayList();
        for (File file : files) {
            Command command = getCommand(file, cmd);
            commands.add(command);
        }
        return commands;
    }

    protected String getJobName(File file) {
        String name = file.getName();
        int pos = name.lastIndexOf(XML_EXTENSION);
        return name.substring(0, pos);
    }

    protected Command getCommand(File file, String cmd) throws IOException {
        String stdin = resourceUtils.read(file.getAbsolutePath());
        String jobName = getJobName(file);
        String[] args = { cmd, jobName };
        Command command = new Command();
        command.setStdin(stdin);
        command.setArgs(Arrays.asList(args));
        return command;
    }

    protected String getInput(Command cmd) {
        if (!StringUtils.isBlank(cmd.getStdinUrl())) {
            try {
                return resourceUtils.read(cmd.getStdinUrl());
            } catch (IOException e) {
                throw new JenkinsException(e);
            }
        } else {
            return cmd.getStdin();
        }
    }

    protected ProcessResult executeCli(File jar, String url, Command cmd) {
        String input = getInput(cmd);
        return executeCli(jar, url, cmd.getArgs(), input);
    }

    protected ProcessResult executeCli(File jar, String url, List args, String input) {
        String[] cliArgs = getCliArgs(url, args);
        return javaHelper.executeJar(jar, cliArgs, input);
    }

    protected String[] getCliArgs(String url, List args) {
        List list = new ArrayList();
        list.add(SERVER_ARG);
        list.add(url);
        list.addAll(args);
        return Helper.toArray(list);
    }

    protected int[] getSuccessCodes(BaseMojo mojo) {
        String csv = mojo.getSuccessCodes();
        return Helper.toIntArray(csv);
    }

    protected void handleResult(Command command, ProcessResult result, BaseMojo mojo) {
        int[] successCodes = getSuccessCodes(mojo);
        int exitValue = result.getExitValue();
        if (Helper.isMatch(exitValue, successCodes)) {
            handleSuccess(mojo, command, result);
        } else {
            handleFailure(mojo, result);
        }
    }

    protected void logInfo(List lines) {
        if (lines.size() == 0) {
            return;
        }
        for (String line : lines) {
            logger.info(line);
        }
    }

    protected void logError(List lines) {
        String top = getTop(lines);
        if (top != null) {
            logger.error(top);
        }
    }

    protected void logWarning(List lines) {
        String top = getTop(lines);
        if (top != null) {
            logger.warn(top);
        }
    }

    protected String getTop(List lines) {
        for (String line : lines) {
            if (!StringUtils.isBlank(line)) {
                return line;
            }
        }
        return null;
    }

    protected void handleFailure(BaseMojo mojo, ProcessResult result) {
        if (mojo.isStopOnError()) {
            logger.error("Jenkins CLI Exception:" + getErrorMessage(mojo, result));
            throw new JenkinsException("Jenkins CLI Exception");
        } else {
            if (mojo.isFailOnError()) {
                logError(result.getOutputLines());
            } else {
                logWarning(result.getOutputLines());
            }
        }
    }

    protected void handleSuccess(BaseMojo mojo, Command command, ProcessResult result) {
        File stdout = command.getStdout();
        if (stdout != null) {
            write(stdout.getAbsolutePath(), result.getOutput());
        } else {
            List lines = result.getOutputLines();
            if (result.getExitValue() == SUCCESS_CODE) {
                logInfo(lines);
            } else {
                String top = getTop(lines);
                if (top != null) {
                    logger.info(top);
                }
            }
        }
    }

    protected void write(String filename, String content) {
        try {
            resourceUtils.write(filename, content);
        } catch (IOException e) {
            throw new JenkinsException(e);
        }
    }

    protected Map getBuildParameters(Map map, String csv) {
        Map buildParameters = new HashMap();
        if (!Helper.isEmpty(map)) {
            buildParameters.putAll(map);
        }
        if (!StringUtils.isBlank(csv)) {
            String[] keyValuePairs = Helper.splitAndTrimCSV(csv);
            Map csvMap = Helper.toMap(keyValuePairs);
            buildParameters.putAll(csvMap);
        }
        return buildParameters;
    }

    protected RunJobCommand getRunJobCommand(RunJobMojo mojo, String jobName, Map params) {
        RunJobCommand rjc = new RunJobCommand();
        rjc.setName(jobName);
        rjc.setParams(params);
        rjc.setCommand(mojo.getCmd());
        rjc.setWait(mojo.isWait());
        rjc.setSkipIfNoChanges(mojo.isSkipIfNoChanges());
        return rjc;
    }

    public void updateMojo(BaseMojo mojo) {
        MavenProject project = mojo.getProject();
        String scmType = extractor.getScmType(project.getScm());
        String scmUrl = extractor.getScmUrl(project.getScm());
        String majorVersion = extractor.getMajorVersion(project.getVersion());

        if (StringUtils.isBlank(mojo.getScmType())) {
            mojo.setScmType(scmType);
        }
        if (StringUtils.isBlank(mojo.getScmUrl())) {
            mojo.setScmUrl(scmUrl);
        }
        if (StringUtils.isBlank(mojo.getMajorVersion())) {
            mojo.setMajorVersion(majorVersion);
        }
    }

    public void execute(DeleteJobMojo mojo) {
        String ignoreCodes = mojo.getIgnoreCodes();
        String successCodes = mojo.getSuccessCodes();
        String newSuccessCodes = successCodes + "," + ignoreCodes;
        mojo.setSuccessCodes(newSuccessCodes);
        String jobName = getJobName(mojo, mojo.getName());
        SimpleJobCommand sjc = getSimpleJobCommand(jobName, mojo.getCmd());
        Command command = new Command();
        command.setArgs(cmdHelper.toArgs(sjc));
        executeCli(mojo, command);
    }

    protected List getSimpleJobCommands(List names, String cmd) {
        List commands = new ArrayList();
        for (String name : names) {
            SimpleJobCommand sjc = getSimpleJobCommand(name, cmd);
            commands.add(sjc);
        }
        return commands;
    }

    protected SimpleJobCommand getSimpleJobCommand(String name, String cmd) {
        SimpleJobCommand sjc = new SimpleJobCommand();
        sjc.setName(name);
        sjc.setCommand(cmd);
        return sjc;
    }

    public void execute(DeleteJobsMojo mojo) {
        String ignoreCodes = mojo.getIgnoreCodes();
        String successCodes = mojo.getSuccessCodes();
        String newSuccessCodes = successCodes + "," + ignoreCodes;
        mojo.setSuccessCodes(newSuccessCodes);
        List jobNames = getJobNames(mojo, mojo.getNames(), mojo.getNameList());
        List sjcs = getSimpleJobCommands(jobNames, mojo.getCmd());
        List commands = getCommandsFromSimple(sjcs);
        executeCli(mojo, commands);
    }

    public void execute(RunJobMojo mojo) {
        String jobName = getJobName(mojo, mojo.getName());
        Map params = getBuildParameters(mojo.getParamMap(), mojo.getParams());
        RunJobCommand rjc = getRunJobCommand(mojo, jobName, params);
        Command command = new Command();
        command.setArgs(cmdHelper.toArgs(rjc));
        executeCli(mojo, command);
    }

    protected void updateCommands(List commands, String cmd, BaseMojo mojo) {
        for (RunJobCommand command : commands) {
            String name = getJobName(mojo, command.getName());
            command.setName(name);
            command.setCommand(cmd);
        }
    }

    protected List getCommandsFromSimple(List sjcs) {
        List commands = new ArrayList();
        for (SimpleJobCommand sjc : sjcs) {
            Command command = new Command();
            command.setArgs(cmdHelper.toArgs(sjc));
            commands.add(command);
        }
        return commands;
    }

    protected List getCommands(List rjcs) {
        List commands = new ArrayList();
        for (RunJobCommand rjc : rjcs) {
            Command command = new Command();
            command.setArgs(cmdHelper.toArgs(rjc));
            commands.add(command);
        }
        return commands;
    }

    public void execute(RunJobsMojo mojo) {
        // nothing to do
        if (Helper.isEmpty(mojo.getCommands())) {
            return;
        }
        updateCommands(mojo.getCommands(), mojo.getCmd(), mojo);
        List commands = getCommands(mojo.getCommands());
        executeCli(mojo, commands);
    }

    public void execute(PushJobsMojo mojo) {
        pushJobs(mojo, mojo.getCmd());
    }

    public void execute(CliMojo mojo) {
        List cmds = cmdHelper.getCommands(mojo);
        executeCli(mojo, cmds);
    }

    protected void executeCli(BaseMojo mojo, Command command) {
        executeCli(mojo, Helper.toList(command));
    }

    protected void executeCli(BaseMojo mojo, List commands) {
        File jar = getJenkinsJar(mojo.getProject(), mojo.getPluginArtifacts());
        String url = mojo.getUrl();
        logger.info("Jenkins CLI: " + jar.getPath());
        logger.info("Jenkins URL: " + url);
        List results = new ArrayList();
        for (Command command : commands) {
            logger.info(Helper.toString(command.getArgs()));
            ProcessResult result = executeCli(jar, url, command);
            handleResult(command, result, mojo);
            results.add(result);
        }
        handleResults(results, mojo);
    }

    protected void handleResults(List results, BaseMojo mojo) {
        int[] successCodes = getSuccessCodes(mojo);
        List errors = new ArrayList();
        for (ProcessResult result : results) {
            int exitValue = result.getExitValue();
            if (!Helper.isMatch(exitValue, successCodes)) {
                errors.add(result);
            }
        }
        if (errors.size() == 0) {
            return;
        }
        if (mojo.isFailOnError()) {
            logger.error(getErrorMessage(mojo, errors));
            throw new JenkinsException("Jenkins CLI error");
        } else {
            logger.warn(getWarnMessage(errors));
        }
    }

    protected String getWarnMessage(List errors) {
        StringBuilder sb = new StringBuilder();
        if (errors.size() == 1) {
            sb.append("There was 1 error.");
        } else {
            sb.append("There were " + errors.size() + " errors.");
        }
        return sb.toString();
    }

    protected String getErrorMessage(BaseMojo mojo, List errors) {
        StringBuilder sb = new StringBuilder();
        if (errors.size() == 1) {
            sb.append("There was 1 error.");
        } else {
            sb.append("There were " + errors.size() + " errors.");
        }
        for (ProcessResult result : errors) {
            sb.append(getErrorMessage(mojo, result));
        }
        return sb.toString();
    }

    protected String getErrorMessage(BaseMojo mojo, ProcessResult result) {
        ProcessContext context = result.getContext();
        int exitValue = result.getExitValue();
        String top = getTop(result.getOutputLines());
        String[] args = result.getContext().getArgs();
        String cmd = Helper.toString(args, " ");
        StringBuilder sb = new StringBuilder();
        sb.append("\n");
        sb.append("msg: " + top + "\n");
        sb.append("executable: " + context.getExecutable() + "\n");
        sb.append("cmd: " + cmd + "\n");
        sb.append("result: " + exitValue + "\n");
        sb.append("input: " + getInputErrorMessage(mojo, context.getInput()) + "\n");
        if (exitValue != NO_SUCH_COMMAND) {
            sb.append("details: " + result.getOutput());
        }
        return sb.toString();
    }

    protected String getInputErrorMessage(BaseMojo mojo, String input) {
        String s = Helper.toEmpty(input);
        if (StringUtils.isBlank(s)) {
            return s;
        }
        int length = input.length();
        if (length > 50) {
            long count = Counter.increment() + 1;
            File dir = mojo.getWorkingDir();
            String filename = dir + FS + "error" + FS + "input-" + count + ".log";
            File file = new File(filename);
            write(filename, input);
            return Helper.getRelativePath(mojo.getProject().getBasedir(), file);
        } else {
            return input;
        }
    }

    public void execute(GenJobsMojo mojo) {
        List types = Helper.splitAndTrimCSVToList(mojo.getTypes());
        generateJobs(mojo, types);
    }

    public void execute(GenJobMojo mojo) {
        generateJob(mojo, mojo.getType());
    }

    protected void generateJobs(BaseMojo mojo, List types) {
        for (String type : types) {
            generateJob(mojo, type);
        }
    }

    protected String getRelativePath(BaseMojo mojo, String filename) {
        File dir = mojo.getProject().getBasedir();
        File file = new File(filename);
        String relativePath = Helper.getRelativePath(dir, file);
        if (relativePath == null) {
            return filename;
        } else {
            return relativePath;
        }
    }

    protected void generateJob(BaseMojo mojo, String type) {
        try {
            String jobName = getJobName(mojo, type);
            String filename = mojo.getWorkingDir() + FS + jobName + XML_EXTENSION;
            String relativePath = getRelativePath(mojo, filename);
            mojo.getLog().info("Generating: " + relativePath);
            Properties properties = getProperties(mojo, type, mojo.getTimestampFormat());
            String xml = resourceUtils.read(mojo.getTemplate());
            String resolvedXml = propertiesUtils.getResolvedValue(xml, properties);
            resourceUtils.write(filename, resolvedXml);
        } catch (IOException e) {
            throw new JenkinsException(e);
        }
    }

    protected boolean isKnownJobType(BaseMojo mojo, String name) {
        String jobTypes = mojo.getJobTypes();
        if (StringUtils.isBlank(jobTypes)) {
            return false;
        }
        if (NONE.equalsIgnoreCase(jobTypes)) {
            return false;
        }
        List jobTypesList = Helper.splitAndTrimCSVToList(mojo.getJobTypes());
        return jobTypesList.contains(name);
    }

    protected String getJobName(BaseMojo mojo, String name) {
        if (isKnownJobType(mojo, name)) {
            StringBuilder sb = new StringBuilder();
            sb.append(mojo.getProject().getArtifactId());
            sb.append(DASH);
            sb.append(mojo.getMajorVersion());
            sb.append(DASH);
            sb.append(name);
            return sb.toString();
        } else {
            return name;
        }
    }

    protected Properties getProperties(BaseMojo mojo, String type, String timestampFormat) throws IOException {

        List locations = getLocations(mojo, type);
        Properties resourceProperties = propertiesUtils.getProperties(locations);
        Properties jenkinsProperties = getJenkinsProperties(mojo, timestampFormat);
        Properties projectProperties = mojo.getProject().getProperties();
        Properties environmentProperties = propertiesUtils.getEnvironmentProperties();
        Properties systemProperties = System.getProperties();

        Properties properties = new Properties();
        properties.putAll(resourceProperties);
        properties.putAll(jenkinsProperties);
        properties.putAll(projectProperties);
        properties.putAll(environmentProperties);
        properties.putAll(systemProperties);
        return properties;
    }

    protected Properties getJenkinsProperties(BaseMojo mojo, String timestampFormat) {
        SimpleDateFormat sdf = new SimpleDateFormat(timestampFormat);
        Date now = new Date(System.currentTimeMillis());
        MavenProject project = mojo.getProject();
        Properties properties = new Properties();
        properties.setProperty("jenkins.project.scmType", mojo.getScmType());
        properties.setProperty("jenkins.project.scmUrl", mojo.getScmUrl());
        properties.setProperty("jenkins.project.majorVersion", mojo.getMajorVersion());
        properties.setProperty("jenkins.project.groupId", project.getGroupId());
        properties.setProperty("jenkins.project.artifactId", project.getArtifactId());
        properties.setProperty("jenkins.build.timestamp", sdf.format(now));
        return properties;
    }

    protected List getLocations(BaseMojo mojo, String type) {
        List locations = new ArrayList();
        locations.add("classpath:org/kuali/jenkins/jobs/properties/common.xml");
        locations.add("classpath:org/kuali/jenkins/jobs/properties/" + mojo.getScmType() + XML_EXTENSION);
        locations.add("classpath:org/kuali/jenkins/jobs/properties/types/" + type + XML_EXTENSION);
        return locations;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy