All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adgear.anoa.plugin.AnoaMojo Maven / Gradle / Ivy

package com.adgear.anoa.plugin;

import com.adgear.anoa.compiler.CommandLineUtils;
import com.adgear.anoa.compiler.CompilationUnit;
import com.adgear.anoa.compiler.ParseException;
import com.adgear.anoa.compiler.SchemaGenerationException;
import com.adgear.anoa.compiler.CodeGenerationException;

import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.model.fileset.FileSet;
import org.apache.maven.shared.model.fileset.util.FileSetManager;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

@Mojo(name = "run", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true)
public class AnoaMojo extends AbstractMojo {

  @Parameter(readonly = true, required = true, defaultValue = "${project}")
  private MavenProject project;

  @Parameter(property = "sourceDirectory",
      defaultValue = "${basedir}/src/main/anoa")
  private File sourceDirectory;

  @Parameter(property = "outputDirectory",
      defaultValue = "${project.build.directory}/generated-sources")
  private File outputDirectory;

  @Parameter(property = "testSourceDirectory",
      defaultValue = "${basedir}/src/test/anoa")
  private File testSourceDirectory;

  @Parameter(property = "testOutputDirectory",
      defaultValue = "${project.build.directory}/generated-test-sources")
  private File testOutputDirectory;

  @Parameter(property = "generateAvroJava", defaultValue = "false")
  private boolean generateAvroJava;

  @Parameter(property = "generateThriftJava", defaultValue = "false")
  private boolean generateThriftJava;

  @Parameter(property = "generateProtobufJava", defaultValue = "false")
  private boolean generateProtobufJava;

  @Parameter(property = "generateProtobufFileDescriptorSet", defaultValue = "false")
  private boolean generateProtobufFileDescriptorSet;

  @Parameter(property = "protobufFileDescriptorSetFileName", defaultValue = "fdset.protobuf")
  private String protobufFileDescriptorSetFileName;

  @Parameter(property = "protocCommand", defaultValue = "protoc")
  private String protocCommand;

  @Parameter(property = "thriftCommand", defaultValue = "thrift")
  private String thriftCommand;

  @Override
  public void execute() throws MojoExecutionException, MojoFailureException {
    Optional source = Optional.ofNullable(sourceDirectory).filter(File::isDirectory);
    Optional test = Optional.ofNullable(testSourceDirectory).filter(File::isDirectory);
    if (!source.isPresent() && !test.isPresent()) {
      throw new MojoExecutionException(
          "neither sourceDirectory '" + sourceDirectory + "' or testSourceDirectory '"
          + testSourceDirectory + "' are directories");
    }
    if (source.isPresent()) {
      execute(source.get(), outputDirectory);
      project.addCompileSourceRoot(new File(outputDirectory, "java").getAbsolutePath());
    }
    if (test.isPresent()) {
      execute(test.get(), testOutputDirectory);
      project.addTestCompileSourceRoot(new File(testOutputDirectory, "java").getAbsolutePath());
    }
  }

  private void execute(File anoaSourceDir, File outDir)
      throws MojoExecutionException, MojoFailureException {
    getLog().info("Parsing all anoa files in '" + anoaSourceDir + "'...");
    List parsed = parse(anoaSourceDir);
    getLog().info("Successfully parsed all anoa files.");
    File schemaDir = new File(outDir, "anoa");
    if (schemaDir.exists() && schemaDir.delete()) {
      throw new MojoExecutionException("Could not delete existing directory " + schemaDir);
    }
    if (!schemaDir.exists() && !schemaDir.mkdirs()) {
      throw new MojoExecutionException("Could not create directory " + schemaDir);
    }
    File javaDir = new File(outDir, "java");
    if (!javaDir.exists() && !javaDir.mkdirs()) {
      throw new MojoExecutionException("Could not create directory " + javaDir);
    }
    try {
      compile(parsed, anoaSourceDir, schemaDir, javaDir);
    } catch (SchemaGenerationException e) {
      throw new MojoExecutionException("Error generating schema.", e);
    } catch (CodeGenerationException e) {
      throw new MojoExecutionException("Error generating java source.", e);
    }
  }

  private void compile(Iterable parsed, File anoaDir, File schemaDir, File javaDir)
      throws SchemaGenerationException, CodeGenerationException {
    List protoFiles = new ArrayList<>();
    for (CompilationUnit cu : parsed) {
      cu.avroGenerator().generateSchema(schemaDir);
      File proto = cu.protobufGenerator().generateSchema(schemaDir);
      if (generateProtobufFileDescriptorSet) {
        protoFiles.add(proto);
      }
      cu.thriftGenerator().generateSchema(schemaDir);
    }
    if (generateProtobufFileDescriptorSet) {
      buildProtobufFileDescriptorSet(schemaDir, protoFiles);
    }
    for (CompilationUnit cu : parsed) {
      cu.interfaceGenerator(generateAvroJava, generateProtobufJava, generateThriftJava)
          .generateJava(anoaDir, javaDir);
      if (generateAvroJava) {
        cu.avroGenerator().generateJava(schemaDir, javaDir);
      }
      if (generateProtobufJava) {
        cu.protobufGenerator(protocCommand).generateJava(schemaDir, javaDir);
      }
      if (generateThriftJava) {
        cu.thriftGenerator(thriftCommand).generateJava(schemaDir, javaDir);
      }
    }
  }

  private void buildProtobufFileDescriptorSet(File schemaDir, List protoFiles)
      throws CodeGenerationException {
    if (!protoFiles.isEmpty()) {
      String out = "--descriptor_set_out=" + protobufFileDescriptorSetFileName;
      Stream files = protoFiles.stream()
          .map(f -> schemaDir.toPath().relativize(f.toPath()).toString());
      Stream args = Stream.concat(Stream.of(out), files);
      CommandLineUtils.runCommand(protocCommand, args, schemaDir, getLog()::info);
    }
  }

  private List parse(File anoaSourceDir)
      throws MojoExecutionException, MojoFailureException {
    FileSet includes = new FileSet();
    includes.setDirectory(anoaSourceDir.getAbsolutePath());
    includes.setFollowSymlinks(false);
    includes.addInclude("**/*.anoa");
    ClassLoader classLoader = getResourceLoader(anoaSourceDir);
    List cu = new ArrayList<>();
    for (String fileName : new FileSetManager().getIncludedFiles(includes)) {
      String namespace = fileName
          .substring(0, fileName.length() - ".anoa".length())
          .replace(File.separatorChar, '.');
      try {
        cu.add(new CompilationUnit(namespace, anoaSourceDir, classLoader).parse(getLog()::info));
      } catch (ParseException e) {
        throw new MojoFailureException("Error parsing '" + fileName + "'.", e);
      } catch (IOException e) {
        throw new MojoExecutionException("Read error for '" + fileName + "'.", e);
      }
    }
    return cu;
  }

  private ClassLoader getResourceLoader(File anoaSourceDir) throws MojoExecutionException {
    try {
      List runtimeClasspathElements = project.getRuntimeClasspathElements();
      List runtimeUrls = new ArrayList<>();
      runtimeUrls.add(anoaSourceDir.toURI().toURL());
      if (runtimeClasspathElements != null) {
        for (String runtimeClasspathElement : runtimeClasspathElements) {
          runtimeUrls.add(new File(runtimeClasspathElement).toURI().toURL());
        }
      }
      return new URLClassLoader(runtimeUrls.toArray(new URL[runtimeUrls.size()]),
                                Thread.currentThread().getContextClassLoader());
    } catch (DependencyResolutionRequiredException | MalformedURLException e) {
      throw new MojoExecutionException("ClassLoader error: " + e);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy