de.dentrassi.rpm.builder.YumMojo.java Source code

Java tutorial

Introduction

Here is the source code for de.dentrassi.rpm.builder.YumMojo.java

Source

/*******************************************************************************
 * Copyright (c) 2016, 2017 IBH SYSTEMS GmbH and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBH SYSTEMS GmbH - initial API and implementation
 *     Red Hat Inc - upgrade to package drone 0.14.0
 *     Bernd Warmuth - introduced skipDependencies property,
                   only consider dependencies of type "rpm",
                   fixed repodata creation for multiple rpm packages
 *******************************************************************************/
package de.dentrassi.rpm.builder;

import static java.util.Collections.singletonMap;
import static org.eclipse.packagedrone.utils.rpm.HashAlgorithm.SHA256;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.eclipse.packagedrone.utils.io.FileSystemSpoolOutTarget;
import org.eclipse.packagedrone.utils.rpm.HashAlgorithm;
import org.eclipse.packagedrone.utils.rpm.info.RpmInformation;
import org.eclipse.packagedrone.utils.rpm.info.RpmInformations;
import org.eclipse.packagedrone.utils.rpm.parse.RpmInputStream;
import org.eclipse.packagedrone.utils.rpm.yum.RepositoryCreator;
import org.eclipse.packagedrone.utils.rpm.yum.RepositoryCreator.Builder;
import org.eclipse.packagedrone.utils.rpm.yum.RepositoryCreator.Context;
import org.eclipse.packagedrone.utils.rpm.yum.RepositoryCreator.FileInformation;
import org.eclipse.packagedrone.utils.security.pgp.SigningStream;

import com.google.common.collect.Lists;

/**
 * Build a YUM repository
 *
 * @author ctron
 */
@Mojo(name = "yum-repository", defaultPhase = LifecyclePhase.PACKAGE, requiresProject = true, requiresDependencyResolution = ResolutionScope.COMPILE, requiresDependencyCollection = ResolutionScope.COMPILE, threadSafe = false)
public class YumMojo extends AbstractMojo {
    /**
     * The maven project
     */
    @Parameter(property = "project", readonly = true, required = true)
    protected MavenProject project;

    @Parameter(defaultValue = "${session}", readonly = true, required = true)
    private MavenSession session;

    @Component
    private MavenProjectHelper projectHelper;

    /**
     * The location of the output directory.
     * <p>
     * This directory will be created if it does not exists.
     * </p>
     */
    @Parameter(property = "yum.repository.output", defaultValue = "${project.build.directory}/yum")
    private File outputDirectory;

    /**
     * A list of files to be added
     * <p>
     * All listed files will be added to the final repository.
     * </p>
     */
    @Parameter
    private List<File> files;

    /**
     * A list of directories
     * <p>
     * These directories will be scanned recursively for files with the
     * extension <code>.rpm</code>. All matching files will be added to the
     * final repository.
     * </p>
     */
    @Parameter
    private List<File> directories;

    private File packagesPath;

    /**
     * An optional signature descriptor for GPP signing the final YUM repository
     * <p>
     * Also see <a href="signing.html">signing</a>
     * </p>
     */
    @Parameter(property = "rpm.signature")
    private Signature signature;

    /**
     * Disable all repository signing
     */
    @Parameter(property = "rpm.skipSigning", defaultValue = "false")
    private boolean skipSigning = false;

    /**
     * Disable the use of RPMs from maven dependency artifacts
     */
    @Parameter(property = "rpm.skipDependencies", defaultValue = "false")
    private boolean skipDependencies = false;

    private Logger logger;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        this.logger = new Logger(getLog());

        try {
            final Builder builder = new RepositoryCreator.Builder();
            builder.setTarget(new FileSystemSpoolOutTarget(this.outputDirectory.toPath()));

            if (!this.skipSigning) {
                final PGPPrivateKey privateKey = SigningHelper.loadKey(this.signature, this.logger);
                if (privateKey != null) {
                    final int digestAlgorithm = HashAlgorithm.from(this.signature.getHashAlgorithm()).getValue();
                    builder.setSigning(output -> new SigningStream(output, privateKey, digestAlgorithm, false,
                            "RPM builder Mojo - de.dentrassi.maven:rpm"));
                }
            }

            final RepositoryCreator creator = builder.build();

            this.packagesPath = new File(this.outputDirectory, "packages");
            Files.createDirectories(this.packagesPath.toPath());

            final Collection<Path> paths = Lists.newArrayList();

            if (!this.skipDependencies) {
                final Set<Artifact> deps = this.project.getArtifacts();
                if (deps != null) {
                    paths.addAll(deps.stream()//
                            .filter(d -> d.getType().equalsIgnoreCase("rpm"))//
                            .map(d -> d.getFile().toPath())//
                            .collect(Collectors.toList()));
                }
            } else {
                this.logger.debug("Skipped RPM artifacts from maven dependencies");
            }

            if (this.files != null) {
                paths.addAll(this.files.stream().map(f -> f.toPath()).collect(Collectors.toList()));
            }
            if (this.directories != null) {
                for (final File dir : this.directories) {
                    Files.walkFileTree(dir.toPath(), new SimpleFileVisitor<Path>() {
                        @Override
                        public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs)
                                throws IOException {
                            if (file.getFileName().toString().toLowerCase().endsWith(".rpm")) {
                                paths.add(file);
                            }
                            return FileVisitResult.CONTINUE;
                        }
                    });
                }
            }

            addPackageList(creator, paths);
        } catch (final IOException e) {
            throw new MojoExecutionException("Failed to write repository", e);
        }
    }

    private void addPackageList(final RepositoryCreator creator, final Collection<Path> paths) {
        try {
            creator.process(context -> {
                for (final Path p : paths) {
                    addSinglePackage(p, context);
                }
                getLog().info(String.format("Added %s packages to the repository", paths.size()));
            });
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void addSinglePackage(final Path path, final Context context) throws IOException {
        final String checksum = makeChecksum(path);
        final String fileName = path.getFileName().toString();
        final String location = "packages/" + fileName;
        final FileInformation fileInformation = new FileInformation(Files.getLastModifiedTime(path).toInstant(),
                Files.size(path), location);

        final RpmInformation rpmInformation;
        try (RpmInputStream ris = new RpmInputStream(Files.newInputStream(path))) {
            rpmInformation = RpmInformations.makeInformation(ris);
        }

        context.addPackage(fileInformation, rpmInformation, singletonMap(SHA256, checksum), SHA256);

        Files.copy(path, this.packagesPath.toPath().resolve(fileName), StandardCopyOption.COPY_ATTRIBUTES);
    }

    private String makeChecksum(final Path path) throws IOException {
        try (InputStream is = Files.newInputStream(path)) {
            return DigestUtils.sha256Hex(is).toLowerCase();
        }
    }
}