org.apache.sis.internal.maven.Assembler.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.sis.internal.maven.Assembler.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.sis.internal.maven;

import java.io.File;
import java.io.IOException;
import java.io.FilenameFilter;
import java.io.FileInputStream;
import java.io.FilterOutputStream;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.project.MavenProject;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;

import static org.apache.sis.internal.maven.Filenames.*;

/**
 * Creates a ZIP files containing the content of the <code>application/sis-console/src/main/artifact</code>
 * directory together with the Pack200 file created by <code>BundleCreator</code>.
 * This mojo can be invoked from the command line as below:
 *
 * <blockquote><code>mvn org.apache.sis.core:sis-build-helper:dist --non-recursive</code></blockquote>
 *
 * Do not forget the <code>--non-recursive</code> option, otherwise the Mojo will be executed many time.
 *
 * <p><b>Current limitation:</b>
 * The current implementation uses some hard-coded paths and filenames.
 * See the <cite>Distribution file and Pack200 bundle</cite> section in the <code>src/site/apt/index.apt</code>
 * file for more information.</p>
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @since   0.4
 * @version 0.7
 * @module
 */
@Mojo(name = "dist", defaultPhase = LifecyclePhase.INSTALL)
public class Assembler extends AbstractMojo implements FilenameFilter {
    /**
     * Project information (name, version, URL).
     */
    @Parameter(property = "project", required = true, readonly = true)
    private MavenProject project;

    /**
     * The root directory (without the "<code>target/binaries</code>" sub-directory) where JARs
     * are to be copied. It should be the directory of the root <code>pom.xml</code>.
     */
    @Parameter(property = "session.executionRootDirectory", required = true)
    private String rootDirectory;

    /**
     * Creates the distribution file.
     *
     * @throws MojoExecutionException if the plugin execution failed.
     */
    @Override
    public void execute() throws MojoExecutionException {
        final File sourceDirectory = new File(rootDirectory, ARTIFACT_PATH);
        if (!sourceDirectory.isDirectory()) {
            throw new MojoExecutionException("Directory not found: " + sourceDirectory);
        }
        final File targetDirectory = new File(rootDirectory, TARGET_DIRECTORY);
        final String version = project.getVersion();
        final String artifactBase = FINALNAME_PREFIX + version;
        try {
            final File targetFile = new File(distributionDirectory(targetDirectory), artifactBase + ".zip");
            final ZipArchiveOutputStream zip = new ZipArchiveOutputStream(targetFile);
            try {
                zip.setLevel(9);
                appendRecursively(sourceDirectory, artifactBase, zip, new byte[8192]);
                /*
                 * At this point, all the "application/sis-console/src/main/artifact" and sub-directories
                 * have been zipped.  Now generate the Pack200 file and zip it directly (without creating
                 * a temporary "sis.pack.gz" file).
                 */
                final Packer packer = new Packer(project.getName(), project.getUrl(), version, targetDirectory);
                final ZipArchiveEntry entry = new ZipArchiveEntry(
                        artifactBase + '/' + LIB_DIRECTORY + '/' + FATJAR_FILE + PACK_EXTENSION);
                entry.setMethod(ZipArchiveEntry.STORED);
                zip.putArchiveEntry(entry);
                packer.preparePack200(FATJAR_FILE + ".jar").pack(new FilterOutputStream(zip) {
                    /*
                     * Closes the archive entry, not the ZIP file.
                     */
                    @Override
                    public void close() throws IOException {
                        zip.closeArchiveEntry();
                    }
                });
            } finally {
                zip.close();
            }
        } catch (IOException e) {
            throw new MojoExecutionException(e.getLocalizedMessage(), e);
        }
    }

    /**
     * Adds the given file in the ZIP file. If the given file is a directory, then this method
     * recursively adds all files contained in this directory. This method is invoked for zipping
     * the "application/sis-console/src/main/artifact" directory and sub-directories before to zip
     * the Pack200 file.
     */
    private void appendRecursively(final File file, String relativeFile, final ZipArchiveOutputStream out,
            final byte[] buffer) throws IOException {
        if (file.isDirectory()) {
            relativeFile += '/';
        }
        final ZipArchiveEntry entry = new ZipArchiveEntry(file, relativeFile);
        if (file.canExecute()) {
            entry.setUnixMode(0744);
        }
        out.putArchiveEntry(entry);
        if (!entry.isDirectory()) {
            final FileInputStream in = new FileInputStream(file);
            try {
                int n;
                while ((n = in.read(buffer)) >= 0) {
                    out.write(buffer, 0, n);
                }
            } finally {
                in.close();
            }
        }
        out.closeArchiveEntry();
        if (entry.isDirectory()) {
            for (final String filename : file.list(this)) {
                appendRecursively(new File(file, filename), relativeFile.concat(filename), out, buffer);
            }
        }
    }

    /**
     * The filter to use for selecting the files to be included in the ZIP file.
     *
     * @param  directory The directory.
     * @param  filename  The filename.
     * @return {@code true} if the given file should be included in the ZIP file.
     */
    @Override
    public boolean accept(final File directory, final String filename) {
        return !filename.isEmpty() && filename.charAt(0) != '.';
    }
}