com.mulesoft.jockey.maven.GenerateMojo.java Source code

Java tutorial

Introduction

Here is the source code for com.mulesoft.jockey.maven.GenerateMojo.java

Source

/*
 * $Id$
 * --------------------------------------------------------------------------------------
 * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 *
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */
package com.mulesoft.jockey.maven;

import com.mulesoft.jockey.AbstractCommand;
import com.mulesoft.jockey.CommandRunner;
import com.mulesoft.jockey.GroovyCommandWrapper;
import com.mulesoft.jockey.script.GenerateCommands;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.zip.GZIPOutputStream;

import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.jruby.ext.posix.POSIX;
import org.jruby.ext.posix.POSIX.ERRORS;
import org.jruby.ext.posix.POSIXFactory;
import org.jruby.ext.posix.POSIXHandler;

/**
 * 
 * @goal generate
 * @requiresDependencyResolution
 */
public class GenerateMojo extends AbstractMojo {

    private static int USER_READ = 00400; //   read by owner
    private static int USER_WRITE = 00200;//   write by owner
    private static int USER_EXEC = 00100; //  execute/search by owner
    private static int GROUP_READ = 00040; //   read by group
    private static int GROUP_EXEC = 00010; //  execute/search by group
    private static int ALL_READ = 00004; //   read by all
    private static int ALL_EXEC = 00001; //  execute/search by all

    private static int EXECUTABLE_MODE = USER_EXEC | USER_READ | USER_WRITE | GROUP_EXEC | GROUP_READ | ALL_EXEC
            | ALL_READ;

    /**
     * @parameter default-value="${project.name}"
     */
    private String distributionName;

    /**
     * The greeting to display.
     * 
     * @parameter default-value="src/main/groovy"
     */
    private String scriptsSourceDirectory;

    /**
     * Location to build the CLI distribution. 
     *
     * @parameter expression="${outputDirectory}"
     *            default-value="${project.build.directory}"
     * @optional
     */
    private String buildDirectory;

    /**
     * @parameter default-value="${project}"
     * @required
     * @readonly
     */
    private MavenProject project;

    /**
     * Used to look up Artifacts in the remote repository.
     *
     * @component
     */
    protected ArtifactResolver resolver;

    /**
     * @parameter expression="${createZip}"
     * @optional
     */
    private boolean createZip = true;

    /**
     * @parameter expression="${createTarGz}"
     * @optional
     */
    private boolean createTarGz = true;

    /**
     * Maven ProjectHelper.
     *
     * @component
     * @readonly
     */
    private MavenProjectHelper projectHelper;
    private URLClassLoader classLoader;

    public void execute() throws MojoExecutionException, MojoFailureException {
        getLog().info("Creating a new Mule Jockey distribution...");
        getLog().info("Output directory " + buildDirectory);

        File distDir = new File(buildDirectory, distributionName);
        distDir.mkdirs();

        populateScripts(distDir);
        copyDependencies(distDir);

        if (createZip) {
            createZip(distDir);
        }

        if (createTarGz) {
            createTarGz(distDir);
        }
    }

    protected ClassLoader getCompileClassLoader() throws Exception {
        if (classLoader == null) {
            List<URL> urls = new ArrayList<URL>();
            for (Object object : project.getCompileClasspathElements()) {
                String path = (String) object;
                urls.add(new File(path).toURL());
            }
            classLoader = new URLClassLoader(urls.toArray(new URL[] {}));
        }
        return classLoader;
    }

    private void createTarGz(File distDir) throws MojoExecutionException {
        File output = new File(buildDirectory, distributionName + ".tar.gz");
        try {
            final OutputStream out = new FileOutputStream(output);
            TarArchiveOutputStream os = new TarArchiveOutputStream(new GZIPOutputStream(out));
            os.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
            copyArchiveFile(distDir, os, false);

            os.finish();

            os.close();
            out.close();
        } catch (IOException e) {
            throw new MojoExecutionException("Could not create zip file.", e);
        }
        projectHelper.attachArtifact(project, "tar.gz", "", output);
    }

    private void createZip(File distDir) throws MojoExecutionException {
        File output = new File(buildDirectory, distributionName + ".zip");
        try {
            final OutputStream out = new FileOutputStream(output);
            ArchiveOutputStream os = new ArchiveStreamFactory().createArchiveOutputStream("zip", out);

            copyArchiveFile(distDir, os, true);

            os.finish();

            os.close();
            out.close();
        } catch (IOException e) {
            throw new MojoExecutionException("Could not create zip file.", e);
        } catch (ArchiveException e) {
            throw new MojoExecutionException("Could not create zip file.", e);
        }
        projectHelper.attachArtifact(project, "zip", "", output);

    }

    private void copyArchiveFile(File file, ArchiveOutputStream os, boolean zipFile) throws IOException {
        if (file.isDirectory()) {
            File[] children = file.listFiles();
            if (children != null) {
                for (File child : children) {
                    copyArchiveFile(child, os, zipFile);
                }
            }
        } else {
            String relativePath = file.getAbsolutePath();
            relativePath = relativePath.substring(new File(buildDirectory).getAbsolutePath().length() + 1);
            relativePath = relativePath.replaceAll("\\\\", "/");

            if (zipFile) {
                ZipArchiveEntry entry = new ZipArchiveEntry(relativePath);

                os.putArchiveEntry(entry);
                if (isScript(file)) {
                    entry.setUnixMode(EXECUTABLE_MODE);
                }
            } else {
                TarArchiveEntry entry = new TarArchiveEntry(relativePath);
                if (isScript(file)) {
                    entry.setMode(EXECUTABLE_MODE);
                }
                entry.setSize(file.length());
                os.putArchiveEntry(entry);
            }

            IOUtils.copy(new FileInputStream(file), os);
            os.closeArchiveEntry();
        }
    }

    private boolean isScript(File file) {
        return file.getParentFile().getName().equals("bin") && !file.getName().contains("groovy");
    }

    private void copyDependencies(File distDir) throws MojoExecutionException {
        File libDir = new File(distDir, "/lib");
        libDir.mkdir();

        if (project != null) { // for testing
            Set artifacts = project.getArtifacts();

            for (Iterator itr = artifacts.iterator(); itr.hasNext();) {
                Artifact a = (Artifact) itr.next();

                try {
                    FileUtils.copyFile(a.getFile(), new File(libDir, a.getFile().getName()));
                } catch (IOException e) {
                    throw new MojoExecutionException("Could not copy artifact " + a.toString(), e);
                }
            }
        }
    }

    protected void populateScripts(File distDir) throws MojoFailureException, MojoExecutionException {
        File binDir = new File(distDir, "/bin");
        binDir.mkdir();

        File scriptsDirFile = new File(project.getBasedir(), scriptsSourceDirectory);

        if (!scriptsDirFile.exists()) {
            throw new MojoFailureException("Could not find scripts directory " + scriptsSourceDirectory);
        }

        ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
        try {
            ClassLoader cl = getCompileClassLoader();
            Thread.currentThread().setContextClassLoader(cl);

            copyGroovyScripts(scriptsDirFile.listFiles(), binDir);

            // There has to be a better way to do this, but I am clearly not thinking of it right now
            Class crCls = cl.loadClass(CommandRunner.class.getName());
            Class absCmdCls = cl.loadClass(AbstractCommand.class.getName());
            Class commandWrapperCls = cl.loadClass(GroovyCommandWrapper.class.getName());
            Class generateCmdsCls = cl.loadClass(GenerateCommands.class.getName());

            Object runner = crCls.newInstance();
            Object wrapper = commandWrapperCls.getConstructor(Class.class).newInstance(generateCmdsCls);
            crCls.getMethod("addCommand", absCmdCls).invoke(runner, wrapper);
            crCls.getMethod("run", String[].class).invoke(runner,
                    new Object[] { new String[] { "generate-commands", "-p", binDir.getAbsolutePath() } });

            POSIX posix = POSIXFactory.getPOSIX(getHandler(), true);

            for (File file : binDir.listFiles()) {
                posix.chmod(file.getAbsolutePath(), EXECUTABLE_MODE);
            }
        } catch (IOException e) {
            throw new MojoExecutionException("Could not copy script files to distribution.", e);
        } catch (Exception e) {
            throw new MojoExecutionException("Could not generate scripts", e);
        } finally {
            Thread.currentThread().setContextClassLoader(oldCL);
        }
    }

    private POSIXHandler getHandler() {
        return new POSIXHandler() {

            public void error(ERRORS error, String extraData) {
            }

            public void unimplementedError(String methodName) {
            }

            public void warn(WARNING_ID id, String message, Object... data) {
            }

            public boolean isVerbose() {
                return false;
            }

            public File getCurrentWorkingDirectory() {
                return null;
            }

            public String[] getEnv() {
                return null;
            }

            public InputStream getInputStream() {
                return null;
            }

            public PrintStream getOutputStream() {
                return null;
            }

            public int getPID() {
                return 0;
            }

            public PrintStream getErrorStream() {
                return null;
            }

        };
    }

    private void copyGroovyScripts(File[] files, File dest) throws IOException {
        if (files == null) {
            return;
        }

        for (File f : files) {
            if (f.isDirectory()) {
                copyGroovyScripts(f.listFiles(), dest);
            } else if (f.getName().endsWith(".groovy")) {
                IOUtils.copy(new FileInputStream(f), new FileOutputStream(new File(dest, f.getName())));
            }
        }
    }

    public void setDistributionName(String distributionName) {
        this.distributionName = distributionName;
    }

    public void setScriptsSourceDirectory(String scriptsSourceDirectory) {
        this.scriptsSourceDirectory = scriptsSourceDirectory;
    }

    public void setBuildDirectory(String buildDirectory) {
        this.buildDirectory = buildDirectory;
    }

    public void setProject(MavenProject project) {
        this.project = project;
    }

    public void setResolver(ArtifactResolver resolver) {
        this.resolver = resolver;
    }

    public void setCreateZip(boolean createZip) {
        this.createZip = createZip;
    }

    public void setCreateTarGz(boolean createTarGz) {
        this.createTarGz = createTarGz;
    }

    public MavenProjectHelper getProjectHelper() {
        return projectHelper;
    }

    public void setProjectHelper(MavenProjectHelper projectHelper) {
        this.projectHelper = projectHelper;
    }

}