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

com.artipie.debian.metadata.PackagesItem Maven / Gradle / Ivy

The newest version!
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2020 Artipie
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.artipie.debian.metadata;

import com.artipie.asto.Key;
import com.artipie.asto.Storage;
import com.artipie.asto.ext.ContentDigest;
import com.artipie.asto.ext.Digests;
import java.util.concurrent.CompletionStage;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Packages index item.
 * @since 0.1
 */
public interface PackagesItem {

    /**
     * Formats packages item by adding filename, size and checksums to control.
     * @param content Deb package content
     * @param key Deb package key
     * @return Completion action with formatted package item
     */
    CompletionStage format(String content, Key key);

    /**
     * {@link PackagesItem} from abstract storage.
     * @since 0.1
     */
    final class Asto implements PackagesItem {

        /**
         * Abstract storage.
         */
        private final Storage asto;

        /**
         * Ctor.
         * @param asto Storage
         */
        public Asto(final Storage asto) {
            this.asto = asto;
        }

        @Override
        public CompletionStage format(final String control, final Key deb) {
            return this.asto.value(deb).thenApply(
                val -> Asto.addSizeAndFilename(
                    val.size().orElseThrow(
                        () -> new IllegalStateException("Content size unknown")
                    ), deb.string(), control
                )
            )
            .thenCompose(
                res -> this.digests(deb, Digests.MD5)
                    .thenApply(hex -> Asto.addDigest(res, "MD5sum", hex))
            )
            .thenCompose(
                res -> this.digests(deb, Digests.SHA1)
                    .thenApply(hex -> Asto.addDigest(res, "SHA1", hex))
            )
            .thenCompose(
                res -> this.digests(deb, Digests.SHA256)
                    .thenApply(hex -> Asto.addDigest(res, "SHA256", hex))
            )
            .thenApply(Asto::sort);
        }

        /**
         * Calculates digest for the given algorithm.
         * @param deb Debian package key
         * @param alg Algorithm
         * @return Digest hex
         */
        private CompletionStage digests(final Key deb, final Digests alg) {
            return this.asto.value(deb).thenCompose(
                val -> new ContentDigest(val, alg).hex()
            );
        }

        /**
         * Adds digest to control.
         * @param control Control to append info to
         * @param alg Algorithm
         * @param hex Hex
         * @return Control with digest
         */
        private static String addDigest(final String control, final String alg, final String hex) {
            return Stream.concat(
                Stream.of(control.split("\n")),
                Stream.of(
                    String.format("%s: %s", alg, hex)
                )
            ).collect(Collectors.joining("\n"));
        }

        /**
         * Adds size and filename to the control.
         * @param size Package size
         * @param filename Filename
         * @param control Control file
         * @return Control with size and file name
         * @checkstyle ParameterNumberCheck (5 lines)
         */
        private static String addSizeAndFilename(
            final long size, final String filename, final String control
        ) {
            return Stream.concat(
                Stream.of(control.split("\n")),
                Stream.of(
                    String.format("Filename: %s", filename),
                    String.format("Size: %d", size)
                )
            ).collect(Collectors.joining("\n"));
        }

        /**
         * Sorts packages item: the only condition is that Package field should be first.
         * @param item Package item to sort
         * @return Sorted package item
         */
        private static String sort(final String item) {
            final String res;
            final String name = "Package";
            if (item.startsWith(name)) {
                res = item;
            } else {
                res = Stream.of(item.split("\n")).sorted(
                    (one, two) -> {
                        final int sort;
                        if (one.startsWith(name)) {
                            sort = -1;
                        } else {
                            sort = 1;
                        }
                        return sort;
                    }
                ).collect(Collectors.joining("\n"));
            }
            return res;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy