org.eclipse.acceleo.maven.AcceleoParserMojo.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.acceleo.maven.AcceleoParserMojo.java

Source

/*******************************************************************************
 * Copyright (c) 2008, 2012 Obeo.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Obeo - initial API and implementation
 *******************************************************************************/
package org.eclipse.acceleo.maven;

import java.io.File;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.eclipse.acceleo.common.internal.utils.AcceleoPackageRegistry;
import org.eclipse.acceleo.internal.parser.compiler.AcceleoParser;
import org.eclipse.acceleo.internal.parser.compiler.AcceleoProjectClasspathEntry;
import org.eclipse.acceleo.internal.parser.compiler.IAcceleoParserURIHandler;
import org.eclipse.acceleo.internal.parser.compiler.IParserListener;
import org.eclipse.acceleo.parser.AcceleoParserProblem;
import org.eclipse.acceleo.parser.AcceleoParserWarning;
import org.eclipse.emf.common.util.BasicMonitor;
import org.eclipse.emf.common.util.URI;

import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;

/**
 * The Acceleo Parser MOJO is used to call the Acceleo Parser from Maven.
 * 
 * @goal acceleo-compile
 * @phase compile
 * @requiresDependencyResolution compile+runtime
 * @author <a href="mailto:stephane.begaudeau@obeo.fr">Stephane Begaudeau</a>
 * @since 3.2
 */
public class AcceleoParserMojo extends AbstractMojo {

    /**
     * @parameter expression="${project}"
     * @required
     * @readonly
     */
    private MavenProject project;

    /**
     * Indicates if we are compiling the Acceleo modules as binary resources.
     * 
     * @parameter expression = "${acceleo-compile.binaryResource}"
     * @required
     */
    private boolean useBinaryResources;

    /**
     * The class to use for the uri converter.
     * 
     * @parameter expression = "${acceleo-compile.uriHandler}"
     */
    private String uriHandler;

    /**
     * The list of packages to register.
     * 
     * @parameter expression = "${acceleo-compile.packagesToRegister}"
     * @required
     */
    private List<String> packagesToRegister;

    /**
     * The Acceleo project that should be built.
     * 
     * @parameter expression = "${acceleo-compile.acceleoProject}"
     * @required
     */
    private AcceleoProject acceleoProject;

    /**
     * Indicates if we are compiling the Acceleo modules as binary resources.
     * 
     * @parameter expression = "${acceleo-compile.usePlatformResourcePath}"
     * @required
     */
    private boolean usePlatformResourcePath;

    /**
     * Indicates if we should fail on errors.
     * 
     * @parameter expression = "${acceleo-compile.failOnError}"
     */
    private boolean failOnError;

    /**
     * {@inheritDoc}
     * 
     * @see org.apache.maven.plugin.AbstractMojo#execute()
     */
    public void execute() throws MojoExecutionException, MojoFailureException {
        Log log = getLog();
        log.info("Acceleo maven stand alone build...");

        log.info("Starting packages registration...");

        URLClassLoader newLoader = null;
        try {
            List<?> runtimeClasspathElements = project.getRuntimeClasspathElements();
            List<?> compileClasspathElements = project.getCompileClasspathElements();
            URL[] runtimeUrls = new URL[runtimeClasspathElements.size() + compileClasspathElements.size()];
            int i = 0;
            for (Object object : runtimeClasspathElements) {
                if (object instanceof String) {
                    String str = (String) object;
                    log.debug("Adding the runtime dependency " + str
                            + " to the classloader for the package resolution");
                    runtimeUrls[i] = new File(str).toURI().toURL();
                    i++;
                } else {
                    log.debug("Runtime classpath entry is not a string: " + object);
                }
            }
            for (Object object : compileClasspathElements) {
                if (object instanceof String) {
                    String str = (String) object;
                    log.debug("Adding the compilation dependency " + str
                            + " to the classloader for the package resolution");
                    runtimeUrls[i] = new File(str).toURI().toURL();
                    i++;
                } else {
                    log.debug("Runtime classpath entry is not a string: " + object);
                }
            }
            newLoader = new URLClassLoader(runtimeUrls, Thread.currentThread().getContextClassLoader());
        } catch (DependencyResolutionRequiredException e) {
            log.error(e);
        } catch (MalformedURLException e) {
            log.error(e);
        }

        for (String packageToRegister : this.packagesToRegister) {
            try {
                if (newLoader != null) {
                    Class<?> forName = Class.forName(packageToRegister, true, newLoader);
                    Field nsUri = forName.getField("eNS_URI");
                    Field eInstance = forName.getField("eINSTANCE");

                    Object nsURIInvoked = nsUri.get(null);
                    if (nsURIInvoked instanceof String) {
                        log.info("Registering package '" + packageToRegister + "'.");
                        AcceleoPackageRegistry.INSTANCE.put((String) nsURIInvoked, eInstance.get(null));
                    } else {
                        log.error("The URI field is not a string.");
                    }
                }
            } catch (ClassNotFoundException e) {
                log.error(e);
            } catch (IllegalAccessException e) {
                log.error(e);
            } catch (SecurityException e) {
                log.error(e);
            } catch (NoSuchFieldException e) {
                log.error(e);
            }

        }

        log.info("Starting the build sequence for the project '" + this.acceleoProject.getRoot() + "'...");
        log.info("Mapping the pom.xml to AcceleoProject...");

        Preconditions.checkNotNull(this.acceleoProject);
        Preconditions.checkNotNull(this.acceleoProject.getRoot());
        Preconditions.checkNotNull(this.acceleoProject.getEntries());
        Preconditions.checkState(this.acceleoProject.getEntries().size() >= 1);

        File root = this.acceleoProject.getRoot();

        org.eclipse.acceleo.internal.parser.compiler.AcceleoProject aProject = new org.eclipse.acceleo.internal.parser.compiler.AcceleoProject(
                root);
        List<Entry> entries = this.acceleoProject.getEntries();
        Set<AcceleoProjectClasspathEntry> classpathEntries = new LinkedHashSet<AcceleoProjectClasspathEntry>();
        for (Entry entry : entries) {
            File inputDirectory = new File(root, entry.getInput());
            File outputDirectory = new File(root, entry.getOutput());

            log.debug("Input: " + inputDirectory.getAbsolutePath());
            log.debug("Output: " + outputDirectory.getAbsolutePath());

            AcceleoProjectClasspathEntry classpathEntry = new AcceleoProjectClasspathEntry(inputDirectory,
                    outputDirectory);
            classpathEntries.add(classpathEntry);
        }
        aProject.addClasspathEntries(classpathEntries);

        List<AcceleoProject> dependencies = this.acceleoProject.getDependencies();
        if (dependencies != null) {
            for (AcceleoProject dependingAcceleoProject : dependencies) {
                File dependingProjectRoot = dependingAcceleoProject.getRoot();
                Preconditions.checkNotNull(dependingProjectRoot);

                org.eclipse.acceleo.internal.parser.compiler.AcceleoProject aDependingProject = new org.eclipse.acceleo.internal.parser.compiler.AcceleoProject(
                        dependingProjectRoot);

                List<Entry> dependingProjectEntries = dependingAcceleoProject.getEntries();
                Set<AcceleoProjectClasspathEntry> dependingClasspathEntries = new LinkedHashSet<AcceleoProjectClasspathEntry>();
                for (Entry entry : dependingProjectEntries) {
                    File inputDirectory = new File(root, entry.getInput());
                    File outputDirectory = new File(root, entry.getOutput());
                    AcceleoProjectClasspathEntry classpathEntry = new AcceleoProjectClasspathEntry(inputDirectory,
                            outputDirectory);
                    dependingClasspathEntries.add(classpathEntry);
                }

                aDependingProject.addClasspathEntries(dependingClasspathEntries);
                aProject.addProjectDependencies(Sets.newHashSet(aDependingProject));
            }
        }

        log.info("Adding jar dependencies...");
        List<String> jars = this.acceleoProject.getJars();
        if (jars != null) {
            Set<URI> newDependencies = new LinkedHashSet<URI>();
            for (String jar : jars) {
                log.info("Resolving jar: '" + jar + "'...");
                File jarFile = new File(jar);
                if (jarFile.isFile()) {
                    URI uri = URI.createFileURI(jar);
                    newDependencies.add(uri);
                    log.info("Found jar for '" + jar + "' on the filesystem: '" + jarFile.getAbsolutePath() + "'.");
                } else {
                    StringTokenizer tok = new StringTokenizer(jar, ":");

                    String groupdId = null;
                    String artifactId = null;
                    String version = null;

                    int c = 0;
                    while (tok.hasMoreTokens()) {
                        String nextToken = tok.nextToken();
                        if (c == 0) {
                            groupdId = nextToken;
                        } else if (c == 1) {
                            artifactId = nextToken;
                        } else if (c == 2) {
                            version = nextToken;
                        }

                        c++;
                    }

                    Set<?> artifacts = this.project.getArtifacts();
                    for (Object object : artifacts) {
                        if (object instanceof Artifact) {
                            Artifact artifact = (Artifact) object;
                            if (groupdId != null && groupdId.equals(artifact.getGroupId()) && artifactId != null
                                    && artifactId.equals(artifact.getArtifactId())) {
                                if (version != null && version.equals(artifact.getVersion())) {
                                    File artifactFile = artifact.getFile();
                                    if (artifactFile != null && artifactFile.exists()) {
                                        URI uri = URI.createFileURI(artifactFile.getAbsolutePath());
                                        newDependencies.add(uri);
                                        log.info("Found jar for '" + jar + "' on the filesystem: '" + uri.toString()
                                                + "'.");
                                    }
                                } else if (version == null) {
                                    File artifactFile = artifact.getFile();
                                    if (artifactFile != null && artifactFile.exists()) {
                                        URI uri = URI.createFileURI(artifactFile.getAbsolutePath());
                                        newDependencies.add(uri);
                                        log.info("Found jar for '" + jar + "' on the filesystem: '" + uri.toString()
                                                + "'.");
                                    }
                                }
                            }
                        }
                    }

                    List<?> mavenDependencies = this.project.getDependencies();
                    for (Object object : mavenDependencies) {
                        if (object instanceof Dependency) {
                            Dependency dependency = (Dependency) object;
                            if (groupdId != null && groupdId.equals(dependency.getGroupId()) && artifactId != null
                                    && artifactId.equals(dependency.getArtifactId())) {
                                if (version != null && version.equals(dependency.getVersion())) {
                                    String systemPath = dependency.getSystemPath();
                                    if (systemPath != null && new File(systemPath).exists()) {
                                        URI uri = URI.createFileURI(systemPath);
                                        newDependencies.add(uri);
                                        log.info("Found jar for '" + jar + "' on the filesystem: '" + uri.toString()
                                                + "'.");
                                    }
                                } else if (version == null) {
                                    String systemPath = dependency.getSystemPath();
                                    if (systemPath != null && new File(systemPath).exists()) {
                                        URI uri = URI.createFileURI(systemPath);
                                        newDependencies.add(uri);
                                        log.info("Found jar for '" + jar + "' on the filesystem: '" + uri.toString()
                                                + "'.");
                                    }
                                }
                            }
                        }
                    }
                }
            }
            aProject.addDependencies(newDependencies);
        }

        log.info("Starting parsing...");
        AcceleoParser parser = new AcceleoParser(aProject, this.useBinaryResources, this.usePlatformResourcePath);
        AcceleoParserListener listener = new AcceleoParserListener();
        parser.addListeners(listener);

        // Load and plug the uri resolver
        if (this.uriHandler != null && newLoader != null) {
            try {
                Class<?> forName = Class.forName(this.uriHandler, true, newLoader);
                Object newInstance = forName.newInstance();
                if (newInstance instanceof IAcceleoParserURIHandler) {
                    IAcceleoParserURIHandler resolver = (IAcceleoParserURIHandler) newInstance;
                    parser.setURIHandler(resolver);
                }
            } catch (ClassNotFoundException e) {
                log.error(e);
            } catch (InstantiationException e) {
                log.error(e);
            } catch (IllegalAccessException e) {
                log.error(e);
            }
        }

        Set<File> builtFiles = parser.buildAll(new BasicMonitor());

        boolean errorFound = false;
        for (File builtFile : builtFiles) {
            Collection<AcceleoParserProblem> problems = parser.getProblems(builtFile);
            Collection<AcceleoParserWarning> warnings = parser.getWarnings(builtFile);

            if (problems.size() > 0) {
                log.info("Errors for file '" + builtFile.getName() + "': " + problems);
                errorFound = true;
            }
            if (warnings.size() > 0) {
                log.info("Warnings for file '" + builtFile.getName() + "': " + warnings);
            }
        }

        if (errorFound && failOnError) {
            throw new MojoExecutionException("Errors have been found during the build of the generator");
        }

        // Removing everything
        AcceleoPackageRegistry.INSTANCE.clear();
        log.info("Build completed.");
    }

    /**
     * The listener used to log message for maven.
     * 
     * @author <a href="mailto:stephane.begaudeau@obeo.fr">Stephane Begaudeau</a>
     * @since 3.2
     */
    private class AcceleoParserListener implements IParserListener {

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.acceleo.internal.parser.compiler.IParserListener#endBuild(java.io.File)
         */
        public void endBuild(File arg0) {
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.acceleo.internal.parser.compiler.IParserListener#fileSaved(java.io.File)
         */
        public void fileSaved(File arg0) {
            getLog().info("Saving ouput file for '" + arg0.getAbsolutePath() + "'.");
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.acceleo.internal.parser.compiler.IParserListener#loadDependency(java.io.File)
         */
        public void loadDependency(File arg0) {
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.acceleo.internal.parser.compiler.IParserListener#loadDependency(org.eclipse.emf.common.util.URI)
         */
        public void loadDependency(URI arg0) {
        }

        /**
         * {@inheritDoc}
         * 
         * @see org.eclipse.acceleo.internal.parser.compiler.IParserListener#startBuild(java.io.File)
         */
        public void startBuild(File arg0) {
        }
    }
}