org.vafer.jdeb.maven.DebMaker.java Source code

Java tutorial

Introduction

Here is the source code for org.vafer.jdeb.maven.DebMaker.java

Source

/*
 * Copyright 2012 The Apache Software Foundation.
 *
 * 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.vafer.jdeb.maven;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collection;

import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureGenerator;
import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder;
import org.vafer.jdeb.Console;
import org.vafer.jdeb.DataProducer;
import org.vafer.jdeb.PackagingException;
import org.vafer.jdeb.Processor;
import org.vafer.jdeb.changes.TextfileChangesProvider;
import org.vafer.jdeb.descriptors.PackageDescriptor;
import org.vafer.jdeb.signing.SigningUtils;
import org.vafer.jdeb.utils.VariableResolver;

/**
 * TODO generalize with DebAntTask
 *
 * A generic class for creating debian archives. Even supports signed changes
 * files.
 *
 * This class is largely based on the DebAntTask class, and provides the same
 * featues to maven developers that the ant task provides to ant developers.
 *
 * @author Bryan Sant
 * @see org.vafer.jdeb.ant.DebAntTask
 */
public class DebMaker {

    /**
     * A console to output log message with
     */
    private Console console;

    /**
     * The Debian package produced
     */
    private File deb;

    /**
     * The directory containing the control files to build the package
     */
    private File control;

    /**
     * The file containing the PGP keys
     */
    private File keyring;

    /**
     * The key to use in the keyring
     */
    private String key;

    /**
     * The passphrase for the key to sign the changes file
     */
    private String passphrase;

    /**
     * The file to read the changes from
     */
    private File changesIn;

    /**
     * The file where to write the changes to
     */
    private File changesOut;

    /**
     * The file where to write the changes of the changes input to
     */
    private File changesSave;

    /**
     * The compression method used for the data file (none, gzip or bzip2)
     */
    private String compression = "gzip";

    /**
     * Whether to sign the package that is created
     */
    private boolean signPackage;

    private final VariableResolver variableResolver;

    private final Collection<DataProducer> dataProducers;

    public DebMaker(Console console, VariableResolver variableResolver) {
        this(console, null, null, null, variableResolver);
    }

    public DebMaker(Console console, File deb, File controlDir, VariableResolver variableResolver) {
        this(console, deb, controlDir, null, variableResolver);
    }

    public DebMaker(Console console, File deb, File controlDir, Collection<DataProducer> dataProducers,
            VariableResolver variableResolver) {
        this.console = console;
        this.deb = deb;
        this.control = controlDir;
        this.variableResolver = variableResolver;
        if (dataProducers != null) {
            this.dataProducers = dataProducers;
        } else {
            this.dataProducers = new ArrayList<DataProducer>();
        }
    }

    public void setDeb(File deb) {
        this.deb = deb;
    }

    public void setControl(File control) {
        this.control = control;
    }

    public void setChangesIn(File changes) {
        this.changesIn = changes;
    }

    public void setChangesOut(File changes) {
        this.changesOut = changes;
    }

    public void setChangesSave(File changes) {
        this.changesSave = changes;
    }

    public void setKeyring(File keyring) {
        this.keyring = keyring;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public void setPassphrase(String passphrase) {
        this.passphrase = passphrase;
    }

    public void setCompression(String compression) {
        this.compression = compression;
    }

    public void setSignPackage(boolean signPackage) {
        this.signPackage = signPackage;
    }

    /**
     * Adds a new data source to the deb. The new data source may point to a
     * single file, a directory, or a tarball.
     *
     * @param file The data source to add
     */
    public void addData(File file) {
        final Data data = new Data();
        data.setSrc(file);
        dataProducers.add(data);
    }

    public void addData(Data data) {
        dataProducers.add(data);
    }

    private boolean isPossibleOutput(File file) {

        if (file.exists()) {
            return file.isFile() && file.canWrite();
        }

        return true;
    }

    public void makeDeb() throws PackagingException {

        if (control == null || !control.isDirectory()) {
            throw new PackagingException("\"" + control + "\" is not a valid 'control' directory)");
        }

        if (changesIn != null) {

            if (!changesIn.isFile() || !changesIn.canRead()) {
                throw new PackagingException("The 'changesIn' setting needs to point to a readable file. "
                        + changesIn + " was not found/readable.");
            }

            if (changesOut == null) {
                throw new PackagingException("A 'changesIn' without a 'changesOut' does not make much sense.");
            }

            if (!isPossibleOutput(changesOut)) {
                throw new PackagingException("Cannot write the output for 'changesOut' to " + changesOut);
            }

            if (changesSave != null && !isPossibleOutput(changesSave)) {
                throw new PackagingException("Cannot write the output for 'changesSave' to " + changesSave);
            }

        } else {
            if (changesOut != null || changesSave != null) {
                throw new PackagingException(
                        "The 'changesOut' or 'changesSave' settings may only be used when there is a 'changesIn' specified.");
            }
        }

        if (!"gzip".equals(compression) && !"bzip2".equals(compression) && !"none".equals(compression)) {
            throw new PackagingException("The compression method '" + compression + "' is not supported");
        }

        if (deb == null) {
            throw new PackagingException("You need to specify where the deb file is supposed to be created.");
        }

        final File[] controlFiles = control.listFiles();

        final DataProducer[] data = new DataProducer[dataProducers.size()];
        dataProducers.toArray(data);

        final Processor processor = new Processor(console, variableResolver);

        final PackageDescriptor packageDescriptor;
        try {

            console.info("Creating debian package: " + deb);

            if (signPackage) {
                if (keyring == null || !keyring.exists()) {
                    throw new PackagingException("Signing requested, but no keyring supplied");
                }

                if (key == null) {
                    throw new PackagingException("Signing requested, but no key supplied");
                }

                if (passphrase == null) {
                    throw new PackagingException("Signing requested, but no passphrase supplied");
                }

                FileInputStream keyRingInput = new FileInputStream(keyring);
                PGPSecretKey secretKey = null;
                try {
                    secretKey = SigningUtils.getSecretKey(keyRingInput, key);
                } finally {
                    keyRingInput.close();
                }

                int digest = PGPUtil.SHA1;

                PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
                        new BcPGPContentSignerBuilder(secretKey.getPublicKey().getAlgorithm(), digest));
                signatureGenerator.init(PGPSignature.BINARY_DOCUMENT,
                        SigningUtils.getPrivateKey(secretKey, passphrase));

                packageDescriptor = processor.createSignedDeb(controlFiles, data, deb, compression,
                        signatureGenerator);
            } else {
                packageDescriptor = processor.createDeb(controlFiles, data, deb, compression);
            }

        } catch (Exception e) {
            throw new PackagingException("Failed to create debian package " + deb, e);
        }

        final TextfileChangesProvider changesProvider;

        try {
            if (changesOut == null) {
                return;
            }

            console.info("Creating changes file: " + changesOut);

            // for now only support reading the changes form a textfile provider
            changesProvider = new TextfileChangesProvider(new FileInputStream(changesIn), packageDescriptor);

            processor.createChanges(packageDescriptor, changesProvider,
                    (keyring != null) ? new FileInputStream(keyring) : null, key, passphrase,
                    new FileOutputStream(changesOut));

        } catch (Exception e) {
            throw new PackagingException("Failed to create debian changes file " + changesOut, e);
        }

        try {
            if (changesSave == null) {
                return;
            }

            console.info("Saving changes to file: " + changesSave);

            changesProvider.save(new FileOutputStream(changesSave));

        } catch (Exception e) {
            throw new PackagingException("Failed to save debian changes file " + changesSave, e);
        }
    }
}