net.ericaro.diezel.plugin.DiezelMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of diezel-maven-plugin Show documentation
Show all versions of diezel-maven-plugin Show documentation
An Embedded Domain Specific Language Parser Generator PLugin compiler
The newest version!
package net.ericaro.diezel.plugin;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import net.ericaro.diezel.core.Diezel;
import net.ericaro.diezel.core.DiezelException;
import net.ericaro.diezel.core.parser.DiezelParser;
import net.ericaro.diezel.core.parser.Graph;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
/** generate a Diezel Mojo
*
*
* @author eric
* @goal diezel
* @phase generate-sources
* @since 2.0
*/
public class DiezelMojo extends AbstractMojo {
/**
* The current Maven project.
*
* @parameter default-value="${project}"
* @readonly
* @required
*/
private MavenProject project;
/**
* The set of compile source roots whose contents are not generated as part of the build, i.e. those that usually
* reside somewhere below "${basedir}/src" in the project structure. Files in these source roots are owned by the
* user and must not be overwritten with generated files.
*/
private Collection nonGeneratedSourceRoots;
/**
* The directory where the Diezel files (*.dzl
) are located.
*
* @parameter expression="${sourceDirectory}" default-value="${basedir}/src/main/diezel"
*/
private File sourceDirectory;
/**
* The directory where the diezel files generated by Diezel will be stored. The directory will be registered as a
* compile source root of the project such that the generated files will participate in later build phases like
* compiling and packaging.
*
* @parameter expression="${outputDirectory}" default-value="${project.build.directory}/generated-sources/diezel"
*/
private File outputDirectory;
/**
* The granularity in milliseconds of the last modification date for testing whether a source needs recompilation.
*
* @parameter expression="${lastModGranularityMs}" default-value="0"
*/
private int staleMillis;
/**
* Verbose mode
*
* @parameter expression="${debug}" default-value="false"
*/
private boolean debug;
/**
* A set of Ant-like inclusion patterns used to select files from the source directory for processing. By default,
* the patterns **/*.xml
and **/*.dzl
are used to select Diezel files.
*
* @parameter
*/
private String[] includes;
/**
* A set of Ant-like exclusion patterns used to prevent certain files from being processed. By default, this set is
* empty such that no files are excluded.
*
* @parameter
*/
private String[] excludes;
/**
* {@inheritDoc}
*/
protected File getSourceDirectory()
{
return this.sourceDirectory;
}
/**
* {@inheritDoc}
*/
protected String[] getIncludes()
{
if ( this.includes != null )
{
return this.includes;
}
else
{
return new String[] { "**/*.xml", "**/*.dzl" };
}
}
/**
* {@inheritDoc}
*/
protected String[] getExcludes()
{
return this.excludes;
}
/**
* {@inheritDoc}
*/
protected File getOutputDirectory()
{
return this.outputDirectory;
}
/**
* {@inheritDoc}
*/
protected int getStaleMillis()
{
return this.staleMillis;
}
/**
* {@inheritDoc}
*/
protected File[] getCompileSourceRoots()
{
return new File[] { getOutputDirectory() };
}
/**
* Execute the tool.
*
* @throws MojoExecutionException
* If the invocation of the tool failed.
* @throws MojoFailureException
* If the tool reported a non-zero exit code.
*/
public void execute() throws MojoExecutionException, MojoFailureException {
Graph.DEBUG= debug ;
File[] diezels = scanForDiezels();
getLog().info("starting Diezel compilation from: " + getSourceDirectory());
if (diezels == null) {
getLog().info("Skipping non-existing diezels in directory: " + getSourceDirectory());
return;
} else if (diezels.length <= 0) {
getLog().info("Skipping - all diezels are up to date");
} else {
determineNonGeneratedSourceRoots();
processDiezel(diezels);
getLog().info("Processed " + diezels.length + " diezel" + (diezels.length != 1 ? "s" : ""));
}
File[] compileSourceRoots = getCompileSourceRoots();
for (int i = 0; i < compileSourceRoots.length; i++)
addSourceRoot(compileSourceRoots[i]);
}
/**
* Passes the specified grammar file through the tool.
*
* @param diezel
* The file containing the diezel file to process, must not be null
.
* @throws MojoExecutionException
* If the invocation of the tool failed.
* @throws MojoFailureException
* If the tool reported a non-zero exit code.
*/
protected void processDiezel(File[] diezel) throws MojoExecutionException, MojoFailureException{
DiezelParser p = new DiezelParser();
try {
//TODO also copy source definition (.xml for languages), into classes, so that it will be possible
// to implement a language defined in another jar.
//TODO after the previous one : also scan the dependencies for any Diezel definitions.
Diezel.generate(outputDirectory, diezel);
} catch (DiezelException e) {
throw new MojoFailureException(e.getMessage());
}
}
/**
* Scans the configured source directory for diezel files which need processing.
*
* @return An array of files containing the found grammar files or null
if the source
* directory does not exist.
* @throws MojoExecutionException
* If the source directory could not be scanned.
*/
private File[] scanForDiezels() throws MojoExecutionException {
if (!getSourceDirectory().isDirectory()) {
return null;
}
getLog().debug("Scanning for grammars: " + getSourceDirectory());
try {
DiezelDirectoryScanner scanner = new DiezelDirectoryScanner();
scanner.setSourceDirectory(getSourceDirectory());
scanner.setIncludes(getIncludes());
scanner.setExcludes(getExcludes());
scanner.setOutputDirectory(getOutputDirectory());
scanner.setStaleMillis(getStaleMillis());
scanner.scan();
File[] diezels = scanner.getIncludedDiezels();
getLog().debug("Found diezels: " + Arrays.asList(diezels));
return diezels;
} catch (Exception e) {
throw new MojoExecutionException("Failed to scan for grammars: " + getSourceDirectory(), e);
}
}
/**
* Determines those compile source roots of the project that do not reside below the project's build directories.
* These compile source roots are assumed to contain hand-crafted sources that must not be overwritten with
* generated files. In most cases, this is simply "${project.build.sourceDirectory}".
*
* @throws MojoExecutionException
* If the compile source rotos could not be determined.
*/
private void determineNonGeneratedSourceRoots() throws MojoExecutionException {
this.nonGeneratedSourceRoots = new LinkedHashSet();
try {
String targetPrefix = new File(this.project.getBuild().getDirectory()).getCanonicalPath() + File.separator;
Collection sourceRoots = this.project.getCompileSourceRoots();
for (Iterator it = sourceRoots.iterator(); it.hasNext();) {
File sourceRoot = new File(it.next().toString());
if (!sourceRoot.isAbsolute()) {
sourceRoot = new File(this.project.getBasedir(), sourceRoot.getPath());
}
String sourcePath = sourceRoot.getCanonicalPath();
if (!sourcePath.startsWith(targetPrefix)) {
this.nonGeneratedSourceRoots.add(sourceRoot);
getLog().debug("Non-generated compile source root: " + sourceRoot);
} else {
getLog().debug("Generated compile source root: " + sourceRoot);
}
}
} catch (IOException e) {
throw new MojoExecutionException("Failed to determine non-generated source roots", e);
}
}
/**
* Determines whether the specified directory denotes a compile source root of the current project.
*
* @param directory
* The directory to check, must not be null
.
* @return true
if the specified directory is a compile source root of the project, false
otherwise.
*/
protected boolean isSourceRoot(File directory) {
return this.nonGeneratedSourceRoots.contains(directory);
}
/**
* Registers the specified directory as a compile source root for the current project.
*
* @param directory
* The absolute path to the source root, must not be null
.
*/
private void addSourceRoot(File directory) {
if (this.project != null) {
getLog().debug("Adding compile source root: " + directory);
this.project.addCompileSourceRoot(directory.getAbsolutePath());
}
}
}