Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/next-release/feature-AWSSDKforJavav2-4a7af00.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "feature",
"category": "AWS SDK for Java v2",
"contributor": "",
"description": "Add support for protocols field in service model"
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import software.amazon.awssdk.codegen.model.service.ServiceModel;
import software.amazon.awssdk.codegen.naming.DefaultNamingStrategy;
import software.amazon.awssdk.codegen.naming.NamingStrategy;
import software.amazon.awssdk.codegen.utils.ProtocolUtils;
import software.amazon.awssdk.utils.Pair;
import software.amazon.awssdk.utils.StringUtils;

Expand Down Expand Up @@ -70,7 +71,7 @@ public static Metadata constructMetadata(ServiceModel serviceModel,
.withBaseExceptionName(String.format(Constant.BASE_EXCEPTION_NAME_PATTERN, serviceName))
.withBaseRequestName(String.format(Constant.BASE_REQUEST_NAME_PATTERN, serviceName))
.withBaseResponseName(String.format(Constant.BASE_RESPONSE_NAME_PATTERN, serviceName))
.withProtocol(Protocol.fromValue(serviceMetadata.getProtocol()))
.withProtocol(Protocol.fromValue(ProtocolUtils.resolveProtocol(serviceMetadata)))
.withJsonVersion(serviceMetadata.getJsonVersion())
.withEndpointPrefix(serviceMetadata.getEndpointPrefix())
.withSigningName(serviceMetadata.getSigningName())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import software.amazon.awssdk.codegen.model.service.ServiceModel;
import software.amazon.awssdk.codegen.model.service.Shape;
import software.amazon.awssdk.codegen.naming.NamingStrategy;
import software.amazon.awssdk.codegen.utils.ProtocolUtils;

/**
* Constructs the operation model for every operation defined by the service.
Expand Down Expand Up @@ -164,7 +165,7 @@ public Map<String, OperationModel> constructOperations() {
OperationModel operationModel = new OperationModel();

operationModel.setOperationName(operationName);
operationModel.setServiceProtocol(serviceModel.getMetadata().getProtocol());
operationModel.setServiceProtocol(ProtocolUtils.resolveProtocol(serviceModel.getMetadata()));
operationModel.setDeprecated(op.isDeprecated());
operationModel.setDeprecatedMessage(op.getDeprecatedMessage());
operationModel.setDocumentation(op.getDocumentation());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import software.amazon.awssdk.codegen.model.service.ServiceModel;
import software.amazon.awssdk.codegen.model.service.Shape;
import software.amazon.awssdk.codegen.naming.NamingStrategy;
import software.amazon.awssdk.codegen.utils.ProtocolUtils;
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.awssdk.utils.Validate;

Expand Down Expand Up @@ -464,6 +465,6 @@ private void fillContainerTypeMemberMetadata(Map<String, Shape> c2jShapes,
}

protected String getProtocol() {
return getServiceModel().getMetadata().getProtocol();
return ProtocolUtils.resolveProtocol(getServiceModel().getMetadata());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import software.amazon.awssdk.codegen.model.service.Output;
import software.amazon.awssdk.codegen.model.service.ServiceModel;
import software.amazon.awssdk.codegen.model.service.Shape;
import software.amazon.awssdk.codegen.utils.ProtocolUtils;

/**
* Operations with explicit String payloads are not supported for services with Query protocol. We fail the codegen if the
Expand All @@ -31,7 +32,7 @@
public class ExplicitStringPayloadQueryProtocolProcessor implements CodegenCustomizationProcessor {
@Override
public void preprocess(ServiceModel serviceModel) {
String protocol = serviceModel.getMetadata().getProtocol();
String protocol = ProtocolUtils.resolveProtocol(serviceModel.getMetadata());
if (!"ec2".equals(protocol) && !"query".equals(protocol)) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import software.amazon.awssdk.codegen.model.service.Http;
import software.amazon.awssdk.codegen.model.service.Operation;
import software.amazon.awssdk.codegen.model.service.ServiceModel;
import software.amazon.awssdk.codegen.utils.ProtocolUtils;

/**
* This processor only runs for services using the <code>smithy-rpc-v2-cbor</code> protocol.
Expand All @@ -29,7 +30,8 @@
public class SmithyRpcV2CborProtocolProcessor implements CodegenCustomizationProcessor {
@Override
public void preprocess(ServiceModel serviceModel) {
if (!"smithy-rpc-v2-cbor".equals(serviceModel.getMetadata().getProtocol())) {
String protocol = ProtocolUtils.resolveProtocol(serviceModel.getMetadata());
if (!"smithy-rpc-v2-cbor".equals(protocol)) {
return;
}
serviceModel.getOperations().forEach((name, op) -> setRequestUri(serviceModel, name, op));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import software.amazon.awssdk.codegen.model.service.ServiceModel;
import software.amazon.awssdk.codegen.model.service.Shape;
import software.amazon.awssdk.codegen.model.service.XmlNamespace;
import software.amazon.awssdk.codegen.utils.ProtocolUtils;
import software.amazon.awssdk.utils.IoUtils;
import software.amazon.awssdk.utils.StringUtils;

Expand Down Expand Up @@ -331,11 +332,13 @@ public static ShapeMarshaller createInputShapeMarshaller(ServiceMetadata service
"The operation parameter must be specified!");
}

String protocol = ProtocolUtils.resolveProtocol(service);

ShapeMarshaller marshaller = new ShapeMarshaller()
.withAction(operation.getName())
.withVerb(operation.getHttp().getMethod())
.withRequestUri(operation.getHttp().getRequestUri())
.withProtocol(service.getProtocol());
.withProtocol(protocol);
Input input = operation.getInput();
if (input != null) {
marshaller.setLocationName(input.getLocationName());
Expand All @@ -345,7 +348,7 @@ public static ShapeMarshaller createInputShapeMarshaller(ServiceMetadata service
marshaller.setXmlNameSpaceUri(xmlNamespace.getUri());
}
}
if (Metadata.usesOperationIdentifier(service.getProtocol())) {
if (Metadata.usesOperationIdentifier(protocol)) {
marshaller.setTarget(StringUtils.isEmpty(service.getTargetPrefix()) ?
operation.getName() :
service.getTargetPrefix() + "." + operation.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.util.List;
import java.util.Map;
import software.amazon.awssdk.codegen.utils.ProtocolUtils;

public class ServiceMetadata {

Expand All @@ -36,6 +37,8 @@ public class ServiceMetadata {

private String protocol;

private List<String> protocols;

private String jsonVersion;

private Map<String, String> awsQueryCompatible;
Expand Down Expand Up @@ -103,6 +106,10 @@ public void setXmlNamespace(String xmlNamespace) {
this.xmlNamespace = xmlNamespace;
}

/**
* {@code protocol} superseded by {@code protocols} field, resolved in {@link ProtocolUtils#resolveProtocol(ServiceMetadata)}
*/
@Deprecated
public String getProtocol() {
return protocol;
}
Expand All @@ -111,6 +118,14 @@ public void setProtocol(String protocol) {
this.protocol = protocol;
}

public List<String> getProtocols() {
Comment thread
davidh44 marked this conversation as resolved.
return protocols;
}

public void setProtocols(List<String> protocols) {
this.protocols = protocols;
}

public String getJsonVersion() {
return jsonVersion;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* 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.utils;

import java.util.Arrays;
import java.util.List;
import software.amazon.awssdk.codegen.model.service.ServiceMetadata;

/**
* Resolves the protocol from the service model {@code protocol} and {@code protocols} fields.
*/
public final class ProtocolUtils {

/**
* Priority-ordered list of protocols supported by the SDK.
*/
private static final List<String> SUPPORTED_PROTOCOLS = Arrays.asList(
"smithy-rpc-v2-cbor", "json", "rest-json", "rest-xml", "query", "ec2");

private ProtocolUtils() {
}

/**
* {@code protocols} supersedes {@code protocol}. The highest priority protocol supported by the SDK that is present in the
* service model {@code protocols} list will be selected. If none of the values in {@code protocols} is supported by the
* SDK, an error will be thrown. If {@code protocols} is empty or null, the value from {@code protocol} will be returned.
*/
public static String resolveProtocol(ServiceMetadata serviceMetadata) {

List<String> protocols = serviceMetadata.getProtocols();
String protocol = serviceMetadata.getProtocol();

// Kinesis uses customization.config customServiceMetadata to set cbor
Comment thread
davidh44 marked this conversation as resolved.
Outdated
if ("cbor".equals(protocol) || protocols == null || protocols.isEmpty()) {
return protocol;
}

for (String supportedProtocol : SUPPORTED_PROTOCOLS) {
if (protocols.contains(supportedProtocol)) {
return supportedProtocol;
}
}

throw new IllegalArgumentException("The SDK does not support any of provided protocols: " + protocols);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* 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.utils;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
import org.junit.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import software.amazon.awssdk.codegen.model.service.ServiceMetadata;

public class ProtocolUtilsTest {

@ParameterizedTest
@MethodSource("protocolsValues")
public void protocolSelection(List<String> protocols, String expectedProtocol) {
ServiceMetadata serviceMetadata = serviceMetadata(protocols);
String selectedProtocol = ProtocolUtils.resolveProtocol(serviceMetadata);
assertThat(selectedProtocol).isEqualTo(expectedProtocol);
}

@Test
public void emptyProtocolsWithPresentProtocol() {
ServiceMetadata serviceMetadata = new ServiceMetadata();
serviceMetadata.setProtocol("json");
String selectedProtocol = ProtocolUtils.resolveProtocol(serviceMetadata);
assertThat(selectedProtocol).isEqualTo("json");
}

@Test
public void protocolsWithJson_protocolCbor_selectsJson() {
ServiceMetadata serviceMetadata = new ServiceMetadata();
serviceMetadata.setProtocols(Collections.singletonList("json"));
serviceMetadata.setProtocol("smithy-rpc-v2-cbor");
String selectedProtocol = ProtocolUtils.resolveProtocol(serviceMetadata);
assertThat(selectedProtocol).isEqualTo("json");
}

private static Stream<Arguments> protocolsValues() {
return Stream.of(Arguments.of(Arrays.asList("smithy-rpc-v2-cbor", "json"), "smithy-rpc-v2-cbor"),
Arguments.of(Collections.singletonList("smithy-rpc-v2-cbor"), "smithy-rpc-v2-cbor"),
Arguments.of(Arrays.asList("smithy-rpc-v2-cbor", "json", "query"), "smithy-rpc-v2-cbor"),
Arguments.of(Arrays.asList("json", "query"), "json"),
Arguments.of(Collections.singletonList("query"), "query"));
}

private static ServiceMetadata serviceMetadata(List<String> protocols) {
ServiceMetadata serviceMetadata = new ServiceMetadata();
serviceMetadata.setProtocols(protocols);
return serviceMetadata;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
"apiVersion":"2023-03-10",
"auth":["aws.auth#sigv4"],
"endpointPrefix":"smithyrpcv2protocol",
"protocol":"smithy-rpc-v2-cbor",
"protocols":["smithy-rpc-v2-cbor"],
"protocols":["smithy-rpc-v2-cbor", "json", "query"],
"serviceFullName":"RpcV2 Protocol Service",
"serviceId":"SmithyRpcV2Protocol",
"signatureVersion":"v4",
Expand Down
Loading