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

org.jfrog.build.util.BuildDependenciesHelper Maven / Gradle / Ivy

There is a newer version: 2.41.24
Show newest version
/*
 * Copyright (C) 2010 JFrog Ltd.
 *
 * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
 *
 * 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.jfrog.build.util;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.lang.StringUtils;
import org.jfrog.build.api.builder.dependency.BuildDependencyBuilder;
import org.jfrog.build.api.builder.dependency.BuildPatternArtifactsRequestBuilder;
import org.jfrog.build.api.dependency.BuildDependency;
import org.jfrog.build.api.dependency.BuildPatternArtifacts;
import org.jfrog.build.api.dependency.BuildPatternArtifactsRequest;
import org.jfrog.build.api.dependency.DownloadableArtifact;
import org.jfrog.build.api.dependency.PatternArtifact;
import org.jfrog.build.api.dependency.PatternResult;
import org.jfrog.build.api.dependency.pattern.BuildDependencyPattern;
import org.jfrog.build.api.dependency.pattern.DependencyPattern;
import org.jfrog.build.api.util.Log;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * Helper class for parsing build dependencies property.
 *
 * @author Evgeny Goldin
 */
public class BuildDependenciesHelper {

    private DependenciesDownloader downloader;
    private Log log;

    public BuildDependenciesHelper(DependenciesDownloader downloader, Log log) {
        this.downloader = downloader;
        this.log = log;
    }

    public List retrieveBuildDependencies(String resolvePattern)
            throws IOException, InterruptedException {
        if (StringUtils.isBlank(resolvePattern)) {
            return Collections.emptyList();
        }

        List patternLines = PublishedItemsHelper.parsePatternsFromProperty(resolvePattern);

        // Don't run if dependencies mapping came out to be empty.
        if (patternLines.isEmpty()) {
            return Collections.emptyList();
        }

        log.info("Beginning to resolve Build Info build dependencies.");
        Map>> buildDependencies = getBuildDependencies(patternLines);
        List artifactsRequests = toArtifactsRequests(buildDependencies);
        List artifactsResponses = downloader.getClient().retrievePatternArtifacts(
                artifactsRequests);
        Set result = Sets.newHashSet();
        downloader.download(
                collectArtifactsToDownload(buildDependencies, artifactsRequests, artifactsResponses, result));
        log.info("Finished resolving Build Info build dependencies.");

        return Lists.newArrayList(result);
    }

    private Map>> getBuildDependencies(List patternLines) {
        Map>> buildsMap = Maps.newHashMap();
        for (String patternLine : patternLines) {
            DependencyPattern dependencyPattern = PatternFactory.create(patternLine);
            if (dependencyPattern instanceof BuildDependencyPattern) {
                BuildDependencyPattern buildDependencyPattern = (BuildDependencyPattern) dependencyPattern;
                String buildName = buildDependencyPattern.getBuildName();
                Map> numbersMap = buildsMap.get(buildName);
                if (numbersMap == null) {
                    buildsMap.put(buildName, Maps.>newHashMap());
                    numbersMap = buildsMap.get(buildName);
                }

                String buildNumber = buildDependencyPattern.getBuildNumber();
                List dependencyPatternList = numbersMap.get(buildNumber);
                if (dependencyPatternList == null) {
                    numbersMap.put(buildNumber, Lists.newLinkedList());
                    dependencyPatternList = numbersMap.get(buildNumber);
                }
                dependencyPatternList.add(buildDependencyPattern);
            }
        }


        return buildsMap;
    }

    private List toArtifactsRequests(
            Map>> dependencyPatterns) {
        List artifactsRequests = Lists.newLinkedList();
        for (String buildName : dependencyPatterns.keySet()) {
            Map> buildNumbers = dependencyPatterns.get(buildName);
            for (String buildNumber : buildNumbers.keySet()) {
                List buildDependencyPatterns = buildNumbers.get(buildNumber);
                BuildPatternArtifactsRequestBuilder builder = new BuildPatternArtifactsRequestBuilder()
                        .buildName(buildName).buildNumber(buildNumber);
                for (BuildDependencyPattern buildDependencyPattern : buildDependencyPatterns) {
                    builder.pattern(buildDependencyPattern.getPattern());
                }
                artifactsRequests.add(builder.build());
            }
        }

        return artifactsRequests;
    }

    private Set collectArtifactsToDownload(
            Map>> dependencyPatterns,
            List artifactsRequests, List artifactsResponses,
            Set buildDependencies) {
        Set downloadableArtifacts = Sets.newHashSet();
        verifySameSize(artifactsRequests, artifactsResponses);

        for (int i = 0; i < artifactsRequests.size(); i++) {
            BuildPatternArtifacts artifacts = artifactsResponses.get(i);
            if (artifacts == null) {
                // Pattern didn't match any results: wrong build name or build number.
                continue;
            }


            List buildDependencyPatterns = dependencyPatterns.get(artifacts.getBuildName()).get(
                    artifactsRequests.get(i).getBuildNumber());
            for (int j = 0; j < buildDependencyPatterns.size(); j++) {
                BuildDependencyPattern buildDependencyPattern = buildDependencyPatterns.get(j);
                if (!buildDependencyPattern.getBuildName().equals(artifacts.getBuildName())) {
                    throw new IllegalArgumentException(String.format("Build names don't match: [%s] != [%s]",
                            buildDependencyPattern.getBuildName(), artifacts.getBuildName()));
                }

                final String message = String.format("Dependency on build [%s], number [%s]",
                        buildDependencyPattern.getBuildName(), buildDependencyPattern.getBuildNumber());

                /**
                 * Build number response is null for unresolved dependencies (wrong build name or build number).
                 */
                if (artifacts.getBuildNumber() == null) {
                    log.info(
                            message + " - no results found, check correctness of dependency build name and build number.");
                } else {
                    PatternResult patternResult = artifacts.getPatternResults().get(j);
                    List patternArtifacts = patternResult.getPatternArtifacts();
                    log.info(message + String.format(", pattern [%s] - [%s] result%s found.",
                            buildDependencyPattern.getPattern(), patternArtifacts.size(),
                            (patternArtifacts.size() == 1 ? "" : "s")));

                    for (PatternArtifact patternArtifact : patternArtifacts) {
                        final String uri = patternArtifact.getUri(); // "libs-release-local/com/goldin/plugins/gradle/0.1.1/gradle-0.1.1.jar"
                        final int indexOfFirstSlash = uri.indexOf('/');

                        assert (indexOfFirstSlash > 0) : String.format("Failed to locate '/' in [%s]", uri);

                        final String repoUrl = patternArtifact.getArtifactoryUrl() + '/' + uri.substring(0,
                                indexOfFirstSlash);
                        final String filePath = uri.substring(indexOfFirstSlash + 1);
                        downloadableArtifacts.add(
                                new DownloadableArtifact(repoUrl, buildDependencyPattern.getTargetDirectory(), filePath,
                                        buildDependencyPattern.getMatrixParams(), buildDependencyPattern.getPattern(),
                                        buildDependencyPattern.getPatternType()));
                    }

                    if (!patternArtifacts.isEmpty()) {
                        BuildDependency buildDependency = new BuildDependencyBuilder()
                                .name(artifacts.getBuildName())
                                .number(artifacts.getBuildNumber())
                                .url(artifacts.getUrl())
                                .started(artifacts.getStarted())
                                .build();
                        buildDependencies.add(buildDependency);
                    }
                }
            }
        }

        return downloadableArtifacts;
    }

    /**
     * Verifies both lists are of the same size.
     *
     * @param l1 first list to check
     * @param l2 second list to check
     * @throws IllegalArgumentException if lists are of different sizes.
     */
    private void verifySameSize(List l1, List l2) {
        if (l1.size() != l2.size()) {
            throw new IllegalArgumentException(
                    String.format("List sizes don't match: [%s] != [%s]", l1.size(), l2.size()));
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy