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

org.eclipse.packager.rpm.info.RpmInformations Maven / Gradle / Ivy

/*
 * Copyright (c) 2016, 2019 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 */

package org.eclipse.packager.rpm.info;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.compress.archivers.cpio.CpioArchiveEntry;
import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream;
import org.eclipse.packager.rpm.RpmSignatureTag;
import org.eclipse.packager.rpm.RpmTag;
import org.eclipse.packager.rpm.RpmTagValue;
import org.eclipse.packager.rpm.info.RpmInformation.Dependency;
import org.eclipse.packager.rpm.parse.InputHeader;
import org.eclipse.packager.rpm.parse.RpmInputStream;

public final class RpmInformations {
    private RpmInformations() {
    }

    public static RpmInformation makeInformation(final RpmInputStream in) throws IOException {
        final InputHeader header = in.getPayloadHeader();
        final InputHeader signature = in.getSignatureHeader();

        final RpmInformation result = new RpmInformation();

        result.setHeaderStart(header.getStart());
        result.setHeaderEnd(header.getStart() + header.getLength());

        result.setName(asString(header.getTag(RpmTag.NAME)));
        result.setArchitecture(asString(header.getTag(RpmTag.ARCH)));
        result.setSummary(asString(header.getTag(RpmTag.SUMMARY)));
        result.setDescription(asString(header.getTag(RpmTag.DESCRIPTION)));
        result.setPackager(asString(header.getTag(RpmTag.PACKAGER)));
        result.setUrl(asString(header.getTag(RpmTag.URL)));
        result.setLicense(asString(header.getTag(RpmTag.LICENSE)));
        result.setVendor(asString(header.getTag(RpmTag.VENDOR)));
        result.setGroup(asString(header.getTag(RpmTag.GROUP)));

        result.setBuildHost(asString(header.getTag(RpmTag.BUILDHOST)));
        result.setBuildTimestamp(asLong(header.getTag(RpmTag.BUILDTIME)));
        result.setSourcePackage(asString(header.getTag(RpmTag.SOURCE_PACKAGE)));

        result.setInstalledSize(asLong(header.getTag(RpmTag.SIZE)));
        result.setArchiveSize(asLong(header.getTag(RpmTag.ARCHIVE_SIZE)));

        if (result.getArchiveSize() == null) {
            result.setArchiveSize(asLong(signature.getTag(RpmSignatureTag.PAYLOAD_SIZE)));
        }

        // version

        final RpmInformation.Version ver = new RpmInformation.Version(asString(header.getTag(RpmTag.VERSION)), asString(header.getTag(RpmTag.RELEASE)), asString(header.getTag(RpmTag.EPOCH)));
        result.setVersion(ver);

        // changelog

        final Object val = header.getTag(RpmTag.CHANGELOG_TIMESTAMP);
        if (val instanceof Long[]) {
            final Long[] ts = (Long[]) val;
            final String[] authors = (String[]) header.getTag(RpmTag.CHANGELOG_AUTHOR);
            final String[] texts = (String[]) header.getTag(RpmTag.CHANGELOG_TEXT);

            final List changes = new ArrayList<>(ts.length);

            for (int i = 0; i < ts.length; i++) {
                changes.add(new RpmInformation.Changelog(ts[i], authors[i], texts[i]));
            }

            Collections.sort(changes, Comparator.comparingLong(RpmInformation.Changelog::getTimestamp));

            result.setChangelog(changes);
        }

        // dependencies

        result.setProvides(makeDependencies(header, RpmTag.PROVIDE_NAME, RpmTag.PROVIDE_VERSION, RpmTag.PROVIDE_FLAGS));
        result.setRequires(makeDependencies(header, RpmTag.REQUIRE_NAME, RpmTag.REQUIRE_VERSION, RpmTag.REQUIRE_FLAGS));
        result.setConflicts(makeDependencies(header, RpmTag.CONFLICT_NAME, RpmTag.CONFLICT_VERSION, RpmTag.CONFLICT_FLAGS));
        result.setObsoletes(makeDependencies(header, RpmTag.OBSOLETE_NAME, RpmTag.OBSOLETE_VERSION, RpmTag.OBSOLETE_FLAGS));

        // files

        final CpioArchiveInputStream cpio = in.getCpioStream();
        CpioArchiveEntry cpioEntry;
        while ((cpioEntry = cpio.getNextEntry()) != null) {
            final String name = normalize(cpioEntry.getName());

            if (cpioEntry.isRegularFile()) {
                result.getFiles().add(name);
            } else if (cpioEntry.isDirectory()) {
                result.getDirectories().add(name);
            }
        }
        cpio.close();

        return result;
    }

    public static List makeDependencies(final InputHeader header, final RpmTag namesTag, final RpmTag versionsTag, final RpmTag flagsTag) {
        Object namesVal = header.getTag(namesTag);
        Object versionsVal = header.getTag(versionsTag);
        Object flagsVal = header.getTag(flagsTag);

        if (namesVal == null || !(namesVal instanceof String[])) {
            if (namesVal instanceof String) {
                namesVal = new String[] { (String) namesVal };
            } else {
                return Collections.emptyList();
            }
        }

        if (versionsVal != null && !(versionsVal instanceof String[])) {
            if (versionsVal instanceof String) {
                versionsVal = new String[] { (String) versionsVal };
            } else {
                throw new IllegalStateException(String.format("Invalid dependencies version format [%s]: %s", versionsTag, versionsVal));
            }
        }

        if (flagsVal != null && !(flagsVal instanceof Long[])) {
            if (flagsVal instanceof Long) {
                flagsVal = new Long[] { (Long) flagsVal };
            } else if (flagsVal instanceof Integer) {
                flagsVal = new Long[] { ((Integer) flagsVal).longValue() };
            } else if (flagsVal instanceof Integer[]) {
                flagsVal = Arrays.stream((Integer[]) flagsVal).map(Integer::longValue).toArray(Long[]::new);
            } else {
                throw new IllegalStateException(String.format("Invalid dependencies flags format [%s]: %s", flagsTag, flagsVal));
            }
        }

        final String[] names = (String[]) namesVal;
        final String[] versions = (String[]) versionsVal;
        final Long[] flags = (Long[]) flagsVal;

        if (versions != null && names.length != versions.length) {
            throw new IllegalStateException(String.format("Invalid size of dependency versions array [%s] - expected: %s, actual: %s", versionsTag, names.length, versions.length));
        }

        if (flags != null && names.length != flags.length) {
            throw new IllegalStateException(String.format("Invalid size of dependency flags array [%s] - expected: %s, actual: %s", flagsTag, names.length, flags.length));
        }

        final List result = new ArrayList<>(names.length);

        final Set known = new HashSet<>();

        for (int i = 0; i < names.length; i++) {
            final String name = names[i];
            String version = versions != null ? versions[i] : null;
            if (version != null && version.isEmpty()) {
                version = null;
            }
            final Long flag = flags != null ? flags[i] : null;

            final String key = name; // for now the key is the name

            if (known.add(key)) {
                result.add(new Dependency(name, version, flag != null ? flag : 0L));
            }
        }

        return result;
    }

    public static String normalize(final String name) {
        if (name.startsWith("./")) {
            return name.substring(1);
        }

        return name;
    }

    public static String asString(final Object value) {
        if (value == null) {
            return null;
        }

        return new RpmTagValue(value).asString().orElse(null);
    }

    public static Long asLong(final Object value) {
        if (value == null) {
            return null;
        }

        return new RpmTagValue(value).asLong().orElse(null);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy