Skip to content

Commit 2f0cdc4

Browse files
authored
Merge pull request #760 from aws/shorea-marshaller-phase-two
AWS/Query and EC2 marshaller support.
2 parents aa98f76 + 985c7bf commit 2f0cdc4

File tree

345 files changed

+5523
-2229
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

345 files changed

+5523
-2229
lines changed

build-tools/src/main/resources/software/amazon/awssdk/spotbugs-suppressions.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@
2727
<Match>
2828
<Or>
2929
<!-- Container classes do not copy arrays for performance reasons at this time. -->
30-
<Class name="software.amazon.awssdk.core.protocol.json.JsonContent" />
30+
<Class name="software.amazon.awssdk.protocols.json.JsonContent" />
3131
</Or>
3232
<Bug pattern="EI_EXPOSE_REP,EI_EXPOSE_REP2" />
3333
</Match>
3434

3535
<!-- Delegate closes input stream. -->
3636
<Match>
37-
<Class name="software.amazon.awssdk.core.internal.protocol.json.IonFactory" />
37+
<Class name="software.amazon.awssdk.protocols.ion.internal.IonFactory" />
3838
<Method name="createParser" />
3939
<Bug pattern="OBL_UNSATISFIED_OBLIGATION" />
4040
</Match>
@@ -44,7 +44,7 @@
4444
<Match>
4545
<Or>
4646
<Class name="software.amazon.awssdk.services.dynamodb.datamodeling.DynamoDBMapper$BatchGetItemException"/>
47-
<Class name="software.amazon.awssdk.core.internal.protocol.json.IonFactory"/>
47+
<Class name="software.amazon.awssdk.protocols.ion.internal.IonFactory"/>
4848
</Or>
4949
<Bug pattern="SE_TRANSIENT_FIELD_NOT_RESTORED" />
5050
</Match>

buildspecs/on-demand-integ-test.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: 0.2
2+
3+
phases:
4+
build:
5+
commands:
6+
- mvn clean verify -Dskip.unit.tests -P integration-tests -Dfindbugs.skip -Dcheckstyle.skip -pl !:dynamodbmapper-v1 -Dfailsafe.rerunFailingTestsCount=1 -Dmaven.wagon.httpconnectionManager.maxPerRoute=2 --fail-at-end

codegen/pom.xml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,31 @@
110110
<groupId>org.reactivestreams</groupId>
111111
<artifactId>reactive-streams</artifactId>
112112
</dependency>
113+
<dependency>
114+
<groupId>software.amazon.awssdk</groupId>
115+
<artifactId>aws-json-protocol</artifactId>
116+
<version>${awsjavasdk.version}</version>
117+
</dependency>
118+
<dependency>
119+
<groupId>software.amazon.awssdk</groupId>
120+
<artifactId>aws-cbor-protocol</artifactId>
121+
<version>${awsjavasdk.version}</version>
122+
</dependency>
123+
<dependency>
124+
<groupId>software.amazon.awssdk</groupId>
125+
<artifactId>aws-ion-protocol</artifactId>
126+
<version>${awsjavasdk.version}</version>
127+
</dependency>
128+
<dependency>
129+
<groupId>software.amazon.awssdk</groupId>
130+
<artifactId>aws-query-protocol</artifactId>
131+
<version>${awsjavasdk.version}</version>
132+
</dependency>
133+
<dependency>
134+
<groupId>software.amazon.awssdk</groupId>
135+
<artifactId>protocol-core</artifactId>
136+
<version>${awsjavasdk.version}</version>
137+
</dependency>
113138

114139
<dependency>
115140
<artifactId>junit</artifactId>

codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -221,18 +221,22 @@ private ParameterHttpMapping generateParameterHttpMapping(Shape parentShape,
221221
ParameterHttpMapping mapping = new ParameterHttpMapping();
222222

223223
Shape memberShape = allC2jShapes.get(member.getShape());
224-
225224
mapping.withLocation(Location.forValue(member.getLocation()))
226-
.withPayload(member.isPayload()).withStreaming(member.isStreaming())
227-
.withFlattened(member.isFlattened() || memberShape.isFlattened())
228-
.withUnmarshallLocationName(deriveUnmarshallerLocationName(memberName, member))
229-
.withMarshallLocationName(
230-
deriveMarshallerLocationName(memberName, member, protocol))
231-
.withIsGreedy(isGreedy(parentShape, allC2jShapes, mapping));
225+
.withPayload(member.isPayload()).withStreaming(member.isStreaming())
226+
.withFlattened(isFlattened(member, memberShape))
227+
.withUnmarshallLocationName(deriveUnmarshallerLocationName(memberShape, memberName, member))
228+
.withMarshallLocationName(
229+
deriveMarshallerLocationName(memberShape, memberName, member, protocol))
230+
.withIsGreedy(isGreedy(parentShape, allC2jShapes, mapping));
232231

233232
return mapping;
234233
}
235234

235+
private boolean isFlattened(Member member, Shape memberShape) {
236+
return member.isFlattened()
237+
|| memberShape.isFlattened();
238+
}
239+
236240
/**
237241
* @param parentShape Shape containing the member in question.
238242
* @param allC2jShapes All shapes in the service model.
@@ -266,9 +270,14 @@ private String findRequestUri(Shape parentShape, Map<String, Shape> allC2jShapes
266270
.findFirst().orElseThrow(() -> new RuntimeException("Could not find request URI for input shape"));
267271
}
268272

269-
private String deriveUnmarshallerLocationName(String memberName, Member member) {
270-
271-
String locationName = member.getLocationName();
273+
private String deriveUnmarshallerLocationName(Shape memberShape, String memberName, Member member) {
274+
String locationName;
275+
if (memberShape.getListMember() != null && memberShape.isFlattened()) {
276+
locationName = memberShape.getListMember().getLocationName() == null ?
277+
member.getLocationName() : memberShape.getListMember().getLocationName();
278+
} else {
279+
locationName = member.getLocationName();
280+
}
272281

273282
if (locationName != null && !locationName.trim().isEmpty()) {
274283
return locationName;
@@ -277,12 +286,13 @@ private String deriveUnmarshallerLocationName(String memberName, Member member)
277286
return memberName;
278287
}
279288

280-
private String deriveMarshallerLocationName(String memberName, Member member, String protocol) {
289+
private String deriveMarshallerLocationName(Shape memberShape, String memberName, Member member, String protocol) {
281290
String queryName = member.getQueryName();
282291
if (queryName != null && !queryName.trim().isEmpty()) {
283292
return queryName;
284293
} else {
285-
String locationName = member.getLocationName();
294+
String locationName = memberShape.getListMember() != null && memberShape.isFlattened() && !protocol.equals("ec2") ?
295+
memberShape.getListMember().getLocationName() : member.getLocationName();
286296
if (locationName != null && !locationName.trim().isEmpty()) {
287297
if (protocol.equals(Protocol.EC2.getValue())) {
288298
return StringUtils.upperCase(locationName.substring(0, 1)) +

codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/MarshallerGeneratorTasks.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import software.amazon.awssdk.codegen.emitters.GeneratorTask;
2929
import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams;
3030
import software.amazon.awssdk.codegen.model.intermediate.Metadata;
31+
import software.amazon.awssdk.codegen.model.intermediate.Protocol;
3132
import software.amazon.awssdk.codegen.model.intermediate.ShapeModel;
3233
import software.amazon.awssdk.codegen.model.intermediate.ShapeType;
3334
import software.amazon.awssdk.codegen.poet.eventstream.EventStreamUtils;
@@ -68,8 +69,7 @@ private boolean shouldGenerate(ShapeModel shapeModel) {
6869
}
6970

7071
private Stream<GeneratorTask> createTask(String javaShapeName, ShapeModel shapeModel) throws Exception {
71-
if (metadata.isJsonProtocol()) {
72-
72+
if (metadata.isJsonProtocol() || metadata.getProtocol() == Protocol.QUERY || metadata.getProtocol() == Protocol.EC2) {
7373
return ShapeType.Request == shapeModel.getShapeType() ||
7474
(ShapeType.Model == shapeModel.getShapeType() && shapeModel.isEvent()
7575
&& EventStreamUtils.isRequestEvent(model, shapeModel))

codegen/src/main/java/software/amazon/awssdk/codegen/internal/Utils.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,10 @@ public static ShapeMarshaller createInputShapeMarshaller(ServiceMetadata service
314314
marshaller.setXmlNameSpaceUri(xmlNamespace.getUri());
315315
}
316316
}
317-
if (!StringUtils.isEmpty(service.getTargetPrefix()) && Metadata.isNotRestProtocol(service.getProtocol())) {
318-
marshaller.setTarget(service.getTargetPrefix() + "." + operation.getName());
317+
if (Metadata.isNotRestProtocol(service.getProtocol())) {
318+
marshaller.setTarget(StringUtils.isEmpty(service.getTargetPrefix()) ?
319+
operation.getName() :
320+
service.getTargetPrefix() + "." + operation.getName());
319321
}
320322
return marshaller;
321323

codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/MemberModel.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import java.util.Map;
2929
import software.amazon.awssdk.codegen.internal.TypeUtils;
3030
import software.amazon.awssdk.core.SdkBytes;
31-
import software.amazon.awssdk.core.protocol.SdkField;
3231
import software.amazon.awssdk.core.runtime.transform.PathMarshaller;
3332
import software.amazon.awssdk.utils.StringUtils;
3433

codegen/src/main/java/software/amazon/awssdk/codegen/naming/NamingStrategy.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import software.amazon.awssdk.codegen.model.intermediate.MemberModel;
1919
import software.amazon.awssdk.codegen.model.service.Shape;
20-
import software.amazon.awssdk.core.protocol.SdkField;
2120

2221
/**
2322
* Strategy to name various Java constructs based on the naming in the model and potentially customizations.

codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler;
4242
import software.amazon.awssdk.awscore.eventstream.EventStreamTaggedUnionJsonMarshaller;
4343
import software.amazon.awssdk.awscore.internal.client.handler.AwsClientHandlerUtils;
44-
import software.amazon.awssdk.awscore.protocol.json.AwsJsonProtocolFactory;
4544
import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams;
4645
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
4746
import software.amazon.awssdk.codegen.model.intermediate.MemberModel;
@@ -56,6 +55,7 @@
5655
import software.amazon.awssdk.core.client.config.SdkAdvancedAsyncClientOption;
5756
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
5857
import software.amazon.awssdk.core.client.handler.AsyncClientHandler;
58+
import software.amazon.awssdk.protocols.json.AwsJsonProtocolFactory;
5959
import software.amazon.awssdk.utils.CompletableFutureUtils;
6060
import software.amazon.awssdk.utils.FunctionalUtils;
6161

@@ -70,7 +70,7 @@ public AsyncClientClass(GeneratorTaskParams dependencies) {
7070
this.model = dependencies.getModel();
7171
this.poetExtensions = dependencies.getPoetExtensions();
7272
this.className = poetExtensions.getClientClass(model.getMetadata().getAsyncClient());
73-
this.protocolSpec = getProtocolSpecs(poetExtensions, model.getMetadata().getProtocol());
73+
this.protocolSpec = getProtocolSpecs(poetExtensions, model);
7474
}
7575

7676
@Override
@@ -94,6 +94,7 @@ public TypeSpec poetSpec() {
9494
.addMethods(operations())
9595
.addMethod(closeMethod())
9696
.addMethods(protocolSpec.additionalMethods())
97+
.addFields(protocolSpec.additionalFields())
9798
.addMethod(protocolSpec.initProtocolFactory(model));
9899

99100
// Kinesis doesn't support CBOR for STS yet so need another protocol factory for JSON
@@ -120,14 +121,15 @@ private MethodSpec constructor(Builder classBuilder) {
120121
.addParameter(SdkClientConfiguration.class, "clientConfiguration")
121122
.addStatement("this.clientHandler = new $T(clientConfiguration)",
122123
AwsAsyncClientHandler.class);
124+
FieldSpec protocolFactoryField = protocolSpec.protocolFactory(model);
123125
if (model.getMetadata().isJsonProtocol()) {
124-
builder.addStatement("this.$N = init($L)", protocolSpec.protocolFactory(model).name,
125-
model.getMetadata().isCborProtocol());
126+
builder.addStatement("this.$N = init($T.builder()).build()", protocolFactoryField.name,
127+
protocolFactoryField.type);
126128
} else {
127-
builder.addStatement("this.$N = init()", protocolSpec.protocolFactory(model).name);
129+
builder.addStatement("this.$N = init()", protocolFactoryField.name);
128130
}
129131
if (model.getMetadata().isCborProtocol()) {
130-
builder.addStatement("this.jsonProtocolFactory = init(false)");
132+
builder.addStatement("this.jsonProtocolFactory = init($T.builder()).build()", AwsJsonProtocolFactory.class);
131133
}
132134
if (hasOperationWithEventStreamOutput()) {
133135
classBuilder.addField(FieldSpec.builder(ClassName.get(Executor.class), "executor",

codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.getCustomResponseHandler;
2323

2424
import com.squareup.javapoet.ClassName;
25+
import com.squareup.javapoet.FieldSpec;
2526
import com.squareup.javapoet.MethodSpec;
2627
import com.squareup.javapoet.TypeSpec;
2728
import com.squareup.javapoet.TypeSpec.Builder;
@@ -42,6 +43,7 @@
4243
import software.amazon.awssdk.codegen.poet.client.specs.JsonProtocolSpec;
4344
import software.amazon.awssdk.codegen.poet.client.specs.ProtocolSpec;
4445
import software.amazon.awssdk.codegen.poet.client.specs.QueryXmlProtocolSpec;
46+
import software.amazon.awssdk.codegen.poet.client.specs.XmlProtocolSpec;
4547
import software.amazon.awssdk.codegen.utils.PaginatorUtils;
4648
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
4749
import software.amazon.awssdk.core.client.handler.SyncClientHandler;
@@ -58,7 +60,7 @@ public SyncClientClass(GeneratorTaskParams taskParams) {
5860
this.model = taskParams.getModel();
5961
this.poetExtensions = taskParams.getPoetExtensions();
6062
this.className = poetExtensions.getClientClass(model.getMetadata().getSyncClient());
61-
this.protocolSpec = getProtocolSpecs(poetExtensions, model.getMetadata().getProtocol());
63+
this.protocolSpec = getProtocolSpecs(poetExtensions, model);
6264
}
6365

6466
@Override
@@ -76,6 +78,8 @@ public TypeSpec poetSpec() {
7678
.addField(SdkClientConfiguration.class, "clientConfiguration", PRIVATE, FINAL)
7779
.addMethod(constructor())
7880
.addMethod(nameMethod())
81+
.addFields(protocolSpec.additionalFields())
82+
.addMethods(protocolSpec.additionalMethods())
7983
.addMethods(operations());
8084

8185
protocolSpec.createErrorResponseHandler().ifPresent(classBuilder::addMethod);
@@ -116,11 +120,12 @@ private MethodSpec constructor() {
116120
.addStatement("this.clientHandler = new $T(clientConfiguration)",
117121
protocolSpec.getClientHandlerClass())
118122
.addStatement("this.clientConfiguration = clientConfiguration");
123+
FieldSpec protocolFactoryField = protocolSpec.protocolFactory(model);
119124
if (model.getMetadata().isJsonProtocol()) {
120-
builder.addStatement("this.$N = init($L)", protocolSpec.protocolFactory(model).name,
121-
model.getMetadata().isCborProtocol());
125+
builder.addStatement("this.$N = init($T.builder()).build()", protocolFactoryField.name,
126+
protocolFactoryField.type);
122127
} else {
123-
builder.addStatement("this.$N = init()", protocolSpec.protocolFactory(model).name);
128+
builder.addStatement("this.$N = init()", protocolFactoryField.name);
124129
}
125130
return builder.build();
126131
}
@@ -182,18 +187,20 @@ private MethodSpec closeMethod() {
182187
.build();
183188
}
184189

185-
static ProtocolSpec getProtocolSpecs(PoetExtensions poetExtensions, Protocol protocol) {
190+
static ProtocolSpec getProtocolSpecs(PoetExtensions poetExtensions, IntermediateModel model) {
191+
Protocol protocol = model.getMetadata().getProtocol();
186192
switch (protocol) {
187193
case QUERY:
188-
case REST_XML:
189194
return new QueryXmlProtocolSpec(poetExtensions);
195+
case REST_XML:
196+
return new XmlProtocolSpec(poetExtensions);
190197
case EC2:
191198
return new Ec2ProtocolSpec(poetExtensions);
192199
case AWS_JSON:
193200
case REST_JSON:
194201
case CBOR:
195202
case ION:
196-
return new JsonProtocolSpec(poetExtensions);
203+
return new JsonProtocolSpec(poetExtensions, model);
197204
case API_GATEWAY:
198205
throw new UnsupportedOperationException("Not yet supported.");
199206
default:

codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/Ec2ProtocolSpec.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.ArrayList;
2020
import java.util.List;
2121
import software.amazon.awssdk.codegen.poet.PoetExtensions;
22+
import software.amazon.awssdk.protocols.query.AwsEc2ProtocolFactory;
2223

2324
public class Ec2ProtocolSpec extends QueryXmlProtocolSpec {
2425

@@ -36,6 +37,11 @@ public List<MethodSpec> additionalMethods() {
3637
return additionalMethods;
3738
}
3839

40+
@Override
41+
protected Class<?> protocolFactoryClass() {
42+
return AwsEc2ProtocolFactory.class;
43+
}
44+
3945
/*
4046
private MethodSpec dryRunMethod() {
4147
TypeVariableName typeVariableName = TypeVariableName.get("X", AmazonWebServiceRequest.class);

0 commit comments

Comments
 (0)