net.morimekta.providence.maven.plugin.BaseGenerateSourcesMojo Maven / Gradle / Ivy
/*
* Copyright 2016 Providence Authors
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package net.morimekta.providence.maven.plugin;
import net.morimekta.providence.generator.Generator;
import net.morimekta.providence.generator.GeneratorException;
import net.morimekta.providence.generator.GeneratorFactory;
import net.morimekta.providence.generator.GeneratorOptions;
import net.morimekta.providence.generator.format.java.JavaGenerator;
import net.morimekta.providence.generator.format.java.JavaGeneratorFactory;
import net.morimekta.providence.generator.format.java.JavaOptions;
import net.morimekta.providence.generator.util.FileManager;
import net.morimekta.providence.maven.util.ProvidenceInput;
import net.morimekta.providence.reflect.ProgramLoader;
import net.morimekta.providence.reflect.ProgramRegistry;
import net.morimekta.providence.reflect.parser.ThriftException;
import net.morimekta.util.FileUtil;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.components.io.fileselectors.IncludeExcludeFileSelector;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.Set;
/**
* mvn net.morimekta.providence:providence-maven-plugin:1.3.1:help -Ddetail=true -Dgoal=compile
*/
public abstract class BaseGenerateSourcesMojo extends AbstractMojo {
// ----------- PARSER OPTIONS ----------- //
/**
* If the thrift program parser should fail if enum value is missing for
* any enum value definition parsed.
*/
@Parameter(defaultValue = "false",
property = "providence.gen.require_enum_value",
alias = "requireEnumValue")
protected boolean require_enum_value;
/**
* If the thrift program parser should fail if field ID is missing for any
* field definitions parsed.
*/
@Parameter(defaultValue = "false",
property = "providence.gen.require_field_id",
alias = "requireFieldId")
protected boolean require_field_id;
/**
* Allow reserved words that would cause name problems in some thrift generated
* code. This allows reserved words as names, not thrift keywords. This applies
* to all type names (enums, messages, services, typedefs), all fields (message
* fields, method params, method throws), method names, const names and enum
* values.
*/
@Parameter(defaultValue = "true",
alias = "allow_reserved_names",
property = "providence.gen.allow_language_reserved_names")
protected boolean allow_language_reserved_names = true;
// ----------- GENERATE OPTIONS ----------- //
/**
* If set to true will add jackson 2 annotations to messages and enums.
* Required additional dependency on jackson 2 extra libraries:
*
* com.fasterxml.jackson.extra:jackson-annotations:2.x
* com.fasterxml.jackson.extra:jackson-extra:2.x
* com.fasterxml.jackson.extra:jackson-databind:2.x
*
*/
@Parameter(defaultValue = "false",
property = "providence.gen.jackson")
protected boolean jackson;
/**
* Generate model methods to read and write same as the binary protocol.
* Can be turned off to reduce the amount of generated code. Serialization
* will work regardless, but keeping this enabled speeds up the binary
* serialization significantly.
*/
@Parameter(defaultValue = "true",
property = "providence.gen.rw_binary")
protected boolean rw_binary = true;
/**
* Make all message types serializable. Defaults to true. If false, only
* exceptions will be serializable (as the java.lang.Throwable
* class implements serializable).
*/
@Parameter(defaultValue = "false",
property = "providence.gen.serializable")
protected boolean serializable = false;
/**
* If set to true will add hazelcast annotations to messages and enums.
*/
@Parameter(defaultValue = "false",
property = "providence.gen.hazelcast_portable")
protected boolean hazelcast_portable;
/**
* If true add version to generated annotations.
*/
@Parameter(defaultValue = "true",
property = "providence.gen.generated_annotation_version")
protected boolean generated_annotation_version;
/**
* If true add date to generated annotations.
*/
@Parameter(defaultValue = "true",
property = "providence.gen.generated_annotation_date")
protected boolean generated_annotation_date;
@Parameter(defaultValue = "false",
property = "providence.gen.generate_providence_core_types")
protected boolean generate_providence_core_types;
/**
* Print extra debug info to the maven log.
*/
@Parameter(defaultValue = "false",
property = "providence.print_debug")
protected boolean print_debug;
/**
* If true will add the generated sources to be compiled.
*/
@Parameter(defaultValue = "true")
protected boolean compileOutput;
/**
* Skip thrift files if they are missing the java namespace.
*/
@Parameter(defaultValue = "false", property = "providence.skip_if_missing_namespace")
protected boolean skipIfMissingNamespace;
// --- After here are internals, components and maven-set params.
/**
* Location of the output artifact.
*/
@Parameter(defaultValue = "${project.build.directory}", readonly = true, required = true)
protected File buildDir = null;
@Parameter(defaultValue = "${project}", readonly = true, required = true)
protected MavenProject project = null;
boolean executeInternal(File outputDir,
IncludeExcludeFileSelector inputSelector,
String defaultInputIncludes,
boolean testCompile) throws MojoExecutionException, MojoFailureException {
Set inputFiles = ProvidenceInput.getInputFiles(
project.getBasedir().toPath(), inputSelector, defaultInputIncludes, print_debug, getLog());
if (inputFiles.isEmpty()) {
return false;
}
if (!outputDir.exists()) {
if (!outputDir.mkdirs()) {
throw new MojoExecutionException("Unable to create target directory " + outputDir);
}
}
Path workingDir = buildDir.toPath().resolve(testCompile ? "providence-test" : "providence");
try {
if (Files.exists(workingDir)) {
Files.list(workingDir).forEach(file -> {
try {
FileUtil.deleteRecursively(file);
} catch (IOException e) {
throw new UncheckedIOException(e.getMessage(), e);
}
});
} else {
Files.createDirectories(workingDir);
}
} catch (IOException | UncheckedIOException e) {
throw new MojoExecutionException(e.getMessage(), e);
}
FileManager fileManager = new FileManager(outputDir.toPath());
ProgramLoader loader = new ProgramLoader(require_field_id,
require_enum_value,
allow_language_reserved_names);
if (print_debug) {
inputFiles.forEach(f -> getLog().info("Compiling: " + f));
}
JavaOptions javaOptions = new JavaOptions();
javaOptions.jackson = jackson;
javaOptions.rw_binary = rw_binary;
javaOptions.serializable = serializable;
javaOptions.hazelcast_portable = hazelcast_portable;
javaOptions.generated_annotation_version = generated_annotation_version;
javaOptions.generated_annotation_date = generated_annotation_date;
javaOptions.generate_providence_core_types = generate_providence_core_types;
GeneratorOptions generatorOptions = new GeneratorOptions();
generatorOptions.generator_program_name = "providence-maven-plugin";
generatorOptions.program_version = getVersionString();
GeneratorFactory factory = new JavaGeneratorFactory();
Generator generator = new JavaGenerator(fileManager,
generatorOptions,
javaOptions);
Path base = project.getBasedir().toPath().toAbsolutePath();
if (project.getParent() != null && project.getParent().getBasedir() != null) {
// Only replace with parent if parent is a parent directory of this.
Path parentBase = project.getParent().getBasedir().toPath().toAbsolutePath();
if (base.toString().startsWith(parentBase.toString())) {
base = parentBase;
}
}
List registries = new ArrayList<>();
for (Path in : inputFiles) {
try {
ProgramRegistry registry = loader.load(in);
if (skipIfMissingNamespace &&
registry.getProgram().getNamespaceForLanguage(factory.generatorName()) == null) {
getLog().warn("Skipping (no " + factory.generatorName() + " namespace) " + base.relativize(in));
} else {
registries.add(registry);
}
} catch (ThriftException e) {
// ParseException is a SerializerException. And serialize exceptions can come from
// failing to make sense of constant definitions.
getLog().error(" ============ >> PROVIDENCE << ============");
getLog().error("");
Arrays.stream(e.displayString().split("\r?\n", Short.MAX_VALUE))
.forEach(l -> getLog().error(l));
getLog().error("");
getLog().error(" ============ << PROVIDENCE >> ============");
throw new MojoFailureException("Failed to parse thrift file: " + in.getFileName(), e);
} catch (IOException e) {
throw new MojoExecutionException("Failed to read thrift file: " + in.getFileName(), e);
}
}
for (ProgramRegistry registry : registries) {
try {
generator.generate(registry);
} catch (GeneratorException e) {
throw new MojoFailureException("Failed to generate program: " + registry.getProgram().getProgramName(), e);
} catch (IOException e) {
throw new MojoExecutionException("Failed to write program file: " + registry.getProgram().getProgramName(), e);
}
}
try {
generator.generateGlobal(loader.getGlobalRegistry(), inputFiles);
} catch (GeneratorException e) {
throw new MojoFailureException("Failed to generate global", e);
} catch (IOException e) {
throw new MojoExecutionException("Failed to write global file", e);
}
return compileOutput;
}
private static String getVersionString() {
Properties properties = new Properties();
try (InputStream in = BaseGenerateSourcesMojo.class.getResourceAsStream(
"/net/morimekta/providence/maven/providence_version.properties")) {
properties.load(in);
} catch (IOException e) {
throw new UncheckedIOException(e.getMessage(), e);
}
return properties.getProperty("providence.version");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy