com.webguys.maven.plugin.st.Controller.java Source code

Java tutorial

Introduction

Here is the source code for com.webguys.maven.plugin.st.Controller.java

Source

/*
 * The MIT License
 *
 * Copyright (c) 2011 Kevin Birch <kevin.birch@gmail.com>. Some rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.webguys.maven.plugin.st;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.maven.ProjectDependenciesResolver;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.sonatype.aether.util.artifact.JavaScopes;
import org.stringtemplate.v4.ST;

import static org.twdata.maven.mojoexecutor.MojoExecutor.*;

public class Controller {
    /**
     * The name of the class to instantiate.
     *
     * @parameter
     * @required
     */
    private String className;

    /**
     * The name of the method to invoke.
     *
     * @parameter
     * @required
     */
    private String method;

    /**
     * Should the this controller attempt to be compiled?
     *
     * @parameter default-value="true"
     */
    private boolean compile = true;

    /**
     * @parameter default-value="1.6"
     */
    private String sourceVersion = "1.6";

    /**
     * @parameter default-value="1.6"
     */
    private String targetVersion = "1.6";

    /**
     * @parameter default-value="2.3.2"
     */
    private String compilerVersion = "2.3.2";

    public void invoke(ST st, ExecutionEnvironment executionEnvironment,
            ProjectDependenciesResolver dependenciesResolver, Log log) throws MojoExecutionException {
        try {
            Class controllerClass = this.findControllerClass(dependenciesResolver, executionEnvironment, log);
            Method method = this.getMethod(controllerClass);

            Object results = this.invoke(controllerClass, method, log);

            this.applyResults(st, results);
        } catch (Exception e) {
            throw new MojoExecutionException(
                    String.format("Unable to invoke controller: %s (%s)", this.className, e.getMessage()), e);
        }
    }

    private Class findControllerClass(ProjectDependenciesResolver dependenciesResolver,
            ExecutionEnvironment executionEnvironment, Log log) throws MojoExecutionException,
            ClassNotFoundException, MalformedURLException, ArtifactResolutionException, ArtifactNotFoundException {
        try {
            return this.loadController(executionEnvironment.getMavenProject(),
                    executionEnvironment.getMavenSession(), dependenciesResolver);
        } catch (ClassNotFoundException e) {
            if (this.compile) {
                log.info(String.format("Unable to find the class: %s.  Attempting to compile it...",
                        this.className));
                return this.compileAndLoadController(log, dependenciesResolver, executionEnvironment);
            } else {
                throw new MojoExecutionException(
                        String.format("The class %s is not in the classpath, and compilation is not enabled.",
                                this.className),
                        e);
            }
        }
    }

    private Class compileAndLoadController(Log log, ProjectDependenciesResolver dependenciesResolver,
            ExecutionEnvironment executionEnvironment) throws MojoExecutionException, ClassNotFoundException,
            MalformedURLException, ArtifactResolutionException, ArtifactNotFoundException {
        MavenProject project = executionEnvironment.getMavenProject();

        Set<Artifact> originalArtifacts = this.configureArtifacts(project);
        this.executeCompilerPlugin(executionEnvironment, log);
        Class result = this.loadController(project, executionEnvironment.getMavenSession(), dependenciesResolver);
        project.setArtifacts(originalArtifacts);
        return result;
    }

    private Set<Artifact> configureArtifacts(MavenProject project) {
        Set<Artifact> originalArtifacts = project.getArtifacts();
        project.setArtifacts(project.getDependencyArtifacts());
        return originalArtifacts;
    }

    private void executeCompilerPlugin(ExecutionEnvironment executionEnvironment, Log log)
            throws MojoExecutionException {
        String path = this.className.replace(".", File.separator) + ".java";
        log.info(String.format("Compiling %s...", path));

        executeMojo(
                plugin(groupId("org.apache.maven.plugins"), artifactId("maven-compiler-plugin"),
                        version(compilerVersion)),
                goal("compile"),
                configuration(element(name("source"), sourceVersion), element(name("target"), targetVersion),
                        element(name("includes"), element("include", path))),
                executionEnvironment);
    }

    private Class loadController(MavenProject project, MavenSession session,
            ProjectDependenciesResolver dependenciesResolver) throws MalformedURLException, ClassNotFoundException,
            ArtifactResolutionException, ArtifactNotFoundException {
        ArrayList<String> scopes = new ArrayList<String>(1);
        scopes.add(JavaScopes.RUNTIME);
        Set<Artifact> artifacts = dependenciesResolver.resolve(project, scopes, session);

        ArrayList<URL> urls = new ArrayList<URL>();
        urls.add(new File(project.getBuild().getOutputDirectory()).getAbsoluteFile().toURI().toURL());
        for (Artifact artifact : artifacts) {
            urls.add(artifact.getFile().getAbsoluteFile().toURI().toURL());
        }

        ClassLoader loader = URLClassLoader.newInstance(urls.toArray(new URL[urls.size()]),
                this.getClass().getClassLoader());
        return loader.loadClass(this.className);
    }

    private Method getMethod(Class controllerClass) throws NoSuchMethodException, MojoExecutionException {
        Method method = controllerClass.getMethod(this.method);

        if (!method.getReturnType().isAssignableFrom(Map.class)) {
            throw new MojoExecutionException(String
                    .format("The return type of the method %s was not of type Map<String, Object>", this.method));
        }

        return method;
    }

    private Object invoke(Class controllerClass, Method method, Log log)
            throws InstantiationException, IllegalAccessException, InvocationTargetException {
        Object controller = null;
        if (!Modifier.isStatic(method.getModifiers())) {
            controller = controllerClass.newInstance();
        }

        log.info(String.format("Invoking controller: %s.%s()", controllerClass.getName(), method.getName()));
        return method.invoke(controller);
    }

    private void applyResults(ST st, Object result) throws MojoExecutionException {
        if (null == result) {
            throw new MojoExecutionException(
                    String.format("The result invoking %s.%s was null.", this.className, this.method));
        }
        Map<Object, Object> attributes = (Map<Object, Object>) result;

        for (Entry<Object, Object> entry : attributes.entrySet()) {
            Object key = entry.getKey();
            if (!(key instanceof String)) {
                String msg = String.format("A non-String key of type %s was found in the %s.%s results.",
                        key.getClass().getName(), this.className, this.method);
                throw new MojoExecutionException(msg);
            }
            st.add((String) key, entry.getValue());
        }
    }
}