    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.release.plugin.mojos;
    018
    019import java.io.File;
    020import java.io.FileInputStream;
    021import java.io.FileOutputStream;
    022import java.io.IOException;
    023import java.util.ArrayList;
    024import java.util.List;
    025import java.util.zip.ZipEntry;
    026import java.util.zip.ZipOutputStream;
    027
    028import org.apache.commons.compress.archivers.zip.ParallelScatterZipCreator;
    029import org.apache.commons.compress.archivers.zip.ScatterZipOutputStream;
    030import org.apache.commons.io.IOUtils;
    031import org.apache.commons.lang3.StringUtils;
    032import org.apache.maven.plugin.AbstractMojo;
    033import org.apache.maven.plugin.MojoExecutionException;
    034import org.apache.maven.plugin.MojoFailureException;
    035import org.apache.maven.plugins.annotations.LifecyclePhase;
    036import org.apache.maven.plugins.annotations.Mojo;
    037import org.apache.maven.plugins.annotations.Parameter;
    038
    039/**
    040 * Takes the built <code>./target/site</code> directory and compresses it to
    041 * <code>./target/commons-release-plugin/site.zip</code>.
    042 *
    043 * @author chtompki
    044 * @since 1.0
    045 * @deprecated - as we no longer wish to compress the site, we are going to put this functionality in the
    046 *               {@link CommonsDistributionStagingMojo}.
    047 */
    048@Deprecated
    049@Mojo(name = "compress-site",
    050        defaultPhase = LifecyclePhase.POST_SITE,
    051        threadSafe = true,
    052        aggregator = true)
    053public class CommonsSiteCompressionMojo extends AbstractMojo {
    054
    055    /**
    056     * The working directory for the plugin which, assuming the maven uses the default
    057     * <code>${project.build.directory}</code>, this becomes <code>target/commons-release-plugin</code>.
    058     */
    059    @Parameter(defaultValue = "${project.build.directory}/commons-release-plugin",
    060            property = "commons.outputDirectory")
    061    private File workingDirectory;
    062
    063    /**
    064     */
    065    @Parameter(defaultValue = "${project.build.directory}/site", property = "commons.siteOutputDirectory")
    066    private File siteDirectory;
    067
    068    /**
    069     * The url of the subversion repository to which we wish the artifacts to be staged. Typicallly
    070     * this would need to be of the form:
    071     * <code>scm:svn:https://dist.apache.org/repos/dist/dev/commons/foo</code>. Note. that the prefix to the
    072     * substring <code>https</code> is a requirement.
    073     */
    074    @Parameter(defaultValue = "", property = "commons.distSvnStagingUrl")
    075    private String distSvnStagingUrl;
    076
    077    /**
    078     * A parameter to generally avoid running unless it is specifically turned on by the consuming module.
    079     */
    080    @Parameter(defaultValue = "false", property = "commons.release.isDistModule")
    081    private Boolean isDistModule;
    082
    083    /**
    084     * A variable for the process of creating the site.zip file.
    085     */
    086    private ScatterZipOutputStream dirs;
    087
    088    /**
    089     * A second variable for the process of creating the site.zip file.
    090     */
    091    private ParallelScatterZipCreator scatterZipCreator;
    092
    093    /**
    094     * The list of files to compress into the site.zip file.
    095     */
    096    private List<File> filesToCompress;
    097
    098    @Override
    099    public void execute() throws MojoExecutionException, MojoFailureException {
    100        if (!isDistModule) {
    101            getLog().info("This module is marked as a non distribution "
    102                    + "or assembly module, and the plugin will not run.");
    103            return;
    104        }
    105        if (StringUtils.isEmpty(distSvnStagingUrl)) {
    106            getLog().warn("commons.distSvnStagingUrl is not set, the commons-release-plugin will not run.");
    107            return;
    108        }
    109        if (!siteDirectory.exists()) {
    110            getLog().error("\"mvn site\" was not run before this goal, or a siteDirectory did not exist.");
    111            throw new MojoFailureException(
    112                    "\"mvn site\" was not run before this goal, or a siteDirectory did not exist."
    113            );
    114        }
    115        if (!workingDirectory.exists()) {
    116            getLog().info("Current project contains no distributions. Not executing.");
    117            return;
    118        }
    119        try {
    120            filesToCompress = new ArrayList<>();
    121            getAllSiteFiles(siteDirectory, filesToCompress);
    122            writeZipFile(workingDirectory, siteDirectory, filesToCompress);
    123        } catch (IOException e) {
    124            getLog().error("Failed to create ./target/commons-release-plugin/site.zip: " + e.getMessage(), e);
    125            throw new MojoExecutionException(
    126                    "Failed to create ./target/commons-release-plugin/site.zip: " + e.getMessage(),
    127                    e
    128            );
    129        }
    130    }
    131
    132    /**
    133     * By default this method iterates across the <code>target/site</code> directory and adds all of the files
    134     * to the {@link CommonsSiteCompressionMojo#filesToCompress} {@link List}.
    135     *
    136     * @param siteDirectory the {@link File} that represents the <code>target/site</code> directory.
    137     * @param filesToCompress the {@link List} to which to add all the files.
    138     */
    139    private void getAllSiteFiles(File siteDirectory, List<File> filesToCompress) {
    140        File[] files = siteDirectory.listFiles();
    141        for (File file : files) {
    142            filesToCompress.add(file);
    143            if (file.isDirectory()) {
    144                getAllSiteFiles(file, filesToCompress);
    145            }
    146        }
    147    }
    148
    149    /**
    150     * A helper method for writing all of the files in our <code>fileList</code> to a <code>site.zip</code> file
    151     * in the <code>workingDirectory</code>.
    152     *
    153     * @param outputDirectory is a {@link File} representing the place to put the site.zip file.
    154     * @param directoryToZip is a {@link File} representing the directory of the site (normally
    155     *                       <code>target/site</code>).
    156     * @param fileList the list of files to be zipped up, generally generated by
    157     *                 {@link CommonsSiteCompressionMojo#getAllSiteFiles(File, List)}.
    158     * @throws IOException when the copying of the files goes incorrectly.
    159     */
    160    private void writeZipFile(File outputDirectory, File directoryToZip, List<File> fileList) throws IOException {
    161        try (FileOutputStream fos = new FileOutputStream(outputDirectory.getAbsolutePath() + "/site.zip");
    162                ZipOutputStream zos = new ZipOutputStream(fos)) {
    163            for (File file : fileList) {
    164                if (!file.isDirectory()) { // we only zip files, not directories
    165                    addToZip(directoryToZip, file, zos);
    166                }
    167            }
    168        }
    169    }
    170
    171    /**
    172     * Given the <code>directoryToZip</code> we add the <code>file</code> to the zip archive represented by
    173     * <code>zos</code>.
    174     *
    175     * @param directoryToZip a {@link File} representing the directory from which the file exists that we are
    176     *                       compressing. Generally this is <code>target/site</code>.
    177     * @param file a {@link File} to add to the {@link ZipOutputStream} <code>zos</code>.
    178     * @param zos the {@link ZipOutputStream} to which to add our <code>file</code>.
    179     * @throws IOException if adding the <code>file</code> doesn't work out properly.
    180     */
    181    private void addToZip(File directoryToZip, File file, ZipOutputStream zos) throws IOException {
    182        try (FileInputStream fis = new FileInputStream(file)) {
    183            // we want the zipEntry's path to be a relative path that is relative
    184            // to the directory being zipped, so chop off the rest of the path
    185            String zipFilePath = file.getCanonicalPath().substring(directoryToZip.getCanonicalPath().length() + 1,
    186                    file.getCanonicalPath().length());
    187            ZipEntry zipEntry = new ZipEntry(zipFilePath);
    188            zos.putNextEntry(zipEntry);
    189            IOUtils.copy(fis, zos);
    190        }
    191    }
    192}