feat: OpenApi-generation from within eclipse (#509) (#1332)

* feat: OpenApi-generation from within eclipse (#509)

* Added life-cycle-mapping for recognition by M2E
* Make BuildContext injectable by M2E in oder to detect if json-source
has been modified and a regeneration is required.

* core: fix indentation problems, remove commented code
This commit is contained in:
andreas-eternach 2018-11-04 10:07:33 +01:00 committed by William Cheng
parent 293d29ab3b
commit eb5a8cc752
3 changed files with 307 additions and 249 deletions

View File

@ -15,6 +15,11 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>org.sonatype.plexus</groupId>
<artifactId>plexus-build-api</artifactId>
<version>0.0.7</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId> <artifactId>maven-core</artifactId>

View File

@ -42,6 +42,7 @@ import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProject;
import org.openapitools.codegen.CliOption; import org.openapitools.codegen.CliOption;
@ -50,6 +51,8 @@ import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenConstants; import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.DefaultGenerator; import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.config.CodegenConfigurator; import org.openapitools.codegen.config.CodegenConfigurator;
import org.sonatype.plexus.build.incremental.BuildContext;
import org.sonatype.plexus.build.incremental.DefaultBuildContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -61,6 +64,13 @@ public class CodeGenMojo extends AbstractMojo {
private static final Logger LOGGER = LoggerFactory.getLogger(CodeGenMojo.class); private static final Logger LOGGER = LoggerFactory.getLogger(CodeGenMojo.class);
/**
* The build context is only avail when running from within eclipse.
* It is used to update the eclipse-m2e-layer when the plugin is executed inside the IDE.
*/
@Component
private BuildContext buildContext = new DefaultBuildContext();
@Parameter(name="validateSpec", required = false, defaultValue = "true") @Parameter(name="validateSpec", required = false, defaultValue = "true")
private Boolean validateSpec; private Boolean validateSpec;
@ -329,19 +339,35 @@ public class CodeGenMojo extends AbstractMojo {
@Parameter(readonly = true, required = true, defaultValue = "${project}") @Parameter(readonly = true, required = true, defaultValue = "${project}")
private MavenProject project; private MavenProject project;
public void setBuildContext(BuildContext buildContext) {
this.buildContext = buildContext;
}
@Override @Override
public void execute() throws MojoExecutionException { public void execute() throws MojoExecutionException {
File inputSpecFile = new File(inputSpec);
addCompileSourceRootIfConfigured();
try {
if (skip) { if (skip) {
getLog().info("Code generation is skipped."); getLog().info("Code generation is skipped.");
// Even when no new sources are generated, the existing ones should
// still be compiled if needed.
addCompileSourceRootIfConfigured();
return; return;
} }
if (buildContext != null) {
if (buildContext.isIncremental()) {
if (inputSpec != null) {
if (inputSpecFile.exists()) {
if (!buildContext.hasDelta(inputSpecFile)) {
getLog().info(
"Code generation is skipped in delta-build because source-json was not modified.");
return;
}
}
}
}
}
// attempt to read from config file // attempt to read from config file
CodegenConfigurator configurator = CodegenConfigurator.fromFile(configurationFile); CodegenConfigurator configurator = CodegenConfigurator.fromFile(configurationFile);
@ -388,17 +414,18 @@ public class CodeGenMojo extends AbstractMojo {
// check if generatorName & language are set together, inform user this needs to be updated to prevent future issues. // check if generatorName & language are set together, inform user this needs to be updated to prevent future issues.
if (isNotEmpty(language)) { if (isNotEmpty(language)) {
LOGGER.warn("The 'language' option is deprecated and was replaced by 'generatorName'. Both can not be set together"); LOGGER.warn("The 'language' option is deprecated and was replaced by 'generatorName'. Both can not be set together");
throw new MojoExecutionException("Illegal configuration: 'language' and 'generatorName' can not be set both, remove 'language' from your configuration"); throw new MojoExecutionException(
"Illegal configuration: 'language' and 'generatorName' can not be set both, remove 'language' from your configuration");
} }
} else if (isNotEmpty(language)) { } else if (isNotEmpty(language)) {
LOGGER.warn("The 'language' option is deprecated and may reference language names only in the next major release (4.0). Please use 'generatorName' instead."); LOGGER.warn(
"The 'language' option is deprecated and may reference language names only in the next major release (4.0). Please use 'generatorName' instead.");
configurator.setGeneratorName(language); configurator.setGeneratorName(language);
} else { } else {
LOGGER.error("A generator name (generatorName) is required."); LOGGER.error("A generator name (generatorName) is required.");
throw new MojoExecutionException("The generator requires 'generatorName'. Refer to documentation for a list of options."); throw new MojoExecutionException("The generator requires 'generatorName'. Refer to documentation for a list of options.");
} }
configurator.setOutputDir(output.getAbsolutePath()); configurator.setOutputDir(output.getAbsolutePath());
if (isNotEmpty(auth)) { if (isNotEmpty(auth)) {
@ -523,7 +550,8 @@ public class CodeGenMojo extends AbstractMojo {
} }
// Apply Language Specific Primitives // Apply Language Specific Primitives
if (languageSpecificPrimitives != null && (configOptions == null || !configOptions.containsKey("language-specific-primitives"))) { if (languageSpecificPrimitives != null
&& (configOptions == null || !configOptions.containsKey("language-specific-primitives"))) {
applyLanguageSpecificPrimitivesCsvList(languageSpecificPrimitives, configurator); applyLanguageSpecificPrimitivesCsvList(languageSpecificPrimitives, configurator);
} }
@ -573,22 +601,25 @@ public class CodeGenMojo extends AbstractMojo {
return; return;
} }
adjustAdditionalProperties(config); adjustAdditionalProperties(config);
try {
new DefaultGenerator().opts(input).generate(); new DefaultGenerator().opts(input).generate();
if (buildContext != null) {
buildContext.refresh(new File(getCompileSourceRoot()));
}
} catch (Exception e) { } catch (Exception e) {
// Maven logs exceptions thrown by plugins only if invoked with -e // Maven logs exceptions thrown by plugins only if invoked with -e
// I find it annoying to jump through hoops to get basic diagnostic information, // I find it annoying to jump through hoops to get basic diagnostic information,
// so let's log it in any case: // so let's log it in any case:
if (buildContext != null) {
buildContext.addError(inputSpecFile, 0, 0, "unexpected error in Open-API generation", e);
}
getLog().error(e); getLog().error(e);
throw new MojoExecutionException( throw new MojoExecutionException(
"Code generation failed. See above for the full exception."); "Code generation failed. See above for the full exception.");
} }
addCompileSourceRootIfConfigured();
} }
private void addCompileSourceRootIfConfigured() { private String getCompileSourceRoot() {
if (addCompileSourceRoot) {
final Object sourceFolderObject = final Object sourceFolderObject =
configOptions == null ? null : configOptions configOptions == null ? null : configOptions
.get(CodegenConstants.SOURCE_FOLDER); .get(CodegenConstants.SOURCE_FOLDER);
@ -596,7 +627,12 @@ public class CodeGenMojo extends AbstractMojo {
sourceFolderObject == null ? "src/main/java" : sourceFolderObject.toString(); sourceFolderObject == null ? "src/main/java" : sourceFolderObject.toString();
String sourceJavaFolder = output.toString() + "/" + sourceFolder; String sourceJavaFolder = output.toString() + "/" + sourceFolder;
project.addCompileSourceRoot(sourceJavaFolder); return sourceJavaFolder;
}
private void addCompileSourceRootIfConfigured() {
if (addCompileSourceRoot) {
project.addCompileSourceRoot(getCompileSourceRoot());
} }
// Reset all environment variables to their original value. This prevents unexpected // Reset all environment variables to their original value. This prevents unexpected

View File

@ -0,0 +1,17 @@
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<goals>
<goal>generate</goal>
</goals>
</pluginExecutionFilter>
<action>
<execute>
<runOnIncremental>true</runOnIncremental>
<runOnConfiguration>true</runOnConfiguration>
</execute>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>