org.metaeffekt.artifact.resolver.rpm.RpmRepositoryAdapter 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.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