Skip to content
6 changes: 6 additions & 0 deletions .changes/next-release/feature-AWSSDKforJavav2-e1e404e.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": "Adding the version of the used service to the useragent"
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import software.amazon.awssdk.codegen.poet.client.EnvironmentTokenSystemSettingsClass;
import software.amazon.awssdk.codegen.poet.client.SdkClientOptions;
import software.amazon.awssdk.codegen.poet.client.specs.ServiceVersionInfoSpec;
import software.amazon.awssdk.codegen.poet.client.specs.ServiceVersionUserAgentSpec;
import software.amazon.awssdk.codegen.poet.common.UserAgentUtilsSpec;

public class CommonInternalGeneratorTasks extends BaseGeneratorTasks {
Expand All @@ -42,6 +43,7 @@ protected List<GeneratorTask> createTasks() throws Exception {
tasks.add(createEnvironmentTokenSystemSettingTask());
}
tasks.add(createServiceVersionInfoTask());
tasks.add(createServiceVersionUserAgentTask());
return tasks;
}

Expand All @@ -65,6 +67,11 @@ private GeneratorTask createServiceVersionInfoTask() {
new ServiceVersionInfoSpec(params.getModel()));
}

private GeneratorTask createServiceVersionUserAgentTask() {
return new PoetGeneratorTask(clientOptionsDir(), params.getModel().getFileHeader(),
new ServiceVersionUserAgentSpec(params.getModel()));
}

private String clientOptionsDir() {
return params.getPathProvider().getClientInternalDirectory();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ public ClassName getServiceVersionInfoClass() {
return ClassName.get(model.getMetadata().getFullClientInternalPackageName(), "ServiceVersionInfo");
}

public ClassName getServiceVersionUserAgentClass() {
return ClassName.get(model.getMetadata().getFullClientInternalPackageName(), "ServiceVersionUserAgent");
}

public ClassName getEnvironmentTokenSystemSettingsClass() {
return ClassName.get(model.getMetadata().getFullClientInternalPackageName(), "EnvironmentTokenSystemSettings");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,13 @@ private MethodSpec constructor(TypeSpec.Builder classBuilder) {
.addStatement("this.clientHandler = new $T(clientConfiguration)", AwsAsyncClientHandler.class)
.addStatement("this.clientConfiguration = clientConfiguration.toBuilder()"
+ ".option($T.SDK_CLIENT, this)"
+ ".build()", SdkClientOption.class);
+ ".option($T.API_METADATA, $T.USER_AGENT)"
+ ".build()",
SdkClientOption.class,
SdkClientOption.class,
ClassName.get(model.getMetadata().getFullClientInternalPackageName(),
"ServiceVersionUserAgent"));

FieldSpec protocolFactoryField = protocolSpec.protocolFactory(model);
if (model.getMetadata().isJsonProtocol()) {
builder.addStatement("this.$N = init($T.builder()).build()", protocolFactoryField.name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,12 @@ private MethodSpec constructor() {
.addStatement("this.clientHandler = new $T(clientConfiguration)", protocolSpec.getClientHandlerClass())
.addStatement("this.clientConfiguration = clientConfiguration.toBuilder()"
+ ".option($T.SDK_CLIENT, this)"
+ ".build()", SdkClientOption.class);
+ ".option($T.API_METADATA, $T.USER_AGENT)"
+ ".build()",
SdkClientOption.class,
SdkClientOption.class,
ClassName.get(model.getMetadata().getFullClientInternalPackageName(),
"ServiceVersionUserAgent"));

FieldSpec protocolFactoryField = protocolSpec.protocolFactory(model);
if (model.getMetadata().isJsonProtocol()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* 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.client.specs;

import static software.amazon.awssdk.core.util.VersionInfo.SDK_VERSION;

import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeSpec;
import javax.lang.model.element.Modifier;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.poet.ClassSpec;
import software.amazon.awssdk.codegen.poet.PoetExtension;
import software.amazon.awssdk.codegen.poet.PoetUtils;


public class ServiceVersionUserAgentSpec implements ClassSpec {
private final PoetExtension poetExtension;
private final IntermediateModel model;

public ServiceVersionUserAgentSpec(IntermediateModel model) {
this.poetExtension = new PoetExtension(model);
this.model = model;
}

@Override
public TypeSpec poetSpec() {
TypeSpec.Builder builder = TypeSpec.classBuilder("ServiceVersionUserAgent")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addAnnotation(PoetUtils.generatedAnnotation())
.addField(userAgentField())
.addMethod(privateConstructor());
return builder.build();
}

private String transformServiceId(String serviceId) {
// According to User Agent 2.0 spec, replace spaces with underscores
return serviceId.replace(" ", "_");
}

private FieldSpec userAgentField() {
return FieldSpec.builder(String.class, "USER_AGENT", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
.initializer("$S", transformServiceId(model.getMetadata().getServiceId()) + "#" + SDK_VERSION)
.addJavadoc("Returns a user agent containing the service and "
+ "version info")
.build();

}

protected MethodSpec privateConstructor() {
return MethodSpec.constructorBuilder()
.addModifiers(Modifier.PRIVATE)
.build();
}

@Override
public ClassName className() {
return poetExtension.getServiceVersionUserAgentClass();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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.client;

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

import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeSpec;
import java.io.InputStream;
import java.util.Scanner;
import org.junit.jupiter.api.Test;
import software.amazon.awssdk.codegen.poet.ClassSpec;
import software.amazon.awssdk.codegen.poet.ClientTestModels;
import software.amazon.awssdk.codegen.poet.client.specs.ServiceVersionUserAgentSpec;
import software.amazon.awssdk.core.util.VersionInfo;

public class ServiceVersionUserAgentSpecTest {

// Fixture test that compares generated ServiceVersionUserAgent class against expected output.
// The fixture file uses {{VERSION}} as a placeholder which gets replaced with the current
// SDK version at test time, since the generated code injects the actual version at build time.
@Test
void testServiceVersionUserAgentClass() {
String currVersion = VersionInfo.SDK_VERSION;
ClassSpec serviceVersionUserAgentSpec = new ServiceVersionUserAgentSpec(ClientTestModels.restJsonServiceModels());

String expectedContent = loadFixtureFile("test-service-version-user-agent-class.java");
expectedContent = expectedContent.replace("{{VERSION}}", currVersion);

String actualContent = generateContent(serviceVersionUserAgentSpec);

assertThat(actualContent).isEqualToIgnoringWhitespace(expectedContent);
}

private String loadFixtureFile(String filename) {
InputStream is = getClass().getResourceAsStream("specs/" + filename);
return new Scanner(is).useDelimiter("\\A").next();
}

private String generateContent(ClassSpec spec) {
TypeSpec typeSpec = spec.poetSpec();
JavaFile javaFile = JavaFile.builder(spec.className().packageName(), typeSpec).build();
return javaFile.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package software.amazon.awssdk.services.json.internal;

import java.lang.String;
import software.amazon.awssdk.annotations.Generated;

@Generated("software.amazon.awssdk:codegen")
public final class ServiceVersionUserAgent {
/**
* Returns a user agent containing the service and version info
*/
public static final String USER_AGENT = "Json_Service#{{VERSION}}";

private ServiceVersionUserAgent() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import software.amazon.awssdk.protocols.json.JsonOperationMetadata;
import software.amazon.awssdk.retries.api.RetryStrategy;
import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder;
import software.amazon.awssdk.services.json.internal.ServiceVersionUserAgent;
import software.amazon.awssdk.services.json.model.APostOperationRequest;
import software.amazon.awssdk.services.json.model.APostOperationResponse;
import software.amazon.awssdk.services.json.model.APostOperationWithOutputRequest;
Expand Down Expand Up @@ -140,7 +141,8 @@ final class DefaultJsonAsyncClient implements JsonAsyncClient {

protected DefaultJsonAsyncClient(SdkClientConfiguration clientConfiguration) {
this.clientHandler = new AwsAsyncClientHandler(clientConfiguration);
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this).build();
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this)
.option(SdkClientOption.API_METADATA, ServiceVersionUserAgent.USER_AGENT).build();
this.protocolFactory = init(AwsJsonProtocolFactory.builder()).build();
this.executor = clientConfiguration.option(SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import software.amazon.awssdk.protocols.json.JsonOperationMetadata;
import software.amazon.awssdk.retries.api.RetryStrategy;
import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder;
import software.amazon.awssdk.services.json.internal.ServiceVersionUserAgent;
import software.amazon.awssdk.services.json.model.APostOperationRequest;
import software.amazon.awssdk.services.json.model.APostOperationResponse;
import software.amazon.awssdk.services.json.model.APostOperationWithOutputRequest;
Expand Down Expand Up @@ -143,7 +144,8 @@ final class DefaultJsonAsyncClient implements JsonAsyncClient {

protected DefaultJsonAsyncClient(SdkClientConfiguration clientConfiguration) {
this.clientHandler = new AwsAsyncClientHandler(clientConfiguration);
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this).build();
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this)
.option(SdkClientOption.API_METADATA, ServiceVersionUserAgent.USER_AGENT).build();
this.protocolFactory = init(AwsCborProtocolFactory.builder()).build();
this.jsonProtocolFactory = init(AwsJsonProtocolFactory.builder()).build();
this.executor = clientConfiguration.option(SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import software.amazon.awssdk.retries.api.RetryStrategy;
import software.amazon.awssdk.services.json.batchmanager.JsonAsyncBatchManager;
import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder;
import software.amazon.awssdk.services.json.internal.ServiceVersionUserAgent;
import software.amazon.awssdk.services.json.model.APostOperationRequest;
import software.amazon.awssdk.services.json.model.APostOperationResponse;
import software.amazon.awssdk.services.json.model.APostOperationWithOutputRequest;
Expand Down Expand Up @@ -153,7 +154,8 @@ final class DefaultJsonAsyncClient implements JsonAsyncClient {

protected DefaultJsonAsyncClient(SdkClientConfiguration clientConfiguration) {
this.clientHandler = new AwsAsyncClientHandler(clientConfiguration);
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this).build();
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this)
.option(SdkClientOption.API_METADATA, ServiceVersionUserAgent.USER_AGENT).build();
this.protocolFactory = init(AwsJsonProtocolFactory.builder()).build();
this.executor = clientConfiguration.option(SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR);
this.executorService = clientConfiguration.option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import software.amazon.awssdk.protocols.json.JsonOperationMetadata;
import software.amazon.awssdk.retries.api.RetryStrategy;
import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder;
import software.amazon.awssdk.services.json.internal.ServiceVersionUserAgent;
import software.amazon.awssdk.services.json.model.APostOperationRequest;
import software.amazon.awssdk.services.json.model.APostOperationResponse;
import software.amazon.awssdk.services.json.model.APostOperationWithOutputRequest;
Expand Down Expand Up @@ -108,7 +109,8 @@ final class DefaultJsonClient implements JsonClient {

protected DefaultJsonClient(SdkClientConfiguration clientConfiguration) {
this.clientHandler = new AwsSyncClientHandler(clientConfiguration);
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this).build();
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this)
.option(SdkClientOption.API_METADATA, ServiceVersionUserAgent.USER_AGENT).build();
this.protocolFactory = init(AwsJsonProtocolFactory.builder()).build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import software.amazon.awssdk.protocols.query.AwsQueryProtocolFactory;
import software.amazon.awssdk.retries.api.RetryStrategy;
import software.amazon.awssdk.services.query.internal.QueryServiceClientConfigurationBuilder;
import software.amazon.awssdk.services.query.internal.ServiceVersionUserAgent;
import software.amazon.awssdk.services.query.model.APostOperationRequest;
import software.amazon.awssdk.services.query.model.APostOperationResponse;
import software.amazon.awssdk.services.query.model.APostOperationWithOutputRequest;
Expand Down Expand Up @@ -122,7 +123,8 @@ final class DefaultQueryAsyncClient implements QueryAsyncClient {

protected DefaultQueryAsyncClient(SdkClientConfiguration clientConfiguration) {
this.clientHandler = new AwsAsyncClientHandler(clientConfiguration);
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this).build();
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this)
.option(SdkClientOption.API_METADATA, ServiceVersionUserAgent.USER_AGENT).build();
this.protocolFactory = init();
this.executorService = clientConfiguration.option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import software.amazon.awssdk.protocols.query.AwsQueryProtocolFactory;
import software.amazon.awssdk.retries.api.RetryStrategy;
import software.amazon.awssdk.services.query.internal.QueryServiceClientConfigurationBuilder;
import software.amazon.awssdk.services.query.internal.ServiceVersionUserAgent;
import software.amazon.awssdk.services.query.model.APostOperationRequest;
import software.amazon.awssdk.services.query.model.APostOperationResponse;
import software.amazon.awssdk.services.query.model.APostOperationWithOutputRequest;
Expand Down Expand Up @@ -113,7 +114,8 @@ final class DefaultQueryClient implements QueryClient {

protected DefaultQueryClient(SdkClientConfiguration clientConfiguration) {
this.clientHandler = new AwsSyncClientHandler(clientConfiguration);
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this).build();
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this)
.option(SdkClientOption.API_METADATA, ServiceVersionUserAgent.USER_AGENT).build();
this.protocolFactory = init();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import software.amazon.awssdk.protocols.xml.AwsXmlProtocolFactory;
import software.amazon.awssdk.protocols.xml.XmlOperationMetadata;
import software.amazon.awssdk.retries.api.RetryStrategy;
import software.amazon.awssdk.services.xml.internal.ServiceVersionUserAgent;
import software.amazon.awssdk.services.xml.internal.XmlServiceClientConfigurationBuilder;
import software.amazon.awssdk.services.xml.model.APostOperationRequest;
import software.amazon.awssdk.services.xml.model.APostOperationResponse;
Expand Down Expand Up @@ -114,7 +115,8 @@ final class DefaultXmlAsyncClient implements XmlAsyncClient {

protected DefaultXmlAsyncClient(SdkClientConfiguration clientConfiguration) {
this.clientHandler = new AwsAsyncClientHandler(clientConfiguration);
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this).build();
this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this)
.option(SdkClientOption.API_METADATA, ServiceVersionUserAgent.USER_AGENT).build();
this.protocolFactory = init();
this.executor = clientConfiguration.option(SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR);
}
Expand Down
Loading
Loading