org.fuin.esmp.AbstractEventStoreMojo.java Source code

Java tutorial

Introduction

Here is the source code for org.fuin.esmp.AbstractEventStoreMojo.java

Source

/**
 * Copyright (C) 2015 Michael Schnell. All rights reserved. 
 * <http://www.fuin.org/>
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 3 of the License, or (at your option) any
 * later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library. If not, see <http://www.gnu.org/licenses/>.
 */
package org.fuin.esmp;

import static java.util.Collections.singletonList;

import java.io.File;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.StringReader;
import java.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.exec.OS;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Parameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.impl.StaticLoggerBinder;

/**
 * Base class for all mojos.
 */
public abstract class AbstractEventStoreMojo extends AbstractMojo {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractEventStoreMojo.class);

    private static final String PID_FILE_NAME = "event-store-pid";

    /**
     * Full URL where the event store file to download is located. If set, this
     * always overrides the <code>base-url</code>, <code>archive-name</code>,
     * <code>archive-version</code> and <code>archive-extension</code>
     * parameters.
     */
    @Parameter(name = "download-url")
    private String downloadUrl;

    /**
     * Base URl where the event store archives are located. This is used to
     * construct an archive URl for the OS where the build script is executed.
     */
    @Parameter(name = "base-url", defaultValue = "http://download.geteventstore.com/binaries/")
    private String baseUrl = "http://download.geteventstore.com/binaries/";

    /**
     * Name of the archive (Like "EventStore-OSS-Win" or "EventStore-OSS-Linux")
     * without version and file extension. This is used to construct an archive
     * URl for the OS where the build script is executed.
     */
    @Parameter(name = "archive-name")
    private String archiveName;

    /**
     * Version of the archive (Like "3.0.5"). This is used to construct an
     * archive URl for the OS where the build script is executed.
     */
    @Parameter(name = "archive-version", defaultValue = "3.0.5")
    private String archiveVersion = "3.0.5";

    /**
     * File extension of the archive (Like "zip" or "tar.gz"). This is used to
     * construct an archive URl for the OS where the build script is executed.
     */
    @Parameter(name = "archive-extension")
    private String archiveExtension;

    /**
     * The target build directory.
     */
    @Parameter(name = "target-dir", property = "project.build.directory")
    private File targetDir = new File("./target");

    /**
     * Directory where the event store should be installed. The downloaded
     * archive will be uncompressed into this directory.
     */
    @Parameter(name = "event-store-dir")
    private File eventStoreDir;

    @Parameter(name = "proxy-ignored", defaultValue = "true")
    private boolean proxyIgnored;

    @Parameter(defaultValue = "${session}")
    private MavenSession mavenSession;

    /**
     * Checks if a variable is not <code>null</code> and throws an
     * <code>IllegalNullArgumentException</code> if this rule is violated.
     * 
     * @param name
     *            Name of the variable to be displayed in an error message.
     * @param value
     *            Value to check for <code>null</code>.
     * 
     * @throws MojoExecutionException
     *             Checked value was NULL.
     */
    protected final void checkNotNull(final String name, final Object value) throws MojoExecutionException {
        if (value == null) {
            throw new MojoExecutionException(name + " cannot be null!");
        }
    }

    @Override
    public final void execute() throws MojoExecutionException {
        StaticLoggerBinder.getSingleton().setMavenLog(getLog());
        init();
        LOG.info("proxy-ignored={}", proxyIgnored);
        LOG.info("download-url={}", downloadUrl);
        LOG.info("base-url={}", baseUrl);
        LOG.info("archive-name={}", archiveName);
        LOG.info("archive-version={}", archiveVersion);
        LOG.info("archive-extension={}", archiveExtension);
        LOG.info("target-dir={}", targetDir);
        LOG.info("event-store-dir={}", eventStoreDir);
        executeGoal();
    }

    // CHECKSTYLE:OFF Cyclomatic complexity - Not nice, but OK for now
    private void init() throws MojoExecutionException {

        // Only initialize other stuff if no full URL is provided
        if (downloadUrl == null) {

            // Make sure base URL always ends with a slash
            if (!baseUrl.endsWith("/")) {
                baseUrl = baseUrl + "/";
            }

            // Supply variables that are OS dependent
            if (OS.isFamilyWindows()) {
                if (archiveName == null) {
                    archiveName = "EventStore-OSS-Win";
                }
                if (archiveExtension == null) {
                    archiveExtension = "zip";
                }
            } else if (OS.isFamilyMac()) {
                if (archiveName == null) {
                    archiveName = "EventStore-OSS-Mac";
                }
                if (archiveExtension == null) {
                    archiveExtension = "tar.gz";
                }
            } else if (OS.isFamilyUnix()) {
                if (archiveName == null) {
                    archiveName = "EventStore-OSS-Linux";
                }
                if (archiveExtension == null) {
                    archiveExtension = "tar.gz";
                }
            } else {
                if (archiveName == null) {
                    throw new MojoExecutionException("Unknown OS - You must use the 'archive-name' parameter");
                }
                if (archiveExtension == null) {
                    throw new MojoExecutionException("Unknown OS - You must use the 'archive-ext' parameter");
                }
            }

            downloadUrl = baseUrl + archiveName + "-v" + archiveVersion + "." + archiveExtension;

        }

        // If it's not explicitly set, create it with target directory
        if (eventStoreDir == null) {

            if (downloadUrl.endsWith(".zip")) {
                eventStoreDir = new File(canonicalFile(targetDir), FilenameUtils.getBaseName(downloadUrl));
            } else if (downloadUrl.endsWith(".tar.gz")) {
                eventStoreDir = new File(canonicalFile(targetDir),
                        FilenameUtils.getBaseName(FilenameUtils.getBaseName(downloadUrl)));
            } else {
                throw new MojoExecutionException("Cannot handle archive with this extension: " + downloadUrl);
            }

        }

    }

    // CHECKSTYLE:ON

    private File canonicalFile(final File file) throws MojoExecutionException {
        try {
            return file.getCanonicalFile();
        } catch (final IOException ex) {
            throw new MojoExecutionException("Error creating canonical file: " + file, ex);
        }
    }

    protected final void setProxy(URL downloadUrl) throws URISyntaxException {
        final String selectedProxyHost;
        final int selectedProxyPort;

        if (mavenSession != null && mavenSession.getSettings().getActiveProxy() != null
                && mavenSession.getSettings().getActiveProxy().getHost() != null) {
            selectedProxyHost = mavenSession.getSettings().getActiveProxy().getHost();
            selectedProxyPort = mavenSession.getSettings().getActiveProxy().getPort();
        } else {
            selectedProxyHost = null;
            selectedProxyPort = 0;
        }

        final String selectedProxyUser;
        final String selectedProxyPassword;
        if (mavenSession != null && mavenSession.getSettings().getActiveProxy() != null
                && mavenSession.getSettings().getActiveProxy().getHost() != null) {
            selectedProxyUser = mavenSession.getSettings().getActiveProxy().getUsername();
            selectedProxyPassword = mavenSession.getSettings().getActiveProxy().getPassword();
        } else {
            selectedProxyUser = null;
            selectedProxyPassword = null;
        }

        LOG.info("Used proxy: {host: " + selectedProxyHost + ", port: " + selectedProxyPort + ", user: "
                + selectedProxyUser + ", passwd: " + selectedProxyPassword + "}");
        addProxySelector(selectedProxyHost, selectedProxyPort, selectedProxyUser, selectedProxyPassword,
                downloadUrl);
    }

    private void addProxySelector(final String proxyHost, final int proxyPort, final String proxyUser,
            final String proxyPassword, final URL downloadUrl) throws URISyntaxException {

        // Add authenticator with proxyUser and proxyPassword
        if (proxyUser != null && proxyPassword != null) {
            Authenticator.setDefault(new Authenticator() {
                @Override
                public PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(proxyUser, proxyPassword.toCharArray());
                }
            });
        }
        final ProxySelector defaultProxySelector = ProxySelector.getDefault();

        final URI downloadUri = downloadUrl.toURI();

        ProxySelector.setDefault(new ProxySelector() {
            @Override
            public List<Proxy> select(final URI uri) {
                if (uri.getHost().equals(downloadUri.getHost()) && proxyHost != null && proxyHost.length() != 0) {
                    return singletonList(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)));
                } else {
                    return defaultProxySelector.select(uri);
                }
            }

            @Override
            public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) {
            }
        });
    }

    /**
     * Returns the full URL where the event store file to download is located.
     * 
     * @return Download archive URL.
     * 
     * @throws MojoExecutionException
     *             Error initializing the variable.
     */
    public final String getDownloadUrl() throws MojoExecutionException {
        if (downloadUrl == null) {
            init();
        }
        return downloadUrl;
    }

    /**
     * Sets the full URL where the event store file to download is located.
     * 
     * @param downloadUrl
     *            Download archive URL to set
     */
    public final void setDownloadUrl(final String downloadUrl) {
        this.downloadUrl = downloadUrl;
    }

    /**
     * Returns the base URl where the event store archives are located.
     * 
     * @return Base URL where archives are located.
     * 
     * @throws MojoExecutionException
     *             Error initializing the variable.
     */
    public final String getBaseUrl() throws MojoExecutionException {
        if (baseUrl == null) {
            init();
        }
        return baseUrl;
    }

    /**
     * Sets the base URl where the event store archives are located.
     * 
     * @param baseUrl
     *            Base URL where archives are located to set
     */
    public final void setBaseUrl(final String baseUrl) {
        this.baseUrl = baseUrl;
    }

    /**
     * Returns the name of the archive (Like "EventStore-OSS-Win" or
     * "EventStore-OSS-Linux") without version and file extension.
     * 
     * @return the archiveName
     * 
     * @throws MojoExecutionException
     *             Error initializing the variable.
     */
    public final String getArchiveName() throws MojoExecutionException {
        if (archiveName == null) {
            init();
        }
        return archiveName;
    }

    /**
     * Sets the name of the archive (Like "EventStore-OSS-Win" or
     * "EventStore-OSS-Linux") without version and file extension.
     * 
     * @param archiveName
     *            Archive name to set.
     */
    public final void setArchiveName(final String archiveName) {
        this.archiveName = archiveName;
    }

    /**
     * Returns the version of the archive (Like "3.0.5").
     * 
     * @return Event store version.
     */
    public final String getArchiveVersion() {
        return archiveVersion;
    }

    /**
     * Sets the version of the archive (Like "3.0.5").
     * 
     * @param archiveVersion
     *            The event store version to set.
     */
    public final void setArchiveVersion(final String archiveVersion) {
        this.archiveVersion = archiveVersion;
    }

    /**
     * Returns the file extension of the archive (Like "zip" or "tar.gz").
     * 
     * @return Archive file extension.
     * 
     * @throws MojoExecutionException
     *             Error initializing the variable.
     */
    public final String getArchiveExtension() throws MojoExecutionException {
        if (archiveExtension == null) {
            init();
        }
        return archiveExtension;
    }

    /**
     * Sets the file extension of the archive (Like "zip" or "tar.gz").
     * 
     * @param archiveExtension
     *            Archive file extension to set.
     */
    public final void setArchiveExtension(final String archiveExtension) {
        this.archiveExtension = archiveExtension;
    }

    /**
     * Returns the directory where the event store should be installed. The
     * downloaded archive will be uncompressed into this directory.
     * 
     * @return Target directory.
     * 
     * @throws MojoExecutionException
     *             Error initializing the variable.
     */
    public final File getEventStoreDir() throws MojoExecutionException {
        if (eventStoreDir == null) {
            init();
        }
        return eventStoreDir;
    }

    /**
     * Sets the directory where the event store should be installed. The
     * downloaded archive will be uncompressed into this directory.
     * 
     * @param eventStoreDir
     *            Target directory to set
     */
    public final void setEventStoreDir(final File eventStoreDir) {
        this.eventStoreDir = eventStoreDir;
    }

    /**
     * Returns the target build directory.
     * 
     * @return The build directory.
     */
    public final File getTargetDir() {
        return targetDir;
    }

    /**
     * Sets the target build directory.
     * 
     * @param targetDir
     *            The build directory to set
     */
    public final void setTargetDir(final File targetDir) {
        this.targetDir = targetDir;
    }

    public boolean isProxyIgnored() {
        return proxyIgnored;
    }

    public void setProxyIgnored(boolean ignoreProxy) {
        this.proxyIgnored = ignoreProxy;
    }

    /**
     * Writes the process ID of the event store to a file in the target
     * directory.
     * 
     * @param pid
     *            PID to write.
     * 
     * @throws MojoExecutionException
     *             Error writing the PID to file.
     */
    protected final void writePid(final String pid) throws MojoExecutionException {
        try {
            FileUtils.write(getPidFile(), pid);
        } catch (final IOException ex) {
            throw new MojoExecutionException("Couldn't write the PID '" + pid + "' to file: " + getPidFile(), ex);
        }
    }

    /**
     * Reads the process ID of the event store from a file in the target
     * directory.
     * 
     * @return PID from file.
     * 
     * @throws MojoExecutionException
     *             Error reading the PID from file.
     */
    protected final String readPid() throws MojoExecutionException {
        try {
            return FileUtils.readFileToString(getPidFile());
        } catch (final IOException ex) {
            throw new MojoExecutionException("Couldn't read the PID from file: " + getPidFile(), ex);
        }
    }

    /**
     * Deletes the process ID file in the target directory.
     * 
     * @throws MojoExecutionException
     *             Error deleting the PID file.
     */
    protected final void deletePid() throws MojoExecutionException {
        final boolean ok = getPidFile().delete();
        if (!ok) {
            throw new MojoExecutionException("Couldn't delete the PID file: " + getPidFile());
        }
    }

    /**
     * Returns the PID file.
     * 
     * @return Process ID file.
     */
    protected final File getPidFile() {
        return new File(getTargetDir(), PID_FILE_NAME);
    }

    /**
     * Returns the string as list.
     * 
     * @param str
     *            String to split into lines.
     * 
     * @return List of lines.
     * 
     * @throws MojoExecutionException
     *             Error splitting the string into lines.
     */
    protected final List<String> asList(final String str) throws MojoExecutionException {
        try {
            final List<String> lines = new ArrayList<String>();
            final LineNumberReader reader = new LineNumberReader(new StringReader(str));
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line);
            }
            return lines;
        } catch (final IOException ex) {
            throw new MojoExecutionException("Error creating string list", ex);
        }
    }

    /**
     * Logs all lines in debug mode.
     * 
     * @param messages
     *            Lines to log.
     */
    protected final void logDebug(final List<String> messages) {
        if (LOG.isDebugEnabled()) {
            for (final String message : messages) {
                LOG.debug(message);
            }
        }
    }

    /**
     * Logs all lines in error mode.
     * 
     * @param messages
     *            Lines to log.
     */
    protected final void logError(final List<String> messages) {
        if (LOG.isErrorEnabled()) {
            for (final String message : messages) {
                LOG.error(message);
            }
        }
    }

    /**
     * Executes the goal code.
     * 
     * @throws MojoExecutionException
     *             if goal execution failed
     */
    protected abstract void executeGoal() throws MojoExecutionException;

}