From 550634da73615234f6830647e2aeeb3ecacfa315 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Tue, 1 Dec 2020 12:44:29 -0800 Subject: [PATCH] Add CreateNewServiceModuleMain and FinalizeNewServiceModuleMain release scripts, which are just a split up version of the NewServiceMain release script. --- .../release/CreateNewServiceModuleMain.java | 145 ++++++++++++++++++ .../release/FinalizeNewServiceModuleMain.java | 130 ++++++++++++++++ 2 files changed, 275 insertions(+) create mode 100644 release-scripts/src/main/java/software/amazon/awssdk/release/CreateNewServiceModuleMain.java create mode 100644 release-scripts/src/main/java/software/amazon/awssdk/release/FinalizeNewServiceModuleMain.java diff --git a/release-scripts/src/main/java/software/amazon/awssdk/release/CreateNewServiceModuleMain.java b/release-scripts/src/main/java/software/amazon/awssdk/release/CreateNewServiceModuleMain.java new file mode 100644 index 000000000000..845a78ec169a --- /dev/null +++ b/release-scripts/src/main/java/software/amazon/awssdk/release/CreateNewServiceModuleMain.java @@ -0,0 +1,145 @@ +/* + * 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.release; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import software.amazon.awssdk.utils.Validate; +import software.amazon.awssdk.utils.internal.CodegenNamingUtils; + +/** + * A command line application to create a new, empty service. This *does not* add the new service to the shared pom.xmls, that + * should be done via {@link FinalizeNewServiceModuleMain}. + * + * Example usage: + *
+ * mvn exec:java -pl :release-scripts \
+ *     -Dexec.mainClass="software.amazon.awssdk.release.CreateNewServiceModuleMain" \
+ *     -Dexec.args="--maven-project-root /path/to/root
+ *                  --maven-project-version 2.1.4-SNAPSHOT
+ *                  --service-id 'Service Id'
+ *                  --service-module-name service-module-name
+ *                  --service-protocol json"
+ * 
+ */ +public class CreateNewServiceModuleMain extends Cli { + private CreateNewServiceModuleMain() { + super(requiredOption("service-module-name", "The name of the service module to be created."), + requiredOption("service-id", "The service ID of the service module to be created."), + requiredOption("service-protocol", "The protocol of the service module to be created."), + requiredOption("maven-project-root", "The root directory for the maven project."), + requiredOption("maven-project-version", "The maven version of the service module to be created.")); + } + + public static void main(String[] args) { + new CreateNewServiceModuleMain().run(args); + } + + @Override + protected void run(CommandLine commandLine) throws Exception { + new NewServiceCreator(commandLine).run(); + } + + private static class NewServiceCreator { + private final Path mavenProjectRoot; + private final String mavenProjectVersion; + private final String serviceModuleName; + private final String serviceId; + private final String serviceProtocol; + + private NewServiceCreator(CommandLine commandLine) { + this.mavenProjectRoot = Paths.get(commandLine.getOptionValue("maven-project-root").trim()); + this.mavenProjectVersion = commandLine.getOptionValue("maven-project-version").trim(); + this.serviceModuleName = commandLine.getOptionValue("service-module-name").trim(); + this.serviceId = commandLine.getOptionValue("service-id").trim(); + this.serviceProtocol = transformSpecialProtocols(commandLine.getOptionValue("service-protocol").trim()); + + Validate.isTrue(Files.exists(mavenProjectRoot), "Project root does not exist: " + mavenProjectRoot); + } + + private String transformSpecialProtocols(String protocol) { + switch (protocol) { + case "ec2": return "query"; + case "rest-xml": return "xml"; + case "rest-json": return "json"; + default: return protocol; + } + } + + public void run() throws Exception { + Path servicesRoot = mavenProjectRoot.resolve("services"); + Path templateModulePath = servicesRoot.resolve("new-service-template"); + Path newServiceModulePath = servicesRoot.resolve(serviceModuleName); + + createNewModuleFromTemplate(templateModulePath, newServiceModulePath); + replaceTemplatePlaceholders(newServiceModulePath); + } + + private void createNewModuleFromTemplate(Path templateModulePath, Path newServiceModule) throws IOException { + FileUtils.copyDirectory(templateModulePath.toFile(), newServiceModule.toFile()); + } + + private void replaceTemplatePlaceholders(Path newServiceModule) throws IOException { + Files.walkFileTree(newServiceModule, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + replacePlaceholdersInFile(file); + return FileVisitResult.CONTINUE; + } + }); + } + + private void replacePlaceholdersInFile(Path file) throws IOException { + String fileContents = new String(Files.readAllBytes(file), UTF_8); + String newFileContents = replacePlaceholders(fileContents); + Files.write(file, newFileContents.getBytes(UTF_8)); + } + + private String replacePlaceholders(String line) { + String[] searchList = { + "{{MVN_ARTIFACT_ID}}", + "{{MVN_NAME}}", + "{{MVN_VERSION}}", + "{{PROTOCOL}}" + }; + String[] replaceList = { + serviceModuleName, + mavenName(serviceId), + mavenProjectVersion, + serviceProtocol + }; + return StringUtils.replaceEach(line, searchList, replaceList); + } + + private String mavenName(String serviceId) { + return Stream.of(CodegenNamingUtils.splitOnWordBoundaries(serviceId)) + .map(StringUtils::capitalize) + .collect(Collectors.joining(" ")); + } + } +} diff --git a/release-scripts/src/main/java/software/amazon/awssdk/release/FinalizeNewServiceModuleMain.java b/release-scripts/src/main/java/software/amazon/awssdk/release/FinalizeNewServiceModuleMain.java new file mode 100644 index 000000000000..7ff318bff5fa --- /dev/null +++ b/release-scripts/src/main/java/software/amazon/awssdk/release/FinalizeNewServiceModuleMain.java @@ -0,0 +1,130 @@ +/* + * 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.release; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.cli.CommandLine; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import software.amazon.awssdk.utils.Validate; + +/** + * A command line application to add new services to the shared pom.xml files. + * + * Example usage: + *
+ * mvn exec:java -pl :release-scripts \
+ *     -Dexec.mainClass="software.amazon.awssdk.release.FinalizeNewServiceModuleMain" \
+ *     -Dexec.args="--maven-project-root /path/to/root
+ *                  --service-module-names service-module-name-1,service-module-name-2"
+ * 
+ */ +public class FinalizeNewServiceModuleMain extends Cli { + private FinalizeNewServiceModuleMain() { + super(requiredOption("service-module-names", + "A comma-separated list containing the name of the service modules to be created."), + requiredOption("maven-project-root", "The root directory for the maven project.")); + } + + public static void main(String[] args) { + new FinalizeNewServiceModuleMain().run(args); + } + + @Override + protected void run(CommandLine commandLine) throws Exception { + new NewServiceCreator(commandLine).run(); + } + + private static class NewServiceCreator { + private final Path mavenProjectRoot; + private final List serviceModuleNames; + + private NewServiceCreator(CommandLine commandLine) { + this.mavenProjectRoot = Paths.get(commandLine.getOptionValue("maven-project-root").trim()); + this.serviceModuleNames = Stream.of(commandLine.getOptionValue("service-module-names").split(",")) + .map(String::trim) + .collect(Collectors.toList()); + + Validate.isTrue(Files.exists(mavenProjectRoot), "Project root does not exist: " + mavenProjectRoot); + } + + public void run() throws Exception { + for (String serviceModuleName : serviceModuleNames) { + Path servicesPomPath = mavenProjectRoot.resolve("services").resolve("pom.xml"); + Path aggregatePomPath = mavenProjectRoot.resolve("aws-sdk-java").resolve("pom.xml"); + Path bomPomPath = mavenProjectRoot.resolve("bom").resolve("pom.xml"); + + new AddSubmoduleTransformer(serviceModuleName).transform(servicesPomPath); + new AddDependencyTransformer(serviceModuleName).transform(aggregatePomPath); + new AddDependencyManagementDependencyTransformer(serviceModuleName).transform(bomPomPath); + } + } + + private static class AddSubmoduleTransformer extends PomTransformer { + private final String serviceModuleName; + + private AddSubmoduleTransformer(String serviceModuleName) { + this.serviceModuleName = serviceModuleName; + } + + @Override + protected void updateDocument(Document doc) { + Node project = findChild(doc, "project"); + Node modules = findChild(project, "modules"); + + modules.appendChild(textElement(doc, "module", serviceModuleName)); + } + } + + private static class AddDependencyTransformer extends PomTransformer { + private final String serviceModuleName; + + private AddDependencyTransformer(String serviceModuleName) { + this.serviceModuleName = serviceModuleName; + } + + @Override + protected void updateDocument(Document doc) { + Node project = findChild(doc, "project"); + Node dependencies = findChild(project, "dependencies"); + + dependencies.appendChild(sdkDependencyElement(doc, serviceModuleName)); + } + } + + private static class AddDependencyManagementDependencyTransformer extends PomTransformer { + private final String serviceModuleName; + + private AddDependencyManagementDependencyTransformer(String serviceModuleName) { + this.serviceModuleName = serviceModuleName; + } + + @Override + protected void updateDocument(Document doc) { + Node project = findChild(doc, "project"); + Node dependencyManagement = findChild(project, "dependencyManagement"); + Node dependencies = findChild(dependencyManagement, "dependencies"); + + dependencies.appendChild(sdkDependencyElement(doc, serviceModuleName)); + } + } + } +}