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

org.metaeffekt.artifact.resolver.pypi.PyPIArtifactResolver Maven / Gradle / Ivy

/*
 * 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.pypi;

import com.github.packageurl.MalformedPackageURLException;
import com.github.packageurl.PackageURL;
import lombok.NonNull;
import org.apache.commons.lang3.StringUtils;
import org.metaeffekt.artifact.resolver.ArtifactResolver;
import org.metaeffekt.artifact.resolver.model.*;
import org.metaeffekt.core.inventory.processor.model.Artifact;

import java.io.File;
import java.util.Collection;
import java.util.HashSet;

import static org.metaeffekt.artifact.resolver.model.ArtifactPartType.BINARY_ARTIFACT;
import static org.metaeffekt.artifact.resolver.model.ArtifactPartType.SOURCE_ARTIFACT;

public class PyPIArtifactResolver implements ArtifactResolver {

    private PyPICliAdapter pyPICliAdapter;

    public PyPIArtifactResolver(DownloadLocation downloadLocation) {
        this.pyPICliAdapter = new PyPICliAdapter(downloadLocation);
    }

    @Override
    public ArtifactPartResolvers collectResolvers(@NonNull Artifact artifact) {
        final Collection parts = new HashSet<>();
        addArtifactResolverPartForPurl(parts, artifact);
        addArtifactResolverPartForNV(parts, artifact);
        return new ArtifactPartResolvers(parts);
    }

    /**
     * Add artifact resolvers for name version pairs.
     *
     * @param parts    modifiable collection to add to.
     * @param artifact artifact to process
     */
    private void addArtifactResolverPartForNV(Collection parts, Artifact artifact) {
        addPartResolvers(artifact, parts, new PyPIArtifactReference(artifact));
    }

    private void addPartResolvers(Artifact artifact, Collection parts, PyPIArtifactReference artifactReference) {
        if (artifactReference.isValid()) {
            parts.add(new ArtifactPartResolver(artifact, SOURCE_ARTIFACT,
                // resolve
                () -> pyPICliAdapter.resolveSourceArtifact(artifactReference),
                // enrich
                rap -> enrich(artifactReference, rap)
            ));
            parts.add(new ArtifactPartResolver(artifact, BINARY_ARTIFACT,
                    () -> pyPICliAdapter.resolveBinaryArtifact(artifactReference),
                    rap -> enrich(artifactReference, rap)
            ));
        }
    }

    private Artifact enrich(PyPIArtifactReference reference, ResolvedArtifactPart resolvedArtifactPart) {
        final Artifact enrichedArtifact = new Artifact(resolvedArtifactPart.getOriginalArtifact());

        // NOTE: we take the information as specified by the reference
        enrichedArtifact.setVersion(reference.getVersion());
        enrichedArtifact.setId(reference.getName() + "-" + reference.getVersion());

        final File resolvedFile = resolvedArtifactPart.getResolvedFile();
        if (resolvedFile != null) {
            final ArtifactPartType artifactPartType = resolvedArtifactPart.getArtifactPartType();
            enrichedArtifact.set(artifactPartType.modulatePathAttribute(), resolvedFile.getAbsolutePath());
        }

        return enrichedArtifact;
    }

    /**
     * Adds resolver parts based on a derived purl.
     *
     * @param parts    modifiable collection to add to
     * @param artifact artifact to process
     */
    private void addArtifactResolverPartForPurl(Collection parts, Artifact artifact) {
        final String purl = artifact.get("PURL");
        if (!StringUtils.isEmpty(purl)) {
            try {
                final PyPIArtifactReference artifactReference = new PyPIArtifactReference(new PackageURL(purl));
                addPartResolvers(artifact, parts, artifactReference);
            } catch (MalformedPackageURLException e) {
                artifact.append("Errors", String.format("[PURL [%s] malformed.]", purl), "\n");
            }
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy