Package org.jfrog.build.extractor.listener

Source Code of org.jfrog.build.extractor.listener.ArtifactoryBuildListener

package org.jfrog.build.extractor.listener;

import org.apache.commons.lang.StringUtils;
import org.apache.ivy.Ivy;
import org.apache.ivy.ant.IvyAntSettings;
import org.apache.ivy.core.event.EventManager;
import org.apache.ivy.core.event.publish.EndArtifactPublishEvent;
import org.apache.ivy.core.event.resolve.EndResolveEvent;
import org.apache.ivy.plugins.trigger.Trigger;
import org.apache.tools.ant.*;
import org.apache.tools.ant.taskdefs.Ant;
import org.jfrog.build.api.*;
import org.jfrog.build.api.builder.BuildInfoBuilder;
import org.jfrog.build.client.*;
import org.jfrog.build.context.BuildContext;
import org.jfrog.build.extractor.BuildInfoExtractorUtils;
import org.jfrog.build.extractor.trigger.ArtifactoryBuildInfoTrigger;
import org.jfrog.build.util.IvyBuildInfoLog;

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


/**
* A listener which listens to the {@link Ant} builds, and is invoking different events during the build of {@code Ant}
* itself! This is not to be confused with {@code Ivy} {@link Trigger} which is called during Ivy related events
*
* @author Tomer Cohen
*/
public class ArtifactoryBuildListener implements BuildListener {
    private static final ArtifactoryBuildInfoTrigger DEPENDENCY_TRIGGER = new ArtifactoryBuildInfoTrigger(EndResolveEvent.NAME);
    private static final ArtifactoryBuildInfoTrigger PUBLISH_TRIGGER = new ArtifactoryBuildInfoTrigger(EndArtifactPublishEvent.NAME);

    private boolean isDidDeploy;
    private BuildContext ctx;
    private IvyBuildInfoLog buildInfoLog;

    private void assertInitialized(BuildEvent event) {
        if (buildInfoLog != null) {
            buildInfoLog.setProject(event.getProject());
            return;
        }
        try {
            buildInfoLog = new IvyBuildInfoLog(event.getProject());
            ArtifactoryClientConfiguration clientConf = new ArtifactoryClientConfiguration(buildInfoLog);
            Properties props = getMergedEnvAndSystemProps();
            clientConf.fillFromProperties(props);
            ctx = new BuildContext(clientConf);
            DEPENDENCY_TRIGGER.setIvyBuildContext(ctx);
            PUBLISH_TRIGGER.setIvyBuildContext(ctx);
            buildInfoLog.info("[buildinfo:ant] Artifactory Build Info Listener Initialized");
        } catch (Exception e) {
            RuntimeException re = new RuntimeException(
                    "Fail to initialize the Ivy listeners for the Artifactory Ivy plugin, due to: " + e.getMessage(),
                    e);
            if (buildInfoLog != null && buildInfoLog.getProject() != null) {
                buildInfoLog.error(re.getMessage(), e);
            }
            throw re;
        }
    }

    private Properties getMergedEnvAndSystemProps() {
        Properties props = new Properties();
        props.putAll(System.getenv());
        return BuildInfoExtractorUtils.mergePropertiesWithSystemAndPropertyFile(props, buildInfoLog);
    }

    public IvyBuildInfoLog getBuildInfoLog(BuildEvent event) {
        assertInitialized(event);
        return buildInfoLog;
    }

    @Override
    public void buildStarted(BuildEvent event) {
        try {
            getBuildInfoLog(event).debug("[buildinfo:ant] Received Build Started Event");
            ctx.setBuildStartTime(System.currentTimeMillis());
            getBuildInfoLog(event).info("[buildinfo:ant] Build Started timestamp=" + ctx.getBuildStartTime());
        } catch (Exception e) {
            RuntimeException re = new RuntimeException("Fail to register start of build, due to: " + e.getMessage(), e);
            getBuildInfoLog(event).error(re.getMessage(), e);
            throw re;
        }
    }

    /**
     * Called when the build has ended, this is the time where we will assemble the build-info object that its
     * information was collected by the {@link org.jfrog.build.extractor.trigger.ArtifactoryBuildInfoTrigger} it will
     * serialize the build-info object into a senadble JSON object to be used by the {@link ArtifactoryBuildInfoClient}
     *
     * @param event The build event.
     */
    @Override
    public void buildFinished(BuildEvent event) {
        try {
            if (event.getException() != null) {
                getBuildInfoLog(event).info(
                        "[buildinfo:ant] Received Build Finished Event with exception => No deployment");
                return;
            }
            getBuildInfoLog(event).debug("[buildinfo:ant] Received Build Finished Event");
            if (!isDidDeploy) {
                try {
                    doDeploy(event);
                } catch (Exception e) {
                    RuntimeException re = new RuntimeException(
                            "Fail to activate deployment using the Artifactory Ivy plugin, due to: " + e.getMessage(),
                            e);
                    getBuildInfoLog(event).error(re.getMessage(), e);
                    throw re;
                }
            }
        } finally {
            String propertyFilePath = System.getenv(BuildInfoConfigProperties.PROP_PROPS_FILE);
            if (StringUtils.isNotBlank(propertyFilePath)) {
                File file = new File(propertyFilePath);
                if (file.exists()) {
                    file.delete();
                }
            }
        }
    }

    private Task extractIvyTask(BuildEvent event) {
        Task task = event.getTask();
        // Interested only in Ivy tasks
        String taskType = task.getTaskType();
        if (taskType != null
                && (taskType.contains("org.apache.ivy") || taskType.contains("fr.jayasoft.ivy"))) {
            return task;
        }
        return null;
    }

    @Override
    public void taskStarted(BuildEvent event) {
        try {
            Task task = extractIvyTask(event);
            if (task != null) {
                String taskType = task.getTaskType();
                getBuildInfoLog(event).debug("[buildinfo:ant] Received Task of type '" + taskType + "' Started Event");
                // Need only retrieve, resolve, and publish tasks, since needs to give ivy settings a chance (BI-131)
                if (taskType.endsWith("retrieve") || taskType.endsWith("resolve")) {
                    getBuildInfoLog(event).debug("[buildinfo:ant] Adding Ivy Resolution Listeners if needed.");
                    List<EventManager> eventManagers = getEventManager(task);
                    for (EventManager eventManager : eventManagers) {
                        if (!eventManager.hasIvyListener(DEPENDENCY_TRIGGER)) {
                            eventManager.addIvyListener(DEPENDENCY_TRIGGER, DEPENDENCY_TRIGGER.getEventFilter());
                            getBuildInfoLog(event).info("[buildinfo:ant] Added resolution report Ivy Listener.");
                        }
                    }
                }
                if (taskType.endsWith("publish")) {
                    getBuildInfoLog(event).debug("[buildinfo:ant] Adding Ivy Publish Listeners if needed.");
                    List<EventManager> eventManagers = getEventManager(task);
                    for (EventManager eventManager : eventManagers) {
                        if (!eventManager.hasIvyListener(PUBLISH_TRIGGER)) {
                            eventManager.addIvyListener(PUBLISH_TRIGGER, PUBLISH_TRIGGER.getEventFilter());
                            getBuildInfoLog(event).info("[buildinfo:ant] Added publish end Ivy Listener to Ivy Engine.");
                        }
                    }
                }
            }
        } catch (Exception e) {
            RuntimeException re = new RuntimeException(
                    "Fail to add the Ivy listeners for the Artifactory Ivy plugin, due to: " + e.getMessage(), e);
            getBuildInfoLog(event).error(re.getMessage(), e);
            throw re;
        }
    }

    /**
     * Retrieves all the event managers of all the ivy settings of the project.
     *
     * @param task the task we need to attach listeners to
     * @return the list of event manager for this task
     */
    private List<EventManager> getEventManager(Task task) {
        List<EventManager> results = new ArrayList<EventManager>();
        Project project = task.getProject();
        Enumeration<Object> elements = project.getReferences().elements();
        while (elements.hasMoreElements()) {
            Object element = elements.nextElement();
            if (element instanceof IvyAntSettings) {
                results.add(((IvyAntSettings) element).getConfiguredIvyInstance(task).getResolveEngine().getEventManager());
            }
        }
        if (results.isEmpty()) {
            throw new BuildException("Did not find ivy settings reference for project " + project.getName());
        }
        return results;
    }

    @Override
    public void taskFinished(BuildEvent event) {
        Task task = extractIvyTask(event);
        if (task != null) {
            getBuildInfoLog(event).debug("[buildinfo:ant] Received Task " + task.getTaskType() + " Finished Event");
        }
    }

    @Override
    public void targetStarted(BuildEvent event) {
    }

    @Override
    public void targetFinished(BuildEvent event) {
    }

    @Override
    public void messageLogged(BuildEvent event) {
    }

    private void doDeploy(BuildEvent event) {
        IvyBuildInfoLog log = getBuildInfoLog(event);
        log.info("[buildinfo:ant] Starting deployment");
        Project project = event.getProject();
        Set<DeployDetails> deployDetails = ctx.getDeployDetails();
        BuildInfoBuilder builder = new BuildInfoBuilder(project.getName()).modules(ctx.getModules())
                .number("0").durationMillis(System.currentTimeMillis() - ctx.getBuildStartTime())
                .startedDate(new Date(ctx.getBuildStartTime()))
                .buildAgent(new BuildAgent("Ivy", Ivy.getIvyVersion()))
                .agent(new Agent("Ivy", Ivy.getIvyVersion()));
        // This is here for backwards compatibility.
        builder.type(BuildType.IVY);
        ArtifactoryClientConfiguration clientConf = ctx.getClientConf();
        String agentName = clientConf.info.getAgentName();
        String agentVersion = clientConf.info.getAgentVersion();
        if (StringUtils.isNotBlank(agentName) && StringUtils.isNotBlank(agentVersion)) {
            builder.agent(new Agent(agentName, agentVersion));
        }
        String buildAgentName = clientConf.info.getBuildAgentName();
        String buildAgentVersion = clientConf.info.getBuildAgentVersion();
        if (StringUtils.isNotBlank(buildAgentName) && StringUtils.isNotBlank(buildAgentVersion)) {
            builder.buildAgent(new BuildAgent(buildAgentName, buildAgentVersion));
        }
        String buildName = clientConf.info.getBuildName();
        if (StringUtils.isNotBlank(buildName)) {
            builder.name(buildName);
        }
        String buildNumber = clientConf.info.getBuildNumber();
        if (StringUtils.isNotBlank(buildNumber)) {
            builder.number(buildNumber);
        }
        String buildUrl = clientConf.info.getBuildUrl();
        if (StringUtils.isNotBlank(buildUrl)) {
            builder.url(buildUrl);
        }
        String vcsRevision = clientConf.info.getVcsRevision();
        if (StringUtils.isNotBlank(vcsRevision)) {
            builder.vcsRevision(vcsRevision);
        }
        String vcsUrl = clientConf.info.getVcsUrl();
        if (StringUtils.isNotBlank(vcsUrl)) {
            builder.vcsUrl(vcsUrl);
        }
        String principal = clientConf.info.getPrincipal();
        if (StringUtils.isNotBlank(principal)) {
            builder.principal(principal);
        }
        String parentBuildName = clientConf.info.getParentBuildName();
        if (StringUtils.isNotBlank(parentBuildName)) {
            builder.parentName(parentBuildName);
        }
        String parentBuildNumber = clientConf.info.getParentBuildNumber();
        if (StringUtils.isNotBlank(parentBuildNumber)) {
            builder.parentNumber(parentBuildNumber);
        }
        LicenseControl licenseControl = new LicenseControl(clientConf.info.licenseControl.isRunChecks());
        String notificationRecipients = clientConf.info.licenseControl.getViolationRecipients();
        if (StringUtils.isNotBlank(notificationRecipients)) {
            licenseControl.setLicenseViolationsRecipientsList(notificationRecipients);
        }
        licenseControl.setIncludePublishedArtifacts(clientConf.info.licenseControl.isIncludePublishedArtifacts());
        String scopes = clientConf.info.licenseControl.getScopes();
        if (StringUtils.isNotBlank(scopes)) {
            licenseControl.setScopesList(scopes);
        }
        licenseControl.setAutoDiscover(clientConf.info.licenseControl.isAutoDiscover());
        builder.licenseControl(licenseControl);

        final BlackDuckProperties blackDuckProperties;
        if (clientConf.info.blackDuckProperties.isRunChecks()) {
            blackDuckProperties = clientConf.info.blackDuckProperties.copyBlackDuckProperties();
        } else {
            blackDuckProperties = new BlackDuckProperties();
        }

        Governance governance = new Governance();
        governance.setBlackDuckProperties(blackDuckProperties);
        builder.governance(governance);

        BuildRetention buildRetention = new BuildRetention(clientConf.info.isDeleteBuildArtifacts());
        if (clientConf.info.getBuildRetentionCount() != null) {
            buildRetention.setCount(clientConf.info.getBuildRetentionCount());
        }
        String buildRetentionMinimumDays = clientConf.info.getBuildRetentionMinimumDate();
        if (StringUtils.isNotBlank(buildRetentionMinimumDays)) {
            int minimumDays = Integer.parseInt(buildRetentionMinimumDays);
            if (minimumDays > -1) {
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.DAY_OF_YEAR, -minimumDays);
                buildRetention.setMinimumBuildDate(calendar.getTime());
            }
        }
        String[] notToDelete = clientConf.info.getBuildNumbersNotToDelete();
        for (String notToDel : notToDelete) {
            buildRetention.addBuildNotToBeDiscarded(notToDel);
        }
        builder.buildRetention(buildRetention);

        String issueTrackerName = clientConf.info.issues.getIssueTrackerName();
        if (StringUtils.isNotBlank(issueTrackerName)) {
            Issues issues = new Issues();
            issues.setAggregateBuildIssues(clientConf.info.issues.getAggregateBuildIssues());
            issues.setAggregationBuildStatus(clientConf.info.issues.getAggregationBuildStatus());
            issues.setTracker(new IssueTracker(issueTrackerName, clientConf.info.issues.getIssueTrackerVersion()));
            Set<Issue> affectedIssuesSet = clientConf.info.issues.getAffectedIssuesSet();
            if (!affectedIssuesSet.isEmpty()) {
                issues.setAffectedIssues(affectedIssuesSet);
            }
            builder.issues(issues);
        }

        if (clientConf.isIncludeEnvVars()) {
            Properties envProperties = new Properties();
            envProperties.putAll(clientConf.getAllProperties());
            envProperties = BuildInfoExtractorUtils.getEnvProperties(envProperties, clientConf.getLog());
            for (Map.Entry<Object, Object> envProp : envProperties.entrySet()) {
                builder.addProperty(envProp.getKey(), envProp.getValue());
            }
        }
        Build build = builder.build();
        String contextUrl = clientConf.publisher.getContextUrl();
        String username = clientConf.publisher.getUsername();
        String password = clientConf.publisher.getPassword();
        try {
            ArtifactoryBuildInfoClient client =
                    new ArtifactoryBuildInfoClient(contextUrl, username, password, log);


            configureProxy(clientConf, client);
            if (clientConf.publisher.isPublishArtifacts()) {
                IncludeExcludePatterns patterns = new IncludeExcludePatterns(
                        clientConf.publisher.getIncludePatterns(), clientConf.publisher.getExcludePatterns());

                deployArtifacts(project, client, deployDetails, patterns);
            }
            if (clientConf.publisher.isPublishBuildInfo()) {
                client.sendBuildInfo(build);
            }
            isDidDeploy = true;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void deployArtifacts(Project project, ArtifactoryBuildInfoClient client, Set<DeployDetails> deployDetails,
                                 IncludeExcludePatterns patterns) throws IOException {
        for (DeployDetails deployDetail : deployDetails) {
            String artifactPath = deployDetail.getArtifactPath();
            if (PatternMatcher.pathConflicts(artifactPath, patterns)) {
                project.log("[buildinfo:deploy] Skipping the deployment of '" + artifactPath +
                        "' due to the defined include-exclude patterns.", Project.MSG_INFO);
                continue;
            }
            client.deployArtifact(deployDetail);
        }
    }

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

Related Classes of org.jfrog.build.extractor.listener.ArtifactoryBuildListener

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.