diff --git a/.changes/next-release/feature-AWSSDKforJavav2-3289c08.json b/.changes/next-release/feature-AWSSDKforJavav2-3289c08.json new file mode 100644 index 000000000000..3edf0465be44 --- /dev/null +++ b/.changes/next-release/feature-AWSSDKforJavav2-3289c08.json @@ -0,0 +1,6 @@ +{ + "category": "AWS SDK for Java v2", + "contributor": "", + "type": "feature", + "description": "Improve the endpoint rules performance by directly passing the needed params instead of using a POJO to keep track of them." +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodeGeneratorVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodeGeneratorVisitor.java index 4cd94ace20ad..04844eebaecb 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodeGeneratorVisitor.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodeGeneratorVisitor.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; @@ -32,14 +33,17 @@ public class CodeGeneratorVisitor extends WalkRuleExpressionVisitor { private final RuleRuntimeTypeMirror typeMirror; private final SymbolTable symbolTable; private final Map knownEndpointAttributes; + private final Map ruleIdToScope; public CodeGeneratorVisitor(RuleRuntimeTypeMirror typeMirror, SymbolTable symbolTable, Map knownEndpointAttributes, + Map ruleIdToScope, CodeBlock.Builder builder) { this.builder = builder; this.symbolTable = symbolTable; this.knownEndpointAttributes = knownEndpointAttributes; + this.ruleIdToScope = ruleIdToScope; this.typeMirror = typeMirror; } @@ -196,28 +200,14 @@ public Void visitRuleSetExpression(RuleSetExpression e) { @Override public Void visitLetExpression(LetExpression expr) { - for (String key : expr.bindings().keySet()) { - RuleType type = symbolTable.locals().get(key); - builder.addStatement("$T $L = null", type.javaType(), key); - } - - int count = 0; for (Map.Entry kvp : expr.bindings().entrySet()) { String k = kvp.getKey(); RuleExpression v = kvp.getValue(); - builder.add("if ("); - builder.add("($L = ", k); + RuleType type = symbolTable.locals().get(k); + builder.add("$T $L = ", type.javaType(), k); v.accept(this); - builder.add(") != null"); - - builder.beginControlFlow(")"); - builder.addStatement("locals = locals.toBuilder().$1L($1L).build()", k); - - if (++count < expr.bindings().size()) { - builder.nextControlFlow("else"); - builder.addStatement("return RuleResult.carryOn()"); - builder.endControlFlow(); - } + builder.addStatement(""); + builder.beginControlFlow("if ($L != null)", k); } return null; } @@ -235,40 +225,101 @@ private void conditionsPreamble(RuleSetExpression expr) { } private void conditionsEpilogue(RuleSetExpression expr) { - int blocksToClose = expr.conditions().size(); - for (int idx = 0; idx < blocksToClose; ++idx) { - builder.endControlFlow(); + for (RuleExpression condition : expr.conditions()) { + if (condition.kind() == RuleExpression.RuleExpressionKind.LET) { + LetExpression let = (LetExpression) condition; + for (int x = 0; x < let.bindings().size(); x++) { + builder.endControlFlow(); + } + } else { + builder.endControlFlow(); + } } - if (!expr.conditions().isEmpty()) { + if (needsReturn(expr)) { builder.addStatement("return $T.carryOn()", typeMirror.rulesResult().type()); } } + private boolean needsReturn(RuleSetExpression expr) { + // If the expression can be inlined, then it doesn't live in + // its own method, no return at the end required + if (canBeInlined(expr)) { + return false; + } + // If the expression has conditions all be be wrapped in + // if-blocks, thus at the end of the method we need to return + // carryOn() + if (!expr.conditions().isEmpty()) { + return true; + } + // If the expression doesn't have any conditions, and doesn't + // have any children then we need to return carryOn(). This + // case SHOULD NOT happen but we assume below that there are + // children, thus adding the test here. + if (expr.children().isEmpty()) { + return true; + } + // We have children, check the last one. + int size = expr.children().size(); + RuleSetExpression child = expr.children().get(size - 1); + // If a tree then we don't need a return. + if (child.isTree()) { + return false; + } + // The child is not a tree, so it was inlined. Check if it + // does have any conditions, if it so, its body will be inside + // a block already so we need to return after it. + return !child.conditions().isEmpty(); + } + private void codegenTreeBody(RuleSetExpression expr) { List children = expr.children(); int size = children.size(); + boolean isFirst = true; for (int idx = 0; idx < size; ++idx) { RuleSetExpression child = children.get(idx); + if (canBeInlined(child)) { + child.accept(this); + continue; + } boolean isLast = idx == size - 1; if (isLast) { - builder.addStatement("return $L(params, locals)", - child.ruleId()); + builder.addStatement("return $L($L)", + child.ruleId(), + callParams(child.ruleId())); continue; } - boolean isFirst = idx == 0; + if (isFirst) { - builder.addStatement("$T result = $L(params, locals)", + isFirst = false; + builder.addStatement("$T result = $L($L)", typeMirror.rulesResult().type(), - child.ruleId()); + child.ruleId(), + callParams(child.ruleId())); } else { - builder.addStatement("result = $L(params, locals)", - child.ruleId()); + builder.addStatement("result = $L($L)", + child.ruleId(), + callParams(child.ruleId())); } builder.beginControlFlow("if (result.isResolved())") .addStatement("return result") .endControlFlow(); } + } + private boolean canBeInlined(RuleSetExpression child) { + return !child.isTree(); + } + + private String callParams(String ruleId) { + ComputeScopeTree.Scope scope = ruleIdToScope.get(ruleId); + String args = scope.usesLocals().stream() + .filter(a -> !scope.defines().contains(a)) + .collect(Collectors.joining(", ")); + if (args.isEmpty()) { + return "params"; + } + return "params, " + args; } @Override @@ -381,7 +432,6 @@ private void addAttributeBlock(String k, RuleExpression v) { builder.add(")"); } - public CodeBlock.Builder builder() { return builder; } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodegenExpressionBuidler.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodegenExpressionBuidler.java index 57aa63980d2b..6488f015ad7b 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodegenExpressionBuidler.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodegenExpressionBuidler.java @@ -21,10 +21,16 @@ public final class CodegenExpressionBuidler { private final RuleSetExpression root; private final SymbolTable symbolTable; + private final Map scopesByName; - public CodegenExpressionBuidler(RuleSetExpression root, SymbolTable symbolTable) { + public CodegenExpressionBuidler( + RuleSetExpression root, + SymbolTable symbolTable, + Map scopesByName + ) { this.root = root; this.symbolTable = symbolTable; + this.scopesByName = scopesByName; } public static CodegenExpressionBuidler from(RuleSetExpression root, RuleRuntimeTypeMirror typeMirror, SymbolTable table) { @@ -36,10 +42,17 @@ public static CodegenExpressionBuidler from(RuleSetExpression root, RuleRuntimeT } table = assignTypesVisitor.symbolTable(); root = assignIdentifier(root); - PrepareForCodegenVisitor prepareForCodegenVisitor = new PrepareForCodegenVisitor(table); - root = (RuleSetExpression) root.accept(prepareForCodegenVisitor); - table = prepareForCodegenVisitor.symbolTable(); - return new CodegenExpressionBuidler(root, table); + + RenameForCodegenVisitor renameForCodegenVisitor = new RenameForCodegenVisitor(table); + root = (RuleSetExpression) root.accept(renameForCodegenVisitor); + table = renameForCodegenVisitor.symbolTable(); + + ComputeScopeTree computeScopeTree = new ComputeScopeTree(table); + root.accept(computeScopeTree); + + PrepareForCodegenVisitor prepareForCodegenVisitor = new PrepareForCodegenVisitor(); + RuleSetExpression newRoot = (RuleSetExpression) root.accept(prepareForCodegenVisitor); + return new CodegenExpressionBuidler(newRoot, table, computeScopeTree.scopesByName()); } private static RuleSetExpression assignIdentifier(RuleSetExpression root) { @@ -51,27 +64,15 @@ public RuleSetExpression root() { return root; } - public boolean isParam(String name) { - return symbolTable.isParam(name); - } - - public boolean isLocal(String name) { - return symbolTable.isLocal(name); - } - public String regionParamName() { return symbolTable.regionParamName(); } - public Map locals() { - return symbolTable.locals(); - } - - public Map params() { - return symbolTable.params(); - } - public SymbolTable symbolTable() { return symbolTable; } + + public Map scopesByName() { + return scopesByName; + } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ComputeScopeTree.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ComputeScopeTree.java new file mode 100644 index 000000000000..42f612f87418 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ComputeScopeTree.java @@ -0,0 +1,193 @@ +/* + * 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.poet.rules2; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * Computes all the symbols, locals and params, used by each of the rules, either directly or transitively. + */ +public final class ComputeScopeTree extends WalkRuleExpressionVisitor { + private final SymbolTable symbolTable; + private final Deque scopes = new ArrayDeque<>(); + private final Map scopesByName = new HashMap<>(); + private Scope result; + + public ComputeScopeTree(SymbolTable symbolTable) { + this.symbolTable = symbolTable; + } + + /** + * Returns the root scope. + */ + public Scope result() { + return result; + } + + /** + * Returns the mapping between rule id and scope. + */ + public Map scopesByName() { + return scopesByName; + } + + @Override + public Void visitRuleSetExpression(RuleSetExpression node) { + ScopeBuilder scopeBuilder = new ScopeBuilder(); + scopeBuilder.ruleId(node.ruleId()); + scopes.push(scopeBuilder); + super.visitRuleSetExpression(node); + result = scopes.pop().build(); + scopesByName.put(result.ruleId(), result); + if (!scopes.isEmpty()) { + scopes.peekFirst().addChild(result); + } + return null; + } + + @Override + public Void visitVariableReferenceExpression(VariableReferenceExpression e) { + String variableName = e.variableName(); + ScopeBuilder current = scopes.peekFirst(); + if (symbolTable.isLocal(variableName)) { + current.usesLocal(variableName); + } else if (symbolTable.isParam(variableName)) { + current.usesParam(variableName); + } + return null; + } + + @Override + public Void visitLetExpression(LetExpression e) { + ScopeBuilder scopeBuilder = scopes.peekFirst(); + for (String binding : e.bindings().keySet()) { + scopeBuilder.defines(binding); + } + return super.visitLetExpression(e); + } + + public static class Scope { + private final String ruleId; + private final Set defines; + private final Set usesLocals; + private final Set usesParams; + private final List children; + + public Scope(ScopeBuilder builder) { + this.ruleId = Objects.requireNonNull(builder.ruleId, "ruleId cannot be null"); + this.defines = Collections.unmodifiableSet(new LinkedHashSet<>(builder.defines)); + this.usesLocals = Collections.unmodifiableSet(new LinkedHashSet<>(builder.usesLocals)); + this.usesParams = Collections.unmodifiableSet(new LinkedHashSet<>(builder.usesParams)); + this.children = Collections.unmodifiableList(new ArrayList<>(builder.children)); + } + + public String ruleId() { + return ruleId; + } + + public Set defines() { + return defines; + } + + public Set usesLocals() { + return usesLocals; + } + + public Set usesParams() { + return usesParams; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + appendTo(0, builder); + return builder.toString(); + } + + public void appendTo(int level, StringBuilder sb) { + String prefix = levelValue(level); + sb.append(prefix).append("=========================================\n"); + sb.append(prefix).append("rule ").append(ruleId).append("\n"); + sb.append(prefix).append("defines ").append(defines).append("\n"); + sb.append(prefix).append("uses ").append(usesLocals).append("\n"); + for (Scope child : children) { + child.appendTo(level + 1, sb); + } + } + + private String levelValue(int level) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < level; i++) { + result.append(" "); + } + return result.toString(); + } + } + + public static class ScopeBuilder { + private String ruleId; + private final Set defines = new LinkedHashSet<>(); + private final Set usesLocals = new LinkedHashSet<>(); + private final Set usesParams = new LinkedHashSet<>(); + private final List children = new ArrayList<>(); + + public ScopeBuilder ruleId(String ruleId) { + this.ruleId = ruleId; + return this; + } + + public ScopeBuilder defines(String define) { + defines.add(define); + return this; + } + + public ScopeBuilder usesLocal(String use) { + usesLocals.add(use); + return this; + } + + public ScopeBuilder usesParam(String use) { + usesParams.add(use); + return this; + } + + public ScopeBuilder addChild(Scope child) { + children.add(child); + for (String local : child.usesLocals) { + if (!child.defines.contains(local)) { + usesLocals.add(local); + } + } + for (String param : child.usesParams) { + usesParams.add(param); + } + return this; + } + + public Scope build() { + return new Scope(this); + } + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointProviderSpec2.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointProviderSpec2.java index adbed805cc40..831b8d88af83 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointProviderSpec2.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointProviderSpec2.java @@ -123,8 +123,6 @@ public TypeSpec poetSpec() { .addSuperinterface(endpointRulesSpecUtils.providerInterfaceName()) .addAnnotation(SdkInternalApi.class); - builder.addType(codegenLocalState()); - builder.addType(codegenLocalStateBuilder()); builder.addMethod(resolveEndpointMethod()); List methods = new ArrayList<>(); createRuleMethod(utils.root(), methods); @@ -154,11 +152,11 @@ private MethodSpec resolveEndpointMethod() { builder.beginControlFlow("try"); String regionParamName = utils.regionParamName(); if (regionParamName != null) { - builder.addStatement("$T result = $L(params, new $T(params.$L()))", ruleResult(), utils.root().ruleId(), - ClassName.bestGuess("LocalState"), regionParamName); + builder.addStatement("$T region = params.$L()", Region.class, regionParamName); + builder.addStatement("$T regionId = region == null ? null : region.id()", String.class); + builder.addStatement("$T result = $L(params, regionId)", ruleResult(), utils.root().ruleId()); } else { - builder.addStatement("$T result = $L(params, new $T())", ruleResult(), utils.root().ruleId(), - ClassName.bestGuess("LocalState")); + builder.addStatement("$T result = $L(params)", ruleResult(), utils.root().ruleId()); } builder.beginControlFlow("if (result.canContinue())") .addStatement("throw $T.create($S)", SdkClientException.class, "Rule engine did not reach an error or " @@ -206,7 +204,9 @@ private void createRuleMethod(RuleSetExpression expr, List m builder.addCode(block.build()); if (expr.isTree()) { for (RuleSetExpression child : expr.children()) { - createRuleMethod(child, methods); + if (child.isTree()) { + createRuleMethod(child, methods); + } } } } @@ -215,110 +215,26 @@ private MethodSpec.Builder methodBuilderForRule(RuleSetExpression expr) { MethodSpec.Builder builder = MethodSpec.methodBuilder(expr.ruleId()) .addModifiers(Modifier.PRIVATE, Modifier.STATIC) - .returns(ruleResult()) - .addParameter(endpointRulesSpecUtils.parametersClassName(), "params"); - builder.addParameter(ClassName.bestGuess("LocalState"), "locals"); + .returns(ruleResult()); + ComputeScopeTree.Scope scope = utils.scopesByName().get(expr.ruleId()); + builder.addParameter(endpointRulesSpecUtils.parametersClassName(), "params"); + for (String param : scope.usesLocals()) { + if (scope.defines().contains(param)) { + continue; + } + RuleType type = utils.symbolTable().localType(param); + builder.addParameter(type.javaType(), param); + } return builder; } - private void codegenExpr(RuleExpression expr, CodeBlock.Builder builder) { + private void codegenExpr(RuleSetExpression expr, CodeBlock.Builder builder) { CodeGeneratorVisitor visitor = new CodeGeneratorVisitor(typeMirror, utils.symbolTable(), knownEndpointAttributes, + utils.scopesByName(), builder); - expr.accept(visitor); - } - - private TypeSpec codegenLocalState() { - TypeSpec.Builder b = TypeSpec.classBuilder("LocalState") - .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL); - Map locals = utils.locals(); - locals.forEach((k, v) -> { - b.addField(v.javaType(), k, Modifier.PRIVATE, Modifier.FINAL); - }); - MethodSpec.Builder emptyCtor = MethodSpec.constructorBuilder(); - locals.forEach((k, v) -> { - emptyCtor.addStatement("this.$1L = null", k); - }); - b.addMethod(emptyCtor.build()); - String regionParamName = utils.regionParamName(); - if (regionParamName != null) { - MethodSpec.Builder regionCtor = MethodSpec.constructorBuilder() - .addParameter(Region.class, "region"); - locals.forEach((k, v) -> { - if (k.equals(regionParamName)) { - regionCtor.beginControlFlow("if (region != null)") - .addStatement("this.$L = region.id()", regionParamName) - .nextControlFlow("else") - .addStatement("this.$L = null", regionParamName) - .endControlFlow(); - } else { - regionCtor.addStatement("this.$1L = null", k); - } - }); - b.addMethod(regionCtor.build()); - - } - ClassName localStateBuilder = ClassName.bestGuess("LocalStateBuilder"); - MethodSpec.Builder builderCtor = MethodSpec - .constructorBuilder() - .addParameter(localStateBuilder, "builder"); - - locals.forEach((k, v) -> { - builderCtor.addStatement("this.$1L = builder.$1L", k); - }); - - b.addMethod(builderCtor.build()); - locals.forEach((k, v) -> { - b.addMethod(MethodSpec.methodBuilder(k) - .addModifiers(Modifier.PUBLIC) - .returns(v.javaType()) - .addStatement("return this.$L", k) - .build()); - }); - b.addMethod(MethodSpec.methodBuilder("toBuilder") - .addModifiers(Modifier.PUBLIC) - .returns(localStateBuilder) - .addStatement("return new $T(this)", localStateBuilder) - .build()); - return b.build(); - } - - private TypeSpec codegenLocalStateBuilder() { - ClassName localStateClass = ClassName.bestGuess("LocalState"); - ClassName builderClass = ClassName.bestGuess("LocalStateBuilder"); - TypeSpec.Builder b = TypeSpec.classBuilder("LocalStateBuilder") - .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL); - Map locals = utils.locals(); - locals.forEach((k, v) -> { - b.addField(v.javaType(), k, Modifier.PRIVATE); - }); - MethodSpec.Builder emptyCtor = MethodSpec.constructorBuilder(); - locals.forEach((k, v) -> { - emptyCtor.addStatement("this.$1L = null", k); - }); - b.addMethod(emptyCtor.build()); - MethodSpec.Builder stateCtor = MethodSpec - .constructorBuilder() - .addParameter(localStateClass, "locals"); - locals.forEach((k, v) -> { - stateCtor.addStatement("this.$1L = locals.$1L", k); - }); - b.addMethod(stateCtor.build()); - locals.forEach((k, v) -> { - b.addMethod(MethodSpec.methodBuilder(k) - .addModifiers(Modifier.PUBLIC) - .returns(builderClass) - .addParameter(v.javaType(), "value") - .addStatement("this.$L = value", k) - .addStatement("return this") - .build()); - }); - b.addMethod(MethodSpec.methodBuilder("build") - .returns(localStateClass) - .addStatement("return new $T(this)", localStateClass) - .build()); - return b.build(); + visitor.visitRuleSetExpression(expr); } private TypeName ruleResult() { diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/PrepareForCodegenVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/PrepareForCodegenVisitor.java index 23c3c4ad7c43..a453812bd5a0 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/PrepareForCodegenVisitor.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/PrepareForCodegenVisitor.java @@ -16,29 +16,13 @@ package software.amazon.awssdk.codegen.poet.rules2; import java.util.List; -import software.amazon.awssdk.codegen.internal.Utils; -import software.amazon.awssdk.utils.internal.CodegenNamingUtils; /** - * Visitor that rewrites some expressions in preparation for codegen and also renaming locals assignments to use idiomatic java - * names. This visitor in particular rewrites variable references to the equivalent to {@code getAttr(params, NAME)} or {@code - * getAttr(locals, NAME)}, depending on whether the reference is an endpoint params variable or a locally assigned one. + * Visitor that rewrites expressions in preparation for codegen. */ public final class PrepareForCodegenVisitor extends RewriteRuleExpressionVisitor { - private final SymbolTable symbolTable; - private final SymbolTable.Builder renames; - public PrepareForCodegenVisitor(SymbolTable symbolTable) { - this.symbolTable = symbolTable; - this.renames = SymbolTable.builder(); - } - - public SymbolTable symbolTable() { - String regionParamName = symbolTable.regionParamName(); - if (regionParamName != null) { - renames.regionParamName(javaName(regionParamName)); - } - return renames.build(); + public PrepareForCodegenVisitor() { } @Override @@ -72,34 +56,6 @@ public RuleExpression visitFunctionCallExpression(FunctionCallExpression e) { } } - @Override - public RuleExpression visitVariableReferenceExpression(VariableReferenceExpression e) { - String name = e.variableName(); - if (symbolTable.isLocal(name)) { - RuleType type = symbolTable.localType(name); - String newName = javaName(name); - renames.putLocal(newName, type); - return MemberAccessExpression - .builder() - .type(e.type()) - .source(VariableReferenceExpression.builder().variableName("locals").build()) - .name(newName) - .build(); - } - if (symbolTable.isParam(name)) { - RuleType type = symbolTable.paramType(name); - String newName = javaName(name); - renames.putParam(newName, type); - return MemberAccessExpression - .builder() - .type(e.type()) - .source(VariableReferenceExpression.builder().variableName("params").build()) - .name(newName) - .build(); - } - return e; - } - @Override public RuleExpression visitIndexedAccessExpression(IndexedAccessExpression e) { e = (IndexedAccessExpression) super.visitIndexedAccessExpression(e); @@ -112,18 +68,6 @@ public RuleExpression visitIndexedAccessExpression(IndexedAccessExpression e) { .build(); } - @Override - public RuleExpression visitLetExpression(LetExpression e) { - LetExpression.Builder builder = LetExpression.builder(); - e.bindings().forEach((k, v) -> { - String newName = javaName(k); - RuleExpression value = v.accept(this); - builder.putBinding(newName, value); - renames.putLocal(newName, value.type()); - }); - return builder.build(); - } - /** * Transforms the following expressions: *
    @@ -212,8 +156,4 @@ private RuleExpression simplifyNotExpression(FunctionCallExpression e) { } return e; } - - private String javaName(String name) { - return Utils.unCapitalize(CodegenNamingUtils.pascalCase(name)); - } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RenameForCodegenVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RenameForCodegenVisitor.java new file mode 100644 index 000000000000..1c09b51c398a --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RenameForCodegenVisitor.java @@ -0,0 +1,86 @@ +/* + * 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.poet.rules2; + +import software.amazon.awssdk.codegen.internal.Utils; +import software.amazon.awssdk.utils.internal.CodegenNamingUtils; + +/** + * Visitor that renames locals assignments to use idiomatic java names. This visitor also rewrites variable references to + * the equivalent to {@code getAttr(params, NAME)}, to call the getter method in the params. + */ +public final class RenameForCodegenVisitor extends RewriteRuleExpressionVisitor { + private final SymbolTable symbolTable; + private final SymbolTable.Builder renames; + + public RenameForCodegenVisitor(SymbolTable symbolTable) { + this.symbolTable = symbolTable; + this.renames = SymbolTable.builder(); + } + + /** + * Returns the new symbol table with the renamed symbols. + */ + public SymbolTable symbolTable() { + String regionParamName = symbolTable.regionParamName(); + if (regionParamName != null) { + renames.regionParamName(javaName(regionParamName)); + } + return renames.build(); + } + + @Override + public RuleExpression visitVariableReferenceExpression(VariableReferenceExpression e) { + String name = e.variableName(); + if (symbolTable.isLocal(name)) { + RuleType type = symbolTable.localType(name); + String newName = javaName(name); + renames.putLocal(newName, type); + return VariableReferenceExpression + .builder() + .variableName(newName) + .build(); + } + if (symbolTable.isParam(name)) { + RuleType type = symbolTable.paramType(name); + String newName = javaName(name); + renames.putParam(newName, type); + return MemberAccessExpression + .builder() + .type(e.type()) + .source(VariableReferenceExpression.builder().variableName("params").build()) + .name(newName) + .build(); + } + return e; + } + + @Override + public RuleExpression visitLetExpression(LetExpression e) { + LetExpression.Builder builder = LetExpression.builder(); + e.bindings().forEach((k, v) -> { + String newName = javaName(k); + RuleExpression value = v.accept(this); + builder.putBinding(newName, value); + renames.putLocal(newName, value.type()); + }); + return builder.build(); + } + + private String javaName(String name) { + return Utils.unCapitalize(CodegenNamingUtils.pascalCase(name)); + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleSetExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleSetExpression.java index f7682eaec0cd..13a3ccafc51b 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleSetExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleSetExpression.java @@ -157,6 +157,16 @@ public boolean isTree() { return endpoint == null && error == null; } + public String category() { + if (isEndpoint()) { + return "endpoint"; + } + if (isError()) { + return "error"; + } + return "tree"; + } + @Override public RuleType type() { return type; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/WalkRuleExpressionVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/WalkRuleExpressionVisitor.java index fa59498b61a1..de952b6d67da 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/WalkRuleExpressionVisitor.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/WalkRuleExpressionVisitor.java @@ -93,7 +93,7 @@ public Void visitRuleSetExpression(RuleSetExpression e) { visitAll(e.conditions()); ErrorExpression error = e.error(); if (error != null) { - e.accept(this); + error.accept(this); } EndpointExpression endpoint = e.endpoint(); if (endpoint != null) { diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-class.java index 942a770b61a3..684823698760 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-class.java @@ -23,7 +23,9 @@ public final class DefaultQueryEndpointProvider implements QueryEndpointProvider public CompletableFuture resolveEndpoint(QueryEndpointParams params) { Validate.notNull(params.region(), "Parameter 'region' must not be null"); try { - RuleResult result = endpointRule0(params, new LocalState(params.region())); + Region region = params.region(); + String regionId = region == null ? null : region.id(); + RuleResult result = endpointRule0(params, regionId); if (result.canContinue()) { throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); } @@ -40,170 +42,101 @@ public CompletableFuture resolveEndpoint(QueryEndpointParams params) { } } - private static RuleResult endpointRule0(QueryEndpointParams params, LocalState locals) { - return endpointRule1(params, locals); + private static RuleResult endpointRule0(QueryEndpointParams params, String region) { + return endpointRule1(params, region); } - private static RuleResult endpointRule1(QueryEndpointParams params, LocalState locals) { - RulePartition partitionResult = null; - if ((partitionResult = RulesFunctions.awsPartition(locals.region())) != null) { - locals = locals.toBuilder().partitionResult(partitionResult).build(); - RuleResult result = endpointRule2(params, locals); + private static RuleResult endpointRule1(QueryEndpointParams params, String region) { + RulePartition partitionResult = RulesFunctions.awsPartition(region); + if (partitionResult != null) { + RuleResult result = endpointRule2(params, partitionResult); if (result.isResolved()) { return result; } - result = endpointRule6(params, locals); + result = endpointRule6(params, region, partitionResult); if (result.isResolved()) { return result; } - result = endpointRule11(params, locals); - if (result.isResolved()) { - return result; + return RuleResult.error(region + " is not a valid HTTP host-label"); + if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint() + && params.arnList() != null) { + String firstArn = RulesFunctions.listAccess(params.arnList(), 0); + if (firstArn != null) { + RuleArn parsedArn = RulesFunctions.awsParseArn(firstArn); + if (parsedArn != null) { + return RuleResult.endpoint(Endpoint + .builder() + .url(URI.create("https://" + params.endpointId() + ".query." + + partitionResult.dualStackDnsSuffix())) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + } } - return endpointRule12(params, locals); } return RuleResult.carryOn(); } - private static RuleResult endpointRule2(QueryEndpointParams params, LocalState locals) { + private static RuleResult endpointRule2(QueryEndpointParams params, RulePartition partitionResult) { if (params.endpointId() != null) { - RuleResult result = endpointRule3(params, locals); - if (result.isResolved()) { - return result; - } - result = endpointRule4(params, locals); - if (result.isResolved()) { - return result; - } - return endpointRule5(params, locals); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule3(QueryEndpointParams params, LocalState locals) { - if (params.useFipsEndpoint() != null && params.useFipsEndpoint()) { - return RuleResult.error("FIPS endpoints not supported with multi-region endpoints"); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule4(QueryEndpointParams params, LocalState locals) { - if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint()) { - return RuleResult - .endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." - + locals.partitionResult().dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule5(QueryEndpointParams params, LocalState locals) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." + locals.partitionResult().dnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) - .build())).build()); - } - - private static RuleResult endpointRule6(QueryEndpointParams params, LocalState locals) { - if (RulesFunctions.isValidHostLabel(locals.region(), false)) { - RuleResult result = endpointRule7(params, locals); - if (result.isResolved()) { - return result; - } - result = endpointRule8(params, locals); - if (result.isResolved()) { - return result; + if (params.useFipsEndpoint() != null && params.useFipsEndpoint()) { + return RuleResult.error("FIPS endpoints not supported with multi-region endpoints"); } - result = endpointRule9(params, locals); - if (result.isResolved()) { - return result; + if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint()) { + return RuleResult.endpoint(Endpoint + .builder() + .url(URI.create("https://" + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix())) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); } - return endpointRule10(params, locals); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule7(QueryEndpointParams params, LocalState locals) { - if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://query-fips." + locals.region() + "." + locals.partitionResult().dnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) - .build())).build()); + .builder() + .url(URI.create("https://" + params.endpointId() + ".query." + partitionResult.dnsSuffix())) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) + .build())).build()); } return RuleResult.carryOn(); } - private static RuleResult endpointRule8(QueryEndpointParams params, LocalState locals) { - if (params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint() == null) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://query." + locals.region() + "." + locals.partitionResult().dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) - .build(), SigV4AuthScheme.builder().signingName("query").signingRegion(locals.region()) - .build())).build()); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule9(QueryEndpointParams params, LocalState locals) { - if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() - && params.useFipsEndpoint()) { - return RuleResult - .endpoint(Endpoint - .builder() - .url(URI.create("https://query-fips." + locals.region() + "." - + locals.partitionResult().dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule10(QueryEndpointParams params, LocalState locals) { - return RuleResult.endpoint(Endpoint.builder() - .url(URI.create("https://query." + locals.region() + "." + locals.partitionResult().dnsSuffix())).build()); - } - - private static RuleResult endpointRule11(QueryEndpointParams params, LocalState locals) { - return RuleResult.error(locals.region() + " is not a valid HTTP host-label"); - } - - private static RuleResult endpointRule12(QueryEndpointParams params, LocalState locals) { - if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint() - && params.arnList() != null) { - String firstArn = null; - RuleArn parsedArn = null; - if ((firstArn = RulesFunctions.listAccess(params.arnList(), 0)) != null) { - locals = locals.toBuilder().firstArn(firstArn).build(); - } else { - return RuleResult.carryOn(); + private static RuleResult endpointRule6(QueryEndpointParams params, String region, RulePartition partitionResult) { + if (RulesFunctions.isValidHostLabel(region, false)) { + if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { + return RuleResult.endpoint(Endpoint + .builder() + .url(URI.create("https://query-fips." + region + "." + partitionResult.dnsSuffix())) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); } - if ((parsedArn = RulesFunctions.awsParseArn(locals.firstArn())) != null) { - locals = locals.toBuilder().parsedArn(parsedArn).build(); + if (params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint() == null) { return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." - + locals.partitionResult().dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); + .builder() + .url(URI.create("https://query." + region + "." + partitionResult.dualStackDnsSuffix())) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build(), + SigV4AuthScheme.builder().signingName("query").signingRegion(region).build())).build()); } + if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() + && params.useFipsEndpoint()) { + return RuleResult.endpoint(Endpoint + .builder() + .url(URI.create("https://query-fips." + region + "." + partitionResult.dualStackDnsSuffix())) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + return RuleResult.endpoint(Endpoint.builder() + .url(URI.create("https://query." + region + "." + partitionResult.dnsSuffix())).build()); } return RuleResult.carryOn(); } @@ -217,107 +150,4 @@ public boolean equals(Object rhs) { public int hashCode() { return getClass().hashCode(); } - - private static final class LocalState { - private final String region; - - private final RulePartition partitionResult; - - private final String firstArn; - - private final RuleArn parsedArn; - - LocalState() { - this.region = null; - this.partitionResult = null; - this.firstArn = null; - this.parsedArn = null; - } - - LocalState(Region region) { - if (region != null) { - this.region = region.id(); - } else { - this.region = null; - } - this.partitionResult = null; - this.firstArn = null; - this.parsedArn = null; - } - - LocalState(LocalStateBuilder builder) { - this.region = builder.region; - this.partitionResult = builder.partitionResult; - this.firstArn = builder.firstArn; - this.parsedArn = builder.parsedArn; - } - - public String region() { - return this.region; - } - - public RulePartition partitionResult() { - return this.partitionResult; - } - - public String firstArn() { - return this.firstArn; - } - - public RuleArn parsedArn() { - return this.parsedArn; - } - - public LocalStateBuilder toBuilder() { - return new LocalStateBuilder(this); - } - } - - private static final class LocalStateBuilder { - private String region; - - private RulePartition partitionResult; - - private String firstArn; - - private RuleArn parsedArn; - - LocalStateBuilder() { - this.region = null; - this.partitionResult = null; - this.firstArn = null; - this.parsedArn = null; - } - - LocalStateBuilder(LocalState locals) { - this.region = locals.region; - this.partitionResult = locals.partitionResult; - this.firstArn = locals.firstArn; - this.parsedArn = locals.parsedArn; - } - - public LocalStateBuilder region(String value) { - this.region = value; - return this; - } - - public LocalStateBuilder partitionResult(RulePartition value) { - this.partitionResult = value; - return this; - } - - public LocalStateBuilder firstArn(String value) { - this.firstArn = value; - return this; - } - - public LocalStateBuilder parsedArn(RuleArn value) { - this.parsedArn = value; - return this; - } - - LocalState build() { - return new LocalState(this); - } - } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-know-prop-override-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-know-prop-override-class.java index 942a770b61a3..684823698760 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-know-prop-override-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-know-prop-override-class.java @@ -23,7 +23,9 @@ public final class DefaultQueryEndpointProvider implements QueryEndpointProvider public CompletableFuture resolveEndpoint(QueryEndpointParams params) { Validate.notNull(params.region(), "Parameter 'region' must not be null"); try { - RuleResult result = endpointRule0(params, new LocalState(params.region())); + Region region = params.region(); + String regionId = region == null ? null : region.id(); + RuleResult result = endpointRule0(params, regionId); if (result.canContinue()) { throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); } @@ -40,170 +42,101 @@ public CompletableFuture resolveEndpoint(QueryEndpointParams params) { } } - private static RuleResult endpointRule0(QueryEndpointParams params, LocalState locals) { - return endpointRule1(params, locals); + private static RuleResult endpointRule0(QueryEndpointParams params, String region) { + return endpointRule1(params, region); } - private static RuleResult endpointRule1(QueryEndpointParams params, LocalState locals) { - RulePartition partitionResult = null; - if ((partitionResult = RulesFunctions.awsPartition(locals.region())) != null) { - locals = locals.toBuilder().partitionResult(partitionResult).build(); - RuleResult result = endpointRule2(params, locals); + private static RuleResult endpointRule1(QueryEndpointParams params, String region) { + RulePartition partitionResult = RulesFunctions.awsPartition(region); + if (partitionResult != null) { + RuleResult result = endpointRule2(params, partitionResult); if (result.isResolved()) { return result; } - result = endpointRule6(params, locals); + result = endpointRule6(params, region, partitionResult); if (result.isResolved()) { return result; } - result = endpointRule11(params, locals); - if (result.isResolved()) { - return result; + return RuleResult.error(region + " is not a valid HTTP host-label"); + if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint() + && params.arnList() != null) { + String firstArn = RulesFunctions.listAccess(params.arnList(), 0); + if (firstArn != null) { + RuleArn parsedArn = RulesFunctions.awsParseArn(firstArn); + if (parsedArn != null) { + return RuleResult.endpoint(Endpoint + .builder() + .url(URI.create("https://" + params.endpointId() + ".query." + + partitionResult.dualStackDnsSuffix())) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + } } - return endpointRule12(params, locals); } return RuleResult.carryOn(); } - private static RuleResult endpointRule2(QueryEndpointParams params, LocalState locals) { + private static RuleResult endpointRule2(QueryEndpointParams params, RulePartition partitionResult) { if (params.endpointId() != null) { - RuleResult result = endpointRule3(params, locals); - if (result.isResolved()) { - return result; - } - result = endpointRule4(params, locals); - if (result.isResolved()) { - return result; - } - return endpointRule5(params, locals); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule3(QueryEndpointParams params, LocalState locals) { - if (params.useFipsEndpoint() != null && params.useFipsEndpoint()) { - return RuleResult.error("FIPS endpoints not supported with multi-region endpoints"); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule4(QueryEndpointParams params, LocalState locals) { - if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint()) { - return RuleResult - .endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." - + locals.partitionResult().dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule5(QueryEndpointParams params, LocalState locals) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." + locals.partitionResult().dnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) - .build())).build()); - } - - private static RuleResult endpointRule6(QueryEndpointParams params, LocalState locals) { - if (RulesFunctions.isValidHostLabel(locals.region(), false)) { - RuleResult result = endpointRule7(params, locals); - if (result.isResolved()) { - return result; - } - result = endpointRule8(params, locals); - if (result.isResolved()) { - return result; + if (params.useFipsEndpoint() != null && params.useFipsEndpoint()) { + return RuleResult.error("FIPS endpoints not supported with multi-region endpoints"); } - result = endpointRule9(params, locals); - if (result.isResolved()) { - return result; + if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint()) { + return RuleResult.endpoint(Endpoint + .builder() + .url(URI.create("https://" + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix())) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); } - return endpointRule10(params, locals); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule7(QueryEndpointParams params, LocalState locals) { - if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://query-fips." + locals.region() + "." + locals.partitionResult().dnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) - .build())).build()); + .builder() + .url(URI.create("https://" + params.endpointId() + ".query." + partitionResult.dnsSuffix())) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) + .build())).build()); } return RuleResult.carryOn(); } - private static RuleResult endpointRule8(QueryEndpointParams params, LocalState locals) { - if (params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint() == null) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://query." + locals.region() + "." + locals.partitionResult().dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) - .build(), SigV4AuthScheme.builder().signingName("query").signingRegion(locals.region()) - .build())).build()); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule9(QueryEndpointParams params, LocalState locals) { - if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() - && params.useFipsEndpoint()) { - return RuleResult - .endpoint(Endpoint - .builder() - .url(URI.create("https://query-fips." + locals.region() + "." - + locals.partitionResult().dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule10(QueryEndpointParams params, LocalState locals) { - return RuleResult.endpoint(Endpoint.builder() - .url(URI.create("https://query." + locals.region() + "." + locals.partitionResult().dnsSuffix())).build()); - } - - private static RuleResult endpointRule11(QueryEndpointParams params, LocalState locals) { - return RuleResult.error(locals.region() + " is not a valid HTTP host-label"); - } - - private static RuleResult endpointRule12(QueryEndpointParams params, LocalState locals) { - if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint() - && params.arnList() != null) { - String firstArn = null; - RuleArn parsedArn = null; - if ((firstArn = RulesFunctions.listAccess(params.arnList(), 0)) != null) { - locals = locals.toBuilder().firstArn(firstArn).build(); - } else { - return RuleResult.carryOn(); + private static RuleResult endpointRule6(QueryEndpointParams params, String region, RulePartition partitionResult) { + if (RulesFunctions.isValidHostLabel(region, false)) { + if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { + return RuleResult.endpoint(Endpoint + .builder() + .url(URI.create("https://query-fips." + region + "." + partitionResult.dnsSuffix())) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); } - if ((parsedArn = RulesFunctions.awsParseArn(locals.firstArn())) != null) { - locals = locals.toBuilder().parsedArn(parsedArn).build(); + if (params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint() == null) { return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." - + locals.partitionResult().dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); + .builder() + .url(URI.create("https://query." + region + "." + partitionResult.dualStackDnsSuffix())) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build(), + SigV4AuthScheme.builder().signingName("query").signingRegion(region).build())).build()); } + if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() + && params.useFipsEndpoint()) { + return RuleResult.endpoint(Endpoint + .builder() + .url(URI.create("https://query-fips." + region + "." + partitionResult.dualStackDnsSuffix())) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + return RuleResult.endpoint(Endpoint.builder() + .url(URI.create("https://query." + region + "." + partitionResult.dnsSuffix())).build()); } return RuleResult.carryOn(); } @@ -217,107 +150,4 @@ public boolean equals(Object rhs) { public int hashCode() { return getClass().hashCode(); } - - private static final class LocalState { - private final String region; - - private final RulePartition partitionResult; - - private final String firstArn; - - private final RuleArn parsedArn; - - LocalState() { - this.region = null; - this.partitionResult = null; - this.firstArn = null; - this.parsedArn = null; - } - - LocalState(Region region) { - if (region != null) { - this.region = region.id(); - } else { - this.region = null; - } - this.partitionResult = null; - this.firstArn = null; - this.parsedArn = null; - } - - LocalState(LocalStateBuilder builder) { - this.region = builder.region; - this.partitionResult = builder.partitionResult; - this.firstArn = builder.firstArn; - this.parsedArn = builder.parsedArn; - } - - public String region() { - return this.region; - } - - public RulePartition partitionResult() { - return this.partitionResult; - } - - public String firstArn() { - return this.firstArn; - } - - public RuleArn parsedArn() { - return this.parsedArn; - } - - public LocalStateBuilder toBuilder() { - return new LocalStateBuilder(this); - } - } - - private static final class LocalStateBuilder { - private String region; - - private RulePartition partitionResult; - - private String firstArn; - - private RuleArn parsedArn; - - LocalStateBuilder() { - this.region = null; - this.partitionResult = null; - this.firstArn = null; - this.parsedArn = null; - } - - LocalStateBuilder(LocalState locals) { - this.region = locals.region; - this.partitionResult = locals.partitionResult; - this.firstArn = locals.firstArn; - this.parsedArn = locals.parsedArn; - } - - public LocalStateBuilder region(String value) { - this.region = value; - return this; - } - - public LocalStateBuilder partitionResult(RulePartition value) { - this.partitionResult = value; - return this; - } - - public LocalStateBuilder firstArn(String value) { - this.firstArn = value; - return this; - } - - public LocalStateBuilder parsedArn(RuleArn value) { - this.parsedArn = value; - return this; - } - - LocalState build() { - return new LocalState(this); - } - } }