software.amazon.awssdk.codegen.maven.plugin.GenerationMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of codegen-maven-plugin Show documentation
Show all versions of codegen-maven-plugin Show documentation
The AWS SDK for Java - Code Generator Maven Plugin module holds a mojo to generate the AWS Java SDK
clients for AWS services.
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.codegen.maven.plugin;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Optional;
import java.util.stream.Stream;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import software.amazon.awssdk.codegen.C2jModels;
import software.amazon.awssdk.codegen.CodeGenerator;
import software.amazon.awssdk.codegen.internal.Utils;
import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig;
import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel;
import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel;
import software.amazon.awssdk.codegen.model.service.Paginators;
import software.amazon.awssdk.codegen.model.service.ServiceModel;
import software.amazon.awssdk.codegen.model.service.Waiters;
import software.amazon.awssdk.codegen.utils.ModelLoaderUtils;
/**
* The Maven mojo to generate Java client code using software.amazon.awssdk:codegen module.
*/
@Mojo(name = "generate")
public class GenerationMojo extends AbstractMojo {
private static final String MODEL_FILE = "service-2.json";
private static final String CUSTOMIZATION_CONFIG_FILE = "customization.config";
private static final String WAITERS_FILE = "waiters-2.json";
private static final String PAGINATORS_FILE = "paginators-1.json";
private static final String ENDPOINT_RULE_SET_FILE = "endpoint-rule-set.json";
private static final String ENDPOINT_TESTS_FILE = "endpoint-tests.json";
@Parameter(property = "codeGenResources", defaultValue = "${basedir}/src/main/resources/codegen-resources/")
private File codeGenResources;
@Parameter(property = "outputDirectory", defaultValue = "${project.build.directory}")
private String outputDirectory;
@Parameter(defaultValue = "false")
private boolean writeIntermediateModel;
@Parameter(defaultValue = "${project}", readonly = true)
private MavenProject project;
private Path sourcesDirectory;
private Path resourcesDirectory;
private Path testsDirectory;
@Override
public void execute() throws MojoExecutionException {
this.sourcesDirectory = Paths.get(outputDirectory).resolve("generated-sources").resolve("sdk");
this.resourcesDirectory = Paths.get(outputDirectory).resolve("generated-resources").resolve("sdk-resources");
this.testsDirectory = Paths.get(outputDirectory).resolve("generated-test-sources").resolve("sdk-tests");
findModelRoots().forEach(p -> {
Path modelRootPath = p.modelRoot;
getLog().info("Loading from: " + modelRootPath.toString());
generateCode(C2jModels.builder()
.customizationConfig(p.customizationConfig)
.serviceModel(loadServiceModel(modelRootPath))
.waitersModel(loadWaiterModel(modelRootPath))
.paginatorsModel(loadPaginatorModel(modelRootPath))
.endpointRuleSetModel(loadEndpointRuleSetModel(modelRootPath))
.endpointTestSuiteModel(loadEndpointTestSuiteModel(modelRootPath))
.build());
});
project.addCompileSourceRoot(sourcesDirectory.toFile().getAbsolutePath());
project.addTestCompileSourceRoot(testsDirectory.toFile().getAbsolutePath());
}
private Stream findModelRoots() throws MojoExecutionException {
try {
return Files.find(codeGenResources.toPath(), 10, this::isModelFile)
.map(Path::getParent)
.map(p -> new ModelRoot(p, loadCustomizationConfig(p)))
.sorted(this::modelSharersLast);
} catch (IOException e) {
throw new MojoExecutionException("Failed to find '" + MODEL_FILE + "' files in " + codeGenResources, e);
}
}
private int modelSharersLast(ModelRoot lhs, ModelRoot rhs) {
return lhs.customizationConfig.getShareModelConfig() == null ? -1 : 1;
}
private boolean isModelFile(Path p, BasicFileAttributes a) {
return p.toString().endsWith(MODEL_FILE);
}
private void generateCode(C2jModels models) {
CodeGenerator.builder()
.models(models)
.sourcesDirectory(sourcesDirectory.toFile().getAbsolutePath())
.resourcesDirectory(resourcesDirectory.toFile().getAbsolutePath())
.testsDirectory(testsDirectory.toFile().getAbsolutePath())
.intermediateModelFileNamePrefix(intermediateModelFileNamePrefix(models))
.build()
.execute();
}
private String intermediateModelFileNamePrefix(C2jModels models) {
return writeIntermediateModel ? Utils.getFileNamePrefix(models.serviceModel()) : null;
}
private CustomizationConfig loadCustomizationConfig(Path root) {
return ModelLoaderUtils.loadOptionalModel(CustomizationConfig.class,
root.resolve(CUSTOMIZATION_CONFIG_FILE).toFile(),
true)
.orElse(CustomizationConfig.create());
}
private ServiceModel loadServiceModel(Path root) {
return loadRequiredModel(ServiceModel.class, root.resolve(MODEL_FILE));
}
private Waiters loadWaiterModel(Path root) {
return loadOptionalModel(Waiters.class, root.resolve(WAITERS_FILE)).orElse(Waiters.none());
}
private Paginators loadPaginatorModel(Path root) {
return loadOptionalModel(Paginators.class, root.resolve(PAGINATORS_FILE)).orElse(Paginators.none());
}
private EndpointRuleSetModel loadEndpointRuleSetModel(Path root) {
return loadOptionalModel(EndpointRuleSetModel.class, root.resolve(ENDPOINT_RULE_SET_FILE)).orElse(null);
}
private EndpointTestSuiteModel loadEndpointTestSuiteModel(Path root) {
return loadOptionalModel(EndpointTestSuiteModel.class, root.resolve(ENDPOINT_TESTS_FILE)).orElse(null);
}
/**
* Load required model from the project resources.
*/
private T loadRequiredModel(Class clzz, Path location) {
return ModelLoaderUtils.loadModel(clzz, location.toFile());
}
/**
* Load an optional model from the project resources.
*
* @return Model or empty optional if not present.
*/
private Optional loadOptionalModel(Class clzz, Path location) {
return ModelLoaderUtils.loadOptionalModel(clzz, location.toFile());
}
private static class ModelRoot {
private final Path modelRoot;
private final CustomizationConfig customizationConfig;
private ModelRoot(Path modelRoot, CustomizationConfig customizationConfig) {
this.modelRoot = modelRoot;
this.customizationConfig = customizationConfig;
}
}
}