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

org.metaeffekt.artifact.resolver.rpm.RpmRepositoryAdapter Maven / Gradle / Ivy

There is a newer version: 0.134.0
Show newest version
/*
 * Copyright 2021-2024 the original author or authors.
 *
 * 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.metaeffekt.artifact.resolver.rpm;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.packagedrone.utils.rpm.RpmTag;
import org.eclipse.packagedrone.utils.rpm.parse.RpmInputStream;
import org.metaeffekt.artifact.resolver.ResolverResult;
import org.metaeffekt.artifact.resolver.download.WebAccess;
import org.metaeffekt.artifact.resolver.generic.AbstractDownloadingAdapter;
import org.metaeffekt.artifact.resolver.generic.FileLocation;
import org.metaeffekt.artifact.resolver.model.DownloadLocation;
import org.metaeffekt.artifact.resolver.rpm.index.RpmIndex;
import org.metaeffekt.artifact.resolver.rpm.index.RpmIndexConfig;
import org.metaeffekt.artifact.resolver.rpm.index.RpmIndexPackageData;
import org.metaeffekt.core.inventory.processor.model.Artifact;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

public class RpmRepositoryAdapter extends AbstractDownloadingAdapter {

    private static final Logger LOG = LoggerFactory.getLogger(RpmRepositoryAdapter.class);

    private final RpmIndex rpmIndex;

    public RpmRepositoryAdapter(DownloadLocation downloadLocation, WebAccess webAccess, RpmIndexConfig rpmIndexConfig) {
        super(downloadLocation, webAccess);

        this.rpmIndex = new RpmIndex(rpmIndexConfig);
    }

    private File downloadArtifact(RpmArtifactReference reference, String defaultArch) {
        try {
            final Set packageSet = rpmIndex.queryPackageData(reference.getName());
            final String archOrSource = reference.getArchOrSource() == null ? defaultArch : reference.getArchOrSource();
            final Set filteredSet = RpmIndexPackageData.filter(packageSet, reference.getVersion(), archOrSource);

            final Optional first = filteredSet.stream().findFirst();

            // FIXME: handle multiple
            if (first.isPresent()) {
                final Set urls = rpmIndex.getRpmUrl(first.get());
                final Optional firstUrl = urls.stream().findFirst();
                if (firstUrl.isPresent()) {
                    File download = download(reference, first.get(), firstUrl.get());
                    if (download != null) {
                        return download;
                    }
                }
            }
        } catch (Exception e) {
            // ignore; missing pom will be handled by caller
        }
        return null;
    }

    private File download(RpmArtifactReference reference, RpmIndexPackageData rpmPackageData, String uri) throws IOException {
        final FileLocation fileLocation = reference.deriveFileLocation();

        final File file = new File(deriveResourceDir(fileLocation), rpmPackageData.toFilename());
        final File markerFile = deriveMarkerFile(fileLocation, uri);

        if (!file.exists()) {
            if (uri.startsWith("http")) {

                // do not reattempt download as long as a recent (less than a day old) marker file exists
                if (hasRecentFailedDownloadAttempt(markerFile)) {
                    LOG.info("Skipping download [{}]. Recent attempt failed:" + file.getAbsolutePath(), uri);
                    return null;
                }

                // manage markers; remove complete folder once we decided to attempt a new download
                removeMarker(markerFile);

                try (WebAccess.WebSession session = getWebAccess().createSession()) {
                    LOG.info("Downloading: [{}]", uri);
                    Optional downloadFile = session.downloadFile(uri, file, manageMarkerErrorResponseConsumer(markerFile));
                    return downloadFile.orElse(null);
                }
            }
        } else {
            LOG.debug("Skipping download [{}]. File already exists: " + file.getAbsolutePath(), uri);
        }
        return file;
    }

    public ResolverResult resolveBinaryArtifact(RpmArtifactReference artifactReference) {
        File resolveFile = downloadArtifact(artifactReference, "x86_64");
        if (resolveFile == null) {
            resolveFile = downloadArtifact(artifactReference, "noarch");
        }
        return resolve(resolveFile);
    }

    public ResolverResult resolveSourceArtifact(RpmArtifactReference artifactReference) {

        // resolve binary artifact
        final ResolverResult resolverResult = resolveBinaryArtifact(artifactReference);

        if (resolverResult != null) {

            // extract metadata
            final Artifact artifact = extractMetaData(resolverResult.getResolvedFile());

            if (artifact != null) {
                final String sourcePackage = artifact.get("Source Package");

                // attempt download source
                if (StringUtils.isNotBlank(sourcePackage)) {
                    RpmIndexPackageData rpmIndexPackageData = new RpmIndexPackageData(sourcePackage);
                    RpmArtifactReference sourceRef = new RpmArtifactReference(
                            rpmIndexPackageData.getName(),
                            rpmIndexPackageData.getVersion() + "-" + rpmIndexPackageData.getRelease(),
                            artifactReference.getVendor(),
                            rpmIndexPackageData.getArchOrSource(),
                            artifactReference.getDistro(),
                            artifactReference.getEpoch());
                    return resolve(downloadArtifact(sourceRef, sourceRef.getArchOrSource()));
                }
            }
        }
        return null;
    }

    protected Artifact extractMetaData(File file) {
        if (file == null || !file.exists()) return null;
        try {
            // skip symlinks
            if (Files.isSymbolicLink(file.toPath())) {
                return null;
            }

            Artifact artifact = new Artifact();
            artifact.setId(file.getName());
            artifact.addProject(file.getAbsolutePath());

            try (RpmInputStream in = new RpmInputStream(new FileInputStream(file))) {
                String[] summary = (String[]) in.getPayloadHeader().getTag(RpmTag.SUMMARY);
                artifact.set("Summary", Arrays.stream(summary).collect(Collectors.joining("\n")));

                artifact.setComponent((String) in.getPayloadHeader().getTag(RpmTag.NAME));
                artifact.set("Vendor", (String) in.getPayloadHeader().getTag(RpmTag.VENDOR));
                artifact.set("Version", (String) in.getPayloadHeader().getTag(RpmTag.VERSION));
                artifact.set("Release", (String) in.getPayloadHeader().getTag(RpmTag.RELEASE));
                artifact.set("Source Package", (String) in.getPayloadHeader().getTag(RpmTag.SOURCE_PACKAGE));
                artifact.set("Build Host", (String) in.getPayloadHeader().getTag(RpmTag.BUILDHOST));

                artifact.set("Specified Package License", (String) in.getPayloadHeader().getTag(RpmTag.LICENSE));

                String[] changeLogAuthors = (String[]) in.getPayloadHeader().getTag(RpmTag.CHANGELOG_AUTHOR);
                if (changeLogAuthors != null) {
                    artifact.set("Changelog Authors", Arrays.stream(changeLogAuthors).collect(Collectors.joining("\n")));
                }

            }
            return artifact;
        } catch (IOException e) {
            // if the rpm cannot be inspected just return without result
            return null;
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy