Package org.jfrog.gradle.plugin.artifactory.task

Source Code of org.jfrog.gradle.plugin.artifactory.task.BuildInfoBaseTask

package org.jfrog.gradle.plugin.artifactory.task;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import groovy.lang.Closure;
import org.apache.commons.lang.StringUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.logging.LogLevel;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.TaskAction;
import org.gradle.util.ConfigureUtil;
import org.jfrog.build.api.Build;
import org.jfrog.build.api.BuildInfoConfigProperties;
import org.jfrog.build.client.ArtifactSpec;
import org.jfrog.build.client.ArtifactSpecs;
import org.jfrog.build.client.ArtifactoryBuildInfoClient;
import org.jfrog.build.client.ArtifactoryClientConfiguration;
import org.jfrog.build.client.DeployDetails;
import org.jfrog.build.client.IncludeExcludePatterns;
import org.jfrog.build.client.PatternMatcher;
import org.jfrog.build.extractor.BuildInfoExtractorUtils;
import org.jfrog.gradle.plugin.artifactory.ArtifactoryPluginUtil;
import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention;
import org.jfrog.gradle.plugin.artifactory.dsl.PropertiesConfig;
import org.jfrog.gradle.plugin.artifactory.dsl.PublisherConfig;
import org.jfrog.gradle.plugin.artifactory.extractor.GradleArtifactoryClientConfigUpdater;
import org.jfrog.gradle.plugin.artifactory.extractor.GradleBuildInfoExtractor;
import org.jfrog.gradle.plugin.artifactory.extractor.GradleClientLogger;
import org.jfrog.gradle.plugin.artifactory.extractor.GradleDeployDetails;
import org.jfrog.gradle.plugin.artifactory.extractor.PublishArtifactInfo;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* Date: 3/20/13 Time: 10:32 AM
*
* @author freds
*/
public abstract class BuildInfoBaseTask extends DefaultTask {
    private static final Logger log = Logging.getLogger(BuildInfoBaseTask.class);

    public static final String BUILD_INFO_TASK_NAME = "artifactoryPublish";
    public static final String PUBLISH_ARTIFACTS = "publishArtifacts";
    public static final String PUBLISH_BUILD_INFO = "publishBuildInfo";
    public static final String ARCHIVES_BASE_NAME = "archivesBaseName";

    @Input
    protected final Multimap<String, CharSequence> properties = ArrayListMultimap.create();

    @Input
    protected final ArtifactSpecs artifactSpecs = new ArtifactSpecs();

    @Input
    private boolean skip = false;

    private final Map<String, Boolean> flags = Maps.newHashMap();

    protected Map<String, String> defaultProps;

    protected final Set<GradleDeployDetails> deployDetails = Sets.newHashSet();

    @Input
    @Optional
    @Nullable
    public Boolean getPublishBuildInfo() {
        return getFlag(PUBLISH_BUILD_INFO);
    }

    public void setPublishBuildInfo(Object publishBuildInfo) {
        setFlag(PUBLISH_BUILD_INFO, toBoolean(publishBuildInfo));
    }

    @Input
    @Optional
    @Nullable
    public Boolean getPublishArtifacts() {
        return getFlag(PUBLISH_ARTIFACTS);
    }

    public void setPublishArtifacts(Object publishArtifacts) {
        setFlag(PUBLISH_ARTIFACTS, toBoolean(publishArtifacts));
    }

    protected Boolean toBoolean(Object publishIvy) {
        return Boolean.valueOf(publishIvy.toString());
    }

    @Nullable
    protected Boolean getFlag(String flagName) {
        return flags.get(flagName);
    }

    protected void setFlag(String flagName, Boolean newValue) {
        flags.put(flagName, newValue);
    }

    public boolean isSkip() {
        return skip;
    }

    public void setSkip(boolean skip) {
        this.skip = skip;
    }

    public Set<GradleDeployDetails> getDeployDetails() {
        return deployDetails;
    }

    public void setProperties(Map<String, CharSequence> props) {
        if (props == null || props.isEmpty()) {
            return;
        }
        for (Map.Entry<String, CharSequence> entry : props.entrySet()) {
            // The key cannot be lazy eval, but we keep the value as GString as long as possible
            String key = entry.getKey();
            if (StringUtils.isNotBlank(key)) {
                CharSequence value = entry.getValue();
                if (value != null) {
                    // Make sure all GString are now Java Strings for key,
                    // and don't call toString for value (keep lazy eval as long as possible)
                    // So, don't use HashMultimap this will call equals on the GString
                    this.properties.put(key, value);
                }
            }
        }
    }

    //For testing
    public ArtifactSpecs getArtifactSpecs() {
        return artifactSpecs;
    }

    public void projectsEvaluated() {
        Project project = getProject();
        if (isSkip()) {
            log.debug("Artifactory plugin artifactoryPublish task '{}' skipped for project '{}'.",
                    this.getPath(), project.getName());
            return;
        }
        ArtifactoryPluginConvention convention = ArtifactoryPluginUtil.getArtifactoryConvention(project);
        ArtifactoryClientConfiguration acc = convention.getClientConfig();
        artifactSpecs.addAll(acc.publisher.getArtifactSpecs());

        //Configure the task using the defaults closure (delegate to the task)
        PublisherConfig config = convention.getPublisherConfig();
        if (config != null) {
            Closure defaultsClosure = config.getDefaultsClosure();
            ConfigureUtil.configure(defaultsClosure, this);
        }

        //Depend on buildInfo task in sub-projects
        for (Project sub : project.getSubprojects()) {
            Task subBiTask = sub.getTasks().findByName(BUILD_INFO_TASK_NAME);
            if (subBiTask != null) {
                dependsOn(subBiTask);
            }
        }

        checkDependsOnArtifactsToPublish(project, acc);
    }

    protected abstract void checkDependsOnArtifactsToPublish(Project project, ArtifactoryClientConfiguration acc);

    @Nonnull
    protected Boolean isPublishArtifacts(ArtifactoryClientConfiguration acc) {
        Boolean publishArtifacts = getPublishArtifacts();
        if (publishArtifacts == null) {
            return acc.publisher.isPublishArtifacts();
        }
        return publishArtifacts;
    }

    @Nonnull
    protected Boolean isPublishBuildInfo(ArtifactoryClientConfiguration acc) {
        Boolean publishBuildInfo = getPublishBuildInfo();
        if (publishBuildInfo == null) {
            return acc.publisher.isPublishBuildInfo();
        }
        return publishBuildInfo;
    }

    protected ArtifactoryClientConfiguration getArtifactoryClientConfiguration() {
        return ArtifactoryPluginUtil.getArtifactoryConvention(getProject()).getClientConfig();
    }

    protected Map<String, String> getPropsToAdd(PublishArtifactInfo artifact, String publicationName) {
        if (defaultProps == null) {
            defaultProps = Maps.newHashMap();
            addProps(defaultProps, properties);
            //Add the publisher properties
            ArtifactoryClientConfiguration clientConf = getArtifactoryClientConfiguration();
            defaultProps.putAll(clientConf.publisher.getMatrixParams());
        }

        Map<String, String> propsToAdd = Maps.newHashMap(defaultProps);
        //Apply artifact-specific props from the artifact specs
        Project project = getProject();
        ArtifactSpec spec =
                ArtifactSpec.builder().configuration(publicationName)
                        .group(project.getGroup().toString())
                        .name(project.getName()).version(project.getVersion().toString())
                        .classifier(artifact.getClassifier())
                        .type(artifact.getType()).build();
        Multimap<String, CharSequence> artifactSpecsProperties = artifactSpecs.getProperties(spec);
        addProps(propsToAdd, artifactSpecsProperties);
        return propsToAdd;
    }

    private void addProps(Map<String, String> target, Multimap<String, CharSequence> props) {
        for (Map.Entry<String, CharSequence> entry : props.entries()) {
            // Make sure all GString are now Java Strings
            String key = entry.getKey();
            String value = entry.getValue().toString();
            //Accumulate multi-value props
            if (!target.containsKey(key)) {
                target.put(key, value);
            } else {
                value = target.get(key) + ", " + value;
                target.put(key, value);
            }
        }
    }

    protected abstract void collectDescriptorsAndArtifactsForUpload() throws IOException;

    /**
     * This method will be activated only at the end of the build, when we reached the root project.
     *
     * @throws java.io.IOException In case the deployment fails.
     */
    protected void prepareAndDeploy() throws IOException {
        ArtifactoryClientConfiguration acc = getArtifactoryClientConfiguration();
        // Reset the default properties, they may have changed
        GradleArtifactoryClientConfigUpdater.setMissingBuildAttributes(acc, getProject().getRootProject());

        String contextUrl = acc.publisher.getContextUrl();
        log.debug("Context URL for deployment '{}", contextUrl);
        String username = acc.publisher.getUsername();
        String password = acc.publisher.getPassword();
        if (StringUtils.isBlank(username)) {
            username = "";
        }
        if (StringUtils.isBlank(password)) {
            password = "";
        }

        Set<GradleDeployDetails> allDeployDetails = Sets.newHashSet();

        // Update the artifacts for all project build info task
        List<BuildInfoBaseTask> orderedTasks = getAllBuildInfoTasks();
        for (BuildInfoBaseTask bit : orderedTasks) {
            if (bit.getDidWork()) {
                bit.collectDescriptorsAndArtifactsForUpload();
                allDeployDetails.addAll(bit.deployDetails);
            }
        }

        ArtifactoryBuildInfoClient client =
                new ArtifactoryBuildInfoClient(contextUrl, username, password, new GradleClientLogger(log));
        try {
            if (isPublishArtifacts(acc)) {
                log.debug("Uploading artifacts to Artifactory at '{}'", contextUrl);
                /**
                 * if the {@link org.jfrog.build.client.ClientProperties#PROP_PUBLISH_ARTIFACT} is set the true,
                 * The uploadArchives task will be triggered ONLY at the end, ensuring that the artifacts will be
                 * published only after a successful build. This is done before the build-info is sent.
                 */

                IncludeExcludePatterns patterns = new IncludeExcludePatterns(
                        acc.publisher.getIncludePatterns(),
                        acc.publisher.getExcludePatterns());
                configureProxy(acc, client);
                deployArtifacts(allDeployDetails, client, patterns);
            }

            //Extract build info and update the clientConf info accordingly (build name, num, etc.)
            GradleBuildInfoExtractor gbie = new GradleBuildInfoExtractor(acc, allDeployDetails);
            Build build = gbie.extract(getProject().getRootProject());
            /**
             * The build-info will be always written to a file in its JSON form.
             */
            exportBuildInfo(build, getExportFile(acc));
            if (isPublishBuildInfo(acc)) {
                log.debug("Publishing build info to artifactory at: '{}'", contextUrl);
                /**
                 * After all the artifacts were uploaded successfully the next task is to send the build-info
                 * object.
                 */
                // If export property set always save the file before sending it to artifactory
                exportBuildInfo(build, getExportFile(acc));
                client.sendBuildInfo(build);
            }
        } finally {
            client.shutdown();
        }
    }

    protected String getModuleName() {
        Project project = getProject();
        //Take into account the archivesBaseName if applied to the project by the Java plugin
        if (project.hasProperty(ARCHIVES_BASE_NAME)) {
            return project.property(ARCHIVES_BASE_NAME).toString();
        }
        return project.getName();
    }

    protected File getExportFile(ArtifactoryClientConfiguration clientConf) {
        String fileExportPath = clientConf.getExportFile();
        if (StringUtils.isNotBlank(fileExportPath)) {
            return new File(fileExportPath);
        }
        Project rootProject = getProject().getRootProject();
        return new File(rootProject.getBuildDir(), "build-info.json");
    }

    protected void configureProxy(ArtifactoryClientConfiguration clientConf, ArtifactoryBuildInfoClient client) {
        ArtifactoryClientConfiguration.ProxyHandler proxy = clientConf.proxy;
        String proxyHost = proxy.getHost();
        if (StringUtils.isNotBlank(proxyHost) && proxy.getPort() != null) {
            log.debug("Found proxy host '{}'", proxyHost);
            String proxyUserName = proxy.getUsername();
            if (StringUtils.isNotBlank(proxyUserName)) {
                log.debug("Found proxy user name '{}'", proxyUserName);
                client.setProxyConfiguration(proxyHost, proxy.getPort(), proxyUserName, proxy.getPassword());
            } else {
                log.debug("No proxy user name and password found, using anonymous proxy");
                client.setProxyConfiguration(proxyHost, proxy.getPort());
            }
        }
    }

    protected void exportBuildInfo(Build build, File toFile) throws IOException {
        log.debug("Exporting generated build info to '{}'", toFile.getAbsolutePath());
        BuildInfoExtractorUtils.saveBuildInfoToFile(build, toFile);
    }

    @TaskAction
    public void collectProjectBuildInfo() throws IOException {
        try {
            log.debug("Task '{}' activated", getPath());
            // Only the last buildInfo execution activate the deployment
            List<BuildInfoBaseTask> orderedTasks = getAllBuildInfoTasks();
            int myIndex = orderedTasks.indexOf(this);
            if (myIndex == -1) {
                log.error("Could not find my own task {} in the task graph!", getPath());
                return;
            }
            if (myIndex == orderedTasks.size() - 1) {
                log.debug("Starting build info extraction for project '{}' using last task in graph '{}'",
                        new Object[]{getProject().getPath(), getPath()});
                prepareAndDeploy();
            }
        } finally {
            String propertyFilePath = System.getenv(BuildInfoConfigProperties.PROP_PROPS_FILE);
            if (StringUtils.isNotBlank(propertyFilePath)) {
                File file = new File(propertyFilePath);
                if (file.exists()) {
                    file.delete();
                }
            }
        }
    }

    /**
     * Analyze the task graph ordered and extract a list of build info tasks
     *
     * @return An ordered list of build info tasks
     */
    protected List<BuildInfoBaseTask> getAllBuildInfoTasks() {
        List<BuildInfoBaseTask> result = new ArrayList<BuildInfoBaseTask>();
        for (Task task : getProject().getGradle().getTaskGraph().getAllTasks()) {
            if (task instanceof BuildInfoBaseTask) {
                result.add((BuildInfoBaseTask) task);
            }
        }
        return result;
    }

    public void properties(Closure closure) {
        Project project = getProject();
        PropertiesConfig propertiesConfig = new PropertiesConfig(project);
        ConfigureUtil.configure(closure, propertiesConfig);
        artifactSpecs.addAll(propertiesConfig.getArtifactSpecs());
    }

    private void deployArtifacts(Set<GradleDeployDetails> allDeployDetails, ArtifactoryBuildInfoClient client,
            IncludeExcludePatterns patterns)
            throws IOException {
        for (GradleDeployDetails detail : allDeployDetails) {
            DeployDetails deployDetails = detail.getDeployDetails();
            String artifactPath = deployDetails.getArtifactPath();
            if (PatternMatcher.pathConflicts(artifactPath, patterns)) {
                log.log(LogLevel.LIFECYCLE, "Skipping the deployment of '" + artifactPath +
                        "' due to the defined include-exclude patterns.");
                continue;
            }
            client.deployArtifact(deployDetails);
        }
    }

    public abstract boolean hasModules();
}
TOP

Related Classes of org.jfrog.gradle.plugin.artifactory.task.BuildInfoBaseTask

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.