diff --git a/.all-contributorsrc b/.all-contributorsrc
index 35f26df90327..21353af60c47 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -1057,6 +1057,24 @@
"contributions": [
"code"
]
+ },
+ {
+ "login": "jencymaryjoseph",
+ "name": "Jency Joseph",
+ "avatar_url": "https://avatars.githubusercontent.com/u/35571282?v=4",
+ "profile": "https://github.com/jencymaryjoseph",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "reifiedbeans",
+ "name": "Drew Davis",
+ "avatar_url": "https://avatars.githubusercontent.com/u/9686215?v=4",
+ "profile": "https://github.com/reifiedbeans",
+ "contributions": [
+ "code"
+ ]
}
],
"contributorsPerLine": 7,
diff --git a/.changes/2.31.40.json b/.changes/2.31.40.json
new file mode 100644
index 000000000000..a2e10f51333c
--- /dev/null
+++ b/.changes/2.31.40.json
@@ -0,0 +1,36 @@
+{
+ "version": "2.31.40",
+ "date": "2025-05-09",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "Amazon Athena",
+ "contributor": "",
+ "description": "Minor API documentation updates"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon CloudWatch Logs",
+ "contributor": "",
+ "description": "We are pleased to announce limit increases to our grok processor logs transformation feature. Now you can define 20 Grok patterns in their configurations, with an expanded total pattern matching limit of 512 characters."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon WorkSpaces",
+ "contributor": "",
+ "description": "Remove parameter EnableWorkDocs from WorkSpacesServiceModel due to end of support of Amazon WorkDocs service."
+ },
+ {
+ "type": "feature",
+ "category": "Synthetics",
+ "contributor": "",
+ "description": "Add support to retry a canary automatically after schedule run failures. Users can enable this feature by configuring the RetryConfig field when calling the CreateCanary or UpdateCanary API. Also includes changes in GetCanary and GetCanaryRuns to support retrieving retry configurations."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.41.json b/.changes/2.31.41.json
new file mode 100644
index 000000000000..730e4a664c41
--- /dev/null
+++ b/.changes/2.31.41.json
@@ -0,0 +1,66 @@
+{
+ "version": "2.31.41",
+ "date": "2025-05-12",
+ "entries": [
+ {
+ "type": "bugfix",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Add `@Mutable` and `@NotThreadSafe` to model Builders"
+ },
+ {
+ "type": "feature",
+ "category": "AWSDeadlineCloud",
+ "contributor": "",
+ "description": "AWS Deadline Cloud service-managed fleets now support configuration scripts. Configuration scripts make it easy to install additional software, like plugins and packages, onto a worker."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Elemental MediaLive",
+ "contributor": "",
+ "description": "Add support to the AV1 rate control mode"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Identity and Access Management",
+ "contributor": "",
+ "description": "Updating the endpoint list for the Identity and access management (IAM) service"
+ },
+ {
+ "type": "feature",
+ "category": "AWS MediaTailor",
+ "contributor": "",
+ "description": "Documenting that EnabledLoggingStrategies is always present in responses of PlaybackConfiguration read operations."
+ },
+ {
+ "type": "feature",
+ "category": "AWS S3 Control",
+ "contributor": "",
+ "description": "Updates to support S3 Express zonal endpoints for directory buckets in AWS CLI"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Supply Chain",
+ "contributor": "",
+ "description": "Launch new AWS Supply Chain public APIs for DataIntegrationEvent, DataIntegrationFlowExecution and DatasetNamespace. Also add more capabilities to existing public APIs to support direct dataset event publish, data deduplication in DataIntegrationFlow, partition specification of custom datasets."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Compute Cloud",
+ "contributor": "",
+ "description": "EC2 - Adding support for AvailabilityZoneId"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon SageMaker Service",
+ "contributor": "",
+ "description": "No API changes from previous release. This release migrated the model to Smithy keeping all features unchanged."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.42.json b/.changes/2.31.42.json
new file mode 100644
index 000000000000..d80760740fca
--- /dev/null
+++ b/.changes/2.31.42.json
@@ -0,0 +1,42 @@
+{
+ "version": "2.31.42",
+ "date": "2025-05-13",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS Control Tower",
+ "contributor": "",
+ "description": "AWS Control Tower now reports the inheritance drift status for EnabledBaselines through the GetEnabledBaseline and ListEnabledBaselines APIs. You can now filter EnabledBaselines by their enablement and drift status using the ListEnabledBaselines API to view accounts and OUs that require attention."
+ },
+ {
+ "type": "feature",
+ "category": "AWS License Manager",
+ "contributor": "",
+ "description": "Add Tagging feature to resources in the Managed Entitlements service. License and Grant resources can now be tagged."
+ },
+ {
+ "type": "feature",
+ "category": "Agents for Amazon Bedrock Runtime",
+ "contributor": "",
+ "description": "Changes for enhanced metadata in trace"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Aurora DSQL",
+ "contributor": "",
+ "description": "CreateMultiRegionClusters and DeleteMultiRegionClusters APIs marked as deprecated. Introduced new multi-Region clusters creation experience through multiRegionProperties parameter in CreateCluster API."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Bedrock",
+ "contributor": "",
+ "description": "Enable cross-Region inference for Amazon Bedrock Guardrails by using the crossRegionConfig parameter when calling the CreateGuardrail or UpdateGuardrail operation."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon EC2 Container Service",
+ "contributor": "",
+ "description": "This release extends functionality for Amazon EBS volumes attached to Amazon ECS tasks by adding support for the new EBS volumeInitializationRate parameter in ECS RunTask/StartTask/CreateService/UpdateService APIs."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.43.json b/.changes/2.31.43.json
new file mode 100644
index 000000000000..79c512337aad
--- /dev/null
+++ b/.changes/2.31.43.json
@@ -0,0 +1,30 @@
+{
+ "version": "2.31.43",
+ "date": "2025-05-14",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS Elemental MediaConvert",
+ "contributor": "",
+ "description": "This update enables cropping for video overlays and adds a new STL to Teletext upconversion toggle to preserve styling."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon CloudWatch Logs",
+ "contributor": "",
+ "description": "This release adds a new API \"ListLogGroups\" and an improvement in API \"DescribeLogGroups\""
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Cognito Identity Provider",
+ "contributor": "",
+ "description": "Add exceptions to WebAuthn operations."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Kinesis Firehose",
+ "contributor": "",
+ "description": "This release adds catalogARN support for s3 tables multi-catalog catalogARNs."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.44.json b/.changes/2.31.44.json
new file mode 100644
index 000000000000..ae8bd0a04f12
--- /dev/null
+++ b/.changes/2.31.44.json
@@ -0,0 +1,48 @@
+{
+ "version": "2.31.44",
+ "date": "2025-05-15",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS CodeBuild",
+ "contributor": "",
+ "description": "AWS CodeBuild now supports Docker Server capability"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Control Tower",
+ "contributor": "",
+ "description": "Updated the descriptions for the AWS Control Tower Baseline APIs to make them more intuitive."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Database Migration Service",
+ "contributor": "",
+ "description": "Introduces Data Resync feature to describe-table-statistics and IAM database authentication for MariaDB, MySQL, and PostgreSQL."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Parallel Computing Service",
+ "contributor": "",
+ "description": "This release adds support for Slurm accounting. For more information, see the Slurm accounting topic in the AWS PCS User Guide. Slurm accounting is supported for Slurm 24.11 and later. This release also adds 24.11 as a valid value for the version parameter of the Scheduler data type."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Small optimization for endpoint rules. Lazily compile the region pattern instead of parsing it every time. This will pay the penalty of parsing it just once at the cost of using a bit more of memory to keep the parsed pattern."
+ },
+ {
+ "type": "feature",
+ "category": "Agents for Amazon Bedrock",
+ "contributor": "",
+ "description": "Amazon Bedrock Flows introduces DoWhile loops nodes, parallel node executions, and enhancements to knowledge base nodes."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon WorkSpaces",
+ "contributor": "",
+ "description": "Added the new AlwaysOn running mode for WorkSpaces Pools. Customers can now choose between AlwaysOn (for instant access, with hourly usage billing regardless of connection status), or AutoStop (to optimize cost, with a brief startup delay) for their pools."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.45.json b/.changes/2.31.45.json
new file mode 100644
index 000000000000..e50da33569f9
--- /dev/null
+++ b/.changes/2.31.45.json
@@ -0,0 +1,66 @@
+{
+ "version": "2.31.45",
+ "date": "2025-05-16",
+ "entries": [
+ {
+ "type": "bugfix",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Fix a regression for the JSON REST protocol for which an structure explicit payload member was set to the empty object instead of null"
+ },
+ {
+ "type": "feature",
+ "category": "AWS CodePipeline",
+ "contributor": "",
+ "description": "CodePipeline now supports new API ListDeployActionExecutionTargets that lists the deployment target details for deploy action executions."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Glue",
+ "contributor": "",
+ "description": "Changes include (1) Excel as S3 Source type and XML and Tableau's Hyper as S3 Sink types, (2) targeted number of partitions parameter in S3 sinks and (3) new compression types in CSV/JSON and Parquet S3 sinks."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon EC2 Container Service",
+ "contributor": "",
+ "description": "This is an Amazon ECs documentation only release to support the change of the container exit \"reason\" field from 255 characters to 1024 characters."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon EMR",
+ "contributor": "",
+ "description": "Added APIs for managing Application UIs: Access Persistent (serverless) UIs via CreatePersistentAppUI DescribePersistentAppUI & GetPersistentAppUIPresignedURL, and Cluster-based UIs through GetOnClusterAppUIPresignedURL. Supports Yarn, Spark History, and TEZ interfaces."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Neptune",
+ "contributor": "",
+ "description": "This release adds Global Cluster Switchover capability which enables you to change your global cluster's primary AWS Region, the region that serves writes, while preserving the replication between all regions in the global cluster."
+ },
+ {
+ "type": "feature",
+ "category": "Data Automation for Amazon Bedrock",
+ "contributor": "",
+ "description": "Add support for VIDEO modality to BlueprintType enum."
+ },
+ {
+ "type": "feature",
+ "category": "Runtime for Amazon Bedrock Data Automation",
+ "contributor": "",
+ "description": "Add AssetProcessingConfiguration for video segment to InputConfiguration"
+ },
+ {
+ "type": "feature",
+ "category": "Service Quotas",
+ "contributor": "",
+ "description": "This release introduces CreateSupportCase operation to SDK."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.46.json b/.changes/2.31.46.json
new file mode 100644
index 000000000000..ee1c6a4e5234
--- /dev/null
+++ b/.changes/2.31.46.json
@@ -0,0 +1,30 @@
+{
+ "version": "2.31.46",
+ "date": "2025-05-19",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS Elemental MediaPackage v2",
+ "contributor": "",
+ "description": "This release adds support for DVB-DASH, EBU-TT-D subtitle format, and non-compacted manifests for DASH in MediaPackage v2 Origin Endpoints."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Aurora DSQL",
+ "contributor": "",
+ "description": "CreateMultiRegionCluster and DeleteMultiRegionCluster APIs removed"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Compute Cloud",
+ "contributor": "",
+ "description": "This release includes new APIs for System Integrity Protection (SIP) configuration and automated root volume ownership delegation for EC2 Mac instances."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.47.json b/.changes/2.31.47.json
new file mode 100644
index 000000000000..8594a937b1f1
--- /dev/null
+++ b/.changes/2.31.47.json
@@ -0,0 +1,48 @@
+{
+ "version": "2.31.47",
+ "date": "2025-05-20",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS DataSync",
+ "contributor": "",
+ "description": "Remove Discovery APIs from the DataSync service"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Glue",
+ "contributor": "",
+ "description": "Enhanced AWS Glue ListConnectionTypes API Model with additional metadata fields."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Compute Cloud",
+ "contributor": "",
+ "description": "This release expands the ModifyInstanceMaintenanceOptions API to enable or disable instance migration during customer-initiated reboots for EC2 Scheduled Reboot Events."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Relational Database Service",
+ "contributor": "",
+ "description": "This release introduces the new DescribeDBMajorEngineVersions API for describing the properties of specific major versions of database engines."
+ },
+ {
+ "type": "feature",
+ "category": "CloudWatch Observability Access Manager",
+ "contributor": "",
+ "description": "Add IncludeTags field to GetLink, GetSink and UpdateLink API"
+ },
+ {
+ "type": "feature",
+ "category": "Inspector2",
+ "contributor": "",
+ "description": "This release adds GetClustersForImage API and filter updates as part of the mapping of container images to running containers feature."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.48.json b/.changes/2.31.48.json
new file mode 100644
index 000000000000..30eedc8e6013
--- /dev/null
+++ b/.changes/2.31.48.json
@@ -0,0 +1,42 @@
+{
+ "version": "2.31.48",
+ "date": "2025-05-21",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "Agents for Amazon Bedrock Runtime",
+ "contributor": "",
+ "description": "Amazon Bedrock introduces asynchronous flows (in preview), which let you run flows for longer durations and yield control so that your application can perform other tasks and you don't have to actively monitor the flow's progress."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon CloudWatch",
+ "contributor": "",
+ "description": "Adds support for setting up Contributor Insight rules on logs transformed via Logs Transformation feature."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Compute Cloud",
+ "contributor": "",
+ "description": "Release of Dualstack and Ipv6-only EC2 Public DNS hostnames"
+ },
+ {
+ "type": "feature",
+ "category": "Application Auto Scaling",
+ "contributor": "",
+ "description": "Doc only update that addresses a customer reported issue."
+ },
+ {
+ "type": "feature",
+ "category": "Partner Central Selling API",
+ "contributor": "",
+ "description": "Modified validation to allow expectedCustomerSpend array with zero elements in Partner Opportunity operations."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.49.json b/.changes/2.31.49.json
new file mode 100644
index 000000000000..20f0ba284e05
--- /dev/null
+++ b/.changes/2.31.49.json
@@ -0,0 +1,36 @@
+{
+ "version": "2.31.49",
+ "date": "2025-05-22",
+ "entries": [
+ {
+ "type": "bugfix",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Update non-streaming error unmarshalling to properly unmarshall exceptions to their expected types."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Audit Manager",
+ "contributor": "",
+ "description": "With this release, the AssessmentControl description field has been deprecated, as of May 19, 2025. Additionally, the UpdateAssessment API can now return a ServiceQuotaExceededException when applicable service quotas are exceeded."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Glue",
+ "contributor": "",
+ "description": "This release supports additional ConversionSpec parameter as part of IntegrationPartition Structure in CreateIntegrationTableProperty API. This parameter is referred to apply appropriate column transformation for columns that are used for timestamp based partitioning"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Aurora DSQL",
+ "contributor": "",
+ "description": "Features: support for customer managed encryption keys"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Prometheus Service",
+ "contributor": "",
+ "description": "Add QueryLoggingConfiguration APIs for Amazon Managed Prometheus"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.50.json b/.changes/2.31.50.json
new file mode 100644
index 000000000000..543efe927680
--- /dev/null
+++ b/.changes/2.31.50.json
@@ -0,0 +1,36 @@
+{
+ "version": "2.31.50",
+ "date": "2025-05-23",
+ "entries": [
+ {
+ "type": "bugfix",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Fix CompletableFuture hanging when RetryStrategy/MetricsCollector raise errors"
+ },
+ {
+ "type": "bugfix",
+ "category": "Netty NIO HTTP Client",
+ "contributor": "",
+ "description": "Enable Netty HTTP header validation when connecting with proxy"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Compute Cloud",
+ "contributor": "",
+ "description": "This release adds support for the C7i-flex, M7i-flex, I7i, I7ie, I8g, P6-b200, Trn2, C8gd, M8gd and R8gd instances"
+ },
+ {
+ "type": "feature",
+ "category": "Security Incident Response",
+ "contributor": "",
+ "description": "Update PrincipalId pattern documentation to reflect what user should receive back from the API call"
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.51.json b/.changes/2.31.51.json
new file mode 100644
index 000000000000..643c131efbcb
--- /dev/null
+++ b/.changes/2.31.51.json
@@ -0,0 +1,24 @@
+{
+ "version": "2.31.51",
+ "date": "2025-05-27",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS Cost Explorer Service",
+ "contributor": "",
+ "description": "This release introduces Cost Comparison feature (GetCostAndUsageComparisons, GetCostComparisonDrivers) allowing you find cost variations across multiple dimensions and identify key drivers of spending changes."
+ },
+ {
+ "type": "feature",
+ "category": "AWSDeadlineCloud",
+ "contributor": "",
+ "description": "AWS Deadline Cloud service-managed fleets now support storage profiles. With storage profiles, you can map file paths between a workstation and the worker hosts running the job."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Compute Cloud",
+ "contributor": "",
+ "description": "This release adds three features - option to store AWS Site-to-Site VPN pre-shared keys in AWS Secrets Manager, GetActiveVpnTunnelStatus API to check the in-use VPN algorithms, and SampleType option in GetVpnConnectionDeviceSampleConfiguration API to get recommended sample configs for VPN devices."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.52.json b/.changes/2.31.52.json
new file mode 100644
index 000000000000..a2a40faf30d8
--- /dev/null
+++ b/.changes/2.31.52.json
@@ -0,0 +1,42 @@
+{
+ "version": "2.31.52",
+ "date": "2025-05-28",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS Network Firewall",
+ "contributor": "",
+ "description": "You can now use VPC endpoint associations to create multiple firewall endpoints for a single firewall."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Compute Cloud",
+ "contributor": "",
+ "description": "Enable the option to automatically delete underlying Amazon EBS snapshots when deregistering Amazon Machine Images (AMIs)"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon EventBridge",
+ "contributor": "",
+ "description": "Allow for more than 2 characters for location codes in EventBridge ARNs"
+ },
+ {
+ "type": "feature",
+ "category": "Cost Optimization Hub",
+ "contributor": "",
+ "description": "This release allows customers to modify their preferred commitment term and payment options."
+ },
+ {
+ "type": "feature",
+ "category": "Synthetics",
+ "contributor": "",
+ "description": "Add support to change ephemeral storage. Add a new field \"TestResult\" under CanaryRunStatus."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.53.json b/.changes/2.31.53.json
new file mode 100644
index 000000000000..2086c9b4320a
--- /dev/null
+++ b/.changes/2.31.53.json
@@ -0,0 +1,78 @@
+{
+ "version": "2.31.53",
+ "date": "2025-05-29",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS Amplify",
+ "contributor": "",
+ "description": "Add support for customizable build instance sizes. CreateApp and UpdateApp operations now accept a new JobConfig parameter composed of BuildComputeType."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Billing and Cost Management Pricing Calculator",
+ "contributor": "",
+ "description": "Add AFTER_DISCOUNTS_AND_COMMITMENTS to Workload Estimate Rate Type. Set ListWorkLoadEstimateUsage maxResults range to minimum of 0 and maximum of 300."
+ },
+ {
+ "type": "feature",
+ "category": "AWS CloudTrail",
+ "contributor": "",
+ "description": "CloudTrail Feature Release: Support for Enriched Events with Configurable Context for Event Data Store"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Data Exchange",
+ "contributor": "",
+ "description": "This release adds Tag support for Event Action resource, through which customers can create event actions with Tags and retrieve event actions with Tags."
+ },
+ {
+ "type": "feature",
+ "category": "AWS DataSync",
+ "contributor": "",
+ "description": "AgentArns field is made optional for Object Storage and Azure Blob location create requests. Location credentials are now managed via Secrets Manager, and may be encrypted with service managed or customer managed keys. Authentication is now optional for Azure Blob locations."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Connect Service",
+ "contributor": "",
+ "description": "Amazon Connect Service Feature: Email Recipient Limit Increase"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon FSx",
+ "contributor": "",
+ "description": "FSx API changes to support the public launch of new Intelligent Tiering storage class on Amazon FSx for Lustre"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Interactive Video Service RealTime",
+ "contributor": "",
+ "description": "IVS Real-Time now offers customers the participant replication that allow customers to copy a participant from one stage to another."
+ },
+ {
+ "type": "feature",
+ "category": "AmazonMWAA",
+ "contributor": "",
+ "description": "Amazon MWAA now lets you choose a worker replacement strategy when updating an environment. This release adds two worker replacement strategies: FORCED (default), which stops workers immediately, and GRACEFUL, which allows workers to finish current tasks before shutting down."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon SageMaker Service",
+ "contributor": "",
+ "description": "Add maintenance status field to DescribeMlflowTrackingServer API response"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Simple Storage Service",
+ "contributor": "",
+ "description": "Adding checksum support for S3 PutBucketOwnershipControls API."
+ },
+ {
+ "type": "feature",
+ "category": "Auto Scaling",
+ "contributor": "",
+ "description": "Add support for \"apple\" CpuManufacturer in ABIS"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.54.json b/.changes/2.31.54.json
new file mode 100644
index 000000000000..e2adfa5957b7
--- /dev/null
+++ b/.changes/2.31.54.json
@@ -0,0 +1,24 @@
+{
+ "version": "2.31.54",
+ "date": "2025-05-30",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "Amazon SageMaker Service",
+ "contributor": "",
+ "description": "Release new parameter CapacityReservationConfig in ProductionVariant"
+ },
+ {
+ "type": "feature",
+ "category": "EMR Serverless",
+ "contributor": "",
+ "description": "This release adds the capability for users to specify an optional Execution IAM policy in the StartJobRun action. The resulting permissions assumed by the job run is the intersection of the permissions in the Execution Role and the specified Execution IAM Policy."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.55.json b/.changes/2.31.55.json
new file mode 100644
index 000000000000..6fd8f18cb2cf
--- /dev/null
+++ b/.changes/2.31.55.json
@@ -0,0 +1,78 @@
+{
+ "version": "2.31.55",
+ "date": "2025-06-02",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS Backup",
+ "contributor": "",
+ "description": "You can now subscribe to Amazon SNS notifications and Amazon EventBridge events for backup indexing. You can now receive notifications when a backup index is created, deleted, or fails to create, enhancing your ability to monitor and track your backup operations."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Compute Optimizer",
+ "contributor": "",
+ "description": "This release enables AWS Compute Optimizer to analyze Amazon Aurora database clusters and generate Aurora I/O-Optimized recommendations."
+ },
+ {
+ "type": "feature",
+ "category": "AWS EntityResolution",
+ "contributor": "",
+ "description": "Add support for generating match IDs in near real-time."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Parallel Computing Service",
+ "contributor": "",
+ "description": "Introduces SUSPENDING and SUSPENDED states for clusters, compute node groups, and queues."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Improve the endpoint rules performance by directly passing the needed params instead of using a POJO to keep track of them."
+ },
+ {
+ "type": "feature",
+ "category": "Agents for Amazon Bedrock",
+ "contributor": "",
+ "description": "This release adds the Agent Lifecycle Paused State feature to Amazon Bedrock agents. By using an agent's alias, you can temporarily suspend agent operations during maintenance, updates, or other situations."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Athena",
+ "contributor": "",
+ "description": "Add support for the managed query result in the workgroup APIs. The managed query result configuration enables users to store query results to Athena owned storage."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon EC2 Container Service",
+ "contributor": "",
+ "description": "Updates Amazon ECS documentation to include note for upcoming default log driver mode change."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Kubernetes Service",
+ "contributor": "",
+ "description": "Add support for filtering ListInsights API calls on MISCONFIGURATION insight category"
+ },
+ {
+ "type": "feature",
+ "category": "Cost Optimization Hub",
+ "contributor": "",
+ "description": "Support recommendations for Aurora instance and Aurora cluster storage."
+ },
+ {
+ "type": "feature",
+ "category": "Synthetics",
+ "contributor": "",
+ "description": "Support for Java runtime handler pattern."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.56.json b/.changes/2.31.56.json
new file mode 100644
index 000000000000..82589878b17e
--- /dev/null
+++ b/.changes/2.31.56.json
@@ -0,0 +1,36 @@
+{
+ "version": "2.31.56",
+ "date": "2025-06-03",
+ "entries": [
+ {
+ "type": "bugfix",
+ "category": "AWS S3 Event Notifications",
+ "contributor": "reifiedbeans",
+ "description": "Fixed parsing of S3 event notifications to allow eventTime to be null when eventName is not"
+ },
+ {
+ "type": "bugfix",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Fix NPE in `ProfileFileSupplier.defaultSupplier` when both credentials and config files do not exist."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon API Gateway",
+ "contributor": "",
+ "description": "Adds support to set the routing mode for a custom domain name."
+ },
+ {
+ "type": "feature",
+ "category": "AmazonApiGatewayV2",
+ "contributor": "",
+ "description": "Adds support to create routing rules and set the routing mode for a custom domain name."
+ },
+ {
+ "type": "feature",
+ "category": "EMR Serverless",
+ "contributor": "",
+ "description": "AWS EMR Serverless: Adds a new option in the CancelJobRun API in EMR 7.9.0+, to cancel a job with grace period. This feature is enabled by default with a 120-second grace period for streaming jobs and is not enabled by default for batch jobs."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.57.json b/.changes/2.31.57.json
new file mode 100644
index 000000000000..bb89037b8928
--- /dev/null
+++ b/.changes/2.31.57.json
@@ -0,0 +1,72 @@
+{
+ "version": "2.31.57",
+ "date": "2025-06-04",
+ "entries": [
+ {
+ "type": "bugfix",
+ "category": "S3 Transfer Manager",
+ "contributor": "jencymaryjoseph",
+ "description": "DownloadFilter type incompatability methods overriden from extended interface"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Amplify",
+ "contributor": "",
+ "description": "Update documentation for cacheConfig in CreateApp API"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Elemental MediaConvert",
+ "contributor": "",
+ "description": "This release includes support for embedding and signing C2PA content credentials in MP4 outputs."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Invoicing",
+ "contributor": "",
+ "description": "Added new Invoicing ListInvoiceSummaries API Operation"
+ },
+ {
+ "type": "feature",
+ "category": "AWS MediaConnect",
+ "contributor": "",
+ "description": "This release updates the DescribeFlow API to show peer IP addresses. You can now identify the peer IP addresses of devices connected to your sources and outputs. This helps you to verify and troubleshoot your flow's active connections."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Network Firewall",
+ "contributor": "",
+ "description": "You can now monitor flow and alert log metrics from the Network Firewall console."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic VMware Service",
+ "contributor": "",
+ "description": "Amazon Elastic VMware Service (Amazon EVS) allows you to run VMware Cloud Foundation (VCF) directly within your Amazon VPC including simplified self-managed migration experience with guided workflow in AWS console or via AWS CLI, get full access to their VCF deployment and VCF license portability."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon SageMaker Service",
+ "contributor": "",
+ "description": "Added support for p6-b200 instance type in SageMaker Training Jobs and Training Plans."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Transcribe Service",
+ "contributor": "",
+ "description": "AWS Healthscribe now supports new templates for the clinical note summary: BIRP, SIRP, DAP, BEHAVIORAL_SOAP, and PHYSICAL_SOAP"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Transcribe Streaming Service",
+ "contributor": "",
+ "description": "AWS Healthscribe now supports new templates for the clinical note summary: BIRP, SIRP, DAP, BEHAVIORAL_SOAP, and PHYSICAL_SOAP"
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.58.json b/.changes/2.31.58.json
new file mode 100644
index 000000000000..cd2c06fabaf6
--- /dev/null
+++ b/.changes/2.31.58.json
@@ -0,0 +1,48 @@
+{
+ "version": "2.31.58",
+ "date": "2025-06-05",
+ "entries": [
+ {
+ "type": "bugfix",
+ "category": "Amazon DynamoDB Enhanced Client",
+ "contributor": "",
+ "description": "Fixed DynamoDbEnhancedClient DefaultDynamoDbAsyncTable::createTable() to create secondary indices that are defined on annotations of the POJO class, similar to DefaultDynamoDbTable::createTable()."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Billing and Cost Management Pricing Calculator",
+ "contributor": "",
+ "description": "Updating the minimum for List APIs to be 1 (instead of 0)"
+ },
+ {
+ "type": "feature",
+ "category": "AWS CloudFormation",
+ "contributor": "",
+ "description": "Add new warning type 'EXCLUDED_PROPERTIES'"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Key Management Service",
+ "contributor": "",
+ "description": "AWS KMS announces the support for on-demand rotation of symmetric-encryption KMS keys with imported key material (EXTERNAL origin)."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Added ability to configure preferred authentication schemes when multiple auth options are available."
+ },
+ {
+ "type": "feature",
+ "category": "AWS WAFV2",
+ "contributor": "",
+ "description": "AWS WAF adds support for ASN-based traffic filtering and support for ASN-based rate limiting."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.59.json b/.changes/2.31.59.json
new file mode 100644
index 000000000000..8f3cfd0c9ea6
--- /dev/null
+++ b/.changes/2.31.59.json
@@ -0,0 +1,60 @@
+{
+ "version": "2.31.59",
+ "date": "2025-06-06",
+ "entries": [
+ {
+ "type": "bugfix",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Fix expiration in past warning during profile credential loading."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Key Management Service",
+ "contributor": "",
+ "description": "Remove unpopulated KeyMaterialId from Encrypt Response"
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Add support for protocols field in service model"
+ },
+ {
+ "type": "feature",
+ "category": "Agents for Amazon Bedrock Runtime",
+ "contributor": "",
+ "description": "This release introduces the `PromptCreationConfigurations` input parameter, which includes fields to control prompt population for `InvokeAgent` or `InvokeInlineAgent` requests."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Rekognition",
+ "contributor": "",
+ "description": "Adds support for defining an ordered preference list of different Rekognition Face Liveness challenge types when calling CreateFaceLivenessSession."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Relational Database Service",
+ "contributor": "",
+ "description": "Include Global Cluster Identifier in DBCluster if the DBCluster is a Global Cluster Member."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Route 53",
+ "contributor": "",
+ "description": "Amazon Route 53 now supports the Asia Pacific (Taipei) Region (ap-east-2) for latency records, geoproximity records, and private DNS for Amazon VPCs in that region."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon S3 Tables",
+ "contributor": "",
+ "description": "S3 Tables now supports getting details about a table via its table ARN."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.60.json b/.changes/2.31.60.json
new file mode 100644
index 000000000000..c8beab43a60d
--- /dev/null
+++ b/.changes/2.31.60.json
@@ -0,0 +1,66 @@
+{
+ "version": "2.31.60",
+ "date": "2025-06-09",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS AppSync",
+ "contributor": "",
+ "description": "Deprecate `atRestEncryptionEnabled` and `transitEncryptionEnabled` attributes in `CreateApiCache` action. Encryption is always enabled for new caches."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Cost Explorer Service",
+ "contributor": "",
+ "description": "Support dual-stack endpoints for ce api"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Marketplace Catalog Service",
+ "contributor": "",
+ "description": "The ListEntities API now supports the EntityID, LastModifiedDate, ProductTitle, and Visibility filters for machine learning products. You can also sort using all of those filters."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Adds support for configuring bearer auth using a token sourced from the environment for services with the `enableEnvironmentBearerToken` customization flag."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated Region class generation to use Partitions.json instead of the Endpoints.json and removed the hardcoded global regions."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Connect Customer Profiles",
+ "contributor": "",
+ "description": "This release introduces capability of Profile Explorer, using correct ingestion timestamp & using historical data for computing calculated attributes, and new standard objects for T&H as part of Amazon Connect Customer Profiles service."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Compute Cloud",
+ "contributor": "",
+ "description": "Release to support Elastic VMware Service (Amazon EVS) Subnet and Amazon EVS Network Interface Types."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic File System",
+ "contributor": "",
+ "description": "Added support for Internet Protocol Version 6 (IPv6) on EFS Service APIs and mount targets."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon WorkSpaces Thin Client",
+ "contributor": "",
+ "description": "Add ConflictException to UpdateEnvironment API"
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.61.json b/.changes/2.31.61.json
new file mode 100644
index 000000000000..108562eba48d
--- /dev/null
+++ b/.changes/2.31.61.json
@@ -0,0 +1,18 @@
+{
+ "version": "2.31.61",
+ "date": "2025-06-10",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "Amazon GameLift Streams",
+ "contributor": "",
+ "description": "Documentation updates for Amazon GameLift Streams to address formatting errors, correct resource ID examples, and update links to other guides"
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.62.json b/.changes/2.31.62.json
new file mode 100644
index 000000000000..cbcc401665a5
--- /dev/null
+++ b/.changes/2.31.62.json
@@ -0,0 +1,54 @@
+{
+ "version": "2.31.62",
+ "date": "2025-06-11",
+ "entries": [
+ {
+ "type": "bugfix",
+ "category": "AWS SDK for Java v2",
+ "contributor": "jencymaryjoseph",
+ "description": "Deprecated DefaultCredentialsProvider.create() since it creates Singleton instance"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Control Catalog",
+ "contributor": "",
+ "description": "Introduced ListControlMappings API that retrieves control mappings. Added control aliases and governed resources fields in GetControl and ListControls APIs. New filtering capability in ListControls API, with implementation identifiers and implementation types."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Network Manager",
+ "contributor": "",
+ "description": "Add support for public DNS hostname resolution to private IP addresses across Cloud WAN-managed VPCs. Add support for security group referencing across Cloud WAN-managed VPCs."
+ },
+ {
+ "type": "feature",
+ "category": "AWS WAFV2",
+ "contributor": "",
+ "description": "WAF now provides two DDoS protection options: resource-level monitoring for Application Load Balancers and the AWSManagedRulesAntiDDoSRuleSet managed rule group for CloudFront distributions."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Kubernetes Service",
+ "contributor": "",
+ "description": "Release for EKS Pod Identity Cross Account feature and disableSessionTags flag."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Lex Model Building V2",
+ "contributor": "",
+ "description": "Add support for the Assisted NLU feature to improve bot performance"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Relational Database Service",
+ "contributor": "",
+ "description": "Updates Amazon RDS documentation for Amazon RDS for Db2 cross-Region replicas in standby mode."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.63.json b/.changes/2.31.63.json
new file mode 100644
index 000000000000..89c3626a137a
--- /dev/null
+++ b/.changes/2.31.63.json
@@ -0,0 +1,54 @@
+{
+ "version": "2.31.63",
+ "date": "2025-06-12",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS IoT FleetWise",
+ "contributor": "",
+ "description": "Add new status READY_FOR_CHECKIN used for vehicle synchronisation"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Key Management Service",
+ "contributor": "",
+ "description": "AWS KMS announces the support of ML-DSA key pairs that creates post-quantum safe digital signatures."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Parallel Computing Service",
+ "contributor": "",
+ "description": "Fixed regex patterns for ARN fields."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon API Gateway",
+ "contributor": "",
+ "description": "Documentation updates for Amazon API Gateway"
+ },
+ {
+ "type": "feature",
+ "category": "AmazonApiGatewayV2",
+ "contributor": "",
+ "description": "Documentation updates for Amazon API Gateway"
+ },
+ {
+ "type": "feature",
+ "category": "AmazonConnectCampaignServiceV2",
+ "contributor": "",
+ "description": "Added PutInstanceCommunicationLimits and GetInstanceCommunicationLimits APIs"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon EC2 Container Service",
+ "contributor": "",
+ "description": "This Amazon ECS release supports updating the capacityProviderStrategy parameter in update-service."
+ },
+ {
+ "type": "feature",
+ "category": "EMR Serverless",
+ "contributor": "",
+ "description": "This release adds support for retrieval of the optional executionIamPolicy field in the GetJobRun API response."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.64.json b/.changes/2.31.64.json
new file mode 100644
index 000000000000..5413641bccd0
--- /dev/null
+++ b/.changes/2.31.64.json
@@ -0,0 +1,36 @@
+{
+ "version": "2.31.64",
+ "date": "2025-06-16",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS Network Firewall",
+ "contributor": "",
+ "description": "You can now create firewalls using a Transit Gateway instead of a VPC, resulting in a TGW attachment."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Add tracking of RequestBody/ResponseTransfromer implementations used in UserAgent."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Bedrock",
+ "contributor": "",
+ "description": "This release of the SDK has the API and documentation for the createcustommodel API. This feature lets you copy a Amazon SageMaker trained Amazon Nova model into Amazon Bedrock for inference."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Container Registry",
+ "contributor": "",
+ "description": "The `DescribeImageScanning` API now includes `lastInUseAt` and `InUseCount` fields that can be used to prioritize vulnerability remediation for images that are actively being used."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon SageMaker Service",
+ "contributor": "",
+ "description": "This release 1) adds a new S3DataType Converse for SageMaker training 2)adds C8g R7gd M8g C6in P6 P6e instance type for SageMaker endpoint 3) adds m7i, r7i, c7i instance type for SageMaker Training and Processing."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.65.json b/.changes/2.31.65.json
new file mode 100644
index 000000000000..af3f7bda357c
--- /dev/null
+++ b/.changes/2.31.65.json
@@ -0,0 +1,90 @@
+{
+ "version": "2.31.65",
+ "date": "2025-06-17",
+ "entries": [
+ {
+ "type": "bugfix",
+ "category": "AWS SDK for Java V2",
+ "contributor": "",
+ "description": "Fix a bug in ConstructorCache when classes are GC'ed but not removed from cache"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Backup",
+ "contributor": "",
+ "description": "AWS Backup is adding support for integration of its logically air-gapped vaults with the AWS Organizations Multi-party approval capability."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Certificate Manager",
+ "contributor": "",
+ "description": "Adds support for Exportable Public Certificates"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Database Migration Service",
+ "contributor": "",
+ "description": "Add \"Virtual\" field to Data Provider as well as \"S3Path\" and \"S3AccessRoleArn\" fields to DataProvider settings"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Multi-party Approval",
+ "contributor": "",
+ "description": "This release enables customers to create Multi-party approval teams and approval requests to protect supported operations."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Network Firewall",
+ "contributor": "",
+ "description": "Release of Active Threat Defense in Network Firewall"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Organizations",
+ "contributor": "",
+ "description": "Add support for policy operations on the SECURITYHUB_POLICY policy type."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SecurityHub",
+ "contributor": "",
+ "description": "Adds operations, structures, and exceptions required for public preview release of Security Hub V2."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Security Token Service",
+ "contributor": "",
+ "description": "The AWS Security Token Service APIs AssumeRoleWithSAML and AssumeRoleWithWebIdentity can now be invoked without pre-configured AWS credentials in the SDK configuration."
+ },
+ {
+ "type": "feature",
+ "category": "AWS WAFV2",
+ "contributor": "",
+ "description": "AWS WAF can now suggest protection packs for you based on the application information you provide when you create a webACL."
+ },
+ {
+ "type": "feature",
+ "category": "Access Analyzer",
+ "contributor": "",
+ "description": "We are launching a new analyzer type, internal access analyzer. The new analyzer will generate internal access findings, which help customers understand who within their AWS organization or AWS Account has access to their critical AWS resources."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Bedrock",
+ "contributor": "",
+ "description": "This release of the SDK has the API and documentation for the createcustommodel API. This feature lets you copy a trained model into Amazon Bedrock for inference."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon GuardDuty",
+ "contributor": "",
+ "description": "Adding support for extended threat detection for EKS Audit Logs and EKS Runtime Monitoring."
+ },
+ {
+ "type": "feature",
+ "category": "Inspector2",
+ "contributor": "",
+ "description": "Add Code Repository Scanning as part of AWS InspectorV2"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.66.json b/.changes/2.31.66.json
new file mode 100644
index 000000000000..310ca92c2a4b
--- /dev/null
+++ b/.changes/2.31.66.json
@@ -0,0 +1,54 @@
+{
+ "version": "2.31.66",
+ "date": "2025-06-18",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS AI Ops",
+ "contributor": "",
+ "description": "This is the initial SDK release for Amazon AI Operations (AIOps). AIOps is a generative AI-powered assistant that helps you respond to incidents in your system by scanning your system's telemetry and quickly surface suggestions that might be related to your issue."
+ },
+ {
+ "type": "feature",
+ "category": "AWS S3",
+ "contributor": "tmccombs",
+ "description": "Adds the ability to presign HeadObject and HeadBucket requests with the S3 Presigner"
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Adding a new method of constructing ARNs without exceptions as control flow"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon CloudWatch Logs",
+ "contributor": "",
+ "description": "Added CloudWatch Logs Transformer support for converting CloudTrail, VPC Flow, EKS Audit, AWS WAF and Route53 Resolver logs to OCSF v1.1 format."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon SageMaker Service",
+ "contributor": "",
+ "description": "Add support for p6-b200 instance type for SageMaker Hyperpod"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Simple Storage Service",
+ "contributor": "",
+ "description": "Added support for renaming objects within the same bucket using the new RenameObject API."
+ },
+ {
+ "type": "feature",
+ "category": "Auto Scaling",
+ "contributor": "",
+ "description": "Add IncludeInstances parameter to DescribeAutoScalingGroups API"
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.67.json b/.changes/2.31.67.json
new file mode 100644
index 000000000000..4e1ccc9fcf25
--- /dev/null
+++ b/.changes/2.31.67.json
@@ -0,0 +1,42 @@
+{
+ "version": "2.31.67",
+ "date": "2025-06-19",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS Lambda",
+ "contributor": "",
+ "description": "Support Schema Registry feature for Kafka Event Source Mapping. Customers can now configure a Schema Registry to enable schema validation and filtering for Avro, Protobuf, and JSON-formatted events in Lambda for Kafka Event Source."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Bedrock",
+ "contributor": "",
+ "description": "This release of the SDK has the API and documentation for the createcustommodel API. This feature lets you copy a trained model into Amazon Bedrock for inference."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon SageMaker Service",
+ "contributor": "",
+ "description": "This release introduces alternative support for utilizing CFN templates from S3 for SageMaker Projects."
+ },
+ {
+ "type": "feature",
+ "category": "EMR Serverless",
+ "contributor": "",
+ "description": "This release adds the capability to enable IAM IdentityCenter Trusted Identity Propagation for users running Interactive Sessions on EMR Serverless Applications."
+ },
+ {
+ "type": "feature",
+ "category": "Payment Cryptography Control Plane",
+ "contributor": "",
+ "description": "Additional support for managing HMAC keys that adheres to changes documented in X9.143-2021 and provides better interoperability for key import/export"
+ },
+ {
+ "type": "feature",
+ "category": "Payment Cryptography Data Plane",
+ "contributor": "",
+ "description": "Additional support for managing HMAC keys that adheres to changes documented in X9.143-2021 and provides better interoperability for key import/export"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.68.json b/.changes/2.31.68.json
new file mode 100644
index 000000000000..a25a216df165
--- /dev/null
+++ b/.changes/2.31.68.json
@@ -0,0 +1,42 @@
+{
+ "version": "2.31.68",
+ "date": "2025-06-20",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS Elemental MediaConvert",
+ "contributor": "",
+ "description": "This release adds a new SPECIFIED_OPTIMAL option for handling DDS when using DVB-Sub with high resolution video."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Glue",
+ "contributor": "",
+ "description": "AWS Glue Data Quality now provides aggregated metrics in evaluation results when publishAggregatedMetrics with row-level results are enabled. These metrics include summary statistics showing total counts of processed, passed, and failed rows and rules in a single view."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Bedrock",
+ "contributor": "",
+ "description": "Add support for tiers in Content Filters and Denied Topics for Amazon Bedrock Guardrails."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon EC2 Container Service",
+ "contributor": "",
+ "description": "Add ECS support for Windows Server 2025"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Location Service Places V2",
+ "contributor": "",
+ "description": "Geocode, ReverseGeocode, and GetPlace APIs added Intersections and SecondaryAddresses. To use, add to the AdditionalFeatures list in your request. This provides info about nearby intersections and secondary addresses that are associated with a main address. Also added MainAddress and ParsedQuery."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.69.json b/.changes/2.31.69.json
new file mode 100644
index 000000000000..563cd23f9453
--- /dev/null
+++ b/.changes/2.31.69.json
@@ -0,0 +1,30 @@
+{
+ "version": "2.31.69",
+ "date": "2025-06-23",
+ "entries": [
+ {
+ "type": "bugfix",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Ignore unknown properties on endpoints in endpoint rules."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Glue",
+ "contributor": "",
+ "description": "AWS Glue now supports sort and z-order strategy for managed automated compaction for Iceberg tables in addition to binpack."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon S3 Tables",
+ "contributor": "",
+ "description": "S3 Tables now supports sort and z-order compaction strategies for Iceberg tables in addition to binpack."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Workspaces Instances",
+ "contributor": "",
+ "description": "Added support for Amazon WorkSpaces Instances API"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.70.json b/.changes/2.31.70.json
new file mode 100644
index 000000000000..817b8aedf076
--- /dev/null
+++ b/.changes/2.31.70.json
@@ -0,0 +1,66 @@
+{
+ "version": "2.31.70",
+ "date": "2025-06-24",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS AI Ops",
+ "contributor": "",
+ "description": "Adds support for cross account investigations for CloudWatch investigations AI Operations (AIOps)."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Batch",
+ "contributor": "",
+ "description": "Add userdataType to LaunchTemplateSpecification and LaunchTemplateSpecificationOverride."
+ },
+ {
+ "type": "feature",
+ "category": "AWS License Manager",
+ "contributor": "",
+ "description": "AWS License Manager now supports license type conversions for AWS Marketplace products. Customers can provide Marketplace codes in the source license context or destination license context in the CreateLicenseConversionTaskForResource requests."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Bedrock",
+ "contributor": "",
+ "description": "We are making ListFoundationModelAgreementOffers, DeleteFoundationModelAgreement, CreateFoundationModelAgreement, GetFoundationModelAvailability, PutUseCaseForModelAccess and GetUseCaseForModelAccess APIs public, previously they were console."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Compute Cloud",
+ "contributor": "",
+ "description": "This release allows you to create and register AMIs while maintaining their underlying EBS snapshots within Local Zones."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon GameLift",
+ "contributor": "",
+ "description": "Add support for UDP ping beacons to ListLocations API, including new PingBeacon and UDPEndpoint data types within its Locations return value. Use UDP ping beacon endpoints to help measure real-time network latency for multiplayer games."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Relational Database Service",
+ "contributor": "",
+ "description": "Adding support for RDS on Dedicated Local Zones, including local backup target, snapshot availability zone and snapshot target"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Route 53 Resolver",
+ "contributor": "",
+ "description": "Add support for iterative DNS queries through the new INBOUND_DELEGATION endpoint. Add delegation support through the Outbound Endpoints with DELEGATE rules."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Transcribe Service",
+ "contributor": "",
+ "description": "This Feature Adds Support for the \"et-EE\" Locale for Batch Operations"
+ },
+ {
+ "type": "feature",
+ "category": "Elastic Load Balancing",
+ "contributor": "",
+ "description": "Add Paginator for DescribeAccountLimits, and fix Paginators for DescribeTrustStoreAssociations, DescribeTrustStoreRevocations, and DescribeTrustStores"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.71.json b/.changes/2.31.71.json
new file mode 100644
index 000000000000..edbc2cad5b36
--- /dev/null
+++ b/.changes/2.31.71.json
@@ -0,0 +1,54 @@
+{
+ "version": "2.31.71",
+ "date": "2025-06-25",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS S3 Control",
+ "contributor": "",
+ "description": "Add support for the ability to use Amazon S3 Access Points with Amazon FSx for OpenZFS file systems."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Adding constant to each SDK module to represent its version"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Storage Gateway",
+ "contributor": "",
+ "description": "This release adds IPv6 support to the Storage Gateway APIs. APIs that previously only accept or return IPv4 address will now accept or return both IPv4 and IPv6 addresses."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon EC2 Container Service",
+ "contributor": "",
+ "description": "Updates for change to Amazon ECS default log driver mode from blocking to non-blocking"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon FSx",
+ "contributor": "",
+ "description": "Add support for the ability to create Amazon S3 Access Points for Amazon FSx for OpenZFS file systems."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Simple Storage Service",
+ "contributor": "",
+ "description": "Adds support for additional server-side encryption mode and storage class values for accessing Amazon FSx data from Amazon S3 using S3 Access Points"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Textract",
+ "contributor": "",
+ "description": "Add RotationAngle field to Geometry of WORD blocks for Textract AnalyzeDocument API"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon WorkSpaces Thin Client",
+ "contributor": "",
+ "description": "Remove Tags field from Get API responses"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.72.json b/.changes/2.31.72.json
new file mode 100644
index 000000000000..d493417e807f
--- /dev/null
+++ b/.changes/2.31.72.json
@@ -0,0 +1,90 @@
+{
+ "version": "2.31.72",
+ "date": "2025-06-26",
+ "entries": [
+ {
+ "type": "bugfix",
+ "category": "EmfMetricLoggingPublisher",
+ "contributor": "",
+ "description": "Fixed the bug that EmfMetricLoggingPublisher not properly publishing Long type metrics"
+ },
+ {
+ "type": "feature",
+ "category": "AWSDeadlineCloud",
+ "contributor": "",
+ "description": "Added fields to track cumulative task retry attempts for steps and jobs"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Key Management Service",
+ "contributor": "",
+ "description": "This release updates AWS CLI examples for KMS APIs."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Add code generation validation for missing request URI on an operation."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Add support for defining service model validators and generating valdiation reports during code generation."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Add support for validating that shared models between two services are identical."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Compute Cloud",
+ "contributor": "",
+ "description": "This release adds support for OdbNetworkArn as a target in VPC Route Tables"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Keyspaces",
+ "contributor": "",
+ "description": "This release provides change data capture (CDC) streams support through updates to the Amazon Keyspaces API."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Keyspaces Streams",
+ "contributor": "",
+ "description": "This release adds change data capture (CDC) streams support through the new Amazon Keyspaces Streams API."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon WorkSpaces",
+ "contributor": "",
+ "description": "Updated modifyStreamingProperties to support PrivateLink VPC endpoints for directories"
+ },
+ {
+ "type": "feature",
+ "category": "Code Generator Maven Plugin",
+ "contributor": "",
+ "description": "Update the generator plugin to support model validation during code generation. In addition, this adds the `writeValidationReport` flag to support writing the validation report to disk."
+ },
+ {
+ "type": "feature",
+ "category": "Managed integrations for AWS IoT Device Management",
+ "contributor": "",
+ "description": "Adding managed integrations APIs for IoT Device Management to onboard and control devices across different manufacturers, connectivity protocols and third party vendor clouds. APIs include managed thing operations, provisioning profile management, and cloud connector operations."
+ },
+ {
+ "type": "feature",
+ "category": "QBusiness",
+ "contributor": "",
+ "description": "Added support for App level authentication for QBusiness DataAccessor using AWS IAM Identity center Trusted Token issuer"
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.73.json b/.changes/2.31.73.json
new file mode 100644
index 000000000000..a102a07f196c
--- /dev/null
+++ b/.changes/2.31.73.json
@@ -0,0 +1,54 @@
+{
+ "version": "2.31.73",
+ "date": "2025-06-27",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS Config",
+ "contributor": "",
+ "description": "Added important considerations to the PutConformancePack and PutOrganizationConformancPack APIs."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Glue",
+ "contributor": "",
+ "description": "AWS Glue now supports schema, partition and sort management of Apache Iceberg tables using Glue SDK"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Connect Service",
+ "contributor": "",
+ "description": "This release adds the following value to an InitiateAs enum: COMPLETED"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon GuardDuty",
+ "contributor": "",
+ "description": "Update JSON target for Kubernetes workload resource type."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Q Connect",
+ "contributor": "",
+ "description": "Adding UnauthorizedException to public SDK"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Relational Database Service",
+ "contributor": "",
+ "description": "StartDBCluster and StopDBCluster can now throw InvalidDBShardGroupStateFault."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Simple Email Service",
+ "contributor": "",
+ "description": "Added support for new SES regions"
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.74.json b/.changes/2.31.74.json
new file mode 100644
index 000000000000..0da6a07188d4
--- /dev/null
+++ b/.changes/2.31.74.json
@@ -0,0 +1,132 @@
+{
+ "version": "2.31.74",
+ "date": "2025-06-30",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS ARC - Zonal Shift",
+ "contributor": "",
+ "description": "Added support for on-demand practice runs and balanced capacity checks in ARC autoshift practice."
+ },
+ {
+ "type": "feature",
+ "category": "AWS B2B Data Interchange",
+ "contributor": "",
+ "description": "Updated APIs to support inbound EDI split capabilities and additional Partnership-level configurations of generated EDI files' contents and format."
+ },
+ {
+ "type": "feature",
+ "category": "AWS CloudFormation",
+ "contributor": "",
+ "description": "Added support for UNKNOWN drift status."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Config",
+ "contributor": "",
+ "description": "Updated ResourceType enum with new resource types onboarded by AWS Config as of June 2025"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Data Exchange",
+ "contributor": "",
+ "description": "This release updates resource Id with alphanumeric constraint, including Asset id, Revision id, Data Set id, Job id, and Event Action id."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Glue",
+ "contributor": "",
+ "description": "releasing source processing properties to support source properties for ODB integrations"
+ },
+ {
+ "type": "feature",
+ "category": "AWS Health Imaging",
+ "contributor": "",
+ "description": "Added new fields to support the concept of primary image sets within the storage hierarchy."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Identity and Access Management",
+ "contributor": "",
+ "description": "Updated IAM ServiceSpecificCredential support to include expiration, API Key output format instead of username and password for services that will support API keys, and the ability to list credentials for all users in the account for a given service configuration."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Outposts",
+ "contributor": "",
+ "description": "Make ContactName and ContactPhoneNumber required fields when creating and updating Outpost Site Addresses."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Parallel Computing Service",
+ "contributor": "",
+ "description": "Fixed the validation pattern for an instance profile Amazon Resource Name (ARN) in AWS PCS."
+ },
+ {
+ "type": "feature",
+ "category": "AWS Transfer Family",
+ "contributor": "",
+ "description": "Added support for dual-stack (IPv4 and IPv6) endpoints for SFTP public endpoints and VPC-internal endpoints (SFTP, FTPS, FTP, and AS2), enabling customers to configure new servers with IPv4 or dual-stack mode, convert existing servers to dual-stack, and use IPv6 with service APIs."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Bedrock",
+ "contributor": "",
+ "description": "Add support for API Keys, Re-Ranker, implicit filter for RAG / KB evaluation for Bedrock APIs."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Bedrock Runtime",
+ "contributor": "",
+ "description": "Add API Key and document citations support for Bedrock Runtime APIs"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon CloudWatch Logs",
+ "contributor": "",
+ "description": "Increase minimum length of queryId parameter to 1 character."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Connect Service",
+ "contributor": "",
+ "description": "This release introduces ChatMetrics to the model, providing comprehensive analytics insights for Amazon Connect chat conversations. Users can access these detailed metrics through the AWS Connect API by using the DescribeContact operation with their specific instance and contact IDs"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon DynamoDB",
+ "contributor": "",
+ "description": "This change adds support for witnesses in global tables. It also adds a new table status, REPLICATION_NOT_AUTHORIZED. This status will indicate scenarios where global replicas table can't be utilized for data plane operations."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon EventBridge",
+ "contributor": "",
+ "description": "Added support for EventBridge Dualstack endpoints in AWS GovCloud (US) regions (us-gov-east-1 and us-gov-west-1). The dualstack endpoints are identical for both FIPS and non-FIPS configurations, following the format: events.{region}.api.aws"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon QuickSight",
+ "contributor": "",
+ "description": "Introduced custom permission capabilities for reporting content. Added menu option in exploration to preserve configuration data when textbox menu option is used. Added support for Athena trusted identity propagation."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Simple Systems Manager (SSM)",
+ "contributor": "",
+ "description": "Introduces AccessType, a new filter value for the DescribeSessions API."
+ },
+ {
+ "type": "feature",
+ "category": "Network Flow Monitor",
+ "contributor": "",
+ "description": "Add ConflictExceptions to UpdateScope and DeleteScope operations for scopes being mutated."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/2.31.75.json b/.changes/2.31.75.json
new file mode 100644
index 000000000000..1f01be61b2ed
--- /dev/null
+++ b/.changes/2.31.75.json
@@ -0,0 +1,60 @@
+{
+ "version": "2.31.75",
+ "date": "2025-07-01",
+ "entries": [
+ {
+ "type": "feature",
+ "category": "AWS Clean Rooms ML",
+ "contributor": "",
+ "description": "This release introduces support for incremental training and distributed training for custom models in AWS Clean Rooms ML."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Add the sdk service client version to the useragent"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon DataZone",
+ "contributor": "",
+ "description": "Add support for the new optional domain-unit-id parameter in the UpdateProject API."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Elastic Compute Cloud",
+ "contributor": "",
+ "description": "Add Context to GetInstanceTypesFromInstanceRequirements API"
+ },
+ {
+ "type": "feature",
+ "category": "Amazon Relational Database Service",
+ "contributor": "",
+ "description": "Amazon RDS Custom for Oracle now supports multi-AZ database instances."
+ },
+ {
+ "type": "feature",
+ "category": "Amazon SageMaker Service",
+ "contributor": "",
+ "description": "Updated field validation requirements for InstanceGroups."
+ },
+ {
+ "type": "feature",
+ "category": "QBusiness",
+ "contributor": "",
+ "description": "New ChatResponseConfiguration to Customize Q Business chat responses for specific use cases and communication needs. Updated Boosting capability allowing admins to provide preference on date attributes for recency and/or provide a preferred data source."
+ },
+ {
+ "type": "feature",
+ "category": "odb",
+ "contributor": "",
+ "description": "This release adds API operations for Oracle Database@AWS. You can use the APIs to create Exadata infrastructure, ODB networks, and Exadata and Autonomous VM clusters inside AWS data centers. The infrastructure is managed by OCI. You can integrate these resources with AWS services."
+ },
+ {
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Updated endpoint and partition metadata."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.changes/next-release/feature-AWSSDKforJavav2-b405876.json b/.changes/next-release/feature-AWSSDKforJavav2-b405876.json
new file mode 100644
index 000000000000..bb9d5276a1ac
--- /dev/null
+++ b/.changes/next-release/feature-AWSSDKforJavav2-b405876.json
@@ -0,0 +1,6 @@
+{
+ "type": "feature",
+ "category": "Amazon DyanmoDB",
+ "contributor": "",
+ "description": "Enable caching calls to URI constructors for account-id based endpoints"
+}
diff --git a/.github/workflows/api-surface-area-review-verification.yml b/.github/workflows/api-surface-area-review-verification.yml
new file mode 100644
index 000000000000..eef6b517dab8
--- /dev/null
+++ b/.github/workflows/api-surface-area-review-verification.yml
@@ -0,0 +1,40 @@
+name: API Surface Area Review Verification
+
+permissions:
+ contents: read
+ pull-requests: read
+
+on:
+ pull_request:
+ types: [ opened, synchronize, reopened, labeled, unlabeled ]
+ branches:
+ - master
+
+jobs:
+ api-surface-area-review-verification:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Verifies updates to protected/public APIs have been reviewed and approved by the team, if any
+ id: api-surface-area-review-verification
+ if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-api-surface-area-change') }}
+ run: |
+ git fetch origin ${{ github.base_ref }} --depth 1
+ FILES=$( git diff remotes/origin/${{ github.base_ref }} --name-only | grep "\.java$" | grep -v -E "(^|/)(internal|test|codegen|v2-migration|it)/" || true)
+ if [ -n "$FILES" ]; then
+ echo "::error::Changes around protected/public APIs found:"
+ echo "$FILES" | while read file; do
+ echo "::error::$file"
+ done
+ echo "has_matches=true" >> $GITHUB_OUTPUT
+ else
+ echo "No changes around protected/public APIs found."
+ echo "has_matches=false" >> $GITHUB_OUTPUT
+ fi
+ - name: Fail if there are changes around protected/public APIs and there's no label
+ if: ${{ steps.api-surface-area-review-verification.outputs.has_matches == 'true' && !contains(github.event.pull_request.labels.*.name, 'api-surface-area-approved-by-team') }}
+ run: |
+ echo "::error ::Change around public/protected APIs has been detected. Please either:"
+ echo "::error ::* Review it with the team and add the 'api-surface-area-reviewed' label to this PR after approval –or–"
+ echo "::error ::* Add the 'no-api-surface-area-change' label to this PR in case this is a false positive"
+ exit 1
diff --git a/.github/workflows/changelog-verification.yml b/.github/workflows/changelog-verification.yml
index ea2df21723c7..bc619e590851 100644
--- a/.github/workflows/changelog-verification.yml
+++ b/.github/workflows/changelog-verification.yml
@@ -1,5 +1,9 @@
name: Changelog verification
+permissions:
+ contents: read
+ pull-requests: read
+
on:
pull_request:
types: [ opened, synchronize, reopened, labeled, unlabeled ]
@@ -12,14 +16,30 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Check for changelog entry
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-changelog') }}
+ if: ${{ !contains(github.event.pull_request.labels.*.name, 'changelog-not-required') }}
run: |
- git fetch origin ${{ github.base_ref }} --depth 1 && \
- git diff remotes/origin/${{ github.base_ref }} --name-only | grep -P "\.changes/next-release/*[a-zA-Z0-9_-]+\.json"
+ git fetch origin ${{ github.base_ref }} --depth 1
+ NON_TEST_FILES=$(git diff remotes/origin/${{ github.base_ref }} --name-only | grep "\.java$" | grep -v -E "(^|/)(test|it)/" || true)
+ if [ -n "$NON_TEST_FILES" ]; then
+ echo "::notice::Non-test Java changes found:"
+ echo "$NON_TEST_FILES" | while read file; do
+ echo "::notice::$file"
+ done
+ echo "Checking for changelog entry..."
+ CHANGELOG_FILES=$(git diff remotes/origin/${{ github.base_ref }} --name-only | grep -P "\.changes/next-release/.*[a-zA-Z0-9_-]+\.json" || true)
+ if [ -z "$CHANGELOG_FILES" ]; then
+ echo "::error::No changelog entry found for Java changes"
+ exit 1
+ else
+ echo "::notice::Changelog entry found: $CHANGELOG_FILES"
+ fi
+ else
+ echo "::notice::No non-test Java changes found. Changelog verification skipped."
+ fi
- name: Error message
if: ${{ failure() }}
run: |
- echo "::error ::No new/updated changelog entry found in /.changes/next-release directory. Please either:"
- echo "::error ::* Add a changelog entry (see CONTRIBUTING.md for instructions) –or–"
- echo "::error ::* Add the 'no-changelog' label to this PR (in rare cases not warranting a changelog entry)"
- exit 1
\ No newline at end of file
+ echo "::error::No new/updated changelog entry found in /.changes/next-release directory. Please either:"
+ echo "::error::* Add a changelog entry (see CONTRIBUTING.md for instructions) –or–"
+ echo "::error::* Add the 'changelog-not-required' label to this PR (in rare cases not warranting a changelog entry)"
+ exit 1
diff --git a/.github/workflows/codebuild-ci.yml b/.github/workflows/codebuild-ci.yml
index c99c8eae844f..72b79d06b3ed 100644
--- a/.github/workflows/codebuild-ci.yml
+++ b/.github/workflows/codebuild-ci.yml
@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@v1
+ uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
aws-region: us-west-2
@@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@v1
+ uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
aws-region: us-west-2
@@ -49,7 +49,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@v1
+ uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
aws-region: us-west-2
@@ -64,7 +64,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@v1
+ uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
aws-region: us-west-2
@@ -79,7 +79,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@v1
+ uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
aws-region: us-west-2
@@ -93,7 +93,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@v1
+ uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
aws-region: us-west-2
@@ -107,7 +107,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@v1
+ uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
aws-region: us-west-2
@@ -130,7 +130,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@v1
+ uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
aws-region: us-west-2
@@ -139,3 +139,134 @@ jobs:
uses: aws-actions/aws-codebuild-run-build@v1
with:
project-name: aws-sdk-java-v2-endpoints-test
+ brazil-json-validation:
+ if: github.repository == 'aws/aws-sdk-java-v2'
+ runs-on: ubuntu-latest
+ steps:
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v4
+ with:
+ role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
+ aws-region: us-west-2
+ role-duration-seconds: 7200
+ - name: Validate Brazil config
+ uses: aws-actions/aws-codebuild-run-build@v1
+ with:
+ project-name: aws-java-sdk-v2-validate-brazil-config
+ migration-tests:
+ if: github.repository == 'aws/aws-sdk-java-v2'
+ runs-on: ubuntu-latest
+ steps:
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v4
+ with:
+ role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
+ aws-region: us-west-2
+ role-duration-seconds: 7200
+ - name: Run migration test
+ uses: aws-actions/aws-codebuild-run-build@v1
+ with:
+ project-name: aws-sdk-java-v2-migration-test
+
+ s3-regression-tests-download:
+ if: github.repository == 'aws/aws-sdk-java-v2'
+ runs-on: ubuntu-latest
+ env:
+ REGRESSION_TEST: DownloadStreamingRegressionTesting
+ steps:
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v4
+ with:
+ role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
+ aws-region: us-west-2
+ role-duration-seconds: 7200
+ - name: Run s3 regression tests for downloads
+ uses: aws-actions/aws-codebuild-run-build@v1
+ with:
+ project-name: aws-sdk-java-v2-s3-regression-tests
+ env-vars-for-codebuild: REGRESSION_TEST
+ s3-regression-tests-control-plane:
+ if: github.repository == 'aws/aws-sdk-java-v2'
+ runs-on: ubuntu-latest
+ env:
+ REGRESSION_TEST: ControlPlaneOperationRegressionTesting
+ steps:
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v4
+ with:
+ role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
+ aws-region: us-west-2
+ role-duration-seconds: 7200
+ - name: Run s3 regression tests for control plane
+ uses: aws-actions/aws-codebuild-run-build@v1
+ with:
+ project-name: aws-sdk-java-v2-s3-regression-tests
+ env-vars-for-codebuild: REGRESSION_TEST
+ s3-regression-tests-upload-sync:
+ if: github.repository == 'aws/aws-sdk-java-v2'
+ runs-on: ubuntu-latest
+ env:
+ REGRESSION_TEST: UploadSyncRegressionTesting
+ steps:
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v4
+ with:
+ role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
+ aws-region: us-west-2
+ role-duration-seconds: 7200
+ - name: Run s3 regression tests for uploads
+ uses: aws-actions/aws-codebuild-run-build@v1
+ with:
+ project-name: aws-sdk-java-v2-s3-regression-tests
+ env-vars-for-codebuild: REGRESSION_TEST
+ s3-regression-tests-upload-async:
+ if: github.repository == 'aws/aws-sdk-java-v2'
+ runs-on: ubuntu-latest
+ env:
+ REGRESSION_TEST: UploadAsyncRegressionTesting
+ steps:
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v4
+ with:
+ role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
+ aws-region: us-west-2
+ role-duration-seconds: 7200
+ - name: Run s3 regression tests for uploads
+ uses: aws-actions/aws-codebuild-run-build@v1
+ with:
+ project-name: aws-sdk-java-v2-s3-regression-tests
+ env-vars-for-codebuild: REGRESSION_TEST
+ s3-regression-tests-upload-crt:
+ if: github.repository == 'aws/aws-sdk-java-v2'
+ runs-on: ubuntu-latest
+ env:
+ REGRESSION_TEST: UploadCrtRegressionTesting
+ steps:
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v4
+ with:
+ role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
+ aws-region: us-west-2
+ role-duration-seconds: 7200
+ - name: Run s3 regression tests for uploads
+ uses: aws-actions/aws-codebuild-run-build@v1
+ with:
+ project-name: aws-sdk-java-v2-s3-regression-tests
+ env-vars-for-codebuild: REGRESSION_TEST
+ s3-regression-tests-upload-multi:
+ if: github.repository == 'aws/aws-sdk-java-v2'
+ runs-on: ubuntu-latest
+ env:
+ REGRESSION_TEST: UploadTransferManagerRegressionTesting
+ steps:
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v4
+ with:
+ role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
+ aws-region: us-west-2
+ role-duration-seconds: 7200
+ - name: Run s3 regression tests for uploads
+ uses: aws-actions/aws-codebuild-run-build@v1
+ with:
+ project-name: aws-sdk-java-v2-s3-regression-tests
+ env-vars-for-codebuild: REGRESSION_TEST
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 000000000000..79405678f4ee
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,90 @@
+name: "CodeQL Analysis"
+
+on:
+ push:
+ branches: [ "master" ]
+ pull_request:
+ schedule:
+ - cron: '44 14 * * 6'
+
+jobs:
+ analyze:
+ name: Analyze (${{ matrix.language }})
+ # Runner size impacts CodeQL analysis time. To learn more, please see:
+ # - https://gh.io/recommended-hardware-resources-for-running-codeql
+ # - https://gh.io/supported-runners-and-hardware-resources
+ # - https://gh.io/using-larger-runners (GitHub.com only)
+ # Consider using larger runners or machines with greater resources for possible analysis time improvements.
+ runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
+ permissions:
+ # required for all workflows
+ security-events: write
+
+ # required to fetch internal or private CodeQL packs
+ packages: read
+
+ # only required for workflows in private repositories
+ actions: read
+ contents: read
+
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - language: actions
+ build-mode: none
+ - language: java-kotlin
+ build-mode: none # This mode only analyzes Java. Set this to 'autobuild' or 'manual' to analyze Kotlin too.
+ - language: python
+ build-mode: none
+ # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
+ # Use `c-cpp` to analyze code written in C, C++ or both
+ # Use 'java-kotlin' to analyze code written in Java, Kotlin or both
+ # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
+ # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
+ # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
+ # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
+ # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ # Add any setup steps before running the `github/codeql-action/init` action.
+ # This includes steps like installing compilers or runtimes (`actions/setup-node`
+ # or others). This is typically only required for manual builds.
+ # - name: Setup runtime (example)
+ # uses: actions/setup-example@v1
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ languages: ${{ matrix.language }}
+ build-mode: ${{ matrix.build-mode }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+
+ # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+ # queries: security-extended,security-and-quality
+
+ # If the analyze step fails for one of the languages you are analyzing with
+ # "We were unable to automatically build your code", modify the matrix above
+ # to set the build mode to "manual" for that language. Then modify this step
+ # to build your code.
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+ - if: matrix.build-mode == 'manual'
+ shell: bash
+ run: |
+ echo 'If you are using a "manual" build mode for one or more of the' \
+ 'languages you are analyzing, replace this with the commands to build' \
+ 'your code, for example:'
+ echo ' make bootstrap'
+ echo ' make release'
+ exit 1
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
+ with:
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/lock-conversation-closed-pr.yml b/.github/workflows/lock-conversation-closed-pr.yml
new file mode 100644
index 000000000000..0e75c1b07aa1
--- /dev/null
+++ b/.github/workflows/lock-conversation-closed-pr.yml
@@ -0,0 +1,35 @@
+name: Lock PR Conversation on Close
+
+on:
+ pull_request:
+ types: [closed]
+
+jobs:
+ lock-conversation-closed-prs:
+ if: github.repository == 'aws/aws-sdk-java-v2'
+ name: Lock PR Conversation on Close
+ runs-on: ubuntu-latest
+ permissions:
+ pull-requests: write
+ steps:
+ - name: Lock PR conversation on Close
+ uses: actions/github-script@v7
+ env:
+ GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
+ with:
+ script: |
+ const prNumber = context.payload.pull_request.number;
+
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber,
+ body: "This pull request has been closed and the conversation has been locked. Comments on closed PRs are hard for our team to see. If you need more assistance, please open a new issue that references this one."
+ });
+
+ await github.rest.issues.lock({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber,
+ lock_reason: "resolved"
+ });
\ No newline at end of file
diff --git a/.github/workflows/merge-queue-metric.yml b/.github/workflows/merge-queue-metric.yml
index f7c12aa12429..259f03e4d268 100644
--- a/.github/workflows/merge-queue-metric.yml
+++ b/.github/workflows/merge-queue-metric.yml
@@ -18,7 +18,7 @@ jobs:
steps:
- name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@v1
+ uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
aws-region: us-west-2
@@ -32,11 +32,11 @@ jobs:
if: ${{ github.repository == 'aws/aws-sdk-java-v2' && github.event.action == 'dequeued' && github.event.reason != 'MERGE'}}
steps:
- name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@v1
+ uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
aws-region: us-west-2
role-duration-seconds: 900
- name: Record merge queue removal
run: |
- aws --region us-west-2 cloudwatch put-metric-data --namespace AwsJavaSdkV2/GitHub --metric-name MergeQueue-Remove --unit Count --value 1 --dimensions Branch=master
\ No newline at end of file
+ aws --region us-west-2 cloudwatch put-metric-data --namespace AwsJavaSdkV2/GitHub --metric-name MergeQueue-Remove --unit Count --value 1 --dimensions Branch=master
diff --git a/.github/workflows/new-module-verification.yml b/.github/workflows/new-module-verification.yml
new file mode 100644
index 000000000000..f04b620d200d
--- /dev/null
+++ b/.github/workflows/new-module-verification.yml
@@ -0,0 +1,194 @@
+name: New Module Verification
+
+on:
+ pull_request:
+ types: [opened, synchronize, reopened, labeled, unlabeled]
+ branches:
+ - master
+ - feature/master/*
+
+permissions:
+ contents: read
+
+jobs:
+ new-module-verification:
+ name: Verify New Modules
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Check for new module additions
+ id: check-new-modules
+ shell: bash
+ run: |
+ set -euo pipefail
+
+ echo "::group::Detecting new modules"
+ git fetch origin ${{ github.base_ref }} --depth 1
+
+ # Find new pom.xml files in the diff
+ NEW_POM_FILES=$(git diff --name-only remotes/origin/${{ github.base_ref }} | grep -E '.*pom\.xml$' | grep -v "target/" || echo "")
+
+ if [ -z "$NEW_POM_FILES" ]; then
+ echo "No new modules detected."
+ echo "new_modules_found=false" >> $GITHUB_OUTPUT
+ exit 0
+ fi
+
+ echo "Potential new modules detected:"
+ echo "$NEW_POM_FILES"
+ echo "new_modules_found=true" >> $GITHUB_OUTPUT
+
+ # Save the list of new pom files for later steps
+ echo "$NEW_POM_FILES" > new_pom_files.txt
+ echo "::endgroup::"
+
+ - name: Verify new modules
+ if: steps.check-new-modules.outputs.new_modules_found == 'true'
+ shell: bash
+ run: |
+ set -euo pipefail
+
+ NEW_POM_FILES=$(cat new_pom_files.txt)
+
+ # Initialize counters and error flag
+ TEST_MODULES=0
+ NON_TEST_MODULES=0
+ HAS_ERRORS=0
+
+ echo "::group::Analyzing new modules"
+
+ for POM_FILE in $NEW_POM_FILES; do
+ MODULE_DIR=$(dirname "$POM_FILE")
+ MODULE_NAME=$(basename "$MODULE_DIR")
+
+ # Check if this is a new module (not just an updated pom.xml)
+ if git show remotes/origin/${{ github.base_ref }}:"$POM_FILE" &>/dev/null; then
+ echo "Skipping $POM_FILE - file already exists in base branch"
+ continue
+ fi
+
+ # Skip modules under services directory
+ if [[ "$MODULE_DIR" == services/* ]]; then
+ echo "Skipping $MODULE_DIR - modules under services/ are excluded from verification"
+ continue
+ fi
+
+ echo "New module detected: $MODULE_DIR"
+
+ # Check if it's a test module
+ if [[ "$MODULE_DIR" == *"/test/"* || "$MODULE_DIR" == *"/it/"* || "$MODULE_DIR" == *"-test"* || "$MODULE_DIR" == *"-tests"* ]]; then
+ echo "::group::Test module: $MODULE_DIR"
+ TEST_MODULES=$((TEST_MODULES + 1))
+
+ echo "Verifying test module requirements..."
+
+ # 1. Check if excluded from maven deploy command
+ if ! grep -q "$MODULE_NAME" buildspecs/release-to-maven.yml 2>/dev/null; then
+ echo "::error::Module $MODULE_NAME is not excluded from maven deploy command in buildspecs/release-to-maven.yml"
+ HAS_ERRORS=1
+ else
+ echo "✅ Module is excluded from maven deploy command"
+ fi
+
+ # 2. Check if excluded from javadoc generation
+ if ! grep -q "$MODULE_NAME" buildspecs/release-javadoc.yml 2>/dev/null; then
+ echo "::error::Module $MODULE_NAME is not excluded from javadoc generation in buildspecs/release-javadoc.yml"
+ HAS_ERRORS=1
+ else
+ echo "✅ Module is excluded from javadoc generation"
+ fi
+
+ # 3. Check if Brazil import is skipped
+ if ! grep -q "\"$MODULE_NAME\".*\"skip\".*true" .brazil.json 2>/dev/null; then
+ echo "::error::Module $MODULE_NAME is not configured to skip Brazil import in .brazil.json"
+ HAS_ERRORS=1
+ else
+ echo "✅ Brazil import is skipped for this module"
+ fi
+ echo "::endgroup::"
+
+ else
+ echo "::group::Non-test module: $MODULE_DIR"
+ NON_TEST_MODULES=$((NON_TEST_MODULES + 1))
+
+ echo "Verifying non-test module requirements..."
+
+ # 1. Check for Automatic-Module-Name in pom.xml
+ if ! grep -q "Automatic-Module-Name" "$POM_FILE" 2>/dev/null; then
+ echo "::error::Automatic-Module-Name is not specified in $POM_FILE"
+ HAS_ERRORS=1
+ else
+ echo "✅ Automatic-Module-Name is specified"
+ fi
+
+ # 2. Check if added to tests-coverage-reporting pom.xml
+ if ! grep -q ".*$MODULE_NAME" test/tests-coverage-reporting/pom.xml 2>/dev/null; then
+ echo "::error::Module $MODULE_NAME is not added to tests-coverage-reporting pom.xml"
+ HAS_ERRORS=1
+ else
+ echo "✅ Module is added to tests-coverage-reporting"
+ fi
+
+ # 3. Check if added to aws-sdk-java pom.xml
+ if ! grep -q ".*$MODULE_NAME" aws-sdk-java/pom.xml 2>/dev/null; then
+ echo "::error::Module $MODULE_NAME is not added to aws-sdk-java pom.xml"
+ HAS_ERRORS=1
+ else
+ echo "✅ Module is added to aws-sdk-java pom.xml"
+ fi
+
+ # 4. Check if added to architecture-tests pom.xml
+ if ! grep -q ".*$MODULE_NAME" test/architecture-tests/pom.xml 2>/dev/null; then
+ echo "::error::Module $MODULE_NAME is not added to architecture-tests pom.xml"
+ HAS_ERRORS=1
+ else
+ echo "✅ Module is added to architecture-tests pom.xml"
+ fi
+
+ # 5. Check if added to bom pom.xml
+ if ! grep -q "$MODULE_NAME" bom/pom.xml 2>/dev/null; then
+ echo "::error::Module $MODULE_NAME is not added to bom pom.xml"
+ HAS_ERRORS=1
+ else
+ echo "✅ Module is added to bom pom.xml"
+ fi
+
+ # 6. Check if japicmp plugin config is updated
+ JAPICMP_CHECK=$(grep -A 50 "japicmp-maven-plugin" pom.xml 2>/dev/null | grep -A 50 "" 2>/dev/null | grep -q "$MODULE_NAME" 2>/dev/null || echo "MISSING")
+ if [ "$JAPICMP_CHECK" = "MISSING" ]; then
+ echo "::error::Module $MODULE_NAME is not included in japicmp-maven-plugin includeModules section in pom.xml"
+ HAS_ERRORS=1
+ else
+ echo "✅ Module is included in japicmp-maven-plugin configuration"
+ fi
+
+ # 7. Check if package name mapping is added in .brazil.json
+ if ! grep -q "\"$MODULE_NAME\"" .brazil.json 2>/dev/null; then
+ echo "::error::Package name mapping for $MODULE_NAME is not added in .brazil.json"
+ HAS_ERRORS=1
+ else
+ echo "✅ Package name mapping is added in .brazil.json"
+ fi
+ echo "::endgroup::"
+ fi
+ done
+ echo "::endgroup::"
+
+ echo "::group::Verification summary"
+ echo "Verification complete."
+ echo "Test modules found: $TEST_MODULES"
+ echo "Non-test modules found: $NON_TEST_MODULES"
+
+ if [ $HAS_ERRORS -eq 1 ]; then
+ echo "::error::Some verification checks failed. Please review the errors above and fix them."
+ exit 1
+ else
+ echo "✅ All automated verification checks passed!"
+ fi
+ echo "::endgroup::"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ee86f1225f41..2f742efa378b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,1137 @@
#### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._
+# __2.31.75__ __2025-07-01__
+## __AWS Clean Rooms ML__
+ - ### Features
+ - This release introduces support for incremental training and distributed training for custom models in AWS Clean Rooms ML.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Add the sdk service client version to the useragent
+ - Updated endpoint and partition metadata.
+
+## __Amazon DataZone__
+ - ### Features
+ - Add support for the new optional domain-unit-id parameter in the UpdateProject API.
+
+## __Amazon Elastic Compute Cloud__
+ - ### Features
+ - Add Context to GetInstanceTypesFromInstanceRequirements API
+
+## __Amazon Relational Database Service__
+ - ### Features
+ - Amazon RDS Custom for Oracle now supports multi-AZ database instances.
+
+## __Amazon SageMaker Service__
+ - ### Features
+ - Updated field validation requirements for InstanceGroups.
+
+## __QBusiness__
+ - ### Features
+ - New ChatResponseConfiguration to Customize Q Business chat responses for specific use cases and communication needs. Updated Boosting capability allowing admins to provide preference on date attributes for recency and/or provide a preferred data source.
+
+## __odb__
+ - ### Features
+ - This release adds API operations for Oracle Database@AWS. You can use the APIs to create Exadata infrastructure, ODB networks, and Exadata and Autonomous VM clusters inside AWS data centers. The infrastructure is managed by OCI. You can integrate these resources with AWS services.
+
+# __2.31.74__ __2025-06-30__
+## __AWS ARC - Zonal Shift__
+ - ### Features
+ - Added support for on-demand practice runs and balanced capacity checks in ARC autoshift practice.
+
+## __AWS B2B Data Interchange__
+ - ### Features
+ - Updated APIs to support inbound EDI split capabilities and additional Partnership-level configurations of generated EDI files' contents and format.
+
+## __AWS CloudFormation__
+ - ### Features
+ - Added support for UNKNOWN drift status.
+
+## __AWS Config__
+ - ### Features
+ - Updated ResourceType enum with new resource types onboarded by AWS Config as of June 2025
+
+## __AWS Data Exchange__
+ - ### Features
+ - This release updates resource Id with alphanumeric constraint, including Asset id, Revision id, Data Set id, Job id, and Event Action id.
+
+## __AWS Glue__
+ - ### Features
+ - releasing source processing properties to support source properties for ODB integrations
+
+## __AWS Health Imaging__
+ - ### Features
+ - Added new fields to support the concept of primary image sets within the storage hierarchy.
+
+## __AWS Identity and Access Management__
+ - ### Features
+ - Updated IAM ServiceSpecificCredential support to include expiration, API Key output format instead of username and password for services that will support API keys, and the ability to list credentials for all users in the account for a given service configuration.
+
+## __AWS Outposts__
+ - ### Features
+ - Make ContactName and ContactPhoneNumber required fields when creating and updating Outpost Site Addresses.
+
+## __AWS Parallel Computing Service__
+ - ### Features
+ - Fixed the validation pattern for an instance profile Amazon Resource Name (ARN) in AWS PCS.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+## __AWS Transfer Family__
+ - ### Features
+ - Added support for dual-stack (IPv4 and IPv6) endpoints for SFTP public endpoints and VPC-internal endpoints (SFTP, FTPS, FTP, and AS2), enabling customers to configure new servers with IPv4 or dual-stack mode, convert existing servers to dual-stack, and use IPv6 with service APIs.
+
+## __Amazon Bedrock__
+ - ### Features
+ - Add support for API Keys, Re-Ranker, implicit filter for RAG / KB evaluation for Bedrock APIs.
+
+## __Amazon Bedrock Runtime__
+ - ### Features
+ - Add API Key and document citations support for Bedrock Runtime APIs
+
+## __Amazon CloudWatch Logs__
+ - ### Features
+ - Increase minimum length of queryId parameter to 1 character.
+
+## __Amazon Connect Service__
+ - ### Features
+ - This release introduces ChatMetrics to the model, providing comprehensive analytics insights for Amazon Connect chat conversations. Users can access these detailed metrics through the AWS Connect API by using the DescribeContact operation with their specific instance and contact IDs
+
+## __Amazon DynamoDB__
+ - ### Features
+ - This change adds support for witnesses in global tables. It also adds a new table status, REPLICATION_NOT_AUTHORIZED. This status will indicate scenarios where global replicas table can't be utilized for data plane operations.
+
+## __Amazon EventBridge__
+ - ### Features
+ - Added support for EventBridge Dualstack endpoints in AWS GovCloud (US) regions (us-gov-east-1 and us-gov-west-1). The dualstack endpoints are identical for both FIPS and non-FIPS configurations, following the format: events.{region}.api.aws
+
+## __Amazon QuickSight__
+ - ### Features
+ - Introduced custom permission capabilities for reporting content. Added menu option in exploration to preserve configuration data when textbox menu option is used. Added support for Athena trusted identity propagation.
+
+## __Amazon Simple Systems Manager (SSM)__
+ - ### Features
+ - Introduces AccessType, a new filter value for the DescribeSessions API.
+
+## __Network Flow Monitor__
+ - ### Features
+ - Add ConflictExceptions to UpdateScope and DeleteScope operations for scopes being mutated.
+
+# __2.31.73__ __2025-06-27__
+## __AWS Config__
+ - ### Features
+ - Added important considerations to the PutConformancePack and PutOrganizationConformancPack APIs.
+
+## __AWS Glue__
+ - ### Features
+ - AWS Glue now supports schema, partition and sort management of Apache Iceberg tables using Glue SDK
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+## __Amazon Connect Service__
+ - ### Features
+ - This release adds the following value to an InitiateAs enum: COMPLETED
+
+## __Amazon GuardDuty__
+ - ### Features
+ - Update JSON target for Kubernetes workload resource type.
+
+## __Amazon Q Connect__
+ - ### Features
+ - Adding UnauthorizedException to public SDK
+
+## __Amazon Relational Database Service__
+ - ### Features
+ - StartDBCluster and StopDBCluster can now throw InvalidDBShardGroupStateFault.
+
+## __Amazon Simple Email Service__
+ - ### Features
+ - Added support for new SES regions
+
+# __2.31.72__ __2025-06-26__
+## __AWS Key Management Service__
+ - ### Features
+ - This release updates AWS CLI examples for KMS APIs.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Add code generation validation for missing request URI on an operation.
+ - Add support for defining service model validators and generating valdiation reports during code generation.
+ - Add support for validating that shared models between two services are identical.
+ - Updated endpoint and partition metadata.
+
+## __AWSDeadlineCloud__
+ - ### Features
+ - Added fields to track cumulative task retry attempts for steps and jobs
+
+## __Amazon Elastic Compute Cloud__
+ - ### Features
+ - This release adds support for OdbNetworkArn as a target in VPC Route Tables
+
+## __Amazon Keyspaces__
+ - ### Features
+ - This release provides change data capture (CDC) streams support through updates to the Amazon Keyspaces API.
+
+## __Amazon Keyspaces Streams__
+ - ### Features
+ - This release adds change data capture (CDC) streams support through the new Amazon Keyspaces Streams API.
+
+## __Amazon WorkSpaces__
+ - ### Features
+ - Updated modifyStreamingProperties to support PrivateLink VPC endpoints for directories
+
+## __Code Generator Maven Plugin__
+ - ### Features
+ - Update the generator plugin to support model validation during code generation. In addition, this adds the `writeValidationReport` flag to support writing the validation report to disk.
+
+## __EmfMetricLoggingPublisher__
+ - ### Bugfixes
+ - Fixed the bug that EmfMetricLoggingPublisher not properly publishing Long type metrics
+
+## __Managed integrations for AWS IoT Device Management__
+ - ### Features
+ - Adding managed integrations APIs for IoT Device Management to onboard and control devices across different manufacturers, connectivity protocols and third party vendor clouds. APIs include managed thing operations, provisioning profile management, and cloud connector operations.
+
+## __QBusiness__
+ - ### Features
+ - Added support for App level authentication for QBusiness DataAccessor using AWS IAM Identity center Trusted Token issuer
+
+# __2.31.71__ __2025-06-25__
+## __AWS S3 Control__
+ - ### Features
+ - Add support for the ability to use Amazon S3 Access Points with Amazon FSx for OpenZFS file systems.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Adding constant to each SDK module to represent its version
+
+## __AWS Storage Gateway__
+ - ### Features
+ - This release adds IPv6 support to the Storage Gateway APIs. APIs that previously only accept or return IPv4 address will now accept or return both IPv4 and IPv6 addresses.
+
+## __Amazon EC2 Container Service__
+ - ### Features
+ - Updates for change to Amazon ECS default log driver mode from blocking to non-blocking
+
+## __Amazon FSx__
+ - ### Features
+ - Add support for the ability to create Amazon S3 Access Points for Amazon FSx for OpenZFS file systems.
+
+## __Amazon Simple Storage Service__
+ - ### Features
+ - Adds support for additional server-side encryption mode and storage class values for accessing Amazon FSx data from Amazon S3 using S3 Access Points
+
+## __Amazon Textract__
+ - ### Features
+ - Add RotationAngle field to Geometry of WORD blocks for Textract AnalyzeDocument API
+
+## __Amazon WorkSpaces Thin Client__
+ - ### Features
+ - Remove Tags field from Get API responses
+
+# __2.31.70__ __2025-06-24__
+## __AWS AI Ops__
+ - ### Features
+ - Adds support for cross account investigations for CloudWatch investigations AI Operations (AIOps).
+
+## __AWS Batch__
+ - ### Features
+ - Add userdataType to LaunchTemplateSpecification and LaunchTemplateSpecificationOverride.
+
+## __AWS License Manager__
+ - ### Features
+ - AWS License Manager now supports license type conversions for AWS Marketplace products. Customers can provide Marketplace codes in the source license context or destination license context in the CreateLicenseConversionTaskForResource requests.
+
+## __Amazon Bedrock__
+ - ### Features
+ - We are making ListFoundationModelAgreementOffers, DeleteFoundationModelAgreement, CreateFoundationModelAgreement, GetFoundationModelAvailability, PutUseCaseForModelAccess and GetUseCaseForModelAccess APIs public, previously they were console.
+
+## __Amazon Elastic Compute Cloud__
+ - ### Features
+ - This release allows you to create and register AMIs while maintaining their underlying EBS snapshots within Local Zones.
+
+## __Amazon GameLift__
+ - ### Features
+ - Add support for UDP ping beacons to ListLocations API, including new PingBeacon and UDPEndpoint data types within its Locations return value. Use UDP ping beacon endpoints to help measure real-time network latency for multiplayer games.
+
+## __Amazon Relational Database Service__
+ - ### Features
+ - Adding support for RDS on Dedicated Local Zones, including local backup target, snapshot availability zone and snapshot target
+
+## __Amazon Route 53 Resolver__
+ - ### Features
+ - Add support for iterative DNS queries through the new INBOUND_DELEGATION endpoint. Add delegation support through the Outbound Endpoints with DELEGATE rules.
+
+## __Amazon Transcribe Service__
+ - ### Features
+ - This Feature Adds Support for the "et-EE" Locale for Batch Operations
+
+## __Elastic Load Balancing__
+ - ### Features
+ - Add Paginator for DescribeAccountLimits, and fix Paginators for DescribeTrustStoreAssociations, DescribeTrustStoreRevocations, and DescribeTrustStores
+
+# __2.31.69__ __2025-06-23__
+## __AWS Glue__
+ - ### Features
+ - AWS Glue now supports sort and z-order strategy for managed automated compaction for Iceberg tables in addition to binpack.
+
+## __AWS SDK for Java v2__
+ - ### Bugfixes
+ - Ignore unknown properties on endpoints in endpoint rules.
+
+## __Amazon S3 Tables__
+ - ### Features
+ - S3 Tables now supports sort and z-order compaction strategies for Iceberg tables in addition to binpack.
+
+## __Amazon Workspaces Instances__
+ - ### Features
+ - Added support for Amazon WorkSpaces Instances API
+
+# __2.31.68__ __2025-06-20__
+## __AWS Elemental MediaConvert__
+ - ### Features
+ - This release adds a new SPECIFIED_OPTIMAL option for handling DDS when using DVB-Sub with high resolution video.
+
+## __AWS Glue__
+ - ### Features
+ - AWS Glue Data Quality now provides aggregated metrics in evaluation results when publishAggregatedMetrics with row-level results are enabled. These metrics include summary statistics showing total counts of processed, passed, and failed rows and rules in a single view.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+## __Amazon Bedrock__
+ - ### Features
+ - Add support for tiers in Content Filters and Denied Topics for Amazon Bedrock Guardrails.
+
+## __Amazon EC2 Container Service__
+ - ### Features
+ - Add ECS support for Windows Server 2025
+
+## __Amazon Location Service Places V2__
+ - ### Features
+ - Geocode, ReverseGeocode, and GetPlace APIs added Intersections and SecondaryAddresses. To use, add to the AdditionalFeatures list in your request. This provides info about nearby intersections and secondary addresses that are associated with a main address. Also added MainAddress and ParsedQuery.
+
+# __2.31.67__ __2025-06-19__
+## __AWS Lambda__
+ - ### Features
+ - Support Schema Registry feature for Kafka Event Source Mapping. Customers can now configure a Schema Registry to enable schema validation and filtering for Avro, Protobuf, and JSON-formatted events in Lambda for Kafka Event Source.
+
+## __Amazon Bedrock__
+ - ### Features
+ - This release of the SDK has the API and documentation for the createcustommodel API. This feature lets you copy a trained model into Amazon Bedrock for inference.
+
+## __Amazon SageMaker Service__
+ - ### Features
+ - This release introduces alternative support for utilizing CFN templates from S3 for SageMaker Projects.
+
+## __EMR Serverless__
+ - ### Features
+ - This release adds the capability to enable IAM IdentityCenter Trusted Identity Propagation for users running Interactive Sessions on EMR Serverless Applications.
+
+## __Payment Cryptography Control Plane__
+ - ### Features
+ - Additional support for managing HMAC keys that adheres to changes documented in X9.143-2021 and provides better interoperability for key import/export
+
+## __Payment Cryptography Data Plane__
+ - ### Features
+ - Additional support for managing HMAC keys that adheres to changes documented in X9.143-2021 and provides better interoperability for key import/export
+
+# __2.31.66__ __2025-06-18__
+## __AWS AI Ops__
+ - ### Features
+ - This is the initial SDK release for Amazon AI Operations (AIOps). AIOps is a generative AI-powered assistant that helps you respond to incidents in your system by scanning your system's telemetry and quickly surface suggestions that might be related to your issue.
+
+## __AWS S3__
+ - ### Features
+ - Adds the ability to presign HeadObject and HeadBucket requests with the S3 Presigner
+ - Contributed by: [@tmccombs](https://github.com/tmccombs)
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Adding a new method of constructing ARNs without exceptions as control flow
+ - Updated endpoint and partition metadata.
+
+## __Amazon CloudWatch Logs__
+ - ### Features
+ - Added CloudWatch Logs Transformer support for converting CloudTrail, VPC Flow, EKS Audit, AWS WAF and Route53 Resolver logs to OCSF v1.1 format.
+
+## __Amazon SageMaker Service__
+ - ### Features
+ - Add support for p6-b200 instance type for SageMaker Hyperpod
+
+## __Amazon Simple Storage Service__
+ - ### Features
+ - Added support for renaming objects within the same bucket using the new RenameObject API.
+
+## __Auto Scaling__
+ - ### Features
+ - Add IncludeInstances parameter to DescribeAutoScalingGroups API
+
+## __Contributors__
+Special thanks to the following contributors to this release:
+
+[@tmccombs](https://github.com/tmccombs)
+# __2.31.65__ __2025-06-17__
+## __AWS Backup__
+ - ### Features
+ - AWS Backup is adding support for integration of its logically air-gapped vaults with the AWS Organizations Multi-party approval capability.
+
+## __AWS Certificate Manager__
+ - ### Features
+ - Adds support for Exportable Public Certificates
+
+## __AWS Database Migration Service__
+ - ### Features
+ - Add "Virtual" field to Data Provider as well as "S3Path" and "S3AccessRoleArn" fields to DataProvider settings
+
+## __AWS Multi-party Approval__
+ - ### Features
+ - This release enables customers to create Multi-party approval teams and approval requests to protect supported operations.
+
+## __AWS Network Firewall__
+ - ### Features
+ - Release of Active Threat Defense in Network Firewall
+
+## __AWS Organizations__
+ - ### Features
+ - Add support for policy operations on the SECURITYHUB_POLICY policy type.
+
+## __AWS SDK for Java V2__
+ - ### Bugfixes
+ - Fix a bug in ConstructorCache when classes are GC'ed but not removed from cache
+
+## __AWS Security Token Service__
+ - ### Features
+ - The AWS Security Token Service APIs AssumeRoleWithSAML and AssumeRoleWithWebIdentity can now be invoked without pre-configured AWS credentials in the SDK configuration.
+
+## __AWS SecurityHub__
+ - ### Features
+ - Adds operations, structures, and exceptions required for public preview release of Security Hub V2.
+
+## __AWS WAFV2__
+ - ### Features
+ - AWS WAF can now suggest protection packs for you based on the application information you provide when you create a webACL.
+
+## __Access Analyzer__
+ - ### Features
+ - We are launching a new analyzer type, internal access analyzer. The new analyzer will generate internal access findings, which help customers understand who within their AWS organization or AWS Account has access to their critical AWS resources.
+
+## __Amazon Bedrock__
+ - ### Features
+ - This release of the SDK has the API and documentation for the createcustommodel API. This feature lets you copy a trained model into Amazon Bedrock for inference.
+
+## __Amazon GuardDuty__
+ - ### Features
+ - Adding support for extended threat detection for EKS Audit Logs and EKS Runtime Monitoring.
+
+## __Inspector2__
+ - ### Features
+ - Add Code Repository Scanning as part of AWS InspectorV2
+
+# __2.31.64__ __2025-06-16__
+## __AWS Network Firewall__
+ - ### Features
+ - You can now create firewalls using a Transit Gateway instead of a VPC, resulting in a TGW attachment.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Add tracking of RequestBody/ResponseTransfromer implementations used in UserAgent.
+
+## __Amazon Bedrock__
+ - ### Features
+ - This release of the SDK has the API and documentation for the createcustommodel API. This feature lets you copy a Amazon SageMaker trained Amazon Nova model into Amazon Bedrock for inference.
+
+## __Amazon Elastic Container Registry__
+ - ### Features
+ - The `DescribeImageScanning` API now includes `lastInUseAt` and `InUseCount` fields that can be used to prioritize vulnerability remediation for images that are actively being used.
+
+## __Amazon SageMaker Service__
+ - ### Features
+ - This release 1) adds a new S3DataType Converse for SageMaker training 2)adds C8g R7gd M8g C6in P6 P6e instance type for SageMaker endpoint 3) adds m7i, r7i, c7i instance type for SageMaker Training and Processing.
+
+# __2.31.63__ __2025-06-12__
+## __AWS IoT FleetWise__
+ - ### Features
+ - Add new status READY_FOR_CHECKIN used for vehicle synchronisation
+
+## __AWS Key Management Service__
+ - ### Features
+ - AWS KMS announces the support of ML-DSA key pairs that creates post-quantum safe digital signatures.
+
+## __AWS Parallel Computing Service__
+ - ### Features
+ - Fixed regex patterns for ARN fields.
+
+## __Amazon API Gateway__
+ - ### Features
+ - Documentation updates for Amazon API Gateway
+
+## __Amazon EC2 Container Service__
+ - ### Features
+ - This Amazon ECS release supports updating the capacityProviderStrategy parameter in update-service.
+
+## __AmazonApiGatewayV2__
+ - ### Features
+ - Documentation updates for Amazon API Gateway
+
+## __AmazonConnectCampaignServiceV2__
+ - ### Features
+ - Added PutInstanceCommunicationLimits and GetInstanceCommunicationLimits APIs
+
+## __EMR Serverless__
+ - ### Features
+ - This release adds support for retrieval of the optional executionIamPolicy field in the GetJobRun API response.
+
+# __2.31.62__ __2025-06-11__
+## __AWS Control Catalog__
+ - ### Features
+ - Introduced ListControlMappings API that retrieves control mappings. Added control aliases and governed resources fields in GetControl and ListControls APIs. New filtering capability in ListControls API, with implementation identifiers and implementation types.
+
+## __AWS Network Manager__
+ - ### Features
+ - Add support for public DNS hostname resolution to private IP addresses across Cloud WAN-managed VPCs. Add support for security group referencing across Cloud WAN-managed VPCs.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+ - ### Bugfixes
+ - Deprecated DefaultCredentialsProvider.create() since it creates Singleton instance
+ - Contributed by: [@jencymaryjoseph](https://github.com/jencymaryjoseph)
+
+## __AWS WAFV2__
+ - ### Features
+ - WAF now provides two DDoS protection options: resource-level monitoring for Application Load Balancers and the AWSManagedRulesAntiDDoSRuleSet managed rule group for CloudFront distributions.
+
+## __Amazon Elastic Kubernetes Service__
+ - ### Features
+ - Release for EKS Pod Identity Cross Account feature and disableSessionTags flag.
+
+## __Amazon Lex Model Building V2__
+ - ### Features
+ - Add support for the Assisted NLU feature to improve bot performance
+
+## __Amazon Relational Database Service__
+ - ### Features
+ - Updates Amazon RDS documentation for Amazon RDS for Db2 cross-Region replicas in standby mode.
+
+## __Contributors__
+Special thanks to the following contributors to this release:
+
+[@jencymaryjoseph](https://github.com/jencymaryjoseph)
+# __2.31.61__ __2025-06-10__
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+## __Amazon GameLift Streams__
+ - ### Features
+ - Documentation updates for Amazon GameLift Streams to address formatting errors, correct resource ID examples, and update links to other guides
+
+# __2.31.60__ __2025-06-09__
+## __AWS AppSync__
+ - ### Features
+ - Deprecate `atRestEncryptionEnabled` and `transitEncryptionEnabled` attributes in `CreateApiCache` action. Encryption is always enabled for new caches.
+
+## __AWS Cost Explorer Service__
+ - ### Features
+ - Support dual-stack endpoints for ce api
+
+## __AWS Marketplace Catalog Service__
+ - ### Features
+ - The ListEntities API now supports the EntityID, LastModifiedDate, ProductTitle, and Visibility filters for machine learning products. You can also sort using all of those filters.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Adds support for configuring bearer auth using a token sourced from the environment for services with the `enableEnvironmentBearerToken` customization flag.
+ - Updated Region class generation to use Partitions.json instead of the Endpoints.json and removed the hardcoded global regions.
+ - Updated endpoint and partition metadata.
+
+## __Amazon Connect Customer Profiles__
+ - ### Features
+ - This release introduces capability of Profile Explorer, using correct ingestion timestamp & using historical data for computing calculated attributes, and new standard objects for T&H as part of Amazon Connect Customer Profiles service.
+
+## __Amazon Elastic Compute Cloud__
+ - ### Features
+ - Release to support Elastic VMware Service (Amazon EVS) Subnet and Amazon EVS Network Interface Types.
+
+## __Amazon Elastic File System__
+ - ### Features
+ - Added support for Internet Protocol Version 6 (IPv6) on EFS Service APIs and mount targets.
+
+## __Amazon WorkSpaces Thin Client__
+ - ### Features
+ - Add ConflictException to UpdateEnvironment API
+
+# __2.31.59__ __2025-06-06__
+## __AWS Key Management Service__
+ - ### Features
+ - Remove unpopulated KeyMaterialId from Encrypt Response
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Add support for protocols field in service model
+ - Updated endpoint and partition metadata.
+
+ - ### Bugfixes
+ - Fix expiration in past warning during profile credential loading.
+
+## __Agents for Amazon Bedrock Runtime__
+ - ### Features
+ - This release introduces the `PromptCreationConfigurations` input parameter, which includes fields to control prompt population for `InvokeAgent` or `InvokeInlineAgent` requests.
+
+## __Amazon Rekognition__
+ - ### Features
+ - Adds support for defining an ordered preference list of different Rekognition Face Liveness challenge types when calling CreateFaceLivenessSession.
+
+## __Amazon Relational Database Service__
+ - ### Features
+ - Include Global Cluster Identifier in DBCluster if the DBCluster is a Global Cluster Member.
+
+## __Amazon Route 53__
+ - ### Features
+ - Amazon Route 53 now supports the Asia Pacific (Taipei) Region (ap-east-2) for latency records, geoproximity records, and private DNS for Amazon VPCs in that region.
+
+## __Amazon S3 Tables__
+ - ### Features
+ - S3 Tables now supports getting details about a table via its table ARN.
+
+# __2.31.58__ __2025-06-05__
+## __AWS Billing and Cost Management Pricing Calculator__
+ - ### Features
+ - Updating the minimum for List APIs to be 1 (instead of 0)
+
+## __AWS CloudFormation__
+ - ### Features
+ - Add new warning type 'EXCLUDED_PROPERTIES'
+
+## __AWS Key Management Service__
+ - ### Features
+ - AWS KMS announces the support for on-demand rotation of symmetric-encryption KMS keys with imported key material (EXTERNAL origin).
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Added ability to configure preferred authentication schemes when multiple auth options are available.
+ - Updated endpoint and partition metadata.
+
+## __AWS WAFV2__
+ - ### Features
+ - AWS WAF adds support for ASN-based traffic filtering and support for ASN-based rate limiting.
+
+## __Amazon DynamoDB Enhanced Client__
+ - ### Bugfixes
+ - Fixed DynamoDbEnhancedClient DefaultDynamoDbAsyncTable::createTable() to create secondary indices that are defined on annotations of the POJO class, similar to DefaultDynamoDbTable::createTable().
+
+# __2.31.57__ __2025-06-04__
+## __AWS Amplify__
+ - ### Features
+ - Update documentation for cacheConfig in CreateApp API
+
+## __AWS Elemental MediaConvert__
+ - ### Features
+ - This release includes support for embedding and signing C2PA content credentials in MP4 outputs.
+
+## __AWS Invoicing__
+ - ### Features
+ - Added new Invoicing ListInvoiceSummaries API Operation
+
+## __AWS MediaConnect__
+ - ### Features
+ - This release updates the DescribeFlow API to show peer IP addresses. You can now identify the peer IP addresses of devices connected to your sources and outputs. This helps you to verify and troubleshoot your flow's active connections.
+
+## __AWS Network Firewall__
+ - ### Features
+ - You can now monitor flow and alert log metrics from the Network Firewall console.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+## __Amazon Elastic VMware Service__
+ - ### Features
+ - Amazon Elastic VMware Service (Amazon EVS) allows you to run VMware Cloud Foundation (VCF) directly within your Amazon VPC including simplified self-managed migration experience with guided workflow in AWS console or via AWS CLI, get full access to their VCF deployment and VCF license portability.
+
+## __Amazon SageMaker Service__
+ - ### Features
+ - Added support for p6-b200 instance type in SageMaker Training Jobs and Training Plans.
+
+## __Amazon Transcribe Service__
+ - ### Features
+ - AWS Healthscribe now supports new templates for the clinical note summary: BIRP, SIRP, DAP, BEHAVIORAL_SOAP, and PHYSICAL_SOAP
+
+## __Amazon Transcribe Streaming Service__
+ - ### Features
+ - AWS Healthscribe now supports new templates for the clinical note summary: BIRP, SIRP, DAP, BEHAVIORAL_SOAP, and PHYSICAL_SOAP
+
+## __S3 Transfer Manager__
+ - ### Bugfixes
+ - DownloadFilter type incompatability methods overriden from extended interface
+ - Contributed by: [@jencymaryjoseph](https://github.com/jencymaryjoseph)
+
+## __Contributors__
+Special thanks to the following contributors to this release:
+
+[@jencymaryjoseph](https://github.com/jencymaryjoseph)
+# __2.31.56__ __2025-06-03__
+## __AWS S3 Event Notifications__
+ - ### Bugfixes
+ - Fixed parsing of S3 event notifications to allow eventTime to be null when eventName is not
+ - Contributed by: [@reifiedbeans](https://github.com/reifiedbeans)
+
+## __AWS SDK for Java v2__
+ - ### Bugfixes
+ - Fix NPE in `ProfileFileSupplier.defaultSupplier` when both credentials and config files do not exist.
+
+## __Amazon API Gateway__
+ - ### Features
+ - Adds support to set the routing mode for a custom domain name.
+
+## __AmazonApiGatewayV2__
+ - ### Features
+ - Adds support to create routing rules and set the routing mode for a custom domain name.
+
+## __EMR Serverless__
+ - ### Features
+ - AWS EMR Serverless: Adds a new option in the CancelJobRun API in EMR 7.9.0+, to cancel a job with grace period. This feature is enabled by default with a 120-second grace period for streaming jobs and is not enabled by default for batch jobs.
+
+## __Contributors__
+Special thanks to the following contributors to this release:
+
+[@reifiedbeans](https://github.com/reifiedbeans)
+# __2.31.55__ __2025-06-02__
+## __AWS Backup__
+ - ### Features
+ - You can now subscribe to Amazon SNS notifications and Amazon EventBridge events for backup indexing. You can now receive notifications when a backup index is created, deleted, or fails to create, enhancing your ability to monitor and track your backup operations.
+
+## __AWS Compute Optimizer__
+ - ### Features
+ - This release enables AWS Compute Optimizer to analyze Amazon Aurora database clusters and generate Aurora I/O-Optimized recommendations.
+
+## __AWS EntityResolution__
+ - ### Features
+ - Add support for generating match IDs in near real-time.
+
+## __AWS Parallel Computing Service__
+ - ### Features
+ - Introduces SUSPENDING and SUSPENDED states for clusters, compute node groups, and queues.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Improve the endpoint rules performance by directly passing the needed params instead of using a POJO to keep track of them.
+ - Updated endpoint and partition metadata.
+
+## __Agents for Amazon Bedrock__
+ - ### Features
+ - This release adds the Agent Lifecycle Paused State feature to Amazon Bedrock agents. By using an agent's alias, you can temporarily suspend agent operations during maintenance, updates, or other situations.
+
+## __Amazon Athena__
+ - ### Features
+ - Add support for the managed query result in the workgroup APIs. The managed query result configuration enables users to store query results to Athena owned storage.
+
+## __Amazon EC2 Container Service__
+ - ### Features
+ - Updates Amazon ECS documentation to include note for upcoming default log driver mode change.
+
+## __Amazon Elastic Kubernetes Service__
+ - ### Features
+ - Add support for filtering ListInsights API calls on MISCONFIGURATION insight category
+
+## __Cost Optimization Hub__
+ - ### Features
+ - Support recommendations for Aurora instance and Aurora cluster storage.
+
+## __Synthetics__
+ - ### Features
+ - Support for Java runtime handler pattern.
+
+# __2.31.54__ __2025-05-30__
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+## __Amazon SageMaker Service__
+ - ### Features
+ - Release new parameter CapacityReservationConfig in ProductionVariant
+
+## __EMR Serverless__
+ - ### Features
+ - This release adds the capability for users to specify an optional Execution IAM policy in the StartJobRun action. The resulting permissions assumed by the job run is the intersection of the permissions in the Execution Role and the specified Execution IAM Policy.
+
+# __2.31.53__ __2025-05-29__
+## __AWS Amplify__
+ - ### Features
+ - Add support for customizable build instance sizes. CreateApp and UpdateApp operations now accept a new JobConfig parameter composed of BuildComputeType.
+
+## __AWS Billing and Cost Management Pricing Calculator__
+ - ### Features
+ - Add AFTER_DISCOUNTS_AND_COMMITMENTS to Workload Estimate Rate Type. Set ListWorkLoadEstimateUsage maxResults range to minimum of 0 and maximum of 300.
+
+## __AWS CloudTrail__
+ - ### Features
+ - CloudTrail Feature Release: Support for Enriched Events with Configurable Context for Event Data Store
+
+## __AWS Data Exchange__
+ - ### Features
+ - This release adds Tag support for Event Action resource, through which customers can create event actions with Tags and retrieve event actions with Tags.
+
+## __AWS DataSync__
+ - ### Features
+ - AgentArns field is made optional for Object Storage and Azure Blob location create requests. Location credentials are now managed via Secrets Manager, and may be encrypted with service managed or customer managed keys. Authentication is now optional for Azure Blob locations.
+
+## __Amazon Connect Service__
+ - ### Features
+ - Amazon Connect Service Feature: Email Recipient Limit Increase
+
+## __Amazon FSx__
+ - ### Features
+ - FSx API changes to support the public launch of new Intelligent Tiering storage class on Amazon FSx for Lustre
+
+## __Amazon Interactive Video Service RealTime__
+ - ### Features
+ - IVS Real-Time now offers customers the participant replication that allow customers to copy a participant from one stage to another.
+
+## __Amazon SageMaker Service__
+ - ### Features
+ - Add maintenance status field to DescribeMlflowTrackingServer API response
+
+## __Amazon Simple Storage Service__
+ - ### Features
+ - Adding checksum support for S3 PutBucketOwnershipControls API.
+
+## __AmazonMWAA__
+ - ### Features
+ - Amazon MWAA now lets you choose a worker replacement strategy when updating an environment. This release adds two worker replacement strategies: FORCED (default), which stops workers immediately, and GRACEFUL, which allows workers to finish current tasks before shutting down.
+
+## __Auto Scaling__
+ - ### Features
+ - Add support for "apple" CpuManufacturer in ABIS
+
+# __2.31.52__ __2025-05-28__
+## __AWS Network Firewall__
+ - ### Features
+ - You can now use VPC endpoint associations to create multiple firewall endpoints for a single firewall.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+## __Amazon Elastic Compute Cloud__
+ - ### Features
+ - Enable the option to automatically delete underlying Amazon EBS snapshots when deregistering Amazon Machine Images (AMIs)
+
+## __Amazon EventBridge__
+ - ### Features
+ - Allow for more than 2 characters for location codes in EventBridge ARNs
+
+## __Cost Optimization Hub__
+ - ### Features
+ - This release allows customers to modify their preferred commitment term and payment options.
+
+## __Synthetics__
+ - ### Features
+ - Add support to change ephemeral storage. Add a new field "TestResult" under CanaryRunStatus.
+
+# __2.31.51__ __2025-05-27__
+## __AWS Cost Explorer Service__
+ - ### Features
+ - This release introduces Cost Comparison feature (GetCostAndUsageComparisons, GetCostComparisonDrivers) allowing you find cost variations across multiple dimensions and identify key drivers of spending changes.
+
+## __AWSDeadlineCloud__
+ - ### Features
+ - AWS Deadline Cloud service-managed fleets now support storage profiles. With storage profiles, you can map file paths between a workstation and the worker hosts running the job.
+
+## __Amazon Elastic Compute Cloud__
+ - ### Features
+ - This release adds three features - option to store AWS Site-to-Site VPN pre-shared keys in AWS Secrets Manager, GetActiveVpnTunnelStatus API to check the in-use VPN algorithms, and SampleType option in GetVpnConnectionDeviceSampleConfiguration API to get recommended sample configs for VPN devices.
+
+# __2.31.50__ __2025-05-23__
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+ - ### Bugfixes
+ - Fix CompletableFuture hanging when RetryStrategy/MetricsCollector raise errors
+
+## __Amazon Elastic Compute Cloud__
+ - ### Features
+ - This release adds support for the C7i-flex, M7i-flex, I7i, I7ie, I8g, P6-b200, Trn2, C8gd, M8gd and R8gd instances
+
+## __Netty NIO HTTP Client__
+ - ### Bugfixes
+ - Enable Netty HTTP header validation when connecting with proxy
+
+## __Security Incident Response__
+ - ### Features
+ - Update PrincipalId pattern documentation to reflect what user should receive back from the API call
+
+# __2.31.49__ __2025-05-22__
+## __AWS Audit Manager__
+ - ### Features
+ - With this release, the AssessmentControl description field has been deprecated, as of May 19, 2025. Additionally, the UpdateAssessment API can now return a ServiceQuotaExceededException when applicable service quotas are exceeded.
+
+## __AWS Glue__
+ - ### Features
+ - This release supports additional ConversionSpec parameter as part of IntegrationPartition Structure in CreateIntegrationTableProperty API. This parameter is referred to apply appropriate column transformation for columns that are used for timestamp based partitioning
+
+## __AWS SDK for Java v2__
+ - ### Bugfixes
+ - Update non-streaming error unmarshalling to properly unmarshall exceptions to their expected types.
+
+## __Amazon Aurora DSQL__
+ - ### Features
+ - Features: support for customer managed encryption keys
+
+## __Amazon Prometheus Service__
+ - ### Features
+ - Add QueryLoggingConfiguration APIs for Amazon Managed Prometheus
+
+# __2.31.48__ __2025-05-21__
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+## __Agents for Amazon Bedrock Runtime__
+ - ### Features
+ - Amazon Bedrock introduces asynchronous flows (in preview), which let you run flows for longer durations and yield control so that your application can perform other tasks and you don't have to actively monitor the flow's progress.
+
+## __Amazon CloudWatch__
+ - ### Features
+ - Adds support for setting up Contributor Insight rules on logs transformed via Logs Transformation feature.
+
+## __Amazon Elastic Compute Cloud__
+ - ### Features
+ - Release of Dualstack and Ipv6-only EC2 Public DNS hostnames
+
+## __Application Auto Scaling__
+ - ### Features
+ - Doc only update that addresses a customer reported issue.
+
+## __Partner Central Selling API__
+ - ### Features
+ - Modified validation to allow expectedCustomerSpend array with zero elements in Partner Opportunity operations.
+
+# __2.31.47__ __2025-05-20__
+## __AWS DataSync__
+ - ### Features
+ - Remove Discovery APIs from the DataSync service
+
+## __AWS Glue__
+ - ### Features
+ - Enhanced AWS Glue ListConnectionTypes API Model with additional metadata fields.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+## __Amazon Elastic Compute Cloud__
+ - ### Features
+ - This release expands the ModifyInstanceMaintenanceOptions API to enable or disable instance migration during customer-initiated reboots for EC2 Scheduled Reboot Events.
+
+## __Amazon Relational Database Service__
+ - ### Features
+ - This release introduces the new DescribeDBMajorEngineVersions API for describing the properties of specific major versions of database engines.
+
+## __CloudWatch Observability Access Manager__
+ - ### Features
+ - Add IncludeTags field to GetLink, GetSink and UpdateLink API
+
+## __Inspector2__
+ - ### Features
+ - This release adds GetClustersForImage API and filter updates as part of the mapping of container images to running containers feature.
+
+# __2.31.46__ __2025-05-19__
+## __AWS Elemental MediaPackage v2__
+ - ### Features
+ - This release adds support for DVB-DASH, EBU-TT-D subtitle format, and non-compacted manifests for DASH in MediaPackage v2 Origin Endpoints.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+## __Amazon Aurora DSQL__
+ - ### Features
+ - CreateMultiRegionCluster and DeleteMultiRegionCluster APIs removed
+
+## __Amazon Elastic Compute Cloud__
+ - ### Features
+ - This release includes new APIs for System Integrity Protection (SIP) configuration and automated root volume ownership delegation for EC2 Mac instances.
+
+# __2.31.45__ __2025-05-16__
+## __AWS CodePipeline__
+ - ### Features
+ - CodePipeline now supports new API ListDeployActionExecutionTargets that lists the deployment target details for deploy action executions.
+
+## __AWS Glue__
+ - ### Features
+ - Changes include (1) Excel as S3 Source type and XML and Tableau's Hyper as S3 Sink types, (2) targeted number of partitions parameter in S3 sinks and (3) new compression types in CSV/JSON and Parquet S3 sinks.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+ - ### Bugfixes
+ - Fix a regression for the JSON REST protocol for which an structure explicit payload member was set to the empty object instead of null
+
+## __Amazon EC2 Container Service__
+ - ### Features
+ - This is an Amazon ECs documentation only release to support the change of the container exit "reason" field from 255 characters to 1024 characters.
+
+## __Amazon EMR__
+ - ### Features
+ - Added APIs for managing Application UIs: Access Persistent (serverless) UIs via CreatePersistentAppUI DescribePersistentAppUI & GetPersistentAppUIPresignedURL, and Cluster-based UIs through GetOnClusterAppUIPresignedURL. Supports Yarn, Spark History, and TEZ interfaces.
+
+## __Amazon Neptune__
+ - ### Features
+ - This release adds Global Cluster Switchover capability which enables you to change your global cluster's primary AWS Region, the region that serves writes, while preserving the replication between all regions in the global cluster.
+
+## __Data Automation for Amazon Bedrock__
+ - ### Features
+ - Add support for VIDEO modality to BlueprintType enum.
+
+## __Runtime for Amazon Bedrock Data Automation__
+ - ### Features
+ - Add AssetProcessingConfiguration for video segment to InputConfiguration
+
+## __Service Quotas__
+ - ### Features
+ - This release introduces CreateSupportCase operation to SDK.
+
+# __2.31.44__ __2025-05-15__
+## __AWS CodeBuild__
+ - ### Features
+ - AWS CodeBuild now supports Docker Server capability
+
+## __AWS Control Tower__
+ - ### Features
+ - Updated the descriptions for the AWS Control Tower Baseline APIs to make them more intuitive.
+
+## __AWS Database Migration Service__
+ - ### Features
+ - Introduces Data Resync feature to describe-table-statistics and IAM database authentication for MariaDB, MySQL, and PostgreSQL.
+
+## __AWS Parallel Computing Service__
+ - ### Features
+ - This release adds support for Slurm accounting. For more information, see the Slurm accounting topic in the AWS PCS User Guide. Slurm accounting is supported for Slurm 24.11 and later. This release also adds 24.11 as a valid value for the version parameter of the Scheduler data type.
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Small optimization for endpoint rules. Lazily compile the region pattern instead of parsing it every time. This will pay the penalty of parsing it just once at the cost of using a bit more of memory to keep the parsed pattern.
+
+## __Agents for Amazon Bedrock__
+ - ### Features
+ - Amazon Bedrock Flows introduces DoWhile loops nodes, parallel node executions, and enhancements to knowledge base nodes.
+
+## __Amazon WorkSpaces__
+ - ### Features
+ - Added the new AlwaysOn running mode for WorkSpaces Pools. Customers can now choose between AlwaysOn (for instant access, with hourly usage billing regardless of connection status), or AutoStop (to optimize cost, with a brief startup delay) for their pools.
+
+# __2.31.43__ __2025-05-14__
+## __AWS Elemental MediaConvert__
+ - ### Features
+ - This update enables cropping for video overlays and adds a new STL to Teletext upconversion toggle to preserve styling.
+
+## __Amazon CloudWatch Logs__
+ - ### Features
+ - This release adds a new API "ListLogGroups" and an improvement in API "DescribeLogGroups"
+
+## __Amazon Cognito Identity Provider__
+ - ### Features
+ - Add exceptions to WebAuthn operations.
+
+## __Amazon Kinesis Firehose__
+ - ### Features
+ - This release adds catalogARN support for s3 tables multi-catalog catalogARNs.
+
+# __2.31.42__ __2025-05-13__
+## __AWS Control Tower__
+ - ### Features
+ - AWS Control Tower now reports the inheritance drift status for EnabledBaselines through the GetEnabledBaseline and ListEnabledBaselines APIs. You can now filter EnabledBaselines by their enablement and drift status using the ListEnabledBaselines API to view accounts and OUs that require attention.
+
+## __AWS License Manager__
+ - ### Features
+ - Add Tagging feature to resources in the Managed Entitlements service. License and Grant resources can now be tagged.
+
+## __Agents for Amazon Bedrock Runtime__
+ - ### Features
+ - Changes for enhanced metadata in trace
+
+## __Amazon Aurora DSQL__
+ - ### Features
+ - CreateMultiRegionClusters and DeleteMultiRegionClusters APIs marked as deprecated. Introduced new multi-Region clusters creation experience through multiRegionProperties parameter in CreateCluster API.
+
+## __Amazon Bedrock__
+ - ### Features
+ - Enable cross-Region inference for Amazon Bedrock Guardrails by using the crossRegionConfig parameter when calling the CreateGuardrail or UpdateGuardrail operation.
+
+## __Amazon EC2 Container Service__
+ - ### Features
+ - This release extends functionality for Amazon EBS volumes attached to Amazon ECS tasks by adding support for the new EBS volumeInitializationRate parameter in ECS RunTask/StartTask/CreateService/UpdateService APIs.
+
+# __2.31.41__ __2025-05-12__
+## __AWS Elemental MediaLive__
+ - ### Features
+ - Add support to the AV1 rate control mode
+
+## __AWS Identity and Access Management__
+ - ### Features
+ - Updating the endpoint list for the Identity and access management (IAM) service
+
+## __AWS MediaTailor__
+ - ### Features
+ - Documenting that EnabledLoggingStrategies is always present in responses of PlaybackConfiguration read operations.
+
+## __AWS S3 Control__
+ - ### Features
+ - Updates to support S3 Express zonal endpoints for directory buckets in AWS CLI
+
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+ - ### Bugfixes
+ - Add `@Mutable` and `@NotThreadSafe` to model Builders
+
+## __AWS Supply Chain__
+ - ### Features
+ - Launch new AWS Supply Chain public APIs for DataIntegrationEvent, DataIntegrationFlowExecution and DatasetNamespace. Also add more capabilities to existing public APIs to support direct dataset event publish, data deduplication in DataIntegrationFlow, partition specification of custom datasets.
+
+## __AWSDeadlineCloud__
+ - ### Features
+ - AWS Deadline Cloud service-managed fleets now support configuration scripts. Configuration scripts make it easy to install additional software, like plugins and packages, onto a worker.
+
+## __Amazon Elastic Compute Cloud__
+ - ### Features
+ - EC2 - Adding support for AvailabilityZoneId
+
+## __Amazon SageMaker Service__
+ - ### Features
+ - No API changes from previous release. This release migrated the model to Smithy keeping all features unchanged.
+
+# __2.31.40__ __2025-05-09__
+## __AWS SDK for Java v2__
+ - ### Features
+ - Updated endpoint and partition metadata.
+
+## __Amazon Athena__
+ - ### Features
+ - Minor API documentation updates
+
+## __Amazon CloudWatch Logs__
+ - ### Features
+ - We are pleased to announce limit increases to our grok processor logs transformation feature. Now you can define 20 Grok patterns in their configurations, with an expanded total pattern matching limit of 512 characters.
+
+## __Amazon WorkSpaces__
+ - ### Features
+ - Remove parameter EnableWorkDocs from WorkSpacesServiceModel due to end of support of Amazon WorkDocs service.
+
+## __Synthetics__
+ - ### Features
+ - Add support to retry a canary automatically after schedule run failures. Users can enable this feature by configuring the RetryConfig field when calling the CreateCanary or UpdateCanary API. Also includes changes in GetCanary and GetCanaryRuns to support retrieving retry configurations.
+
# __2.31.39__ __2025-05-08__
## __AWS CodePipeline__
- ### Features
diff --git a/README.md b/README.md
index b947c1f42261..138e78fe5d87 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
[](https://search.maven.org/search?q=g:%22software.amazon.awssdk%22%20AND%20a:%22s3%22)
[](https://codecov.io/gh/aws/aws-sdk-java-v2)
-[](#contributors-)
+[](#contributors-)
The **AWS SDK for Java 2.0** is a rewrite of 1.0 with some great new features. As with version 1.0,
@@ -51,7 +51,7 @@ To automatically manage module versions (currently all modules have the same ver
software.amazon.awssdk
bom
- 2.31.39
+ 2.31.75
pom
import
@@ -85,12 +85,12 @@ Alternatively you can add dependencies for the specific services you use only:
software.amazon.awssdk
ec2
- 2.31.39
+ 2.31.75
software.amazon.awssdk
s3
- 2.31.39
+ 2.31.75
```
@@ -102,7 +102,7 @@ You can import the whole SDK into your project (includes *ALL* services). Please
software.amazon.awssdk
aws-sdk-java
- 2.31.39
+ 2.31.75
```
@@ -340,6 +340,8 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 Ran Vaknin 💻 |
 Greg Oledzki 💻 |
 Kevin Stich 💻 |
+  Jency Joseph 💻 |
+  Drew Davis 💻 |
diff --git a/archetypes/archetype-app-quickstart/pom.xml b/archetypes/archetype-app-quickstart/pom.xml
index 801b6a8fd2fa..dd4bf1d68a1a 100644
--- a/archetypes/archetype-app-quickstart/pom.xml
+++ b/archetypes/archetype-app-quickstart/pom.xml
@@ -20,7 +20,7 @@
archetypes
software.amazon.awssdk
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
4.0.0
diff --git a/archetypes/archetype-lambda/pom.xml b/archetypes/archetype-lambda/pom.xml
index fae3cb9cc124..ef2ea74c4c5f 100644
--- a/archetypes/archetype-lambda/pom.xml
+++ b/archetypes/archetype-lambda/pom.xml
@@ -20,7 +20,7 @@
archetypes
software.amazon.awssdk
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
4.0.0
archetype-lambda
diff --git a/archetypes/archetype-tools/pom.xml b/archetypes/archetype-tools/pom.xml
index cf95e34e9d2f..ca41b0676686 100644
--- a/archetypes/archetype-tools/pom.xml
+++ b/archetypes/archetype-tools/pom.xml
@@ -20,7 +20,7 @@
archetypes
software.amazon.awssdk
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
4.0.0
diff --git a/archetypes/archetype-tools/src/main/resources/map-service-to-client-prefix b/archetypes/archetype-tools/src/main/resources/map-service-to-client-prefix
index 8574844e7283..846018dd9677 100755
--- a/archetypes/archetype-tools/src/main/resources/map-service-to-client-prefix
+++ b/archetypes/archetype-tools/src/main/resources/map-service-to-client-prefix
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import json
import os
@@ -14,8 +14,9 @@ SERVICE_DIR = os.path.join(
def load_all_service_modules():
service_mapping = {}
- for f in [f for f in os.listdir(SERVICE_DIR) if os.path.isdir(os.path.join(SERVICE_DIR, f)) & os.path.exists(os.path.join(SERVICE_DIR, f, 'target'))]:
- for s in [s for s in os.listdir(os.path.join(SERVICE_DIR, f, 'target', 'generated-sources/sdk/software/amazon/awssdk/services', f)) if s.endswith('AsyncClient.java') & s.startswith('Default')]:
+ # Use logical AND (and) instead of bitwise AND (&) for boolean operations
+ for f in [f for f in os.listdir(SERVICE_DIR) if os.path.isdir(os.path.join(SERVICE_DIR, f)) and os.path.exists(os.path.join(SERVICE_DIR, f, 'target'))]:
+ for s in [s for s in os.listdir(os.path.join(SERVICE_DIR, f, 'target', 'generated-sources/sdk/software/amazon/awssdk/services', f)) if s.endswith('AsyncClient.java') and s.startswith('Default')]:
service_mapping[f] = find_client_prefix(s)
return service_mapping
diff --git a/archetypes/pom.xml b/archetypes/pom.xml
index b122efe43b16..ef7e4795d710 100644
--- a/archetypes/pom.xml
+++ b/archetypes/pom.xml
@@ -20,7 +20,7 @@
aws-sdk-java-pom
software.amazon.awssdk
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
4.0.0
archetypes
diff --git a/aws-sdk-java/pom.xml b/aws-sdk-java/pom.xml
index aa5ed51232ed..71038e870e86 100644
--- a/aws-sdk-java/pom.xml
+++ b/aws-sdk-java/pom.xml
@@ -17,7 +17,7 @@
software.amazon.awssdk
aws-sdk-java-pom
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
../pom.xml
aws-sdk-java
@@ -1538,11 +1538,6 @@ Amazon AutoScaling, etc).
licensemanagerusersubscriptions
${awsjavasdk.version}
-
- software.amazon.awssdk
- privatenetworks
- ${awsjavasdk.version}
-
software.amazon.awssdk
supportapp
@@ -2073,6 +2068,36 @@ Amazon AutoScaling, etc).
ssmguiconnect
${awsjavasdk.version}
+
+ software.amazon.awssdk
+ evs
+ ${awsjavasdk.version}
+
+
+ software.amazon.awssdk
+ mpa
+ ${awsjavasdk.version}
+
+
+ software.amazon.awssdk
+ aiops
+ ${awsjavasdk.version}
+
+
+ software.amazon.awssdk
+ workspacesinstances
+ ${awsjavasdk.version}
+
+
+ software.amazon.awssdk
+ keyspacesstreams
+ ${awsjavasdk.version}
+
+
+ software.amazon.awssdk
+ odb
+ ${awsjavasdk.version}
+
${project.artifactId}-${project.version}
diff --git a/bom-internal/pom.xml b/bom-internal/pom.xml
index f33dc87e72ee..5db756cda2de 100644
--- a/bom-internal/pom.xml
+++ b/bom-internal/pom.xml
@@ -20,7 +20,7 @@
aws-sdk-java-pom
software.amazon.awssdk
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
4.0.0
diff --git a/bom/pom.xml b/bom/pom.xml
index f02e527b0b6f..9219c536ef6e 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -17,7 +17,7 @@
software.amazon.awssdk
aws-sdk-java-pom
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
../pom.xml
bom
@@ -1743,11 +1743,6 @@
licensemanagerusersubscriptions
${awsjavasdk.version}
-
- software.amazon.awssdk
- privatenetworks
- ${awsjavasdk.version}
-
software.amazon.awssdk
supportapp
@@ -2273,6 +2268,36 @@
ssmguiconnect
${awsjavasdk.version}
+
+ software.amazon.awssdk
+ evs
+ ${awsjavasdk.version}
+
+
+ software.amazon.awssdk
+ mpa
+ ${awsjavasdk.version}
+
+
+ software.amazon.awssdk
+ aiops
+ ${awsjavasdk.version}
+
+
+ software.amazon.awssdk
+ workspacesinstances
+ ${awsjavasdk.version}
+
+
+ software.amazon.awssdk
+ keyspacesstreams
+ ${awsjavasdk.version}
+
+
+ software.amazon.awssdk
+ odb
+ ${awsjavasdk.version}
+
diff --git a/build-tools/src/main/resources/software/amazon/awssdk/spotbugs-suppressions.xml b/build-tools/src/main/resources/software/amazon/awssdk/spotbugs-suppressions.xml
index e123f641d076..7206acceb577 100644
--- a/build-tools/src/main/resources/software/amazon/awssdk/spotbugs-suppressions.xml
+++ b/build-tools/src/main/resources/software/amazon/awssdk/spotbugs-suppressions.xml
@@ -359,4 +359,8 @@
+
+
+
+
diff --git a/buildspecs/migration-test.yml b/buildspecs/migration-test.yml
new file mode 100644
index 000000000000..504cf4c1d074
--- /dev/null
+++ b/buildspecs/migration-test.yml
@@ -0,0 +1,18 @@
+version: 0.2
+
+phases:
+ install:
+ runtime-versions:
+ java: "$JAVA_RUNTIME"
+
+ build:
+ commands:
+ - mvn clean install -pl :v2-migration-tests,:bom-internal -am -P quick $MAVEN_OPTIONS
+ - mvn install -pl :v2-migration-tests -P migration-tests -T2C $MAVEN_OPTIONS
+ finally:
+ - mkdir -p codebuild-test-reports
+ - find ./ -name 'TEST-*.xml' -type f -exec cp {} codebuild-test-reports/ \;
+reports:
+ IntegTests:
+ files:
+ - 'codebuild-test-reports/**/*'
diff --git a/buildspecs/release-javadoc.yml b/buildspecs/release-javadoc.yml
index 3795526d25f1..ea262f492b12 100644
--- a/buildspecs/release-javadoc.yml
+++ b/buildspecs/release-javadoc.yml
@@ -13,12 +13,15 @@ phases:
pre_build:
commands:
- DOC_PATH='s3://aws-java-sdk-javadoc/java/api'
+ - MODULES_TO_SKIP="protocol-tests,protocol-tests-core,codegen-generated-classes-test,sdk-benchmarks,s3-benchmarks,module-path-tests,test-utils,http-client-tests,tests-coverage-reporting,sdk-native-image-test,ruleset-testing-core,old-client-version-compatibility-test,crt-unavailable-tests,bundle-shading-tests,v2-migration,v2-migration-tests,architecture-tests,s3-tests"
build:
commands:
- python ./scripts/doc_crosslinks/generate_cross_link_data.py --apiDefinitionsBasePath ./services/ --apiDefinitionsRelativeFilePath src/main/resources/codegen-resources/service-2.json --templateFilePath ./scripts/doc_crosslinks/crosslink_redirect.html --outputFilePath ./scripts/crosslink_redirect.html
- mvn install -P quick -T1C
- - mvn clean install javadoc:aggregate -B -Ppublic-javadoc -Dcheckstyle.skip -Dspotbugs.skip -DskipTests -Ddoclint=none -pl '!:protocol-tests,!:protocol-tests-core,!:codegen-generated-classes-test,!:sdk-benchmarks,!:s3-benchmarks,!:module-path-tests,!:test-utils,!:http-client-tests,!:tests-coverage-reporting,!:sdk-native-image-test,!:ruleset-testing-core,!:old-client-version-compatibility-test,!:crt-unavailable-tests,!:bundle-shading-tests,!:v2-migration,!:v2-migration-tests,!:architecture-tests,!:s3-tests'
+ # Convert comma-separated list to space-separated list with !: prefix for each module
+ - MODULES_TO_SKIP_FORMATTED=$(echo $MODULES_TO_SKIP | sed 's/,/,!:/g' | sed 's/^/!:/')
+ - mvn clean install javadoc:aggregate -B -Ppublic-javadoc -Dcheckstyle.skip -Dspotbugs.skip -DskipTests -Ddoclint=none -pl $MODULES_TO_SKIP_FORMATTED
- RELEASE_VERSION=`mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec`
-
- aws s3 sync target/site/apidocs/ $DOC_PATH/$RELEASE_VERSION/ --acl="public-read"
diff --git a/buildspecs/release-to-maven.yml b/buildspecs/release-to-maven.yml
index 451f977c9a56..fafb8fae03c6 100644
--- a/buildspecs/release-to-maven.yml
+++ b/buildspecs/release-to-maven.yml
@@ -16,6 +16,7 @@ phases:
- SDK_SIGNING_GPG_PASSPHRASE_ARN="arn:aws:secretsmanager:us-east-1:103431983078:secret:sdk-signing-gpg-passphrase-A0H1Kq"
- SONATYPE_PASSWORD_ARN="arn:aws:secretsmanager:us-east-1:103431983078:secret:sonatype-password-I2V6Y0"
- SONATYPE_USERNAME_ARN="arn:aws:secretsmanager:us-east-1:103431983078:secret:sonatype-username-HphNZQ"
+ - MODULES_TO_SKIP="protocol-tests,protocol-tests-core,codegen-generated-classes-test,sdk-benchmarks,module-path-tests,tests-coverage-reporting,stability-tests,sdk-native-image-test,auth-tests,s3-benchmarks,region-testing,old-client-version-compatibility-test,crt-unavailable-tests,bundle-shading-tests,v2-migration-tests,architecture-tests,s3-tests"
build:
commands:
@@ -37,7 +38,10 @@ phases:
awk 'BEGIN { var=ENVIRON["SDK_SIGNING_GPG_KEYNAME"] } { gsub("\\$SDK_SIGNING_GPG_KEYNAME", var, $0); print }' > \
$SETTINGS_XML
- mvn clean deploy -B -s $SETTINGS_XML -Ppublishing -DperformRelease -Dspotbugs.skip -DskipTests -Dcheckstyle.skip -Djapicmp.skip -Ddoclint=none -pl !:protocol-tests,!:protocol-tests-core,!:codegen-generated-classes-test,!:sdk-benchmarks,!:module-path-tests,!:tests-coverage-reporting,!:stability-tests,!:sdk-native-image-test,!:auth-tests,!:s3-benchmarks,!:region-testing,!:old-client-version-compatibility-test,!:crt-unavailable-tests,!:bundle-shading-tests,!:v2-migration-tests,!:architecture-tests,!:s3-tests -DautoReleaseAfterClose=true -DstagingProgressTimeoutMinutes=30 -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.requestSentEnabled=true
+ # Convert comma-separated list to space-separated list with !: prefix for each module
+ MODULES_TO_SKIP_FORMATTED=$(echo $MODULES_TO_SKIP | sed 's/,/,!:/g' | sed 's/^/!:/')
+
+ mvn clean deploy -B -s $SETTINGS_XML -Ppublishing -DperformRelease -Dspotbugs.skip -DskipTests -Dcheckstyle.skip -Djapicmp.skip -Ddoclint=none -pl $MODULES_TO_SKIP_FORMATTED -DautoReleaseAfterClose=true -DstagingProgressTimeoutMinutes=30 -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.requestSentEnabled=true
else
echo "This version was already released."
fi
diff --git a/buildspecs/resources/ci.cloudformation.yml b/buildspecs/resources/ci.cloudformation.yml
index 02adcf3a24c4..740be418648c 100644
--- a/buildspecs/resources/ci.cloudformation.yml
+++ b/buildspecs/resources/ci.cloudformation.yml
@@ -57,6 +57,8 @@ Resources:
- !Sub arn:aws:codebuild:${ AWS::Region }:${ AWS::AccountId }:project/aws-sdk-java-v2-native-image-test
- !Sub arn:aws:codebuild:${ AWS::Region }:${ AWS::AccountId }:project/aws-sdk-java-v2-sonar
- !Sub arn:aws:codebuild:${ AWS::Region }:${ AWS::AccountId }:project/aws-sdk-java-v2-endpoints-test
+ - !Sub arn:aws:codebuild:${ AWS::Region }:${ AWS::AccountId }:project/aws-sdk-java-v2-migration-test
+ - !Sub arn:aws:codebuild:${ AWS::Region }:${ AWS::AccountId }:project/aws-sdk-java-v2-s3-regression-tests
- Effect: Allow
Action:
- logs:GetLogEvents
@@ -69,6 +71,8 @@ Resources:
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/aws-sdk-java-v2-native-image-test:*
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/aws-sdk-java-v2-sonar:*
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/aws-sdk-java-v2-endpoints-test:*
+ - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/aws-sdk-java-v2-migration-test:*
+ - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/aws-sdk-java-v2-s3-regression-tests:*
GithubOidc:
Type: AWS::IAM::OIDCProvider
diff --git a/buildspecs/s3-regression-tests.yml b/buildspecs/s3-regression-tests.yml
new file mode 100644
index 000000000000..4b7102350ce0
--- /dev/null
+++ b/buildspecs/s3-regression-tests.yml
@@ -0,0 +1,14 @@
+version: 0.2
+
+phases:
+ build:
+ commands:
+ - mvn clean install -P s3-regression-tests -pl :s3-tests -am -T1C -Dregression.test=$REGRESSION_TEST $MAVEN_OPTIONS
+ - echo $MAVEN_OPTIONS
+ finally:
+ - mkdir -p codebuild-test-reports
+ - find ./ -name 'TEST-*.xml' -type f -exec cp {} codebuild-test-reports/ \;
+reports:
+ ChecksumsTests:
+ files:
+ - 'codebuild-test-reports/**/*'
diff --git a/buildspecs/validate-brazil-config.yml b/buildspecs/validate-brazil-config.yml
new file mode 100644
index 000000000000..481aa791f4ab
--- /dev/null
+++ b/buildspecs/validate-brazil-config.yml
@@ -0,0 +1,14 @@
+version: 0.2
+
+phases:
+ install:
+ runtime-versions:
+ java: "$JAVA_RUNTIME"
+ python: 3.13
+
+ build:
+ commands:
+ - mvn clean install -P quick -T0.4C
+ - mvn exec:exec -Dexec.executable=pwd -pl !:aws-sdk-java-pom,!:sdk-benchmarks,!:module-path-tests -q 2>&1 > modules.txt
+ - mvn dependency:list -DexcludeTransitive=true -DincludeScope=runtime 2>&1 > deps.txt
+ - scripts/validate-brazil-config modules.txt deps.txt
\ No newline at end of file
diff --git a/bundle-logging-bridge/pom.xml b/bundle-logging-bridge/pom.xml
index 355425911a33..0decc070a4f7 100644
--- a/bundle-logging-bridge/pom.xml
+++ b/bundle-logging-bridge/pom.xml
@@ -21,7 +21,7 @@
software.amazon.awssdk
aws-sdk-java-pom
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
bundle-logging-bridge
jar
diff --git a/bundle-sdk/pom.xml b/bundle-sdk/pom.xml
index fd7e794886d8..a89e0182f5f2 100644
--- a/bundle-sdk/pom.xml
+++ b/bundle-sdk/pom.xml
@@ -21,7 +21,7 @@
software.amazon.awssdk
aws-sdk-java-pom
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
bundle-sdk
jar
diff --git a/bundle/pom.xml b/bundle/pom.xml
index 1d7f5a43ed85..b095bb7b81c4 100644
--- a/bundle/pom.xml
+++ b/bundle/pom.xml
@@ -21,7 +21,7 @@
software.amazon.awssdk
aws-sdk-java-pom
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
bundle
jar
diff --git a/codegen-lite-maven-plugin/pom.xml b/codegen-lite-maven-plugin/pom.xml
index 56871379696e..c8cb7e848abe 100644
--- a/codegen-lite-maven-plugin/pom.xml
+++ b/codegen-lite-maven-plugin/pom.xml
@@ -22,7 +22,7 @@
software.amazon.awssdk
aws-sdk-java-pom
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
../pom.xml
codegen-lite-maven-plugin
diff --git a/codegen-lite-maven-plugin/src/main/java/software/amazon/awssdk/codegen/lite/maven/plugin/RegionGenerationMojo.java b/codegen-lite-maven-plugin/src/main/java/software/amazon/awssdk/codegen/lite/maven/plugin/RegionGenerationMojo.java
index e02358f3a67c..10422e931450 100644
--- a/codegen-lite-maven-plugin/src/main/java/software/amazon/awssdk/codegen/lite/maven/plugin/RegionGenerationMojo.java
+++ b/codegen-lite-maven-plugin/src/main/java/software/amazon/awssdk/codegen/lite/maven/plugin/RegionGenerationMojo.java
@@ -29,6 +29,7 @@
import software.amazon.awssdk.codegen.lite.regions.EndpointTagGenerator;
import software.amazon.awssdk.codegen.lite.regions.PartitionMetadataGenerator;
import software.amazon.awssdk.codegen.lite.regions.PartitionMetadataProviderGenerator;
+import software.amazon.awssdk.codegen.lite.regions.PartitionsRegionsMetadataLoader;
import software.amazon.awssdk.codegen.lite.regions.RegionGenerator;
import software.amazon.awssdk.codegen.lite.regions.RegionMetadataGenerator;
import software.amazon.awssdk.codegen.lite.regions.RegionMetadataLoader;
@@ -36,6 +37,7 @@
import software.amazon.awssdk.codegen.lite.regions.ServiceMetadataGenerator;
import software.amazon.awssdk.codegen.lite.regions.ServiceMetadataProviderGenerator;
import software.amazon.awssdk.codegen.lite.regions.model.Partitions;
+import software.amazon.awssdk.codegen.lite.regions.model.PartitionsRegionsMetadata;
import software.amazon.awssdk.utils.StringUtils;
/**
@@ -59,19 +61,24 @@ public class RegionGenerationMojo extends AbstractMojo {
"${basedir}/src/main/resources/software/amazon/awssdk/regions/internal/region/endpoints.json")
private File endpoints;
+ @Parameter(property = "partitionsJson", defaultValue =
+ "${basedir}/../../codegen/src/main/resources/software/amazon/awssdk/codegen/rules/partitions.json.resource")
+ private File partitionsJson;
+
@Override
public void execute() throws MojoExecutionException {
Path baseSourcesDirectory = Paths.get(outputDirectory).resolve("generated-sources").resolve("sdk");
Path testsDirectory = Paths.get(outputDirectory).resolve("generated-test-sources").resolve("sdk-tests");
Partitions partitions = RegionMetadataLoader.build(endpoints);
+ PartitionsRegionsMetadata regionPartitions = PartitionsRegionsMetadataLoader.build(partitionsJson);
generatePartitionMetadataClass(baseSourcesDirectory, partitions);
- generateRegionClass(baseSourcesDirectory, partitions);
+ generateRegionClass(baseSourcesDirectory, regionPartitions);
generateServiceMetadata(baseSourcesDirectory, partitions);
- generateRegions(baseSourcesDirectory, partitions);
+ generateRegions(baseSourcesDirectory, regionPartitions);
generatePartitionProvider(baseSourcesDirectory, partitions);
- generateRegionProvider(baseSourcesDirectory, partitions);
+ generateRegionProvider(baseSourcesDirectory, regionPartitions);
generateServiceProvider(baseSourcesDirectory, partitions);
generateEndpointTags(baseSourcesDirectory, partitions);
@@ -88,7 +95,7 @@ public void generatePartitionMetadataClass(Path baseSourcesDirectory, Partitions
REGION_BASE)).generate());
}
- public void generateRegionClass(Path baseSourcesDirectory, Partitions partitions) {
+ public void generateRegionClass(Path baseSourcesDirectory, PartitionsRegionsMetadata partitions) {
Path sourcesDirectory = baseSourcesDirectory.resolve(StringUtils.replace(REGION_BASE, ".", "/"));
new CodeGenerator(sourcesDirectory.toString(), new RegionGenerator(partitions, REGION_BASE)).generate();
}
@@ -105,7 +112,7 @@ public void generateServiceMetadata(Path baseSourcesDirectory, Partitions partit
.generate());
}
- public void generateRegions(Path baseSourcesDirectory, Partitions partitions) {
+ public void generateRegions(Path baseSourcesDirectory, PartitionsRegionsMetadata partitions) {
Path sourcesDirectory = baseSourcesDirectory.resolve(StringUtils.replace(REGION_METADATA_BASE, ".", "/"));
partitions.getPartitions()
.forEach(p -> p.getRegions().forEach((k, v) ->
@@ -126,7 +133,7 @@ public void generatePartitionProvider(Path baseSourcesDirectory, Partitions part
.generate();
}
- public void generateRegionProvider(Path baseSourcesDirectory, Partitions partitions) {
+ public void generateRegionProvider(Path baseSourcesDirectory, PartitionsRegionsMetadata partitions) {
Path sourcesDirectory = baseSourcesDirectory.resolve(StringUtils.replace(REGION_BASE, ".", "/"));
new CodeGenerator(sourcesDirectory.toString(), new RegionMetadataProviderGenerator(partitions,
REGION_METADATA_BASE,
diff --git a/codegen-lite/pom.xml b/codegen-lite/pom.xml
index 146093d0aebb..81beb659771e 100644
--- a/codegen-lite/pom.xml
+++ b/codegen-lite/pom.xml
@@ -21,7 +21,7 @@
software.amazon.awssdk
aws-sdk-java-pom
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
codegen-lite
AWS Java SDK :: Code Generator Lite
diff --git a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/PartitionsRegionsMetadataLoader.java b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/PartitionsRegionsMetadataLoader.java
new file mode 100644
index 000000000000..692ee7758081
--- /dev/null
+++ b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/PartitionsRegionsMetadataLoader.java
@@ -0,0 +1,47 @@
+/*
+ * 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.lite.regions;
+
+import com.fasterxml.jackson.jr.ob.JSON;
+import java.io.File;
+import java.io.IOException;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.codegen.lite.regions.model.PartitionsRegionsMetadata;
+
+/**
+ * Loads and parses the partitions.json file into {@link PartitionsRegionsMetadata}.
+ */
+@SdkInternalApi
+public final class PartitionsRegionsMetadataLoader {
+
+ private PartitionsRegionsMetadataLoader() {
+ }
+
+ public static PartitionsRegionsMetadata build(File path) {
+ return loadPartitionFromStream(path, path.toString());
+ }
+
+ private static PartitionsRegionsMetadata loadPartitionFromStream(File stream, String location) {
+
+ try {
+ return JSON.std.with(JSON.Feature.USE_IS_GETTERS)
+ .beanFrom(PartitionsRegionsMetadata.class, stream);
+
+ } catch (IOException | RuntimeException e) {
+ throw new RuntimeException("Error while loading partitions file from " + location, e);
+ }
+ }
+}
diff --git a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/RegionGenerator.java b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/RegionGenerator.java
index fa5467bc847f..27421f2b6b16 100644
--- a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/RegionGenerator.java
+++ b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/RegionGenerator.java
@@ -38,16 +38,16 @@
import software.amazon.awssdk.annotations.Generated;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.codegen.lite.PoetClass;
-import software.amazon.awssdk.codegen.lite.regions.model.Partitions;
+import software.amazon.awssdk.codegen.lite.regions.model.PartitionsRegionsMetadata;
import software.amazon.awssdk.utils.Validate;
import software.amazon.awssdk.utils.http.SdkHttpUtils;
public class RegionGenerator implements PoetClass {
- private final Partitions partitions;
+ private final PartitionsRegionsMetadata partitions;
private final String basePackage;
- public RegionGenerator(Partitions partitions,
+ public RegionGenerator(PartitionsRegionsMetadata partitions,
String basePackage) {
this.partitions = partitions;
this.basePackage = basePackage;
@@ -100,21 +100,15 @@ private void regions(TypeSpec.Builder builder) {
.add("$T.unmodifiableList($T.asList(", Collections.class, Arrays.class);
String regionsCodeBlock = regions.stream().map(r -> {
+ boolean isGlobal = r.contains("global");
builder.addField(FieldSpec.builder(className(), regionName(r))
.addModifiers(PUBLIC, STATIC, FINAL)
- .initializer("$T.of($S)", className(), r)
+ .initializer(isGlobal ? "$T.of($S, true)" : "$T.of($S)", className(), r)
.build());
return regionName(r);
}).collect(Collectors.joining(", "));
- addGlobalRegions(builder);
-
- regionsArray.add(regionsCodeBlock + ", ")
- .add("AWS_GLOBAL, ")
- .add("AWS_CN_GLOBAL, ")
- .add("AWS_US_GOV_GLOBAL, ")
- .add("AWS_ISO_GLOBAL, ")
- .add("AWS_ISO_B_GLOBAL");
+ regionsArray.add(regionsCodeBlock);
regionsArray.add("))");
TypeName listOfRegions = ParameterizedTypeName.get(ClassName.get(List.class), className());
@@ -123,29 +117,6 @@ private void regions(TypeSpec.Builder builder) {
.initializer(regionsArray.build()).build());
}
- private void addGlobalRegions(TypeSpec.Builder builder) {
- builder.addField(FieldSpec.builder(className(), "AWS_GLOBAL")
- .addModifiers(PUBLIC, STATIC, FINAL)
- .initializer("$T.of($S, true)", className(), "aws-global")
- .build())
- .addField(FieldSpec.builder(className(), "AWS_CN_GLOBAL")
- .addModifiers(PUBLIC, STATIC, FINAL)
- .initializer("$T.of($S, true)", className(), "aws-cn-global")
- .build())
- .addField(FieldSpec.builder(className(), "AWS_US_GOV_GLOBAL")
- .addModifiers(PUBLIC, STATIC, FINAL)
- .initializer("$T.of($S, true)", className(), "aws-us-gov-global")
- .build())
- .addField(FieldSpec.builder(className(), "AWS_ISO_GLOBAL")
- .addModifiers(PUBLIC, STATIC, FINAL)
- .initializer("$T.of($S, true)", className(), "aws-iso-global")
- .build())
- .addField(FieldSpec.builder(className(), "AWS_ISO_B_GLOBAL")
- .addModifiers(PUBLIC, STATIC, FINAL)
- .initializer("$T.of($S, true)", className(), "aws-iso-b-global")
- .build());
- }
-
private String regionName(String region) {
return region.replace("-", "_").toUpperCase(Locale.US);
}
diff --git a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/RegionMetadataGenerator.java b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/RegionMetadataGenerator.java
index 92011139d2c6..b71e7c2bb671 100644
--- a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/RegionMetadataGenerator.java
+++ b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/RegionMetadataGenerator.java
@@ -32,17 +32,17 @@
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.codegen.lite.PoetClass;
import software.amazon.awssdk.codegen.lite.Utils;
-import software.amazon.awssdk.codegen.lite.regions.model.Partition;
+import software.amazon.awssdk.codegen.lite.regions.model.PartitionRegionsMetadata;
public class RegionMetadataGenerator implements PoetClass {
- private final Partition partition;
+ private final PartitionRegionsMetadata partition;
private final String region;
private final String regionDescription;
private final String basePackage;
private final String regionBasePackage;
- public RegionMetadataGenerator(Partition partition,
+ public RegionMetadataGenerator(PartitionRegionsMetadata partition,
String region,
String regionDescription,
String basePackage,
@@ -65,9 +65,9 @@ public TypeSpec poetClass() {
.addModifiers(FINAL)
.addSuperinterface(ClassName.get(regionBasePackage, "RegionMetadata"))
.addField(staticFinalField("ID", region))
- .addField(staticFinalField("DOMAIN", partition.getDnsSuffix()))
+ .addField(staticFinalField("DOMAIN", partition.getOutputs().getDnsSuffix()))
.addField(staticFinalField("DESCRIPTION", regionDescription))
- .addField(staticFinalField("PARTITION_ID", partition.getPartition()))
+ .addField(staticFinalField("PARTITION_ID", partition.getId()))
.addMethod(getter("id", "ID"))
.addMethod(getter("domain", "DOMAIN"))
.addMethod(getter("description", "DESCRIPTION"))
diff --git a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/RegionMetadataProviderGenerator.java b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/RegionMetadataProviderGenerator.java
index 0203bbbfb649..fdd16ab73eec 100644
--- a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/RegionMetadataProviderGenerator.java
+++ b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/RegionMetadataProviderGenerator.java
@@ -36,16 +36,16 @@
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.codegen.lite.PoetClass;
import software.amazon.awssdk.codegen.lite.Utils;
-import software.amazon.awssdk.codegen.lite.regions.model.Partitions;
+import software.amazon.awssdk.codegen.lite.regions.model.PartitionsRegionsMetadata;
import software.amazon.awssdk.utils.ImmutableMap;
public class RegionMetadataProviderGenerator implements PoetClass {
- private final Partitions partitions;
+ private final PartitionsRegionsMetadata partitions;
private final String basePackage;
private final String regionBasePackage;
- public RegionMetadataProviderGenerator(Partitions partitions,
+ public RegionMetadataProviderGenerator(PartitionsRegionsMetadata partitions,
String basePackage,
String regionBasePackage) {
this.partitions = partitions;
@@ -79,7 +79,7 @@ public ClassName className() {
return ClassName.get(regionBasePackage, "GeneratedRegionMetadataProvider");
}
- private CodeBlock regions(Partitions partitions) {
+ private CodeBlock regions(PartitionsRegionsMetadata partitions) {
CodeBlock.Builder builder = CodeBlock.builder().add("$T.builder()", ImmutableMap.class);
partitions.getPartitions()
diff --git a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/model/Partition.java b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/model/Partition.java
index e225d47bfd82..f8b030f64edb 100644
--- a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/model/Partition.java
+++ b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/model/Partition.java
@@ -67,9 +67,9 @@ public Partition() {
public Partition(@JsonProperty(value = "partition") String partition,
@JsonProperty(value = "regions") Map
- regions,
+ regions,
@JsonProperty(value = "services") Map services) {
+ Service> services) {
this.partition = Validate.paramNotNull(partition, "Partition");
this.regions = regions;
this.services = services;
@@ -186,4 +186,4 @@ private boolean hasServiceEndpoint(String endpoint) {
}
return false;
}
-}
+}
\ No newline at end of file
diff --git a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/model/PartitionRegionsMetadata.java b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/model/PartitionRegionsMetadata.java
new file mode 100644
index 000000000000..f780e766f71e
--- /dev/null
+++ b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/model/PartitionRegionsMetadata.java
@@ -0,0 +1,177 @@
+/*
+ * 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.lite.regions.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Map;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+
+/**
+ * This class models a single partition from partitions.json.
+ */
+@SdkInternalApi
+public final class PartitionRegionsMetadata {
+ private String id;
+ private PartitionOutputs outputs;
+ private String regionRegex;
+ private Map regions;
+
+ public PartitionRegionsMetadata() {
+ }
+
+ public PartitionRegionsMetadata(@JsonProperty(value = "id") String id,
+ @JsonProperty(value = "outputs") PartitionOutputs outputs,
+ @JsonProperty(value = "regionRegex") String regionRegex,
+ @JsonProperty(value = "regions") Map regions) {
+ this.id = id;
+ this.outputs = outputs;
+ this.regionRegex = regionRegex;
+ this.regions = regions;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public PartitionOutputs getOutputs() {
+ return outputs;
+ }
+
+ public void setOutputs(PartitionOutputs outputs) {
+ this.outputs = outputs;
+ }
+
+ public String getRegionRegex() {
+ return regionRegex;
+ }
+
+ public void setRegionRegex(String regionRegex) {
+ this.regionRegex = regionRegex;
+ }
+
+ public Map getRegions() {
+ return regions;
+ }
+
+ public void setRegions(Map regions) {
+ this.regions = regions;
+ }
+
+ /**
+ * This class models the outputs field of a partition in partitions.json.
+ */
+ @SdkInternalApi
+ public static final class PartitionOutputs {
+ private String dnsSuffix;
+ private String dualStackDnsSuffix;
+ private String implicitGlobalRegion;
+ private String name;
+ private boolean supportsDualStack;
+ private boolean supportsFIPS;
+
+ public PartitionOutputs() {
+ }
+
+ public PartitionOutputs(@JsonProperty(value = "dnsSuffix") String dnsSuffix,
+ @JsonProperty(value = "dualStackDnsSuffix") String dualStackDnsSuffix,
+ @JsonProperty(value = "implicitGlobalRegion") String implicitGlobalRegion,
+ @JsonProperty(value = "name") String name,
+ @JsonProperty(value = "supportsDualStack") boolean supportsDualStack,
+ @JsonProperty(value = "supportsFIPS") boolean supportsFIPS) {
+ this.dnsSuffix = dnsSuffix;
+ this.dualStackDnsSuffix = dualStackDnsSuffix;
+ this.implicitGlobalRegion = implicitGlobalRegion;
+ this.name = name;
+ this.supportsDualStack = supportsDualStack;
+ this.supportsFIPS = supportsFIPS;
+ }
+
+ public String getDnsSuffix() {
+ return dnsSuffix;
+ }
+
+ public void setDnsSuffix(String dnsSuffix) {
+ this.dnsSuffix = dnsSuffix;
+ }
+
+ public String getDualStackDnsSuffix() {
+ return dualStackDnsSuffix;
+ }
+
+ public void setDualStackDnsSuffix(String dualStackDnsSuffix) {
+ this.dualStackDnsSuffix = dualStackDnsSuffix;
+ }
+
+ public String getImplicitGlobalRegion() {
+ return implicitGlobalRegion;
+ }
+
+ public void setImplicitGlobalRegion(String implicitGlobalRegion) {
+ this.implicitGlobalRegion = implicitGlobalRegion;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public boolean isSupportsDualStack() {
+ return supportsDualStack;
+ }
+
+ public void setSupportsDualStack(boolean supportsDualStack) {
+ this.supportsDualStack = supportsDualStack;
+ }
+
+ public boolean isSupportsFIPS() {
+ return supportsFIPS;
+ }
+
+ public void setSupportsFIPS(boolean supportsFIPS) {
+ this.supportsFIPS = supportsFIPS;
+ }
+ }
+
+ /**
+ * This class models a region in partitions.json.
+ */
+ @SdkInternalApi
+ public static final class RegionMetadata {
+ private String description;
+
+ public RegionMetadata() {
+ }
+
+ public RegionMetadata(@JsonProperty(value = "description") String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+ }
+}
diff --git a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/model/PartitionsRegionsMetadata.java b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/model/PartitionsRegionsMetadata.java
new file mode 100644
index 000000000000..7c5092e41c66
--- /dev/null
+++ b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/model/PartitionsRegionsMetadata.java
@@ -0,0 +1,55 @@
+/*
+ * 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.lite.regions.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.utils.Validate;
+
+/**
+ * This class models the AWS partitions metadata from partitions.json.
+ */
+@SdkInternalApi
+public final class PartitionsRegionsMetadata {
+ private List partitions;
+ private String version;
+
+ public PartitionsRegionsMetadata() {
+ }
+
+ public PartitionsRegionsMetadata(@JsonProperty(value = "partitions") List partitions,
+ @JsonProperty(value = "version") String version) {
+ this.partitions = Validate.paramNotNull(partitions, "partitions");
+ this.version = Validate.paramNotNull(version, "version");
+ }
+
+ public List getPartitions() {
+ return partitions;
+ }
+
+ public void setPartitions(List partitions) {
+ this.partitions = partitions;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+}
diff --git a/codegen-lite/src/test/java/software/amazon/awssdk/codegen/lite/regions/RegionGenerationTest.java b/codegen-lite/src/test/java/software/amazon/awssdk/codegen/lite/regions/RegionGenerationTest.java
index 0240958a17d9..2ace744a0392 100644
--- a/codegen-lite/src/test/java/software/amazon/awssdk/codegen/lite/regions/RegionGenerationTest.java
+++ b/codegen-lite/src/test/java/software/amazon/awssdk/codegen/lite/regions/RegionGenerationTest.java
@@ -21,35 +21,42 @@
import java.nio.file.Paths;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import software.amazon.awssdk.codegen.lite.regions.model.Partition;
import software.amazon.awssdk.codegen.lite.regions.model.Partitions;
+import software.amazon.awssdk.codegen.lite.regions.model.PartitionsRegionsMetadata;
+import software.amazon.awssdk.codegen.lite.regions.model.PartitionRegionsMetadata;
public class RegionGenerationTest {
private static final String ENDPOINTS = "/software/amazon/awssdk/codegen/lite/test-endpoints.json";
+ private static final String PARTITIONS = "/software/amazon/awssdk/codegen/lite/test-partitions.json.resource";
private static final String SERVICE_METADATA_BASE = "software.amazon.awssdk.regions.servicemetadata";
private static final String REGION_METADATA_BASE = "software.amazon.awssdk.regions.regionmetadata";
private static final String PARTITION_METADATA_BASE = "software.amazon.awssdk.regions.partitionmetadata";
private static final String REGION_BASE = "software.amazon.awssdk.regions";
private File endpoints;
+ private File partitionsFile;
private Partitions partitions;
+ private PartitionsRegionsMetadata partitionsRegions;
+
@BeforeEach
public void before() throws Exception {
this.endpoints = Paths.get(getClass().getResource(ENDPOINTS).toURI()).toFile();
+ this.partitionsFile = Paths.get(getClass().getResource(PARTITIONS).toURI()).toFile();
this.partitions = RegionMetadataLoader.build(endpoints);
+ this.partitionsRegions = PartitionsRegionsMetadataLoader.build(partitionsFile);
}
@Test
public void regionClass() {
- RegionGenerator regions = new RegionGenerator(partitions, REGION_BASE);
+ RegionGenerator regions = new RegionGenerator(partitionsRegions, REGION_BASE);
assertThat(regions, generatesTo("regions.java"));
}
@Test
public void regionMetadataClass() {
- Partition partition = partitions.getPartitions().get(0);
+ PartitionRegionsMetadata partition = partitionsRegions.getPartitions().get(0);
RegionMetadataGenerator metadataGenerator = new RegionMetadataGenerator(partition,
"us-east-1",
"US East (N. Virginia)",
@@ -61,7 +68,7 @@ public void regionMetadataClass() {
@Test
public void regionMetadataProviderClass() {
- RegionMetadataProviderGenerator providerGenerator = new RegionMetadataProviderGenerator(partitions,
+ RegionMetadataProviderGenerator providerGenerator = new RegionMetadataProviderGenerator(partitionsRegions,
REGION_METADATA_BASE,
REGION_BASE);
assertThat(providerGenerator, generatesTo("region-metadata-provider.java"));
diff --git a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/region-metadata-provider.java b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/region-metadata-provider.java
index 9380df896357..798644de1fef 100644
--- a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/region-metadata-provider.java
+++ b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/region-metadata-provider.java
@@ -9,18 +9,37 @@
import software.amazon.awssdk.regions.regionmetadata.ApNortheast2;
import software.amazon.awssdk.regions.regionmetadata.ApNortheast3;
import software.amazon.awssdk.regions.regionmetadata.ApSouth1;
+import software.amazon.awssdk.regions.regionmetadata.ApSouth2;
import software.amazon.awssdk.regions.regionmetadata.ApSoutheast1;
import software.amazon.awssdk.regions.regionmetadata.ApSoutheast2;
+import software.amazon.awssdk.regions.regionmetadata.ApSoutheast3;
+import software.amazon.awssdk.regions.regionmetadata.ApSoutheast4;
+import software.amazon.awssdk.regions.regionmetadata.ApSoutheast5;
+import software.amazon.awssdk.regions.regionmetadata.ApSoutheast7;
+import software.amazon.awssdk.regions.regionmetadata.AwsCnGlobal;
+import software.amazon.awssdk.regions.regionmetadata.AwsGlobal;
+import software.amazon.awssdk.regions.regionmetadata.AwsIsoBGlobal;
+import software.amazon.awssdk.regions.regionmetadata.AwsIsoFGlobal;
+import software.amazon.awssdk.regions.regionmetadata.AwsIsoGlobal;
+import software.amazon.awssdk.regions.regionmetadata.AwsUsGovGlobal;
import software.amazon.awssdk.regions.regionmetadata.CaCentral1;
+import software.amazon.awssdk.regions.regionmetadata.CaWest1;
import software.amazon.awssdk.regions.regionmetadata.CnNorth1;
import software.amazon.awssdk.regions.regionmetadata.CnNorthwest1;
import software.amazon.awssdk.regions.regionmetadata.EuCentral1;
+import software.amazon.awssdk.regions.regionmetadata.EuCentral2;
+import software.amazon.awssdk.regions.regionmetadata.EuIsoeWest1;
import software.amazon.awssdk.regions.regionmetadata.EuNorth1;
import software.amazon.awssdk.regions.regionmetadata.EuSouth1;
+import software.amazon.awssdk.regions.regionmetadata.EuSouth2;
import software.amazon.awssdk.regions.regionmetadata.EuWest1;
import software.amazon.awssdk.regions.regionmetadata.EuWest2;
import software.amazon.awssdk.regions.regionmetadata.EuWest3;
+import software.amazon.awssdk.regions.regionmetadata.EuscDeEast1;
+import software.amazon.awssdk.regions.regionmetadata.IlCentral1;
+import software.amazon.awssdk.regions.regionmetadata.MeCentral1;
import software.amazon.awssdk.regions.regionmetadata.MeSouth1;
+import software.amazon.awssdk.regions.regionmetadata.MxCentral1;
import software.amazon.awssdk.regions.regionmetadata.SaEast1;
import software.amazon.awssdk.regions.regionmetadata.UsEast1;
import software.amazon.awssdk.regions.regionmetadata.UsEast2;
@@ -29,6 +48,8 @@
import software.amazon.awssdk.regions.regionmetadata.UsIsoEast1;
import software.amazon.awssdk.regions.regionmetadata.UsIsoWest1;
import software.amazon.awssdk.regions.regionmetadata.UsIsobEast1;
+import software.amazon.awssdk.regions.regionmetadata.UsIsofEast1;
+import software.amazon.awssdk.regions.regionmetadata.UsIsofSouth1;
import software.amazon.awssdk.regions.regionmetadata.UsWest1;
import software.amazon.awssdk.regions.regionmetadata.UsWest2;
import software.amazon.awssdk.utils.ImmutableMap;
@@ -40,15 +61,26 @@ public final class GeneratedRegionMetadataProvider implements RegionMetadataProv
.put(Region.AF_SOUTH_1, new AfSouth1()).put(Region.AP_EAST_1, new ApEast1())
.put(Region.AP_NORTHEAST_1, new ApNortheast1()).put(Region.AP_NORTHEAST_2, new ApNortheast2())
.put(Region.AP_NORTHEAST_3, new ApNortheast3()).put(Region.AP_SOUTH_1, new ApSouth1())
- .put(Region.AP_SOUTHEAST_1, new ApSoutheast1()).put(Region.AP_SOUTHEAST_2, new ApSoutheast2())
- .put(Region.CA_CENTRAL_1, new CaCentral1()).put(Region.EU_CENTRAL_1, new EuCentral1())
- .put(Region.EU_NORTH_1, new EuNorth1()).put(Region.EU_SOUTH_1, new EuSouth1()).put(Region.EU_WEST_1, new EuWest1())
- .put(Region.EU_WEST_2, new EuWest2()).put(Region.EU_WEST_3, new EuWest3()).put(Region.ME_SOUTH_1, new MeSouth1())
+ .put(Region.AP_SOUTH_2, new ApSouth2()).put(Region.AP_SOUTHEAST_1, new ApSoutheast1())
+ .put(Region.AP_SOUTHEAST_2, new ApSoutheast2()).put(Region.AP_SOUTHEAST_3, new ApSoutheast3())
+ .put(Region.AP_SOUTHEAST_4, new ApSoutheast4()).put(Region.AP_SOUTHEAST_5, new ApSoutheast5())
+ .put(Region.AP_SOUTHEAST_7, new ApSoutheast7()).put(Region.AWS_GLOBAL, new AwsGlobal())
+ .put(Region.CA_CENTRAL_1, new CaCentral1()).put(Region.CA_WEST_1, new CaWest1())
+ .put(Region.EU_CENTRAL_1, new EuCentral1()).put(Region.EU_CENTRAL_2, new EuCentral2())
+ .put(Region.EU_NORTH_1, new EuNorth1()).put(Region.EU_SOUTH_1, new EuSouth1()).put(Region.EU_SOUTH_2, new EuSouth2())
+ .put(Region.EU_WEST_1, new EuWest1()).put(Region.EU_WEST_2, new EuWest2()).put(Region.EU_WEST_3, new EuWest3())
+ .put(Region.IL_CENTRAL_1, new IlCentral1()).put(Region.ME_CENTRAL_1, new MeCentral1())
+ .put(Region.ME_SOUTH_1, new MeSouth1()).put(Region.MX_CENTRAL_1, new MxCentral1())
.put(Region.SA_EAST_1, new SaEast1()).put(Region.US_EAST_1, new UsEast1()).put(Region.US_EAST_2, new UsEast2())
- .put(Region.US_WEST_1, new UsWest1()).put(Region.US_WEST_2, new UsWest2()).put(Region.CN_NORTH_1, new CnNorth1())
- .put(Region.CN_NORTHWEST_1, new CnNorthwest1()).put(Region.US_GOV_EAST_1, new UsGovEast1())
- .put(Region.US_GOV_WEST_1, new UsGovWest1()).put(Region.US_ISO_EAST_1, new UsIsoEast1())
- .put(Region.US_ISO_WEST_1, new UsIsoWest1()).put(Region.US_ISOB_EAST_1, new UsIsobEast1()).build();
+ .put(Region.US_WEST_1, new UsWest1()).put(Region.US_WEST_2, new UsWest2())
+ .put(Region.AWS_CN_GLOBAL, new AwsCnGlobal()).put(Region.CN_NORTH_1, new CnNorth1())
+ .put(Region.CN_NORTHWEST_1, new CnNorthwest1()).put(Region.AWS_US_GOV_GLOBAL, new AwsUsGovGlobal())
+ .put(Region.US_GOV_EAST_1, new UsGovEast1()).put(Region.US_GOV_WEST_1, new UsGovWest1())
+ .put(Region.AWS_ISO_GLOBAL, new AwsIsoGlobal()).put(Region.US_ISO_EAST_1, new UsIsoEast1())
+ .put(Region.US_ISO_WEST_1, new UsIsoWest1()).put(Region.AWS_ISO_B_GLOBAL, new AwsIsoBGlobal())
+ .put(Region.US_ISOB_EAST_1, new UsIsobEast1()).put(Region.EU_ISOE_WEST_1, new EuIsoeWest1())
+ .put(Region.AWS_ISO_F_GLOBAL, new AwsIsoFGlobal()).put(Region.US_ISOF_EAST_1, new UsIsofEast1())
+ .put(Region.US_ISOF_SOUTH_1, new UsIsofSouth1()).put(Region.EUSC_DE_EAST_1, new EuscDeEast1()).build();
public RegionMetadata regionMetadata(Region region) {
return REGION_METADATA.get(region);
diff --git a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/regions.java b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/regions.java
index e007c4fbaf79..9935ffd3f4d9 100644
--- a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/regions.java
+++ b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/regions.java
@@ -36,17 +36,11 @@
@SdkPublicApi
@Generated("software.amazon.awssdk:codegen")
public final class Region {
- public static final Region AP_SOUTH_1 = Region.of("ap-south-1");
-
- public static final Region EU_SOUTH_1 = Region.of("eu-south-1");
-
- public static final Region US_GOV_EAST_1 = Region.of("us-gov-east-1");
+ public static final Region ME_CENTRAL_1 = Region.of("me-central-1");
- public static final Region CA_CENTRAL_1 = Region.of("ca-central-1");
+ public static final Region AWS_CN_GLOBAL = Region.of("aws-cn-global", true);
- public static final Region EU_CENTRAL_1 = Region.of("eu-central-1");
-
- public static final Region US_ISO_WEST_1 = Region.of("us-iso-west-1");
+ public static final Region US_ISOF_SOUTH_1 = Region.of("us-isof-south-1");
public static final Region US_WEST_1 = Region.of("us-west-1");
@@ -54,14 +48,6 @@ public final class Region {
public static final Region AF_SOUTH_1 = Region.of("af-south-1");
- public static final Region EU_NORTH_1 = Region.of("eu-north-1");
-
- public static final Region EU_WEST_3 = Region.of("eu-west-3");
-
- public static final Region EU_WEST_2 = Region.of("eu-west-2");
-
- public static final Region EU_WEST_1 = Region.of("eu-west-1");
-
public static final Region AP_NORTHEAST_3 = Region.of("ap-northeast-3");
public static final Region AP_NORTHEAST_2 = Region.of("ap-northeast-2");
@@ -72,41 +58,89 @@ public final class Region {
public static final Region SA_EAST_1 = Region.of("sa-east-1");
- public static final Region AP_EAST_1 = Region.of("ap-east-1");
-
public static final Region CN_NORTH_1 = Region.of("cn-north-1");
- public static final Region US_GOV_WEST_1 = Region.of("us-gov-west-1");
-
public static final Region AP_SOUTHEAST_1 = Region.of("ap-southeast-1");
public static final Region AP_SOUTHEAST_2 = Region.of("ap-southeast-2");
- public static final Region US_ISO_EAST_1 = Region.of("us-iso-east-1");
+ public static final Region AP_SOUTHEAST_3 = Region.of("ap-southeast-3");
+
+ public static final Region AP_SOUTHEAST_4 = Region.of("ap-southeast-4");
+
+ public static final Region AP_SOUTHEAST_5 = Region.of("ap-southeast-5");
public static final Region US_EAST_1 = Region.of("us-east-1");
public static final Region US_EAST_2 = Region.of("us-east-2");
+ public static final Region AP_SOUTHEAST_7 = Region.of("ap-southeast-7");
+
public static final Region CN_NORTHWEST_1 = Region.of("cn-northwest-1");
- public static final Region US_ISOB_EAST_1 = Region.of("us-isob-east-1");
+ public static final Region AP_SOUTH_2 = Region.of("ap-south-2");
+
+ public static final Region AP_SOUTH_1 = Region.of("ap-south-1");
+
+ public static final Region EU_SOUTH_1 = Region.of("eu-south-1");
+
+ public static final Region EU_SOUTH_2 = Region.of("eu-south-2");
+
+ public static final Region US_GOV_EAST_1 = Region.of("us-gov-east-1");
+
+ public static final Region IL_CENTRAL_1 = Region.of("il-central-1");
+
+ public static final Region CA_CENTRAL_1 = Region.of("ca-central-1");
+
+ public static final Region MX_CENTRAL_1 = Region.of("mx-central-1");
+
+ public static final Region EU_CENTRAL_1 = Region.of("eu-central-1");
+
+ public static final Region US_ISO_WEST_1 = Region.of("us-iso-west-1");
+
+ public static final Region EUSC_DE_EAST_1 = Region.of("eusc-de-east-1");
+
+ public static final Region EU_CENTRAL_2 = Region.of("eu-central-2");
+
+ public static final Region EU_ISOE_WEST_1 = Region.of("eu-isoe-west-1");
public static final Region AWS_GLOBAL = Region.of("aws-global", true);
- public static final Region AWS_CN_GLOBAL = Region.of("aws-cn-global", true);
+ public static final Region EU_NORTH_1 = Region.of("eu-north-1");
- public static final Region AWS_US_GOV_GLOBAL = Region.of("aws-us-gov-global", true);
+ public static final Region EU_WEST_3 = Region.of("eu-west-3");
+
+ public static final Region EU_WEST_2 = Region.of("eu-west-2");
+
+ public static final Region EU_WEST_1 = Region.of("eu-west-1");
public static final Region AWS_ISO_GLOBAL = Region.of("aws-iso-global", true);
+ public static final Region AP_EAST_1 = Region.of("ap-east-1");
+
+ public static final Region CA_WEST_1 = Region.of("ca-west-1");
+
+ public static final Region US_GOV_WEST_1 = Region.of("us-gov-west-1");
+
+ public static final Region US_ISO_EAST_1 = Region.of("us-iso-east-1");
+
public static final Region AWS_ISO_B_GLOBAL = Region.of("aws-iso-b-global", true);
- private static final List REGIONS = Collections.unmodifiableList(Arrays.asList(AP_SOUTH_1, EU_SOUTH_1, US_GOV_EAST_1,
- CA_CENTRAL_1, EU_CENTRAL_1, US_ISO_WEST_1, US_WEST_1, US_WEST_2, AF_SOUTH_1, EU_NORTH_1, EU_WEST_3, EU_WEST_2,
- EU_WEST_1, AP_NORTHEAST_3, AP_NORTHEAST_2, AP_NORTHEAST_1, ME_SOUTH_1, SA_EAST_1, AP_EAST_1, CN_NORTH_1,
- US_GOV_WEST_1, AP_SOUTHEAST_1, AP_SOUTHEAST_2, US_ISO_EAST_1, US_EAST_1, US_EAST_2, CN_NORTHWEST_1, US_ISOB_EAST_1,
- AWS_GLOBAL, AWS_CN_GLOBAL, AWS_US_GOV_GLOBAL, AWS_ISO_GLOBAL, AWS_ISO_B_GLOBAL));
+ public static final Region AWS_ISO_F_GLOBAL = Region.of("aws-iso-f-global", true);
+
+ public static final Region AWS_US_GOV_GLOBAL = Region.of("aws-us-gov-global", true);
+
+ public static final Region US_ISOB_EAST_1 = Region.of("us-isob-east-1");
+
+ public static final Region US_ISOF_EAST_1 = Region.of("us-isof-east-1");
+
+ private static final List REGIONS = Collections.unmodifiableList(Arrays.asList(ME_CENTRAL_1, AWS_CN_GLOBAL,
+ US_ISOF_SOUTH_1, US_WEST_1, US_WEST_2, AF_SOUTH_1, AP_NORTHEAST_3, AP_NORTHEAST_2, AP_NORTHEAST_1, ME_SOUTH_1,
+ SA_EAST_1, CN_NORTH_1, AP_SOUTHEAST_1, AP_SOUTHEAST_2, AP_SOUTHEAST_3, AP_SOUTHEAST_4, AP_SOUTHEAST_5, US_EAST_1,
+ US_EAST_2, AP_SOUTHEAST_7, CN_NORTHWEST_1, AP_SOUTH_2, AP_SOUTH_1, EU_SOUTH_1, EU_SOUTH_2, US_GOV_EAST_1,
+ IL_CENTRAL_1, CA_CENTRAL_1, MX_CENTRAL_1, EU_CENTRAL_1, US_ISO_WEST_1, EUSC_DE_EAST_1, EU_CENTRAL_2, EU_ISOE_WEST_1,
+ AWS_GLOBAL, EU_NORTH_1, EU_WEST_3, EU_WEST_2, EU_WEST_1, AWS_ISO_GLOBAL, AP_EAST_1, CA_WEST_1, US_GOV_WEST_1,
+ US_ISO_EAST_1, AWS_ISO_B_GLOBAL, AWS_ISO_F_GLOBAL, AWS_US_GOV_GLOBAL, US_ISOB_EAST_1, US_ISOF_EAST_1));
private final boolean isGlobalRegion;
diff --git a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/test-partitions.json.resource b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/test-partitions.json.resource
new file mode 100644
index 000000000000..3d7e9530924e
--- /dev/null
+++ b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/test-partitions.json.resource
@@ -0,0 +1,255 @@
+{
+ "partitions" : [ {
+ "id" : "aws",
+ "outputs" : {
+ "dnsSuffix" : "amazonaws.com",
+ "dualStackDnsSuffix" : "api.aws",
+ "implicitGlobalRegion" : "us-east-1",
+ "name" : "aws",
+ "supportsDualStack" : true,
+ "supportsFIPS" : true
+ },
+ "regionRegex" : "^(us|eu|ap|sa|ca|me|af|il|mx)\\-\\w+\\-\\d+$",
+ "regions" : {
+ "af-south-1" : {
+ "description" : "Africa (Cape Town)"
+ },
+ "ap-east-1" : {
+ "description" : "Asia Pacific (Hong Kong)"
+ },
+ "ap-northeast-1" : {
+ "description" : "Asia Pacific (Tokyo)"
+ },
+ "ap-northeast-2" : {
+ "description" : "Asia Pacific (Seoul)"
+ },
+ "ap-northeast-3" : {
+ "description" : "Asia Pacific (Osaka)"
+ },
+ "ap-south-1" : {
+ "description" : "Asia Pacific (Mumbai)"
+ },
+ "ap-south-2" : {
+ "description" : "Asia Pacific (Hyderabad)"
+ },
+ "ap-southeast-1" : {
+ "description" : "Asia Pacific (Singapore)"
+ },
+ "ap-southeast-2" : {
+ "description" : "Asia Pacific (Sydney)"
+ },
+ "ap-southeast-3" : {
+ "description" : "Asia Pacific (Jakarta)"
+ },
+ "ap-southeast-4" : {
+ "description" : "Asia Pacific (Melbourne)"
+ },
+ "ap-southeast-5" : {
+ "description" : "Asia Pacific (Malaysia)"
+ },
+ "ap-southeast-7" : {
+ "description" : "Asia Pacific (Thailand)"
+ },
+ "aws-global" : {
+ "description" : "AWS Standard global region"
+ },
+ "ca-central-1" : {
+ "description" : "Canada (Central)"
+ },
+ "ca-west-1" : {
+ "description" : "Canada West (Calgary)"
+ },
+ "eu-central-1" : {
+ "description" : "Europe (Frankfurt)"
+ },
+ "eu-central-2" : {
+ "description" : "Europe (Zurich)"
+ },
+ "eu-north-1" : {
+ "description" : "Europe (Stockholm)"
+ },
+ "eu-south-1" : {
+ "description" : "Europe (Milan)"
+ },
+ "eu-south-2" : {
+ "description" : "Europe (Spain)"
+ },
+ "eu-west-1" : {
+ "description" : "Europe (Ireland)"
+ },
+ "eu-west-2" : {
+ "description" : "Europe (London)"
+ },
+ "eu-west-3" : {
+ "description" : "Europe (Paris)"
+ },
+ "il-central-1" : {
+ "description" : "Israel (Tel Aviv)"
+ },
+ "me-central-1" : {
+ "description" : "Middle East (UAE)"
+ },
+ "me-south-1" : {
+ "description" : "Middle East (Bahrain)"
+ },
+ "mx-central-1" : {
+ "description" : "Mexico (Central)"
+ },
+ "sa-east-1" : {
+ "description" : "South America (Sao Paulo)"
+ },
+ "us-east-1" : {
+ "description" : "US East (N. Virginia)"
+ },
+ "us-east-2" : {
+ "description" : "US East (Ohio)"
+ },
+ "us-west-1" : {
+ "description" : "US West (N. California)"
+ },
+ "us-west-2" : {
+ "description" : "US West (Oregon)"
+ }
+ }
+ }, {
+ "id" : "aws-cn",
+ "outputs" : {
+ "dnsSuffix" : "amazonaws.com.cn",
+ "dualStackDnsSuffix" : "api.amazonwebservices.com.cn",
+ "implicitGlobalRegion" : "cn-northwest-1",
+ "name" : "aws-cn",
+ "supportsDualStack" : true,
+ "supportsFIPS" : true
+ },
+ "regionRegex" : "^cn\\-\\w+\\-\\d+$",
+ "regions" : {
+ "aws-cn-global" : {
+ "description" : "AWS China global region"
+ },
+ "cn-north-1" : {
+ "description" : "China (Beijing)"
+ },
+ "cn-northwest-1" : {
+ "description" : "China (Ningxia)"
+ }
+ }
+ }, {
+ "id" : "aws-us-gov",
+ "outputs" : {
+ "dnsSuffix" : "amazonaws.com",
+ "dualStackDnsSuffix" : "api.aws",
+ "implicitGlobalRegion" : "us-gov-west-1",
+ "name" : "aws-us-gov",
+ "supportsDualStack" : true,
+ "supportsFIPS" : true
+ },
+ "regionRegex" : "^us\\-gov\\-\\w+\\-\\d+$",
+ "regions" : {
+ "aws-us-gov-global" : {
+ "description" : "AWS GovCloud (US) global region"
+ },
+ "us-gov-east-1" : {
+ "description" : "AWS GovCloud (US-East)"
+ },
+ "us-gov-west-1" : {
+ "description" : "AWS GovCloud (US-West)"
+ }
+ }
+ }, {
+ "id" : "aws-iso",
+ "outputs" : {
+ "dnsSuffix" : "c2s.ic.gov",
+ "dualStackDnsSuffix" : "c2s.ic.gov",
+ "implicitGlobalRegion" : "us-iso-east-1",
+ "name" : "aws-iso",
+ "supportsDualStack" : false,
+ "supportsFIPS" : true
+ },
+ "regionRegex" : "^us\\-iso\\-\\w+\\-\\d+$",
+ "regions" : {
+ "aws-iso-global" : {
+ "description" : "AWS ISO (US) global region"
+ },
+ "us-iso-east-1" : {
+ "description" : "US ISO East"
+ },
+ "us-iso-west-1" : {
+ "description" : "US ISO WEST"
+ }
+ }
+ }, {
+ "id" : "aws-iso-b",
+ "outputs" : {
+ "dnsSuffix" : "sc2s.sgov.gov",
+ "dualStackDnsSuffix" : "sc2s.sgov.gov",
+ "implicitGlobalRegion" : "us-isob-east-1",
+ "name" : "aws-iso-b",
+ "supportsDualStack" : false,
+ "supportsFIPS" : true
+ },
+ "regionRegex" : "^us\\-isob\\-\\w+\\-\\d+$",
+ "regions" : {
+ "aws-iso-b-global" : {
+ "description" : "AWS ISOB (US) global region"
+ },
+ "us-isob-east-1" : {
+ "description" : "US ISOB East (Ohio)"
+ }
+ }
+ }, {
+ "id" : "aws-iso-e",
+ "outputs" : {
+ "dnsSuffix" : "cloud.adc-e.uk",
+ "dualStackDnsSuffix" : "cloud.adc-e.uk",
+ "implicitGlobalRegion" : "eu-isoe-west-1",
+ "name" : "aws-iso-e",
+ "supportsDualStack" : false,
+ "supportsFIPS" : true
+ },
+ "regionRegex" : "^eu\\-isoe\\-\\w+\\-\\d+$",
+ "regions" : {
+ "eu-isoe-west-1" : {
+ "description" : "EU ISOE West"
+ }
+ }
+ }, {
+ "id" : "aws-iso-f",
+ "outputs" : {
+ "dnsSuffix" : "csp.hci.ic.gov",
+ "dualStackDnsSuffix" : "csp.hci.ic.gov",
+ "implicitGlobalRegion" : "us-isof-south-1",
+ "name" : "aws-iso-f",
+ "supportsDualStack" : false,
+ "supportsFIPS" : true
+ },
+ "regionRegex" : "^us\\-isof\\-\\w+\\-\\d+$",
+ "regions" : {
+ "aws-iso-f-global" : {
+ "description" : "AWS ISOF global region"
+ },
+ "us-isof-east-1" : {
+ "description" : "US ISOF EAST"
+ },
+ "us-isof-south-1" : {
+ "description" : "US ISOF SOUTH"
+ }
+ }
+ }, {
+ "id" : "aws-eusc",
+ "outputs" : {
+ "dnsSuffix" : "amazonaws.eu",
+ "dualStackDnsSuffix" : "amazonaws.eu",
+ "implicitGlobalRegion" : "eusc-de-east-1",
+ "name" : "aws-eusc",
+ "supportsDualStack" : false,
+ "supportsFIPS" : true
+ },
+ "regionRegex" : "^eusc\\-(de)\\-\\w+\\-\\d+$",
+ "regions" : {
+ "eusc-de-east-1" : {
+ "description" : "EU (Germany)"
+ }
+ }
+ } ],
+ "version" : "1.1"
+}
\ No newline at end of file
diff --git a/codegen-maven-plugin/pom.xml b/codegen-maven-plugin/pom.xml
index a9fcbe256f50..64fa80df5b50 100644
--- a/codegen-maven-plugin/pom.xml
+++ b/codegen-maven-plugin/pom.xml
@@ -22,7 +22,7 @@
software.amazon.awssdk
aws-sdk-java-pom
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
../pom.xml
codegen-maven-plugin
@@ -57,6 +57,11 @@
software.amazon.awssdk
${awsjavasdk.version}
+
+ utils
+ software.amazon.awssdk
+ ${awsjavasdk.version}
+
org.junit.jupiter
junit-jupiter
diff --git a/codegen-maven-plugin/src/main/java/software/amazon/awssdk/codegen/maven/plugin/GenerationMojo.java b/codegen-maven-plugin/src/main/java/software/amazon/awssdk/codegen/maven/plugin/GenerationMojo.java
index 4ce4e7be116b..3d17b4d84bb2 100644
--- a/codegen-maven-plugin/src/main/java/software/amazon/awssdk/codegen/maven/plugin/GenerationMojo.java
+++ b/codegen-maven-plugin/src/main/java/software/amazon/awssdk/codegen/maven/plugin/GenerationMojo.java
@@ -17,11 +17,17 @@
import java.io.File;
import java.io.IOException;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.Optional;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
@@ -30,21 +36,26 @@
import org.apache.maven.project.MavenProject;
import software.amazon.awssdk.codegen.C2jModels;
import software.amazon.awssdk.codegen.CodeGenerator;
+import software.amazon.awssdk.codegen.IntermediateModelBuilder;
+import software.amazon.awssdk.codegen.internal.Jackson;
import software.amazon.awssdk.codegen.internal.Utils;
import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel;
import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel;
import software.amazon.awssdk.codegen.model.service.Paginators;
import software.amazon.awssdk.codegen.model.service.ServiceModel;
import software.amazon.awssdk.codegen.model.service.Waiters;
import software.amazon.awssdk.codegen.utils.ModelLoaderUtils;
+import software.amazon.awssdk.codegen.validation.ModelInvalidException;
+import software.amazon.awssdk.codegen.validation.ModelValidationReport;
+import software.amazon.awssdk.utils.StringUtils;
/**
* The Maven mojo to generate Java client code using software.amazon.awssdk:codegen module.
*/
@Mojo(name = "generate")
public class GenerationMojo extends AbstractMojo {
-
private static final String MODEL_FILE = "service-2.json";
private static final String CUSTOMIZATION_CONFIG_FILE = "customization.config";
private static final String WAITERS_FILE = "waiters-2.json";
@@ -62,6 +73,8 @@ public class GenerationMojo extends AbstractMojo {
@Parameter(property = "writeIntermediateModel", defaultValue = "false")
private boolean writeIntermediateModel;
+ @Parameter(property = "writeValidationReport", defaultValue = "false")
+ private boolean writeValidationReport;
@Parameter(defaultValue = "${project}", readonly = true)
private MavenProject project;
@@ -76,22 +89,72 @@ public void execute() throws MojoExecutionException {
this.resourcesDirectory = Paths.get(outputDirectory).resolve("generated-resources").resolve("sdk-resources");
this.testsDirectory = Paths.get(outputDirectory).resolve("generated-test-sources").resolve("sdk-tests");
- findModelRoots().forEach(p -> {
- Path modelRootPath = p.modelRoot;
- getLog().info("Loading from: " + modelRootPath.toString());
- generateCode(C2jModels.builder()
- .customizationConfig(p.customizationConfig)
- .serviceModel(loadServiceModel(modelRootPath))
- .waitersModel(loadWaiterModel(modelRootPath))
- .paginatorsModel(loadPaginatorModel(modelRootPath))
- .endpointRuleSetModel(loadEndpointRuleSetModel(modelRootPath))
- .endpointTestSuiteModel(loadEndpointTestSuiteModel(modelRootPath))
- .build());
+ List generationParams;
+
+ try {
+ generationParams = initGenerationParams();
+ } catch (ModelInvalidException e) {
+ if (writeValidationReport) {
+ ModelValidationReport report = new ModelValidationReport();
+ report.setValidationEntries(e.validationEntries());
+ emitValidationReport(report);
+ }
+ throw e;
+ }
+
+ Map serviceNameToModelMap = new HashMap<>();
+
+ generationParams.forEach(
+ params -> {
+ IntermediateModel model = params.intermediateModel;
+ String lowercaseServiceName = StringUtils.lowerCase(model.getMetadata().getServiceName());
+ IntermediateModel previous = serviceNameToModelMap.put(lowercaseServiceName, model);
+ if (previous != null) {
+ String warning = String.format("Multiple service models found with service name %s. Model validation "
+ + "will likely be incorrect", lowercaseServiceName);
+ getLog().warn(warning);
+ }
+ });
+
+ // Update each param with the intermediate model it shares models with, if any
+ generationParams.forEach(params -> {
+ CustomizationConfig customizationConfig = params.intermediateModel.getCustomizationConfig();
+
+ if (customizationConfig.getShareModelConfig() != null) {
+ String shareModelWithName = customizationConfig.getShareModelConfig().getShareModelWith();
+ params.withShareModelsTarget(serviceNameToModelMap.get(shareModelWithName));
+ }
});
+
+ generationParams.forEach(this::generateCode);
+
project.addCompileSourceRoot(sourcesDirectory.toFile().getAbsolutePath());
project.addTestCompileSourceRoot(testsDirectory.toFile().getAbsolutePath());
}
+ private List initGenerationParams() throws MojoExecutionException {
+ List modelRoots = findModelRoots().collect(Collectors.toList());
+
+ return modelRoots.stream().map(r -> {
+ Path modelRootPath = r.modelRoot;
+ getLog().info("Loading from: " + modelRootPath.toString());
+ C2jModels c2jModels = C2jModels.builder()
+ .customizationConfig(r.customizationConfig)
+ .serviceModel(loadServiceModel(modelRootPath))
+ .waitersModel(loadWaiterModel(modelRootPath))
+ .paginatorsModel(loadPaginatorModel(modelRootPath))
+ .endpointRuleSetModel(loadEndpointRuleSetModel(modelRootPath))
+ .endpointTestSuiteModel(loadEndpointTestSuiteModel(modelRootPath))
+ .build();
+ String intermediateModelFileNamePrefix = intermediateModelFileNamePrefix(c2jModels);
+ IntermediateModel intermediateModel = new IntermediateModelBuilder(c2jModels).build();
+ return new GenerationParams().withIntermediateModel(intermediateModel)
+ .withIntermediateModelFileNamePrefix(intermediateModelFileNamePrefix);
+ }).collect(Collectors.toList());
+ }
+
+
+
private Stream findModelRoots() throws MojoExecutionException {
try {
return Files.find(codeGenResources.toPath(), 10, this::isModelFile)
@@ -111,13 +174,15 @@ private boolean isModelFile(Path p, BasicFileAttributes a) {
return p.toString().endsWith(MODEL_FILE);
}
- private void generateCode(C2jModels models) {
+ private void generateCode(GenerationParams params) {
CodeGenerator.builder()
- .models(models)
+ .intermediateModel(params.intermediateModel)
+ .shareModelsTarget(params.shareModelsTarget)
.sourcesDirectory(sourcesDirectory.toFile().getAbsolutePath())
.resourcesDirectory(resourcesDirectory.toFile().getAbsolutePath())
.testsDirectory(testsDirectory.toFile().getAbsolutePath())
- .intermediateModelFileNamePrefix(intermediateModelFileNamePrefix(models))
+ .intermediateModelFileNamePrefix(params.intermediateModelFileNamePrefix)
+ .emitValidationReport(writeValidationReport)
.build()
.execute();
}
@@ -169,6 +234,17 @@ private Optional loadOptionalModel(Class clzz, Path location) {
return ModelLoaderUtils.loadOptionalModel(clzz, location.toFile());
}
+ private void emitValidationReport(ModelValidationReport report) {
+ Path modelsDir = sourcesDirectory.resolve("models");
+ try (Writer writer = Files.newBufferedWriter(modelsDir.resolve("validation-report.json"),
+ StandardCharsets.UTF_8);) {
+
+ Jackson.writeWithObjectMapper(report, writer);
+ } catch (IOException e) {
+ getLog().warn("Failed to write validation report to " + modelsDir, e);
+ }
+ }
+
private static class ModelRoot {
private final Path modelRoot;
private final CustomizationConfig customizationConfig;
@@ -178,4 +254,25 @@ private ModelRoot(Path modelRoot, CustomizationConfig customizationConfig) {
this.customizationConfig = customizationConfig;
}
}
+
+ private static class GenerationParams {
+ private IntermediateModel intermediateModel;
+ private IntermediateModel shareModelsTarget;
+ private String intermediateModelFileNamePrefix;
+
+ public GenerationParams withIntermediateModel(IntermediateModel intermediateModel) {
+ this.intermediateModel = intermediateModel;
+ return this;
+ }
+
+ public GenerationParams withShareModelsTarget(IntermediateModel shareModelsTarget) {
+ this.shareModelsTarget = shareModelsTarget;
+ return this;
+ }
+
+ public GenerationParams withIntermediateModelFileNamePrefix(String intermediateModelFileNamePrefix) {
+ this.intermediateModelFileNamePrefix = intermediateModelFileNamePrefix;
+ return this;
+ }
+ }
}
diff --git a/codegen/pom.xml b/codegen/pom.xml
index b8419b94d163..b5b94a594ad0 100644
--- a/codegen/pom.xml
+++ b/codegen/pom.xml
@@ -21,7 +21,7 @@
software.amazon.awssdk
aws-sdk-java-pom
- 2.31.40-SNAPSHOT
+ 2.31.76-SNAPSHOT
codegen
AWS Java SDK :: Code Generator
@@ -239,5 +239,10 @@
mockito-core
compile
+
+ nl.jqno.equalsverifier
+ equalsverifier
+ test
+
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddMetadata.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddMetadata.java
index 56ed58996ac8..41d1f32693f8 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddMetadata.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddMetadata.java
@@ -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;
@@ -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())
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddOperations.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddOperations.java
index 1f247fe61b9f..6953ce6b066f 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddOperations.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddOperations.java
@@ -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.
@@ -164,7 +165,7 @@ public Map 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());
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java
index 4e7811bebdda..46b15ae7dbbd 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddShapes.java
@@ -21,6 +21,7 @@
import static software.amazon.awssdk.codegen.internal.Utils.isMapShape;
import static software.amazon.awssdk.codegen.internal.Utils.isScalar;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -37,9 +38,15 @@
import software.amazon.awssdk.codegen.model.intermediate.VariableModel;
import software.amazon.awssdk.codegen.model.service.Location;
import software.amazon.awssdk.codegen.model.service.Member;
+import software.amazon.awssdk.codegen.model.service.Operation;
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.codegen.validation.ModelInvalidException;
+import software.amazon.awssdk.codegen.validation.ValidationEntry;
+import software.amazon.awssdk.codegen.validation.ValidationErrorId;
+import software.amazon.awssdk.codegen.validation.ValidationErrorSeverity;
import software.amazon.awssdk.utils.StringUtils;
import software.amazon.awssdk.utils.Validate;
@@ -345,11 +352,20 @@ private boolean isGreedy(Shape parentShape, Map allC2jShapes, Par
* @throws RuntimeException If operation can't be found.
*/
private String findRequestUri(Shape parentShape, Map allC2jShapes) {
- return builder.getService().getOperations().values().stream()
- .filter(o -> o.getInput() != null)
- .filter(o -> allC2jShapes.get(o.getInput().getShape()).equals(parentShape))
- .map(o -> o.getHttp().getRequestUri())
- .findFirst().orElseThrow(() -> new RuntimeException("Could not find request URI for input shape"));
+ Optional operation = builder.getService().getOperations().values().stream()
+ .filter(o -> o.getInput() != null)
+ .filter(o -> allC2jShapes.get(o.getInput().getShape()).equals(parentShape))
+ .findFirst();
+
+ return operation.map(o -> o.getHttp().getRequestUri())
+ .orElseThrow(() -> {
+ String detailMsg = "Could not find request URI for input shape";
+ ValidationEntry entry =
+ new ValidationEntry().withErrorId(ValidationErrorId.REQUEST_URI_NOT_FOUND)
+ .withDetailMessage(detailMsg)
+ .withSeverity(ValidationErrorSeverity.DANGER);
+ return ModelInvalidException.builder().validationEntries(Collections.singletonList(entry)).build();
+ });
}
private String deriveUnmarshallerLocationName(Shape memberShape, String memberName, Member member) {
@@ -464,6 +480,6 @@ private void fillContainerTypeMemberMetadata(Map c2jShapes,
}
protected String getProtocol() {
- return getServiceModel().getMetadata().getProtocol();
+ return ProtocolUtils.resolveProtocol(getServiceModel().getMetadata());
}
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/CodeGenerator.java b/codegen/src/main/java/software/amazon/awssdk/codegen/CodeGenerator.java
index 4c097fadb4d2..0361fc6d0fdd 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/CodeGenerator.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/CodeGenerator.java
@@ -19,6 +19,9 @@
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.concurrent.ForkJoinTask;
import software.amazon.awssdk.codegen.emitters.GeneratorTask;
import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams;
@@ -26,13 +29,26 @@
import software.amazon.awssdk.codegen.internal.Jackson;
import software.amazon.awssdk.codegen.internal.Utils;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+import software.amazon.awssdk.codegen.validation.ModelInvalidException;
+import software.amazon.awssdk.codegen.validation.ModelValidationContext;
+import software.amazon.awssdk.codegen.validation.ModelValidationReport;
+import software.amazon.awssdk.codegen.validation.ModelValidator;
+import software.amazon.awssdk.codegen.validation.SharedModelsValidator;
+import software.amazon.awssdk.codegen.validation.ValidationEntry;
import software.amazon.awssdk.utils.Logger;
public class CodeGenerator {
private static final Logger log = Logger.loggerFor(CodeGenerator.class);
private static final String MODEL_DIR_NAME = "models";
- private final C2jModels models;
+ private static final List DEFAULT_MODEL_VALIDATORS = Collections.singletonList(
+ new SharedModelsValidator()
+ );
+
+ private final C2jModels c2jModels;
+
+ private final IntermediateModel intermediateModel;
+ private final IntermediateModel shareModelsTarget;
private final String sourcesDirectory;
private final String resourcesDirectory;
private final String testsDirectory;
@@ -42,6 +58,9 @@ public class CodeGenerator {
*/
private final String fileNamePrefix;
+ private final List modelValidators;
+ private final boolean emitValidationReport;
+
static {
// Make sure ClassName is statically initialized before we do anything in parallel.
// Parallel static initialization of ClassName and TypeName can result in a deadlock:
@@ -50,12 +69,21 @@ public class CodeGenerator {
}
public CodeGenerator(Builder builder) {
- this.models = builder.models;
+ this.c2jModels = builder.models;
+ this.intermediateModel = builder.intermediateModel;
+
+ if (this.c2jModels != null && this.intermediateModel != null) {
+ throw new IllegalArgumentException("Only one of c2jModels and intermediateModel must be specified");
+ }
+
+ this.shareModelsTarget = builder.shareModelsTarget;
this.sourcesDirectory = builder.sourcesDirectory;
this.testsDirectory = builder.testsDirectory;
this.resourcesDirectory = builder.resourcesDirectory != null ? builder.resourcesDirectory
: builder.sourcesDirectory;
this.fileNamePrefix = builder.fileNamePrefix;
+ this.modelValidators = builder.modelValidators == null ? DEFAULT_MODEL_VALIDATORS : builder.modelValidators;
+ this.emitValidationReport = builder.emitValidationReport;
}
public static File getModelDirectory(String outputDirectory) {
@@ -76,22 +104,72 @@ public static Builder builder() {
* code.
*/
public void execute() {
- try {
- IntermediateModel intermediateModel = new IntermediateModelBuilder(models).build();
+ ModelValidationReport report = new ModelValidationReport();
+
+ IntermediateModel modelToGenerate;
+ if (c2jModels != null) {
+ modelToGenerate = new IntermediateModelBuilder(c2jModels).build();
+ } else {
+ modelToGenerate = intermediateModel;
+ }
+ List validatorEntries = runModelValidators(modelToGenerate);
+ report.setValidationEntries(validatorEntries);
+
+ if (emitValidationReport) {
+ writeValidationReport(report);
+ }
+
+ if (!validatorEntries.isEmpty()) {
+ throw new RuntimeException("Validation failed. See validation report for details.");
+ }
+
+ try {
if (fileNamePrefix != null) {
- writeIntermediateModel(intermediateModel);
+ writeIntermediateModel(modelToGenerate);
}
- emitCode(intermediateModel);
+ emitCode(modelToGenerate);
} catch (Exception e) {
log.error(() -> "Failed to generate code. ", e);
+
+ if (e instanceof ModelInvalidException && emitValidationReport) {
+ ModelInvalidException invalidException = (ModelInvalidException) e;
+ report.setValidationEntries(invalidException.validationEntries());
+ writeValidationReport(report);
+ }
+
throw new RuntimeException(
"Failed to generate code. Exception message : " + e.getMessage(), e);
}
}
+ private List runModelValidators(IntermediateModel intermediateModel) {
+ ModelValidationContext ctx = ModelValidationContext.builder()
+ .intermediateModel(intermediateModel)
+ .shareModelsTarget(shareModelsTarget)
+ .build();
+
+ List validationEntries = new ArrayList<>();
+
+ modelValidators.forEach(v -> validationEntries.addAll(v.validateModels(ctx)));
+
+ return validationEntries;
+ }
+
+ private void writeValidationReport(ModelValidationReport report) {
+ try {
+ writeModel(report, "validation-report.json");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
private void writeIntermediateModel(IntermediateModel model) throws IOException {
+ writeModel(model, fileNamePrefix + "-intermediate.json");
+ }
+
+ private void writeModel(Object model, String name) throws IOException {
File modelDir = getModelDirectory(sourcesDirectory);
PrintWriter writer = null;
try {
@@ -100,7 +178,7 @@ private void writeIntermediateModel(IntermediateModel model) throws IOException
throw new RuntimeException("Failed to create " + outDir.getAbsolutePath());
}
- File outputFile = new File(modelDir, fileNamePrefix + "-intermediate.json");
+ File outputFile = new File(modelDir, name);
if (!outputFile.exists() && !outputFile.createNewFile()) {
throw new RuntimeException("Error creating file " + outputFile.getAbsolutePath());
@@ -134,10 +212,14 @@ private GeneratorTask createGeneratorTasks(IntermediateModel intermediateModel)
public static final class Builder {
private C2jModels models;
+ private IntermediateModel intermediateModel;
+ private IntermediateModel shareModelsTarget;
private String sourcesDirectory;
private String resourcesDirectory;
private String testsDirectory;
private String fileNamePrefix;
+ private List modelValidators;
+ private boolean emitValidationReport;
private Builder() {
}
@@ -147,6 +229,16 @@ public Builder models(C2jModels models) {
return this;
}
+ public Builder intermediateModel(IntermediateModel intermediateModel) {
+ this.intermediateModel = intermediateModel;
+ return this;
+ }
+
+ public Builder shareModelsTarget(IntermediateModel shareModelsTarget) {
+ this.shareModelsTarget = shareModelsTarget;
+ return this;
+ }
+
public Builder sourcesDirectory(String sourcesDirectory) {
this.sourcesDirectory = sourcesDirectory;
return this;
@@ -167,6 +259,16 @@ public Builder intermediateModelFileNamePrefix(String fileNamePrefix) {
return this;
}
+ public Builder modelValidators(List modelValidators) {
+ this.modelValidators = modelValidators;
+ return this;
+ }
+
+ public Builder emitValidationReport(boolean emitValidationReport) {
+ this.emitValidationReport = emitValidationReport;
+ return this;
+ }
+
/**
* @return An immutable {@link CodeGenerator} object.
*/
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/ExplicitStringPayloadQueryProtocolProcessor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/ExplicitStringPayloadQueryProtocolProcessor.java
index 273c231b136d..74ab28dd3417 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/ExplicitStringPayloadQueryProtocolProcessor.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/ExplicitStringPayloadQueryProtocolProcessor.java
@@ -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
@@ -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;
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/MetadataModifiersProcessor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/MetadataModifiersProcessor.java
index 1c0786425507..6e4441203516 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/MetadataModifiersProcessor.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/MetadataModifiersProcessor.java
@@ -15,6 +15,7 @@
package software.amazon.awssdk.codegen.customization.processors;
+import java.util.Collections;
import software.amazon.awssdk.codegen.customization.CodegenCustomizationProcessor;
import software.amazon.awssdk.codegen.model.config.customization.MetadataConfig;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
@@ -44,7 +45,7 @@ public void preprocess(ServiceModel serviceModel) {
String customProtocol = metadataConfig.getProtocol();
if (customProtocol != null) {
- serviceMetadata.setProtocol(customProtocol);
+ serviceMetadata.setProtocols(Collections.singletonList(customProtocol));
}
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/SmithyRpcV2CborProtocolProcessor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/SmithyRpcV2CborProtocolProcessor.java
index 7db556fa63ed..2bfb74bef54c 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/SmithyRpcV2CborProtocolProcessor.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/SmithyRpcV2CborProtocolProcessor.java
@@ -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 smithy-rpc-v2-cbor
protocol.
@@ -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));
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AuthSchemeGeneratorTasks.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AuthSchemeGeneratorTasks.java
index fbcec7931bd8..38c170898f27 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AuthSchemeGeneratorTasks.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AuthSchemeGeneratorTasks.java
@@ -28,6 +28,7 @@
import software.amazon.awssdk.codegen.poet.auth.scheme.EndpointAwareAuthSchemeParamsSpec;
import software.amazon.awssdk.codegen.poet.auth.scheme.EndpointBasedAuthSchemeProviderSpec;
import software.amazon.awssdk.codegen.poet.auth.scheme.ModelBasedAuthSchemeProviderSpec;
+import software.amazon.awssdk.codegen.poet.auth.scheme.PreferredAuthSchemeProviderSpec;
public final class AuthSchemeGeneratorTasks extends BaseGeneratorTasks {
private final GeneratorTaskParams generatorTaskParams;
@@ -45,6 +46,7 @@ protected List createTasks() {
tasks.add(generateProviderInterface());
tasks.add(generateDefaultParamsImpl());
tasks.add(generateModelBasedProvider());
+ tasks.add(generatePreferenceProvider());
tasks.add(generateAuthSchemeInterceptor());
if (authSchemeSpecUtils.useEndpointBasedAuthProvider()) {
tasks.add(generateEndpointBasedProvider());
@@ -69,6 +71,10 @@ private GeneratorTask generateModelBasedProvider() {
return new PoetGeneratorTask(authSchemeInternalDir(), model.getFileHeader(), new ModelBasedAuthSchemeProviderSpec(model));
}
+ private GeneratorTask generatePreferenceProvider() {
+ return new PoetGeneratorTask(authSchemeInternalDir(), model.getFileHeader(), new PreferredAuthSchemeProviderSpec(model));
+ }
+
private GeneratorTask generateEndpointBasedProvider() {
return new PoetGeneratorTask(authSchemeInternalDir(), model.getFileHeader(),
new EndpointBasedAuthSchemeProviderSpec(model));
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/BaseGeneratorTasks.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/BaseGeneratorTasks.java
index 731f70e0cba3..cdabdbf219cd 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/BaseGeneratorTasks.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/BaseGeneratorTasks.java
@@ -71,6 +71,8 @@ protected void compute() {
ForkJoinTask.invokeAll(createTasks());
log.info(" Completed " + taskName + ".");
}
+ } catch (RuntimeException e) {
+ throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/CommonInternalGeneratorTasks.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/CommonInternalGeneratorTasks.java
index 7d407f582f7d..c02571f181c0 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/CommonInternalGeneratorTasks.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/CommonInternalGeneratorTasks.java
@@ -15,12 +15,14 @@
package software.amazon.awssdk.codegen.emitters.tasks;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.List;
import software.amazon.awssdk.codegen.emitters.GeneratorTask;
import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams;
import software.amazon.awssdk.codegen.emitters.PoetGeneratorTask;
+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.common.UserAgentUtilsSpec;
public class CommonInternalGeneratorTasks extends BaseGeneratorTasks {
@@ -33,7 +35,14 @@ public CommonInternalGeneratorTasks(GeneratorTaskParams params) {
@Override
protected List createTasks() throws Exception {
- return Arrays.asList(createClientOptionTask(), createUserAgentTask());
+ List tasks = new ArrayList<>();
+ tasks.add(createClientOptionTask());
+ tasks.add(createUserAgentTask());
+ if (params.getModel().getCustomizationConfig().isEnableEnvironmentBearerToken()) {
+ tasks.add(createEnvironmentTokenSystemSettingTask());
+ }
+ tasks.add(createServiceVersionInfoTask());
+ return tasks;
}
private PoetGeneratorTask createClientOptionTask() {
@@ -46,6 +55,16 @@ private PoetGeneratorTask createUserAgentTask() {
new UserAgentUtilsSpec(params.getModel()));
}
+ private GeneratorTask createEnvironmentTokenSystemSettingTask() {
+ return new PoetGeneratorTask(clientOptionsDir(), params.getModel().getFileHeader(),
+ new EnvironmentTokenSystemSettingsClass(params.getModel()));
+ }
+
+ private GeneratorTask createServiceVersionInfoTask() {
+ return new PoetGeneratorTask(clientOptionsDir(), params.getModel().getFileHeader(),
+ new ServiceVersionInfoSpec(params.getModel()));
+ }
+
private String clientOptionsDir() {
return params.getPathProvider().getClientInternalDirectory();
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/internal/Utils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/internal/Utils.java
index 1efeefb9b27a..becbdfd18a32 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/internal/Utils.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/internal/Utils.java
@@ -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;
@@ -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());
@@ -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());
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/CustomizationConfig.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/CustomizationConfig.java
index 32cecd79feb5..cfa719d4c738 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/CustomizationConfig.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/CustomizationConfig.java
@@ -350,6 +350,18 @@ public class CustomizationConfig {
*/
private boolean enableFastUnmarshaller;
+ /**
+ * A boolean flag to indicate if support for configuring a bearer token sourced from the environment should be added to the
+ * generated service. When enabled, the generated client will use bearer auth with the token sourced from the
+ * `AWS_BEARER_TOKEN_[SigningName]` environment variable.
+ */
+ private boolean enableEnvironmentBearerToken = false;
+
+ /**
+ * A boolean flag to indicate if the code-generated endpoint providers class should cache the calls to URI constructors.
+ */
+ private boolean enableEndpointProviderUriCaching;
+
private CustomizationConfig() {
}
@@ -924,4 +936,20 @@ public boolean getEnableFastUnmarshaller() {
public void setEnableFastUnmarshaller(boolean enableFastUnmarshaller) {
this.enableFastUnmarshaller = enableFastUnmarshaller;
}
+
+ public boolean isEnableEnvironmentBearerToken() {
+ return enableEnvironmentBearerToken;
+ }
+
+ public void setEnableEnvironmentBearerToken(boolean enableEnvironmentBearerToken) {
+ this.enableEnvironmentBearerToken = enableEnvironmentBearerToken;
+ }
+
+ public boolean getEnableEndpointProviderUriCaching() {
+ return enableEndpointProviderUriCaching;
+ }
+
+ public void setEnableEndpointProviderUriCaching(boolean enableEndpointProviderUriCaching) {
+ this.enableEndpointProviderUriCaching = enableEndpointProviderUriCaching;
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ArgumentModel.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ArgumentModel.java
index 5013db7d3f9e..16e848303a4f 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ArgumentModel.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ArgumentModel.java
@@ -15,6 +15,8 @@
package software.amazon.awssdk.codegen.model.intermediate;
+import java.util.Objects;
+
public class ArgumentModel extends DocumentationModel {
private String name;
@@ -61,4 +63,28 @@ public ArgumentModel withIsEnumArg(boolean isEnumArg) {
this.isEnumArg = isEnumArg;
return this;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ ArgumentModel that = (ArgumentModel) o;
+ return isEnumArg == that.isEnumArg
+ && Objects.equals(name, that.name)
+ && Objects.equals(type, that.type);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + Objects.hashCode(name);
+ result = 31 * result + Objects.hashCode(type);
+ result = 31 * result + Boolean.hashCode(isEnumArg);
+ return result;
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/AuthorizerModel.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/AuthorizerModel.java
index ce98c0dfea8e..316f4e741139 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/AuthorizerModel.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/AuthorizerModel.java
@@ -16,6 +16,7 @@
package software.amazon.awssdk.codegen.model.intermediate;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import java.util.Objects;
import software.amazon.awssdk.codegen.model.service.Location;
public class AuthorizerModel extends DocumentationModel {
@@ -63,4 +64,30 @@ public String getAddAuthTokenMethod() {
authTokenLocation));
}
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ AuthorizerModel that = (AuthorizerModel) o;
+ return Objects.equals(name, that.name)
+ && Objects.equals(interfaceName, that.interfaceName)
+ && authTokenLocation == that.authTokenLocation
+ && Objects.equals(tokenName, that.tokenName);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + Objects.hashCode(name);
+ result = 31 * result + Objects.hashCode(interfaceName);
+ result = 31 * result + Objects.hashCode(authTokenLocation);
+ result = 31 * result + Objects.hashCode(tokenName);
+ return result;
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/DocumentationModel.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/DocumentationModel.java
index 5be891040acc..55fd39f4a7c7 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/DocumentationModel.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/DocumentationModel.java
@@ -17,6 +17,8 @@
import static software.amazon.awssdk.codegen.internal.DocumentationUtils.escapeIllegalCharacters;
+import java.util.Objects;
+
public class DocumentationModel {
protected String documentation;
@@ -28,4 +30,22 @@ public String getDocumentation() {
public void setDocumentation(String documentation) {
this.documentation = escapeIllegalCharacters(documentation);
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ DocumentationModel that = (DocumentationModel) o;
+ return Objects.equals(documentation, that.documentation);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(documentation);
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/EndpointDiscovery.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/EndpointDiscovery.java
index 91a5f3b60f25..e372079fc541 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/EndpointDiscovery.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/EndpointDiscovery.java
@@ -26,4 +26,22 @@ public boolean isRequired() {
public void setRequired(boolean required) {
this.required = required;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ EndpointDiscovery that = (EndpointDiscovery) o;
+ return required == that.required;
+ }
+
+ @Override
+ public int hashCode() {
+ return Boolean.hashCode(required);
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/EnumModel.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/EnumModel.java
index f469b5de99fd..652f2c2aca6e 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/EnumModel.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/EnumModel.java
@@ -15,6 +15,8 @@
package software.amazon.awssdk.codegen.model.intermediate;
+import java.util.Objects;
+
/**
* Represents a single enum field in a enum.
*/
@@ -49,4 +51,23 @@ public String getValue() {
return value;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ EnumModel enumModel = (EnumModel) o;
+ return Objects.equals(value, enumModel.value) && Objects.equals(name, enumModel.name);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hashCode(value);
+ result = 31 * result + Objects.hashCode(name);
+ return result;
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/MemberModel.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/MemberModel.java
index fddf93d4d72d..3e905aa1ed56 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/MemberModel.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/MemberModel.java
@@ -28,6 +28,7 @@
import com.squareup.javapoet.ClassName;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import software.amazon.awssdk.codegen.internal.TypeUtils;
import software.amazon.awssdk.codegen.model.service.ContextParam;
@@ -785,4 +786,98 @@ public void ignoreDataTypeConversionFailures(boolean ignoreDataTypeConversionFai
public boolean ignoreDataTypeConversionFailures() {
return ignoreDataTypeConversionFailures;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ MemberModel that = (MemberModel) o;
+ return deprecated == that.deprecated
+ && required == that.required
+ && synthetic == that.synthetic
+ && idempotencyToken == that.idempotencyToken
+ && isJsonValue == that.isJsonValue
+ && eventPayload == that.eventPayload
+ && eventHeader == that.eventHeader
+ && endpointDiscoveryId == that.endpointDiscoveryId
+ && sensitive == that.sensitive
+ && xmlAttribute == that.xmlAttribute
+ && ignoreDataTypeConversionFailures == that.ignoreDataTypeConversionFailures
+ && Objects.equals(name, that.name)
+ && Objects.equals(c2jName, that.c2jName)
+ && Objects.equals(c2jShape, that.c2jShape)
+ && Objects.equals(variable, that.variable)
+ && Objects.equals(setterModel, that.setterModel)
+ && Objects.equals(getterModel, that.getterModel)
+ && Objects.equals(http, that.http)
+ && Objects.equals(deprecatedMessage, that.deprecatedMessage)
+ && Objects.equals(listModel, that.listModel)
+ && Objects.equals(mapModel, that.mapModel)
+ && Objects.equals(enumType, that.enumType)
+ && Objects.equals(xmlNameSpaceUri, that.xmlNameSpaceUri)
+ && Objects.equals(shape, that.shape)
+ && Objects.equals(fluentGetterMethodName, that.fluentGetterMethodName)
+ && Objects.equals(fluentEnumGetterMethodName, that.fluentEnumGetterMethodName)
+ && Objects.equals(fluentSetterMethodName, that.fluentSetterMethodName)
+ && Objects.equals(fluentEnumSetterMethodName, that.fluentEnumSetterMethodName)
+ && Objects.equals(existenceCheckMethodName, that.existenceCheckMethodName)
+ && Objects.equals(beanStyleGetterName, that.beanStyleGetterName)
+ && Objects.equals(beanStyleSetterName, that.beanStyleSetterName)
+ && Objects.equals(unionEnumTypeName, that.unionEnumTypeName)
+ && Objects.equals(timestampFormat, that.timestampFormat)
+ && Objects.equals(deprecatedName, that.deprecatedName)
+ && Objects.equals(fluentDeprecatedGetterMethodName, that.fluentDeprecatedGetterMethodName)
+ && Objects.equals(fluentDeprecatedSetterMethodName, that.fluentDeprecatedSetterMethodName)
+ && Objects.equals(deprecatedBeanStyleSetterMethodName, that.deprecatedBeanStyleSetterMethodName)
+ && Objects.equals(contextParam, that.contextParam);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + Objects.hashCode(name);
+ result = 31 * result + Objects.hashCode(c2jName);
+ result = 31 * result + Objects.hashCode(c2jShape);
+ result = 31 * result + Objects.hashCode(variable);
+ result = 31 * result + Objects.hashCode(setterModel);
+ result = 31 * result + Objects.hashCode(getterModel);
+ result = 31 * result + Objects.hashCode(http);
+ result = 31 * result + Boolean.hashCode(deprecated);
+ result = 31 * result + Objects.hashCode(deprecatedMessage);
+ result = 31 * result + Boolean.hashCode(required);
+ result = 31 * result + Boolean.hashCode(synthetic);
+ result = 31 * result + Objects.hashCode(listModel);
+ result = 31 * result + Objects.hashCode(mapModel);
+ result = 31 * result + Objects.hashCode(enumType);
+ result = 31 * result + Objects.hashCode(xmlNameSpaceUri);
+ result = 31 * result + Boolean.hashCode(idempotencyToken);
+ result = 31 * result + Objects.hashCode(shape);
+ result = 31 * result + Objects.hashCode(fluentGetterMethodName);
+ result = 31 * result + Objects.hashCode(fluentEnumGetterMethodName);
+ result = 31 * result + Objects.hashCode(fluentSetterMethodName);
+ result = 31 * result + Objects.hashCode(fluentEnumSetterMethodName);
+ result = 31 * result + Objects.hashCode(existenceCheckMethodName);
+ result = 31 * result + Objects.hashCode(beanStyleGetterName);
+ result = 31 * result + Objects.hashCode(beanStyleSetterName);
+ result = 31 * result + Objects.hashCode(unionEnumTypeName);
+ result = 31 * result + Boolean.hashCode(isJsonValue);
+ result = 31 * result + Objects.hashCode(timestampFormat);
+ result = 31 * result + Boolean.hashCode(eventPayload);
+ result = 31 * result + Boolean.hashCode(eventHeader);
+ result = 31 * result + Boolean.hashCode(endpointDiscoveryId);
+ result = 31 * result + Boolean.hashCode(sensitive);
+ result = 31 * result + Boolean.hashCode(xmlAttribute);
+ result = 31 * result + Objects.hashCode(deprecatedName);
+ result = 31 * result + Objects.hashCode(fluentDeprecatedGetterMethodName);
+ result = 31 * result + Objects.hashCode(fluentDeprecatedSetterMethodName);
+ result = 31 * result + Objects.hashCode(deprecatedBeanStyleSetterMethodName);
+ result = 31 * result + Objects.hashCode(contextParam);
+ result = 31 * result + Boolean.hashCode(ignoreDataTypeConversionFailures);
+ return result;
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/OperationModel.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/OperationModel.java
index a2a060c7a915..6b192644da1d 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/OperationModel.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/OperationModel.java
@@ -19,6 +19,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import software.amazon.awssdk.codegen.checksum.HttpChecksum;
import software.amazon.awssdk.codegen.compression.RequestCompression;
import software.amazon.awssdk.codegen.docs.ClientType;
@@ -379,4 +380,63 @@ public boolean isUnsignedPayload() {
public void setUnsignedPayload(boolean unsignedPayload) {
this.unsignedPayload = unsignedPayload;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ OperationModel that = (OperationModel) o;
+ return deprecated == that.deprecated && hasBlobMemberAsPayload == that.hasBlobMemberAsPayload
+ && hasStringMemberAsPayload == that.hasStringMemberAsPayload && isAuthenticated == that.isAuthenticated
+ && isPaginated == that.isPaginated && endpointOperation == that.endpointOperation
+ && endpointCacheRequired == that.endpointCacheRequired && httpChecksumRequired == that.httpChecksumRequired
+ && unsignedPayload == that.unsignedPayload && Objects.equals(operationName, that.operationName)
+ && Objects.equals(serviceProtocol, that.serviceProtocol)
+ && Objects.equals(deprecatedMessage, that.deprecatedMessage) && Objects.equals(input, that.input)
+ && Objects.equals(returnType, that.returnType) && Objects.equals(exceptions, that.exceptions)
+ && Objects.equals(simpleMethods, that.simpleMethods) && authType == that.authType
+ && Objects.equals(auth, that.auth) && Objects.equals(endpointDiscovery, that.endpointDiscovery)
+ && Objects.equals(inputShape, that.inputShape) && Objects.equals(outputShape, that.outputShape)
+ && Objects.equals(endpointTrait, that.endpointTrait) && Objects.equals(httpChecksum, that.httpChecksum)
+ && Objects.equals(requestcompression, that.requestcompression)
+ && Objects.equals(staticContextParams, that.staticContextParams)
+ && Objects.equals(operationContextParams, that.operationContextParams);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + Objects.hashCode(operationName);
+ result = 31 * result + Objects.hashCode(serviceProtocol);
+ result = 31 * result + Boolean.hashCode(deprecated);
+ result = 31 * result + Objects.hashCode(deprecatedMessage);
+ result = 31 * result + Objects.hashCode(input);
+ result = 31 * result + Objects.hashCode(returnType);
+ result = 31 * result + Objects.hashCode(exceptions);
+ result = 31 * result + Objects.hashCode(simpleMethods);
+ result = 31 * result + Boolean.hashCode(hasBlobMemberAsPayload);
+ result = 31 * result + Boolean.hashCode(hasStringMemberAsPayload);
+ result = 31 * result + Boolean.hashCode(isAuthenticated);
+ result = 31 * result + Objects.hashCode(authType);
+ result = 31 * result + Objects.hashCode(auth);
+ result = 31 * result + Boolean.hashCode(isPaginated);
+ result = 31 * result + Boolean.hashCode(endpointOperation);
+ result = 31 * result + Boolean.hashCode(endpointCacheRequired);
+ result = 31 * result + Objects.hashCode(endpointDiscovery);
+ result = 31 * result + Objects.hashCode(inputShape);
+ result = 31 * result + Objects.hashCode(outputShape);
+ result = 31 * result + Objects.hashCode(endpointTrait);
+ result = 31 * result + Boolean.hashCode(httpChecksumRequired);
+ result = 31 * result + Objects.hashCode(httpChecksum);
+ result = 31 * result + Objects.hashCode(requestcompression);
+ result = 31 * result + Objects.hashCode(staticContextParams);
+ result = 31 * result + Objects.hashCode(operationContextParams);
+ result = 31 * result + Boolean.hashCode(unsignedPayload);
+ return result;
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ParameterHttpMapping.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ParameterHttpMapping.java
index 22ed4a8e6880..fc9a776059a7 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ParameterHttpMapping.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ParameterHttpMapping.java
@@ -15,6 +15,7 @@
package software.amazon.awssdk.codegen.model.intermediate;
+import java.util.Objects;
import software.amazon.awssdk.codegen.model.service.Location;
import software.amazon.awssdk.core.protocol.MarshallLocation;
@@ -199,4 +200,40 @@ public MarshallLocation getMarshallLocation() {
}
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ ParameterHttpMapping that = (ParameterHttpMapping) o;
+ return isPayload == that.isPayload
+ && isStreaming == that.isStreaming
+ && flattened == that.flattened
+ && isGreedy == that.isGreedy
+ && requiresLength == that.requiresLength
+ && Objects.equals(unmarshallLocationName, that.unmarshallLocationName)
+ && Objects.equals(marshallLocationName, that.marshallLocationName)
+ && Objects.equals(additionalUnmarshallingPath, that.additionalUnmarshallingPath)
+ && Objects.equals(additionalMarshallingPath, that.additionalMarshallingPath)
+ && location == that.location;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hashCode(unmarshallLocationName);
+ result = 31 * result + Objects.hashCode(marshallLocationName);
+ result = 31 * result + Objects.hashCode(additionalUnmarshallingPath);
+ result = 31 * result + Objects.hashCode(additionalMarshallingPath);
+ result = 31 * result + Boolean.hashCode(isPayload);
+ result = 31 * result + Boolean.hashCode(isStreaming);
+ result = 31 * result + Objects.hashCode(location);
+ result = 31 * result + Boolean.hashCode(flattened);
+ result = 31 * result + Boolean.hashCode(isGreedy);
+ result = 31 * result + Boolean.hashCode(requiresLength);
+ return result;
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ReturnTypeModel.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ReturnTypeModel.java
index 77dff4c71481..1d46c2802cda 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ReturnTypeModel.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ReturnTypeModel.java
@@ -15,6 +15,8 @@
package software.amazon.awssdk.codegen.model.intermediate;
+import java.util.Objects;
+
public class ReturnTypeModel {
private String returnType;
@@ -48,4 +50,24 @@ public ReturnTypeModel withDocumentation(String documentation) {
setDocumentation(documentation);
return this;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ ReturnTypeModel that = (ReturnTypeModel) o;
+ return Objects.equals(returnType, that.returnType) && Objects.equals(documentation, that.documentation);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hashCode(returnType);
+ result = 31 * result + Objects.hashCode(documentation);
+ return result;
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ShapeModel.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ShapeModel.java
index 098ea46bc7e4..3c26965302d5 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ShapeModel.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/ShapeModel.java
@@ -26,6 +26,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.stream.Collectors;
import software.amazon.awssdk.codegen.model.intermediate.customization.ShapeCustomizationInfo;
import software.amazon.awssdk.codegen.model.service.XmlNamespace;
@@ -669,4 +670,84 @@ public ShapeModel withIsThrottling(boolean throttling) {
this.throttling = throttling;
return this;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ ShapeModel that = (ShapeModel) o;
+ return deprecated == that.deprecated
+ && hasPayloadMember == that.hasPayloadMember
+ && hasHeaderMember == that.hasHeaderMember
+ && hasStatusCodeMember == that.hasStatusCodeMember
+ && hasStreamingMember == that.hasStreamingMember
+ && hasRequiresLengthMember == that.hasRequiresLengthMember
+ && wrapper == that.wrapper
+ && simpleMethod == that.simpleMethod
+ && fault == that.fault
+ && isEventStream == that.isEventStream
+ && isEvent == that.isEvent
+ && document == that.document
+ && union == that.union
+ && retryable == that.retryable
+ && throttling == that.throttling
+ && Objects.equals(c2jName, that.c2jName)
+ && Objects.equals(shapeName, that.shapeName)
+ && Objects.equals(deprecatedMessage, that.deprecatedMessage)
+ && Objects.equals(type, that.type)
+ && Objects.equals(required, that.required)
+ && Objects.equals(requestSignerClassFqcn, that.requestSignerClassFqcn)
+ && Objects.equals(endpointDiscovery, that.endpointDiscovery)
+ && Objects.equals(members, that.members)
+ && Objects.equals(enums, that.enums)
+ && Objects.equals(variable, that.variable)
+ && Objects.equals(marshaller, that.marshaller)
+ && Objects.equals(unmarshaller, that.unmarshaller)
+ && Objects.equals(errorCode, that.errorCode)
+ && Objects.equals(httpStatusCode, that.httpStatusCode)
+ && Objects.equals(customization, that.customization)
+ && Objects.equals(xmlNamespace, that.xmlNamespace);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + Objects.hashCode(c2jName);
+ result = 31 * result + Objects.hashCode(shapeName);
+ result = 31 * result + Boolean.hashCode(deprecated);
+ result = 31 * result + Objects.hashCode(deprecatedMessage);
+ result = 31 * result + Objects.hashCode(type);
+ result = 31 * result + Objects.hashCode(required);
+ result = 31 * result + Boolean.hashCode(hasPayloadMember);
+ result = 31 * result + Boolean.hashCode(hasHeaderMember);
+ result = 31 * result + Boolean.hashCode(hasStatusCodeMember);
+ result = 31 * result + Boolean.hashCode(hasStreamingMember);
+ result = 31 * result + Boolean.hashCode(hasRequiresLengthMember);
+ result = 31 * result + Boolean.hashCode(wrapper);
+ result = 31 * result + Boolean.hashCode(simpleMethod);
+ result = 31 * result + Objects.hashCode(requestSignerClassFqcn);
+ result = 31 * result + Objects.hashCode(endpointDiscovery);
+ result = 31 * result + Objects.hashCode(members);
+ result = 31 * result + Objects.hashCode(enums);
+ result = 31 * result + Objects.hashCode(variable);
+ result = 31 * result + Objects.hashCode(marshaller);
+ result = 31 * result + Objects.hashCode(unmarshaller);
+ result = 31 * result + Objects.hashCode(errorCode);
+ result = 31 * result + Objects.hashCode(httpStatusCode);
+ result = 31 * result + Boolean.hashCode(fault);
+ result = 31 * result + Objects.hashCode(customization);
+ result = 31 * result + Boolean.hashCode(isEventStream);
+ result = 31 * result + Boolean.hashCode(isEvent);
+ result = 31 * result + Objects.hashCode(xmlNamespace);
+ result = 31 * result + Boolean.hashCode(document);
+ result = 31 * result + Boolean.hashCode(union);
+ result = 31 * result + Boolean.hashCode(retryable);
+ result = 31 * result + Boolean.hashCode(throttling);
+ return result;
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/VariableModel.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/VariableModel.java
index bdf0668a9d21..b9355009e748 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/VariableModel.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/VariableModel.java
@@ -17,6 +17,7 @@
import java.util.Collection;
import java.util.List;
+import java.util.Objects;
public class VariableModel extends DocumentationModel {
@@ -98,4 +99,31 @@ public String getVariableSetterType() {
public String toString() {
return variableName;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ VariableModel that = (VariableModel) o;
+ return Objects.equals(variableName, that.variableName)
+ && Objects.equals(variableType, that.variableType)
+ && Objects.equals(variableDeclarationType, that.variableDeclarationType);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + Objects.hashCode(variableName);
+ result = 31 * result + Objects.hashCode(variableType);
+ result = 31 * result + Objects.hashCode(variableDeclarationType);
+ return result;
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/customization/ArtificialResultWrapper.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/customization/ArtificialResultWrapper.java
index e8adab25b48c..dd0b91d86301 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/customization/ArtificialResultWrapper.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/customization/ArtificialResultWrapper.java
@@ -15,6 +15,8 @@
package software.amazon.awssdk.codegen.model.intermediate.customization;
+import java.util.Objects;
+
public class ArtificialResultWrapper {
private String wrappedMemberName;
private String wrappedMemberSimpleType;
@@ -34,4 +36,25 @@ public String getWrappedMemberSimpleType() {
public void setWrappedMemberSimpleType(String wrappedMemberSimpleType) {
this.wrappedMemberSimpleType = wrappedMemberSimpleType;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ ArtificialResultWrapper that = (ArtificialResultWrapper) o;
+ return Objects.equals(wrappedMemberName, that.wrappedMemberName)
+ && Objects.equals(wrappedMemberSimpleType, that.wrappedMemberSimpleType);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hashCode(wrappedMemberName);
+ result = 31 * result + Objects.hashCode(wrappedMemberSimpleType);
+ return result;
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/customization/ShapeCustomizationInfo.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/customization/ShapeCustomizationInfo.java
index b6d3950985b2..2e031eabb9a4 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/customization/ShapeCustomizationInfo.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/customization/ShapeCustomizationInfo.java
@@ -16,6 +16,7 @@
package software.amazon.awssdk.codegen.model.intermediate.customization;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import java.util.Objects;
public class ShapeCustomizationInfo {
@@ -72,4 +73,33 @@ public void setStaxTargetDepthOffset(int staxTargetDepthOffset) {
public boolean hasStaxTargetDepthOffset() {
return hasStaxTargetDepthOffset;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ ShapeCustomizationInfo that = (ShapeCustomizationInfo) o;
+ return skipGeneratingModelClass == that.skipGeneratingModelClass
+ && skipGeneratingMarshaller == that.skipGeneratingMarshaller
+ && skipGeneratingUnmarshaller == that.skipGeneratingUnmarshaller
+ && staxTargetDepthOffset == that.staxTargetDepthOffset
+ && hasStaxTargetDepthOffset == that.hasStaxTargetDepthOffset
+ && Objects.equals(artificialResultWrapper, that.artificialResultWrapper);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hashCode(artificialResultWrapper);
+ result = 31 * result + Boolean.hashCode(skipGeneratingModelClass);
+ result = 31 * result + Boolean.hashCode(skipGeneratingMarshaller);
+ result = 31 * result + Boolean.hashCode(skipGeneratingUnmarshaller);
+ result = 31 * result + staxTargetDepthOffset;
+ result = 31 * result + Boolean.hashCode(hasStaxTargetDepthOffset);
+ return result;
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/service/ContextParam.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/service/ContextParam.java
index 96f363cd84f1..8650d1145bcb 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/service/ContextParam.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/service/ContextParam.java
@@ -15,6 +15,8 @@
package software.amazon.awssdk.codegen.model.service;
+import java.util.Objects;
+
public class ContextParam {
private String name;
@@ -25,4 +27,22 @@ public String getName() {
public void setName(String name) {
this.name = name;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ ContextParam that = (ContextParam) o;
+ return Objects.equals(name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name);
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/service/ServiceMetadata.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/service/ServiceMetadata.java
index 073f97e05f8f..95f7f7349d95 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/service/ServiceMetadata.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/service/ServiceMetadata.java
@@ -17,6 +17,7 @@
import java.util.List;
import java.util.Map;
+import software.amazon.awssdk.codegen.utils.ProtocolUtils;
public class ServiceMetadata {
@@ -36,6 +37,8 @@ public class ServiceMetadata {
private String protocol;
+ private List protocols;
+
private String jsonVersion;
private Map awsQueryCompatible;
@@ -103,14 +106,30 @@ 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;
}
+ /**
+ * {@code protocol} superseded by {@code protocols} field, resolved in {@link ProtocolUtils#resolveProtocol(ServiceMetadata)}
+ */
+ @Deprecated
public void setProtocol(String protocol) {
this.protocol = protocol;
}
+ public List getProtocols() {
+ return protocols;
+ }
+
+ public void setProtocols(List protocols) {
+ this.protocols = protocols;
+ }
+
public String getJsonVersion() {
return jsonVersion;
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategy.java b/codegen/src/main/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategy.java
index e5a4904f295f..efb230313efb 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategy.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategy.java
@@ -432,6 +432,22 @@ private boolean isDisallowedNameForShape(String name, Shape parentShape) {
}
}
+ @Override
+ public String getSigningName() {
+ return Optional.ofNullable(serviceModel.getMetadata().getSigningName())
+ .orElseGet(() -> serviceModel.getMetadata().getEndpointPrefix());
+ }
+
+ @Override
+ public String getSigningNameForEnvironmentVariables() {
+ return screamCase(getSigningName());
+ }
+
+ @Override
+ public String getSigningNameForSystemProperties() {
+ return pascalCase(getSigningName());
+ }
+
@Override
public void validateCustomerVisibleNaming(IntermediateModel trimmedModel) {
Metadata metadata = trimmedModel.getMetadata();
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/naming/NamingStrategy.java b/codegen/src/main/java/software/amazon/awssdk/codegen/naming/NamingStrategy.java
index 1fe32773d71f..637920be14de 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/naming/NamingStrategy.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/naming/NamingStrategy.java
@@ -200,6 +200,21 @@ public interface NamingStrategy {
*/
String getExistenceCheckMethodName(String memberName, Shape parentShape);
+ /**
+ * Retrieve the service's signing name that should be used based on the model.
+ */
+ String getSigningName();
+
+ /**
+ * Retrieve the service's signing name that should be used for environment variables.
+ */
+ String getSigningNameForEnvironmentVariables();
+
+ /**
+ * Retrieve the service's signing name that should be used for system properties.
+ */
+ String getSigningNameForSystemProperties();
+
/**
* Verify the customer-visible naming in the provided intermediate model will compile and is idiomatic to Java.
*/
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetExtension.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetExtension.java
index b126fd2f201e..f119507809c2 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetExtension.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetExtension.java
@@ -79,6 +79,14 @@ public ClassName getUserAgentClass() {
return ClassName.get(model.getMetadata().getFullClientInternalPackageName(), "UserAgentUtils");
}
+ public ClassName getServiceVersionInfoClass() {
+ return ClassName.get(model.getMetadata().getFullClientInternalPackageName(), "ServiceVersionInfo");
+ }
+
+ public ClassName getEnvironmentTokenSystemSettingsClass() {
+ return ClassName.get(model.getMetadata().getFullClientInternalPackageName(), "EnvironmentTokenSystemSettings");
+ }
+
/**
* @param operationName Name of the operation
* @return A Poet {@link ClassName} for the response type of a paginated operation in the base service package.
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeInterceptorSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeInterceptorSpec.java
index 7686ef132271..043bf74ba9d9 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeInterceptorSpec.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeInterceptorSpec.java
@@ -49,8 +49,10 @@
import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
import software.amazon.awssdk.core.internal.util.MetricUtils;
import software.amazon.awssdk.core.metrics.CoreMetric;
+import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
import software.amazon.awssdk.endpoints.EndpointProvider;
import software.amazon.awssdk.http.auth.aws.signer.RegionSet;
+import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme;
import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
import software.amazon.awssdk.http.auth.spi.signer.HttpSigner;
@@ -70,8 +72,10 @@
public final class AuthSchemeInterceptorSpec implements ClassSpec {
private final AuthSchemeSpecUtils authSchemeSpecUtils;
private final EndpointRulesSpecUtils endpointRulesSpecUtils;
+ private final IntermediateModel intermediateModel;
public AuthSchemeInterceptorSpec(IntermediateModel intermediateModel) {
+ this.intermediateModel = intermediateModel;
this.authSchemeSpecUtils = new AuthSchemeSpecUtils(intermediateModel);
this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(intermediateModel);
}
@@ -99,9 +103,42 @@ public TypeSpec poetSpec() {
.addMethod(generateTrySelectAuthScheme())
.addMethod(generateGetIdentityMetric())
.addMethod(putSelectedAuthSchemeMethodSpec());
+ if (intermediateModel.getCustomizationConfig().isEnableEnvironmentBearerToken()) {
+ builder.addMethod(generateEnvironmentTokenMetric());
+ }
return builder.build();
}
+ private MethodSpec generateEnvironmentTokenMetric() {
+ return MethodSpec
+ .methodBuilder("recordEnvironmentTokenBusinessMetric")
+ .addModifiers(Modifier.PRIVATE)
+ .addTypeVariable(TypeVariableName.get("T", Identity.class))
+ .addParameter(ParameterSpec.builder(
+ ParameterizedTypeName.get(ClassName.get(SelectedAuthScheme.class),
+ TypeVariableName.get("T")),
+ "selectedAuthScheme").build())
+ .addParameter(ExecutionAttributes.class, "executionAttributes")
+ .addStatement("$T tokenFromEnv = executionAttributes.getAttribute($T.TOKEN_CONFIGURED_FROM_ENV)",
+ String.class, SdkInternalExecutionAttribute.class)
+ .beginControlFlow("if (selectedAuthScheme != null && selectedAuthScheme.authSchemeOption().schemeId().equals($T"
+ + ".SCHEME_ID) && selectedAuthScheme.identity().isDone())", BearerAuthScheme.class)
+ .beginControlFlow("if (selectedAuthScheme.identity().getNow(null) instanceof $T)", TokenIdentity.class)
+
+ .addStatement("$T configuredToken = ($T) selectedAuthScheme.identity().getNow(null)",
+ TokenIdentity.class, TokenIdentity.class)
+ .beginControlFlow("if (configuredToken.token().equals(tokenFromEnv))")
+ .addStatement("executionAttributes.getAttribute($T.BUSINESS_METRICS)"
+ + ".addMetric($T.BEARER_SERVICE_ENV_VARS.value())",
+ SdkInternalExecutionAttribute.class, BusinessMetricFeatureId.class)
+ .endControlFlow()
+ .endControlFlow()
+ .endControlFlow()
+ .build();
+
+
+ }
+
private MethodSpec generateBeforeExecution() {
MethodSpec.Builder builder = MethodSpec.methodBuilder("beforeExecution")
.addAnnotation(Override.class)
@@ -116,6 +153,11 @@ private MethodSpec generateBeforeExecution() {
.addStatement("$T selectedAuthScheme = selectAuthScheme(authOptions, executionAttributes)",
wildcardSelectedAuthScheme())
.addStatement("putSelectedAuthScheme(executionAttributes, selectedAuthScheme)");
+
+ if (intermediateModel.getCustomizationConfig().isEnableEnvironmentBearerToken()) {
+ builder.addStatement("recordEnvironmentTokenBusinessMetric(selectedAuthScheme, "
+ + "executionAttributes)");
+ }
return builder.build();
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeProviderSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeProviderSpec.java
index bc5255695ad1..b43c577e9931 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeProviderSpec.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeProviderSpec.java
@@ -21,6 +21,7 @@
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
+import java.util.List;
import java.util.function.Consumer;
import javax.lang.model.element.Modifier;
import software.amazon.awssdk.annotations.SdkPublicApi;
@@ -54,6 +55,7 @@ public TypeSpec poetSpec() {
.addMethod(resolveAuthSchemeMethod())
.addMethod(resolveAuthSchemeConsumerBuilderMethod())
.addMethod(defaultProviderMethod())
+ .addMethod(defaultPreferredProviderMethod())
.build();
}
@@ -93,6 +95,17 @@ private MethodSpec defaultProviderMethod() {
.build();
}
+ private MethodSpec defaultPreferredProviderMethod() {
+ return MethodSpec.methodBuilder("defaultProvider")
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+ .addParameter(ParameterizedTypeName.get(List.class, String.class), "authSchemePreference")
+ .returns(className())
+ .addJavadoc("Get the default auth scheme provider the preferred auth schemes in order of preference.")
+ .addStatement("return new $T(defaultProvider(), authSchemePreference)",
+ authSchemeSpecUtils.preferredAuthSchemeProviderName())
+ .build();
+ }
+
private CodeBlock interfaceJavadoc() {
CodeBlock.Builder b = CodeBlock.builder();
@@ -105,3 +118,4 @@ private CodeBlock interfaceJavadoc() {
return b.build();
}
}
+
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecUtils.java
index a02f3e8bc893..f6ea9e684b59 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecUtils.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecUtils.java
@@ -97,6 +97,15 @@ public ClassName modeledAuthSchemeProviderName() {
return ClassName.get(internalPackage(), "Modeled" + providerInterfaceName().simpleName());
}
+ public ClassName preferredAuthSchemeProviderName() {
+ return ClassName.get(internalPackage(), "Preferred" + providerInterfaceName().simpleName());
+ }
+
+ public ClassName authSchemeProviderBuilderName() {
+ return ClassName.get(basePackage(),
+ intermediateModel.getMetadata().getServiceName() + "AuthSchemeProviderBuilder");
+ }
+
public ClassName authSchemeInterceptor() {
return ClassName.get(internalPackage(), intermediateModel.getMetadata().getServiceName() + "AuthSchemeInterceptor");
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/PreferredAuthSchemeProviderSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/PreferredAuthSchemeProviderSpec.java
new file mode 100644
index 000000000000..0481d707d999
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/PreferredAuthSchemeProviderSpec.java
@@ -0,0 +1,108 @@
+/*
+ * 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.auth.scheme;
+
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterizedTypeName;
+import com.squareup.javapoet.TypeSpec;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.lang.model.element.Modifier;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+import software.amazon.awssdk.codegen.poet.ClassSpec;
+import software.amazon.awssdk.codegen.poet.PoetUtils;
+import software.amazon.awssdk.utils.CollectionUtils;
+
+public class PreferredAuthSchemeProviderSpec implements ClassSpec {
+ private final AuthSchemeSpecUtils authSchemeSpecUtils;
+
+ public PreferredAuthSchemeProviderSpec(IntermediateModel intermediateModel) {
+ this.authSchemeSpecUtils = new AuthSchemeSpecUtils(intermediateModel);
+ }
+
+ @Override
+ public ClassName className() {
+ return authSchemeSpecUtils.preferredAuthSchemeProviderName();
+ }
+
+ @Override
+ public TypeSpec poetSpec() {
+ return PoetUtils.createClassBuilder(className())
+ .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+ .addAnnotation(SdkInternalApi.class)
+ .addField(
+ authSchemeSpecUtils.providerInterfaceName(), "delegate",
+ Modifier.PRIVATE, Modifier.FINAL)
+ .addField(
+ ParameterizedTypeName.get(List.class, String.class), "authSchemePreference",
+ Modifier.PRIVATE, Modifier.FINAL)
+ .addSuperinterface(authSchemeSpecUtils.providerInterfaceName())
+ .addMethod(constructor())
+ .addMethod(resolveAuthSchemeMethod())
+ .build();
+ }
+
+ private MethodSpec constructor() {
+ return MethodSpec
+ .constructorBuilder()
+ .addModifiers(Modifier.PUBLIC)
+ .addParameter(authSchemeSpecUtils.providerInterfaceName(), "delegate")
+ .addParameter(ParameterizedTypeName.get(List.class, String.class), "authSchemePreference")
+ .addStatement("this.delegate = delegate")
+ .addStatement("this.authSchemePreference = authSchemePreference != null ? authSchemePreference "
+ + ": $T.emptyList()",
+ Collections.class)
+ .build();
+ }
+
+ private MethodSpec resolveAuthSchemeMethod() {
+ MethodSpec.Builder b = MethodSpec.methodBuilder("resolveAuthScheme")
+ .addModifiers(Modifier.PUBLIC)
+ .addAnnotation(Override.class)
+ .returns(authSchemeSpecUtils.resolverReturnType())
+ .addParameter(authSchemeSpecUtils.parametersInterfaceName(), "params");
+ b.addJavadoc("Resolve the auth schemes based on the given set of parameters.");
+ b.addStatement("$T candidateAuthSchemes = delegate.resolveAuthScheme(params)",
+ authSchemeSpecUtils.resolverReturnType());
+ b.beginControlFlow("if ($T.isNullOrEmpty(authSchemePreference))", CollectionUtils.class)
+ .addStatement("return candidateAuthSchemes")
+ .endControlFlow();
+
+ b.addStatement("$T authSchemes = new $T<>()", authSchemeSpecUtils.resolverReturnType(), ArrayList.class);
+
+ b.beginControlFlow("authSchemePreference.forEach(preferredSchemeId -> ");
+
+ b.beginControlFlow("candidateAuthSchemes.stream().filter(candidate -> ");
+ b.addStatement("String candidateSchemeName = candidate.schemeId().contains(\"#\") ? " +
+ "candidate.schemeId().split(\"#\")[1] : candidate.schemeId()");
+ b.addStatement("return candidateSchemeName.equals(preferredSchemeId)");
+ b.endControlFlow(").findFirst().ifPresent(authSchemes::add)");
+ b.endControlFlow(")");
+
+ b.beginControlFlow("candidateAuthSchemes.forEach(candidate -> ")
+ .beginControlFlow("if (!authSchemes.contains(candidate))")
+ .addStatement("authSchemes.add(candidate)")
+ .endControlFlow()
+ .endControlFlow(")");
+
+ b.addStatement("return authSchemes");
+ return b.build();
+ }
+
+}
\ No newline at end of file
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClass.java
index b57d7cb8d7aa..96d95f3650f8 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClass.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClass.java
@@ -41,8 +41,10 @@
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.auth.credentials.TokenUtils;
import software.amazon.awssdk.auth.signer.Aws4Signer;
+import software.amazon.awssdk.auth.token.credentials.StaticTokenProvider;
import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
import software.amazon.awssdk.auth.token.signer.aws.BearerTokenSigner;
+import software.amazon.awssdk.awscore.auth.AuthSchemePreferenceResolver;
import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider;
@@ -52,6 +54,7 @@
import software.amazon.awssdk.codegen.model.service.AuthType;
import software.amazon.awssdk.codegen.model.service.ClientContextParam;
import software.amazon.awssdk.codegen.poet.ClassSpec;
+import software.amazon.awssdk.codegen.poet.PoetExtension;
import software.amazon.awssdk.codegen.poet.PoetUtils;
import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeSpecUtils;
import software.amazon.awssdk.codegen.poet.auth.scheme.ModelAuthSchemeClassesKnowledgeIndex;
@@ -70,7 +73,9 @@
import software.amazon.awssdk.core.client.config.SdkClientOption;
import software.amazon.awssdk.core.endpointdiscovery.providers.DefaultEndpointDiscoveryProviderChain;
import software.amazon.awssdk.core.interceptor.ClasspathInterceptorChainFactory;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
import software.amazon.awssdk.core.retry.RetryMode;
import software.amazon.awssdk.core.signer.Signer;
import software.amazon.awssdk.http.Protocol;
@@ -101,6 +106,8 @@ public class BaseClientBuilderClass implements ClassSpec {
private final AuthSchemeSpecUtils authSchemeSpecUtils;
private final ServiceClientConfigurationUtils configurationUtils;
private final EndpointParamsKnowledgeIndex endpointParamsKnowledgeIndex;
+ private final PoetExtension poetExtensions;
+
public BaseClientBuilderClass(IntermediateModel model) {
this.model = model;
@@ -111,6 +118,7 @@ public BaseClientBuilderClass(IntermediateModel model) {
this.authSchemeSpecUtils = new AuthSchemeSpecUtils(model);
this.configurationUtils = new ServiceClientConfigurationUtils(model);
this.endpointParamsKnowledgeIndex = EndpointParamsKnowledgeIndex.of(model);
+ this.poetExtensions = new PoetExtension(model);
}
@Override
@@ -265,24 +273,24 @@ private MethodSpec serviceNameMethod() {
}
private MethodSpec mergeServiceDefaultsMethod() {
- boolean crc32FromCompressedDataEnabled = model.getCustomizationConfig().isCalculateCrc32FromCompressedData();
-
MethodSpec.Builder builder = MethodSpec.methodBuilder("mergeServiceDefaults")
.addAnnotation(Override.class)
.addModifiers(PROTECTED, FINAL)
.returns(SdkClientConfiguration.class)
- .addParameter(SdkClientConfiguration.class, "config")
- .addCode("return config.merge(c -> c");
+ .addParameter(SdkClientConfiguration.class, "config");
- builder.addCode(".option($T.ENDPOINT_PROVIDER, defaultEndpointProvider())", SdkClientOption.class);
+ boolean crc32FromCompressedDataEnabled = model.getCustomizationConfig().isCalculateCrc32FromCompressedData();
+
+ builder.beginControlFlow("return config.merge(c -> ");
+ builder.addCode("c.option($T.ENDPOINT_PROVIDER, defaultEndpointProvider())", SdkClientOption.class);
if (authSchemeSpecUtils.useSraAuth()) {
- builder.addCode(".option($T.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())", SdkClientOption.class);
- builder.addCode(".option($T.AUTH_SCHEMES, authSchemes())", SdkClientOption.class);
- } else {
- if (defaultAwsAuthSignerMethod().isPresent()) {
- builder.addCode(".option($T.SIGNER, defaultSigner())\n", SdkAdvancedClientOption.class);
+ if (!model.getCustomizationConfig().isEnableEnvironmentBearerToken()) {
+ builder.addCode(".option($T.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config))", SdkClientOption.class);
}
+ builder.addCode(".option($T.AUTH_SCHEMES, authSchemes())", SdkClientOption.class);
+ } else if (defaultAwsAuthSignerMethod().isPresent()) {
+ builder.addCode(".option($T.SIGNER, defaultSigner())\n", SdkAdvancedClientOption.class);
}
builder.addCode(".option($T.CRC32_FROM_COMPRESSED_DATA_ENABLED, $L)\n",
SdkClientOption.class, crc32FromCompressedDataEnabled);
@@ -301,11 +309,47 @@ private MethodSpec mergeServiceDefaultsMethod() {
builder.addCode(".option($T.TOKEN_SIGNER, defaultTokenSigner())", SdkAdvancedClientOption.class);
}
}
+ builder.addStatement("");
- builder.addCode(");");
+ if (model.getCustomizationConfig().isEnableEnvironmentBearerToken()) {
+ configureEnvironmentBearerToken(builder);
+ }
+ builder.endControlFlow(")");
return builder.build();
}
+ private void configureEnvironmentBearerToken(MethodSpec.Builder builder) {
+ if (!authSchemeSpecUtils.useSraAuth()) {
+ throw new IllegalStateException("The enableEnvironmentBearerToken customization requires SRA Auth.");
+ }
+ if (!AuthUtils.usesBearerAuth(model)) {
+ throw new IllegalStateException("The enableEnvironmentBearerToken customization requires the service to model and "
+ + "support smithy.api#httpBearerAuth.");
+ }
+
+ builder.addStatement("$T tokenFromEnv = new $T().getStringValue()",
+ ParameterizedTypeName.get(Optional.class, String.class),
+ poetExtensions.getEnvironmentTokenSystemSettingsClass());
+
+ builder
+ .beginControlFlow("if (tokenFromEnv.isPresent() && config.option($T.AUTH_SCHEME_PROVIDER) == null && config.option($T"
+ + ".TOKEN_IDENTITY_PROVIDER) == null)",
+ SdkClientOption.class, AwsClientOption.class)
+ .addStatement("c.option($T.AUTH_SCHEME_PROVIDER, $T.defaultProvider($T.singletonList($S)))",
+ SdkClientOption.class, authSchemeSpecUtils.providerInterfaceName(), Collections.class,
+ "httpBearerAuth")
+ .addStatement("c.option($T.TOKEN_IDENTITY_PROVIDER, $T.create(tokenFromEnv::get))",
+ AwsClientOption.class, StaticTokenProvider.class)
+ .addStatement("c.option($T.EXECUTION_ATTRIBUTES, "
+ + "$T.builder().put($T.TOKEN_CONFIGURED_FROM_ENV, tokenFromEnv.get()).build())",
+ SdkClientOption.class, ExecutionAttributes.class, SdkInternalExecutionAttribute.class)
+ .endControlFlow()
+ .beginControlFlow("else")
+ .addStatement("c.option($T.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config))", SdkClientOption.class)
+ .endControlFlow();
+
+ }
+
private Optional mergeInternalDefaultsMethod() {
String userAgent = model.getCustomizationConfig().getUserAgent();
RetryMode defaultRetryMode = model.getCustomizationConfig().getDefaultRetryMode();
@@ -442,7 +486,7 @@ private MethodSpec finalizeServiceConfigurationMethod() {
// serviceConfigBuilder; the service configuration classes (e.g. S3Configuration) return primitive booleans that
// have a default when not present.
builder.addStatement("builder.option($T.DUALSTACK_ENDPOINT_ENABLED, serviceConfigBuilder.dualstackEnabled())",
- AwsClientOption.class);
+ AwsClientOption.class);
}
if (model.getCustomizationConfig().getServiceConfig().hasFipsProperty()) {
@@ -452,14 +496,14 @@ private MethodSpec finalizeServiceConfigurationMethod() {
if (model.getEndpointOperation().isPresent()) {
builder.addStatement("builder.option($T.ENDPOINT_DISCOVERY_ENABLED, endpointDiscoveryEnabled)\n",
- SdkClientOption.class);
+ SdkClientOption.class);
}
if (StringUtils.isNotBlank(model.getCustomizationConfig().getCustomRetryStrategy())) {
builder.addStatement("builder.option($1T.RETRY_STRATEGY, $2T.resolveRetryStrategy(config))",
- SdkClientOption.class,
- PoetUtils.classNameFromFqcn(model.getCustomizationConfig().getCustomRetryStrategy()));
+ SdkClientOption.class,
+ PoetUtils.classNameFromFqcn(model.getCustomizationConfig().getCustomRetryStrategy()));
}
if (StringUtils.isNotBlank(model.getCustomizationConfig().getCustomRetryPolicy())) {
@@ -485,7 +529,7 @@ private MethodSpec finalizeServiceConfigurationMethod() {
if (endpointParamsKnowledgeIndex.hasAccountIdEndpointModeBuiltIn()) {
builder.addStatement("builder.option($T.$L, resolveAccountIdEndpointMode(config))",
- AwsClientOption.class, model.getNamingStrategy().getEnumValueName("accountIdEndpointMode"));
+ AwsClientOption.class, model.getNamingStrategy().getEnumValueName("accountIdEndpointMode"));
}
String serviceNameForEnvVar = model.getNamingStrategy().getServiceNameForEnvironmentVariables();
@@ -829,7 +873,19 @@ private MethodSpec sigv4aSigningRegionSetMethod() {
private MethodSpec defaultAuthSchemeProviderMethod() {
return MethodSpec.methodBuilder("defaultAuthSchemeProvider")
.addModifiers(PRIVATE)
+ .addParameter(SdkClientConfiguration.class, "config")
.returns(authSchemeSpecUtils.providerInterfaceName())
+ .addCode("$T authSchemePreferenceProvider = "
+ + "$T.builder()",
+ AuthSchemePreferenceResolver.class, AuthSchemePreferenceResolver.class)
+ .addCode(".profileFile(config.option($T.PROFILE_FILE_SUPPLIER))", SdkClientOption.class)
+ .addCode(".profileName(config.option($T.PROFILE_NAME))", SdkClientOption.class)
+ .addStatement(".build()")
+ .addStatement("List preferences = authSchemePreferenceProvider.resolveAuthSchemePreference()")
+ .beginControlFlow("if(!preferences.isEmpty())")
+ .addStatement("return $T.defaultProvider(preferences)",
+ authSchemeSpecUtils.providerInterfaceName())
+ .endControlFlow()
.addStatement("return $T.defaultProvider()", authSchemeSpecUtils.providerInterfaceName())
.build();
}
@@ -965,10 +1021,10 @@ private MethodSpec internalPluginsMethod() {
List internalPlugins = model.getCustomizationConfig().getInternalPlugins();
if (internalPlugins.isEmpty()) {
return builder.addStatement("return $T.emptyList()", Collections.class)
- .build();
+ .build();
}
- builder.addStatement("$T internalPlugins = new $T<>()", parameterizedTypeName, ArrayList.class);
+ builder.addStatement("$T internalPlugins = new $T<>()", parameterizedTypeName, ArrayList.class);
for (String internalPlugin : internalPlugins) {
String arguments = internalPluginNewArguments(internalPlugin);
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java
index aaa729662c17..9829133551c3 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java
@@ -26,6 +26,7 @@
import static software.amazon.awssdk.codegen.internal.Constant.EVENT_PUBLISHER_PARAM_NAME;
import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.addS3ArnableFieldCode;
import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.applySignerOverrideMethod;
+import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.transformServiceId;
import static software.amazon.awssdk.codegen.poet.client.SyncClientClass.addRequestModifierCode;
import static software.amazon.awssdk.codegen.poet.client.SyncClientClass.getProtocolSpecs;
@@ -229,7 +230,14 @@ 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, $S + \"#\" + $T.VERSION)"
+ + ".build()",
+ SdkClientOption.class,
+ SdkClientOption.class,
+ transformServiceId(model.getMetadata().getServiceId()),
+ ClassName.get(model.getMetadata().getFullClientInternalPackageName(),
+ "ServiceVersionInfo"));
+
FieldSpec protocolFactoryField = protocolSpec.protocolFactory(model);
if (model.getMetadata().isJsonProtocol()) {
builder.addStatement("this.$N = init($T.builder()).build()", protocolFactoryField.name,
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/ClientClassUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/ClientClassUtils.java
index 87e8339e54a5..c058c1d7b654 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/ClientClassUtils.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/ClientClassUtils.java
@@ -280,4 +280,9 @@ public static MethodSpec updateRetryStrategyClientConfigurationMethod() {
builder.addStatement("configuration.option($T.CONFIGURED_RETRY_CONFIGURATOR, null)", SdkClientOption.class);
return builder.build();
}
+
+ // According to User Agent 2.0 spec, replace spaces with underscores
+ static String transformServiceId(String serviceId) {
+ return serviceId.replace(" ", "_");
+ }
}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/EnvironmentTokenSystemSettingsClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/EnvironmentTokenSystemSettingsClass.java
new file mode 100644
index 000000000000..3ca3fb56ab41
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/EnvironmentTokenSystemSettingsClass.java
@@ -0,0 +1,76 @@
+/*
+ * 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 com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeSpec;
+import javax.lang.model.element.Modifier;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+import software.amazon.awssdk.codegen.naming.NamingStrategy;
+import software.amazon.awssdk.codegen.poet.ClassSpec;
+import software.amazon.awssdk.codegen.poet.PoetExtension;
+import software.amazon.awssdk.codegen.poet.PoetUtils;
+import software.amazon.awssdk.utils.SystemSetting;
+
+public class EnvironmentTokenSystemSettingsClass implements ClassSpec {
+ protected final IntermediateModel model;
+ protected final PoetExtension poetExtensions;
+
+ public EnvironmentTokenSystemSettingsClass(IntermediateModel model) {
+ this.model = model;
+ this.poetExtensions = new PoetExtension(model);
+ }
+
+ @Override
+ public TypeSpec poetSpec() {
+ NamingStrategy namingStrategy = model.getNamingStrategy();
+
+ String systemPropertyName = "aws.bearerToken" + namingStrategy.getSigningNameForSystemProperties();
+ String envName = "AWS_BEARER_TOKEN_" + namingStrategy.getSigningNameForEnvironmentVariables();
+
+ return TypeSpec.classBuilder(className())
+ .addModifiers(Modifier.PUBLIC)
+ .addAnnotation(PoetUtils.generatedAnnotation())
+ .addAnnotation(SdkInternalApi.class)
+ .addSuperinterface(SystemSetting.class)
+ .addMethod(MethodSpec.methodBuilder("property")
+ .addAnnotation(Override.class)
+ .addModifiers(Modifier.PUBLIC)
+ .returns(String.class)
+ .addStatement("return $S", systemPropertyName)
+ .build())
+ .addMethod(MethodSpec.methodBuilder("environmentVariable")
+ .addAnnotation(Override.class)
+ .addModifiers(Modifier.PUBLIC)
+ .returns(String.class)
+ .addStatement("return $S", envName)
+ .build())
+ .addMethod(MethodSpec.methodBuilder("defaultValue")
+ .addAnnotation(Override.class)
+ .addModifiers(Modifier.PUBLIC)
+ .returns(String.class)
+ .addStatement("return null")
+ .build())
+ .build();
+ }
+
+ @Override
+ public ClassName className() {
+ return poetExtensions.getEnvironmentTokenSystemSettingsClass();
+ }
+}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java
index 2695e43f8746..780d15a8298b 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java
@@ -23,6 +23,7 @@
import static software.amazon.awssdk.codegen.poet.PoetUtils.classNameFromFqcn;
import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.addS3ArnableFieldCode;
import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.applySignerOverrideMethod;
+import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.transformServiceId;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
@@ -201,7 +202,13 @@ 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, $S + \"#\" + $T.VERSION)"
+ + ".build()",
+ SdkClientOption.class,
+ SdkClientOption.class,
+ transformServiceId(model.getMetadata().getServiceId()),
+ ClassName.get(model.getMetadata().getFullClientInternalPackageName(),
+ "ServiceVersionInfo"));
FieldSpec protocolFactoryField = protocolSpec.protocolFactory(model);
if (model.getMetadata().isJsonProtocol()) {
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java
index 9fa214efb8fe..8e1afb25e8e0 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java
@@ -39,6 +39,7 @@
import software.amazon.awssdk.codegen.model.intermediate.OperationModel;
import software.amazon.awssdk.codegen.model.intermediate.Protocol;
import software.amazon.awssdk.codegen.model.intermediate.ShapeModel;
+import software.amazon.awssdk.codegen.model.intermediate.ShapeType;
import software.amazon.awssdk.codegen.poet.PoetExtension;
import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeSpecUtils;
import software.amazon.awssdk.codegen.poet.client.traits.HttpChecksumRequiredTrait;
@@ -116,7 +117,6 @@ public MethodSpec initProtocolFactory(IntermediateModel model) {
methodSpec.addCode("$L", hasAwsQueryCompatible());
}
- registerModeledExceptions(model, poetExtensions).forEach(methodSpec::addCode);
methodSpec.addCode(";");
return methodSpec.build();
@@ -170,11 +170,40 @@ public CodeBlock responseHandler(IntermediateModel model, OperationModel opModel
public Optional errorResponseHandler(OperationModel opModel) {
String protocolFactory = protocolFactoryLiteral(model, opModel);
- return Optional.of(
- CodeBlock.builder()
- .add("\n\n$T<$T> errorResponseHandler = createErrorResponseHandler($L, operationMetadata);",
- HttpResponseHandler.class, AwsServiceException.class, protocolFactory)
- .build());
+ CodeBlock.Builder builder = CodeBlock.builder();
+ ParameterizedTypeName metadataMapperType = ParameterizedTypeName.get(
+ ClassName.get(Function.class),
+ ClassName.get(String.class),
+ ParameterizedTypeName.get(Optional.class, ExceptionMetadata.class));
+
+ builder.add("\n$T exceptionMetadataMapper = errorCode -> {\n", metadataMapperType);
+ builder.add("if (errorCode == null) {\n");
+ builder.add("return $T.empty();\n", Optional.class);
+ builder.add("}\n");
+ builder.add("switch (errorCode) {\n");
+ model.getShapes().values().stream()
+ .filter(shape -> shape.getShapeType() == ShapeType.Exception)
+ .forEach(exceptionShape -> {
+ String exceptionName = exceptionShape.getShapeName();
+ String errorCode = exceptionShape.getErrorCode();
+
+ builder.add("case $S:\n", errorCode);
+ builder.add("return $T.of($T.builder()\n", Optional.class, ExceptionMetadata.class)
+ .add(".errorCode($S)\n", errorCode);
+ builder.add(populateHttpStatusCode(exceptionShape, model));
+ builder.add(".exceptionBuilderSupplier($T::builder)\n",
+ poetExtensions.getModelClassFromShape(exceptionShape))
+ .add(".build());\n");
+ });
+
+ builder.add("default: return $T.empty();\n", Optional.class);
+ builder.add("}\n");
+ builder.add("};\n");
+
+ builder.add("$T<$T> errorResponseHandler = createErrorResponseHandler($L, operationMetadata, exceptionMetadataMapper);",
+ HttpResponseHandler.class, AwsServiceException.class, protocolFactory);
+
+ return Optional.of(builder.build());
}
@Override
@@ -206,6 +235,10 @@ public CodeBlock executionHandler(OperationModel opModel) {
codeBlock.add(RequestCompressionTrait.create(opModel, model));
+ if (opModel.hasStreamingOutput()) {
+ codeBlock.add(".withResponseTransformer(responseTransformer)");
+ }
+
if (opModel.hasStreamingInput()) {
codeBlock.add(".withRequestBody(requestBody)")
.add(".withMarshaller($L)", syncStreamingMarshaller(model, opModel, marshaller));
@@ -281,6 +314,10 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper
builder.add(NoneAuthTypeRequestTrait.create(opModel));
}
+ if (opModel.hasStreamingOutput()) {
+ builder.add(".withAsyncResponseTransformer(asyncResponseTransformer)");
+ }
+
builder.add(RequestCompressionTrait.create(opModel, model))
.add(".withInput($L)$L)",
opModel.getInput().getVariableName(), asyncResponseTransformerVariable(isStreaming, isRestJson, opModel))
@@ -411,21 +448,6 @@ public Optional createErrorResponseHandler() {
ClassName httpResponseHandler = ClassName.get(HttpResponseHandler.class);
ClassName sdkBaseException = ClassName.get(AwsServiceException.class);
TypeName responseHandlerOfException = ParameterizedTypeName.get(httpResponseHandler, sdkBaseException);
-
- return Optional.of(MethodSpec.methodBuilder("createErrorResponseHandler")
- .addParameter(BaseAwsJsonProtocolFactory.class, "protocolFactory")
- .addParameter(JsonOperationMetadata.class, "operationMetadata")
- .returns(responseHandlerOfException)
- .addModifiers(Modifier.PRIVATE)
- .addStatement("return protocolFactory.createErrorResponseHandler(operationMetadata)")
- .build());
- }
-
- @Override
- public Optional createEventstreamErrorResponseHandler() {
- ClassName httpResponseHandler = ClassName.get(HttpResponseHandler.class);
- ClassName sdkBaseException = ClassName.get(AwsServiceException.class);
- TypeName responseHandlerOfException = ParameterizedTypeName.get(httpResponseHandler, sdkBaseException);
ParameterizedTypeName mapperType = ParameterizedTypeName.get(ClassName.get(Function.class),
ClassName.get(String.class), ParameterizedTypeName.get(Optional.class, ExceptionMetadata.class));
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java
index b6cca23e38cf..4bf7d45d5f9c 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java
@@ -128,7 +128,9 @@ public CodeBlock executionHandler(OperationModel opModel) {
}
codeBlock.add(RequestCompressionTrait.create(opModel, intermediateModel));
-
+ if (opModel.hasStreamingOutput()) {
+ codeBlock.add(".withResponseTransformer(responseTransformer)");
+ }
if (opModel.hasStreamingInput()) {
return codeBlock.add(".withRequestBody(requestBody)")
.add(".withMarshaller($L));", syncStreamingMarshaller(intermediateModel, opModel, marshaller))
@@ -170,6 +172,10 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper
builder.add(RequestCompressionTrait.create(opModel, intermediateModel));
+ if (opModel.hasStreamingOutput()) {
+ builder.add(".withAsyncResponseTransformer(asyncResponseTransformer)");
+ }
+
builder.add(hostPrefixExpression(opModel) + asyncRequestBody + ".withInput($L)$L);",
opModel.getInput().getVariableName(),
opModel.hasStreamingOutput() ? ", asyncResponseTransformer" : "");
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ServiceVersionInfoSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ServiceVersionInfoSpec.java
new file mode 100644
index 000000000000..145e482ad899
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ServiceVersionInfoSpec.java
@@ -0,0 +1,65 @@
+/*
+ * 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.annotations.SdkInternalApi;
+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 ServiceVersionInfoSpec implements ClassSpec {
+ private final PoetExtension poetExtension;
+
+ public ServiceVersionInfoSpec(IntermediateModel model) {
+ this.poetExtension = new PoetExtension(model);
+ }
+
+ @Override
+ public TypeSpec poetSpec() {
+ TypeSpec.Builder builder = TypeSpec.classBuilder("ServiceVersionInfo")
+ .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+ .addAnnotation(PoetUtils.generatedAnnotation())
+ .addAnnotation(SdkInternalApi.class)
+ .addField(FieldSpec.builder(
+ String.class, "VERSION", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
+ .initializer("$S", SDK_VERSION)
+ .addJavadoc("Returns the current version for the AWS SDK in which"
+ + " this class is running.")
+ .build())
+ .addMethod(privateConstructor());
+
+ return builder.build();
+ }
+
+ protected MethodSpec privateConstructor() {
+ return MethodSpec.constructorBuilder()
+ .addModifiers(Modifier.PRIVATE)
+ .build();
+ }
+
+ @Override
+ public ClassName className() {
+ return poetExtension.getServiceVersionInfoClass();
+ }
+}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ModelBuilderSpecs.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ModelBuilderSpecs.java
index aa61dea0a16a..2573d2c0680d 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ModelBuilderSpecs.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ModelBuilderSpecs.java
@@ -35,6 +35,8 @@
import java.util.Set;
import java.util.function.Consumer;
import javax.lang.model.element.Modifier;
+import software.amazon.awssdk.annotations.Mutable;
+import software.amazon.awssdk.annotations.NotThreadSafe;
import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration;
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.model.intermediate.MemberModel;
@@ -83,6 +85,8 @@ public ClassName builderImplName() {
public TypeSpec builderInterface() {
TypeSpec.Builder builder = TypeSpec.interfaceBuilder(builderInterfaceName())
.addSuperinterfaces(builderSuperInterfaces())
+ .addAnnotation(Mutable.class)
+ .addAnnotation(NotThreadSafe.class)
.addModifiers(PUBLIC);
shapeModel.getNonStreamingMembers()
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationUtils.java
index 22f06d253b56..320506822765 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationUtils.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/ServiceClientConfigurationUtils.java
@@ -36,6 +36,7 @@
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeSpecUtils;
import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils;
+import software.amazon.awssdk.codegen.utils.AuthUtils;
import software.amazon.awssdk.core.ClientEndpointProvider;
import software.amazon.awssdk.core.checksums.RequestChecksumCalculation;
import software.amazon.awssdk.core.checksums.ResponseChecksumValidation;
@@ -48,6 +49,7 @@
import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider;
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
import software.amazon.awssdk.identity.spi.IdentityProvider;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.utils.AttributeMap;
import software.amazon.awssdk.utils.Validate;
@@ -105,10 +107,34 @@ private List fields(IntermediateModel model) {
authSchemeProviderField()
));
fields.addAll(addCustomClientParams(model));
+ fields.addAll(addModeledIdentityProviders(model));
fields.addAll(addCustomClientConfigParams(model));
return fields;
}
+ private List addModeledIdentityProviders(IntermediateModel model) {
+ List identityProviderFields = new ArrayList<>();
+ if (AuthUtils.usesBearerAuth(model)) {
+ identityProviderFields.add(tokenIdentityProviderField());
+ }
+ return identityProviderFields;
+ }
+
+ private Field tokenIdentityProviderField() {
+ TypeName tokenIdentityProviderType =
+ ParameterizedTypeName.get(ClassName.get(IdentityProvider.class),
+ WildcardTypeName.subtypeOf(TokenIdentity.class));
+
+ return fieldBuilder("tokenProvider", tokenIdentityProviderType)
+ .doc("token provider")
+ .isInherited(false)
+ .localSetter(basicLocalSetterCode("tokenProvider"))
+ .localGetter(basicLocalGetterCode("tokenProvider"))
+ .configSetter(basicConfigSetterCode(AwsClientOption.TOKEN_IDENTITY_PROVIDER, "tokenProvider"))
+ .configGetter(basicConfigGetterCode(AwsClientOption.TOKEN_IDENTITY_PROVIDER))
+ .build();
+ }
+
private List addCustomClientParams(IntermediateModel model) {
List customClientParamFields = new ArrayList<>();
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesClientTestSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesClientTestSpec.java
index ce7adb6066ee..d077473f532a 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesClientTestSpec.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesClientTestSpec.java
@@ -61,6 +61,10 @@
import software.amazon.awssdk.codegen.poet.PoetExtension;
import software.amazon.awssdk.codegen.poet.PoetUtils;
import software.amazon.awssdk.codegen.utils.AuthUtils;
+import software.amazon.awssdk.codegen.validation.ModelInvalidException;
+import software.amazon.awssdk.codegen.validation.ValidationEntry;
+import software.amazon.awssdk.codegen.validation.ValidationErrorId;
+import software.amazon.awssdk.codegen.validation.ValidationErrorSeverity;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.core.rules.testing.AsyncTestCase;
@@ -445,6 +449,20 @@ private CodeBlock requestCreation(OperationModel opModel, Map
if (opParams != null) {
opParams.forEach((n, v) -> {
MemberModel memberModel = opModel.getInputShape().getMemberByC2jName(n);
+
+ if (memberModel == null) {
+ String detailMsg = String.format("Endpoint test definition references member '%s' on the input shape '%s' "
+ + "but no such member is defined.", n, opModel.getInputShape().getC2jName());
+ ValidationEntry entry =
+ new ValidationEntry()
+ .withSeverity(ValidationErrorSeverity.DANGER)
+ .withErrorId(ValidationErrorId.UNKNOWN_SHAPE_MEMBER)
+ .withDetailMessage(detailMsg);
+
+ throw ModelInvalidException.builder()
+ .validationEntries(Collections.singletonList(entry))
+ .build();
+ }
CodeBlock memberValue = createMemberValue(memberModel, v);
b.add(".$N($L)", memberModel.getFluentSetterMethodName(), memberValue);
});
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java
index bad36fe6594f..dfcf68b056fd 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java
@@ -29,7 +29,12 @@
import com.squareup.javapoet.TypeName;
import java.io.IOException;
import java.io.UncheckedIOException;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
@@ -52,6 +57,7 @@
import software.amazon.awssdk.utils.internal.CodegenNamingUtils;
public class EndpointRulesSpecUtils {
+ private static final String RULES_ENGINE_RESOURCE_FILES_PREFIX = "software/amazon/awssdk/codegen/rules/";
private final IntermediateModel intermediateModel;
public EndpointRulesSpecUtils(IntermediateModel intermediateModel) {
@@ -213,16 +219,45 @@ public TypeName resolverReturnType() {
public List rulesEngineResourceFiles() {
URL currentJarUrl = EndpointRulesSpecUtils.class.getProtectionDomain().getCodeSource().getLocation();
+
+ // This would happen if the classes aren't loaded from a JAR, e.g. when unit testing
+ if (!currentJarUrl.toString().endsWith(".jar")) {
+ return rulesEngineFilesFromDirectory(currentJarUrl);
+ }
+
try (JarFile jarFile = new JarFile(currentJarUrl.getFile())) {
return jarFile.stream()
.map(ZipEntry::getName)
- .filter(e -> e.startsWith("software/amazon/awssdk/codegen/rules/"))
+ .filter(e -> e.startsWith(RULES_ENGINE_RESOURCE_FILES_PREFIX))
.collect(Collectors.toList());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
+ public List rulesEngineFilesFromDirectory(URL location) {
+ URI locationUri;
+ try {
+ locationUri = location.toURI();
+ if (!"file".equals(locationUri.getScheme())) {
+ throw new RuntimeException("Expected location to be a directory");
+ }
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+
+ try {
+ Path directory = Paths.get(locationUri);
+ return Files.walk(directory)
+ // Remove the root directory if the classes, paths are expected to be relative to this directory
+ .map(f -> directory.relativize(f).toString())
+ .filter(f -> f.startsWith(RULES_ENGINE_RESOURCE_FILES_PREFIX))
+ .collect(Collectors.toList());
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
public List rulesEngineResourceFiles2() {
URL currentJarUrl = EndpointRulesSpecUtils.class.getProtectionDomain().getCodeSource().getLocation();
try (JarFile jarFile = new JarFile(currentJarUrl.getFile())) {
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..72f8b28a1fa2 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,26 +21,38 @@
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute;
import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme;
import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme;
import software.amazon.awssdk.codegen.model.config.customization.KeyTypePair;
import software.amazon.awssdk.endpoints.Endpoint;
+import software.amazon.awssdk.utils.uri.SdkUri;
public class CodeGeneratorVisitor extends WalkRuleExpressionVisitor {
+ private static final Logger log = LoggerFactory.getLogger(CodeGeneratorVisitor.class);
+
private final CodeBlock.Builder builder;
private final RuleRuntimeTypeMirror typeMirror;
private final SymbolTable symbolTable;
private final Map knownEndpointAttributes;
+ private final Map ruleIdToScope;
+ private final boolean endpointCaching;
public CodeGeneratorVisitor(RuleRuntimeTypeMirror typeMirror,
SymbolTable symbolTable,
Map knownEndpointAttributes,
+ Map ruleIdToScope,
+ boolean endpointCaching,
CodeBlock.Builder builder) {
this.builder = builder;
this.symbolTable = symbolTable;
this.knownEndpointAttributes = knownEndpointAttributes;
+ this.ruleIdToScope = ruleIdToScope;
this.typeMirror = typeMirror;
+ this.endpointCaching = endpointCaching;
}
@Override
@@ -196,28 +208,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,46 +233,111 @@ 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
public Void visitEndpointExpression(EndpointExpression e) {
builder.add("return $T.endpoint(", typeMirror.rulesResult().type());
- builder.add("$T.builder().url($T.create(", Endpoint.class, URI.class);
+ if (endpointCaching) {
+ builder.add("$T.builder().url($T.getInstance().create(", Endpoint.class, SdkUri.class);
+ } else {
+ builder.add("$T.builder().url($T.create(", Endpoint.class, URI.class);
+ }
e.url().accept(this);
builder.add("))");
e.headers().accept(this);
@@ -293,7 +356,7 @@ public Void visitPropertiesExpression(PropertiesExpression e) {
} else if (knownEndpointAttributes.containsKey(k)) {
addAttributeBlock(k, v);
} else {
- throw new RuntimeException("unknown endpoint property: " + k);
+ log.warn("Ignoring unknown endpoint property: {}", k);
}
});
return null;
@@ -381,7 +444,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..55dbf5358842 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,28 @@ 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) {
+ boolean useEndpointCaching = intermediateModel.getCustomizationConfig().getEnableEndpointProviderUriCaching();
CodeGeneratorVisitor visitor = new CodeGeneratorVisitor(typeMirror,
utils.symbolTable(),
knownEndpointAttributes,
+ utils.scopesByName(),
+ useEndpointCaching,
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/main/java/software/amazon/awssdk/codegen/utils/AuthUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/utils/AuthUtils.java
index f870ceea284d..004d64fac245 100644
--- a/codegen/src/main/java/software/amazon/awssdk/codegen/utils/AuthUtils.java
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/utils/AuthUtils.java
@@ -68,7 +68,8 @@ public static boolean isOpBearerAuth(IntermediateModel model, OperationModel opM
}
private static boolean isServiceBearerAuth(IntermediateModel model) {
- return model.getMetadata().getAuthType() == AuthType.BEARER;
+ return model.getMetadata().getAuthType() == AuthType.BEARER ||
+ (model.getMetadata().getAuth() != null && model.getMetadata().getAuth().contains(AuthType.BEARER));
}
private static boolean isServiceSigv4a(IntermediateModel model) {
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/utils/ProtocolUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/utils/ProtocolUtils.java
new file mode 100644
index 000000000000..0c3dfbccf2e8
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/utils/ProtocolUtils.java
@@ -0,0 +1,63 @@
+/*
+ * 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 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 protocols = serviceMetadata.getProtocols();
+ String protocol = serviceMetadata.getProtocol();
+
+ if (protocols == null || protocols.isEmpty()) {
+ return protocol;
+ }
+
+ // Kinesis uses customization.config customServiceMetadata to set cbor
+ if ("cbor".equals(protocols.get(0))) {
+ return "cbor";
+ }
+
+ for (String supportedProtocol : SUPPORTED_PROTOCOLS) {
+ if (protocols.contains(supportedProtocol)) {
+ return supportedProtocol;
+ }
+ }
+
+ throw new IllegalArgumentException("The SDK does not support any of provided protocols: " + protocols);
+ }
+}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ModelInvalidException.java b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ModelInvalidException.java
new file mode 100644
index 000000000000..28f482328253
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ModelInvalidException.java
@@ -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.validation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Exception thrown during code generation to signal that the model is invalid.
+ */
+public class ModelInvalidException extends RuntimeException {
+ private final List validationEntries;
+
+ private ModelInvalidException(Builder b) {
+ super("Validation failed with the following errors: " + b.validationEntries);
+ this.validationEntries = Collections.unmodifiableList(new ArrayList<>(b.validationEntries));
+ }
+
+ public List validationEntries() {
+ return validationEntries;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private List validationEntries;
+
+ public Builder validationEntries(List validationEntries) {
+ if (validationEntries == null) {
+ this.validationEntries = Collections.emptyList();
+ } else {
+ this.validationEntries = validationEntries;
+ }
+
+ return this;
+ }
+
+ public ModelInvalidException build() {
+ return new ModelInvalidException(this);
+ }
+ }
+}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ModelValidationContext.java b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ModelValidationContext.java
new file mode 100644
index 000000000000..55c2bedcba19
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ModelValidationContext.java
@@ -0,0 +1,79 @@
+/*
+ * 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.validation;
+
+import java.util.Optional;
+import software.amazon.awssdk.codegen.model.config.customization.ShareModelConfig;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+
+/**
+ * Context object for {@link ModelValidator}s. This object contains all the information available to the validations in order
+ * for them to perform their tasks.
+ */
+public final class ModelValidationContext {
+ private final IntermediateModel intermediateModel;
+ private final IntermediateModel shareModelsTarget;
+
+ private ModelValidationContext(Builder builder) {
+ this.intermediateModel = builder.intermediateModel;
+ this.shareModelsTarget = builder.shareModelsTarget;
+ }
+
+ /**
+ * The service model for which code is being generated.
+ */
+ public IntermediateModel intermediateModel() {
+ return intermediateModel;
+ }
+
+ /**
+ * The model of the service that the currently generating service shares models with. In other words, this is the service
+ * model for the service defined in {@link ShareModelConfig#getShareModelWith()}.
+ */
+ public Optional shareModelsTarget() {
+ return Optional.ofNullable(shareModelsTarget);
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private IntermediateModel intermediateModel;
+ private IntermediateModel shareModelsTarget;
+
+ /**
+ * The service model for which code is being generated.
+ */
+ public Builder intermediateModel(IntermediateModel intermediateModel) {
+ this.intermediateModel = intermediateModel;
+ return this;
+ }
+
+ /**
+ * The model of the service that the currently generating service shares models with. In other words, this is the service
+ * model for the service defined in {@link ShareModelConfig#getShareModelWith()}.
+ */
+ public Builder shareModelsTarget(IntermediateModel shareModelsTarget) {
+ this.shareModelsTarget = shareModelsTarget;
+ return this;
+ }
+
+ public ModelValidationContext build() {
+ return new ModelValidationContext(this);
+ }
+ }
+}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ModelValidationReport.java b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ModelValidationReport.java
new file mode 100644
index 000000000000..1112dc2190d5
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ModelValidationReport.java
@@ -0,0 +1,40 @@
+/*
+ * 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.validation;
+
+import java.util.Collections;
+import java.util.List;
+
+public class ModelValidationReport {
+ private List validationEntries = Collections.emptyList();
+
+ public List getValidationEntries() {
+ return validationEntries;
+ }
+
+ public void setValidationEntries(List validationEntries) {
+ if (validationEntries != null) {
+ this.validationEntries = validationEntries;
+ } else {
+ this.validationEntries = Collections.emptyList();
+ }
+ }
+
+ public ModelValidationReport withValidationEntries(List validationEntries) {
+ setValidationEntries(validationEntries);
+ return this;
+ }
+}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ModelValidator.java b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ModelValidator.java
new file mode 100644
index 000000000000..b544a030eaf5
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ModelValidator.java
@@ -0,0 +1,22 @@
+/*
+ * 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.validation;
+
+import java.util.List;
+
+public interface ModelValidator {
+ List validateModels(ModelValidationContext context);
+}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/validation/SharedModelsValidator.java b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/SharedModelsValidator.java
new file mode 100644
index 000000000000..6b7f8471da7c
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/SharedModelsValidator.java
@@ -0,0 +1,210 @@
+/*
+ * 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.validation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+import software.amazon.awssdk.codegen.model.intermediate.ListModel;
+import software.amazon.awssdk.codegen.model.intermediate.MapModel;
+import software.amazon.awssdk.codegen.model.intermediate.MemberModel;
+import software.amazon.awssdk.codegen.model.intermediate.ShapeModel;
+import software.amazon.awssdk.utils.Logger;
+
+/**
+ * Validator that ensures any shapes shared between two services are completely identical. This validator returns a validation
+ * entry for each shape that is present in both service models but has differing definitions in each model.
+ */
+public final class SharedModelsValidator implements ModelValidator {
+ private static final Logger LOG = Logger.loggerFor(SharedModelsValidator.class);
+
+ @Override
+ public List validateModels(ModelValidationContext context) {
+ if (!context.shareModelsTarget().isPresent()) {
+ return Collections.emptyList();
+ }
+
+ return validateSharedShapes(context.intermediateModel(), context.shareModelsTarget().get());
+ }
+
+ private List validateSharedShapes(IntermediateModel m1, IntermediateModel m2) {
+ List errors = new ArrayList<>();
+
+ Map m1Shapes = m1.getShapes();
+ Map m2Shapes = m2.getShapes();
+
+ m1Shapes.forEach((name, m1Shape) -> {
+ if (!m2Shapes.containsKey(name)) {
+ return;
+ }
+
+ ShapeModel m2Shape = m2Shapes.get(name);
+
+ if (!shapesAreIdentical(m1Shape, m2Shape)) {
+ String detailMsg = String.format("Services '%s' and '%s' have differing definitions of the shared model '%s'",
+ m1.getMetadata().getServiceName(),
+ m2.getMetadata().getServiceName(),
+ name);
+ LOG.warn(() -> detailMsg);
+
+ errors.add(new ValidationEntry().withErrorId(ValidationErrorId.SHARED_MODELS_DIFFER)
+ .withSeverity(ValidationErrorSeverity.DANGER)
+ .withDetailMessage(detailMsg));
+ }
+ });
+
+ return errors;
+ }
+
+ private boolean shapesAreIdentical(ShapeModel m1, ShapeModel m2) {
+ // Note: We can't simply do m1.equals(m2) because shared models can still differ slightly in the
+ // marshalling/unmarshalling info such as the exact request operation name on the wire.
+ // In particular, we leave out comparing the `unmarshaller` and `marshaller` members of ShapeModel.
+ // Additionally, the List are not compared with equals() because we handle MemberModel equality specially
+ // as well.
+ return m1.isDeprecated() == m2.isDeprecated()
+ && m1.isHasPayloadMember() == m2.isHasPayloadMember()
+ && m1.isHasHeaderMember() == m2.isHasHeaderMember()
+ && m1.isHasStatusCodeMember() == m2.isHasStatusCodeMember()
+ && m1.isHasStreamingMember() == m2.isHasStreamingMember()
+ && m1.isHasRequiresLengthMember() == m2.isHasRequiresLengthMember()
+ && m1.isWrapper() == m2.isWrapper()
+ && m1.isSimpleMethod() == m2.isSimpleMethod()
+ && m1.isFault() == m2.isFault()
+ && m1.isEventStream() == m2.isEventStream()
+ && m1.isEvent() == m2.isEvent()
+ && m1.isDocument() == m2.isDocument()
+ && m1.isUnion() == m2.isUnion()
+ && m1.isRetryable() == m2.isRetryable()
+ && m1.isThrottling() == m2.isThrottling()
+ && Objects.equals(m1.getC2jName(), m2.getC2jName())
+ && Objects.equals(m1.getShapeName(), m2.getShapeName())
+ && Objects.equals(m1.getDeprecatedMessage(), m2.getDeprecatedMessage())
+ && Objects.equals(m1.getType(), m2.getType())
+ && Objects.equals(m1.getRequired(), m2.getRequired())
+ && Objects.equals(m1.getRequestSignerClassFqcn(), m2.getRequestSignerClassFqcn())
+ && Objects.equals(m1.getEndpointDiscovery(), m2.getEndpointDiscovery())
+ && memberListsAreIdentical(m1.getMembers(), m2.getMembers())
+ && Objects.equals(m1.getEnums(), m2.getEnums())
+ && Objects.equals(m1.getVariable(), m2.getVariable())
+ && Objects.equals(m1.getErrorCode(), m2.getErrorCode())
+ && Objects.equals(m1.getHttpStatusCode(), m2.getHttpStatusCode())
+ && Objects.equals(m1.getCustomization(), m2.getCustomization())
+ && Objects.equals(m1.getXmlNamespace(), m2.getXmlNamespace())
+ ;
+ }
+
+ private boolean memberListsAreIdentical(List memberList1, List memberList2) {
+ if (memberList1.size() != memberList2.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < memberList1.size(); i++) {
+ MemberModel m1 = memberList1.get(i);
+ MemberModel m2 = memberList2.get(i);
+ if (!memberModelsAreIdentical(m1, m2)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean memberModelsAreIdentical(MemberModel m1, MemberModel m2) {
+ // Similar to ShapeModel, can't call equals() directly. It has a ShapeModel property that is ignored, and ListModel and
+ // MapModel are treated similarly
+ return m1.isDeprecated() == m2.isDeprecated()
+ && m1.isRequired() == m2.isRequired()
+ && m1.isSynthetic() == m2.isSynthetic()
+ && m1.isIdempotencyToken() == m2.isIdempotencyToken()
+ && m1.isJsonValue() == m2.isJsonValue()
+ && m1.isEventPayload() == m2.isEventPayload()
+ && m1.isEventHeader() == m2.isEventHeader()
+ && m1.isEndpointDiscoveryId() == m2.isEndpointDiscoveryId()
+ && m1.isSensitive() == m2.isSensitive()
+ && m1.isXmlAttribute() == m2.isXmlAttribute()
+ && m1.ignoreDataTypeConversionFailures() == m2.ignoreDataTypeConversionFailures()
+ && Objects.equals(m1.getName(), m2.getName())
+ && Objects.equals(m1.getC2jName(), m2.getC2jName())
+ && Objects.equals(m1.getC2jShape(), m2.getC2jShape())
+ && Objects.equals(m1.getVariable(), m2.getVariable())
+ && Objects.equals(m1.getSetterModel(), m2.getSetterModel())
+ && Objects.equals(m1.getGetterModel(), m2.getGetterModel())
+ && Objects.equals(m1.getHttp(), m2.getHttp())
+ && Objects.equals(m1.getDeprecatedMessage(), m2.getDeprecatedMessage())
+ // Note: not equals()
+ && listModelsAreIdentical(m1.getListModel(), m2.getListModel())
+ // Note: not equals()
+ && mapModelsAreIdentical(m1.getMapModel(), m2.getMapModel())
+ && Objects.equals(m1.getEnumType(), m2.getEnumType())
+ && Objects.equals(m1.getXmlNameSpaceUri(), m2.getXmlNameSpaceUri())
+ && Objects.equals(m1.getFluentGetterMethodName(), m2.getFluentGetterMethodName())
+ && Objects.equals(m1.getFluentEnumGetterMethodName(), m2.getFluentEnumGetterMethodName())
+ && Objects.equals(m1.getFluentSetterMethodName(), m2.getFluentSetterMethodName())
+ && Objects.equals(m1.getFluentEnumSetterMethodName(), m2.getFluentEnumSetterMethodName())
+ && Objects.equals(m1.getExistenceCheckMethodName(), m2.getExistenceCheckMethodName())
+ && Objects.equals(m1.getBeanStyleGetterMethodName(), m2.getBeanStyleGetterMethodName())
+ && Objects.equals(m1.getBeanStyleSetterMethodName(), m2.getBeanStyleSetterMethodName())
+ && Objects.equals(m1.getUnionEnumTypeName(), m2.getUnionEnumTypeName())
+ && Objects.equals(m1.getTimestampFormat(), m2.getTimestampFormat())
+ && Objects.equals(m1.getDeprecatedName(), m2.getDeprecatedName())
+ && Objects.equals(m1.getDeprecatedFluentGetterMethodName(), m2.getDeprecatedFluentGetterMethodName())
+ && Objects.equals(m1.getDeprecatedFluentSetterMethodName(), m2.getDeprecatedFluentSetterMethodName())
+ && Objects.equals(m1.getDeprecatedBeanStyleSetterMethodName(), m2.getDeprecatedBeanStyleSetterMethodName())
+ && Objects.equals(m1.getContextParam(), m2.getContextParam());
+ }
+
+ private boolean listModelsAreIdentical(ListModel m1, ListModel m2) {
+ if (m1 == null ^ m2 == null) {
+ return false;
+ }
+
+ if (m1 == null) {
+ return true;
+ }
+
+ return Objects.equals(m1.getImplType(), m2.getImplType())
+ && Objects.equals(m1.getMemberType(), m2.getMemberType())
+ && Objects.equals(m1.getInterfaceType(), m2.getInterfaceType())
+ // Note: not equals()
+ && memberModelsAreIdentical(m1.getListMemberModel(), m2.getListMemberModel())
+ && Objects.equals(m1.getMemberLocationName(), m2.getMemberLocationName())
+ && Objects.equals(m1.getMemberAdditionalMarshallingPath(), m2.getMemberAdditionalMarshallingPath())
+ && Objects.equals(m1.getMemberAdditionalUnmarshallingPath(), m2.getMemberAdditionalUnmarshallingPath());
+ }
+
+ private boolean mapModelsAreIdentical(MapModel m1, MapModel m2) {
+ if (m1 == null ^ m2 == null) {
+ return false;
+ }
+
+ if (m1 == null) {
+ return true;
+ }
+
+ return Objects.equals(m1.getImplType(), m2.getImplType())
+ && Objects.equals(m1.getInterfaceType(), m2.getInterfaceType())
+ && Objects.equals(m1.getKeyLocationName(), m2.getKeyLocationName())
+ // Note: not equals()
+ && memberModelsAreIdentical(m1.getKeyModel(), m2.getKeyModel())
+ && Objects.equals(m1.getValueLocationName(), m2.getValueLocationName())
+ // Note: not equals()
+ && memberModelsAreIdentical(m1.getValueModel(), m2.getValueModel());
+ }
+}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ValidationEntry.java b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ValidationEntry.java
new file mode 100644
index 000000000000..4e84bd625185
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ValidationEntry.java
@@ -0,0 +1,72 @@
+/*
+ * 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.validation;
+
+import software.amazon.awssdk.utils.ToString;
+
+public final class ValidationEntry {
+ private ValidationErrorId errorId;
+ private ValidationErrorSeverity severity;
+ private String detailMessage;
+
+ public ValidationErrorId getErrorId() {
+ return errorId;
+ }
+
+ public void setErrorId(ValidationErrorId errorId) {
+ this.errorId = errorId;
+ }
+
+ public ValidationEntry withErrorId(ValidationErrorId errorId) {
+ setErrorId(errorId);
+ return this;
+ }
+
+ public ValidationErrorSeverity getSeverity() {
+ return severity;
+ }
+
+ public void setSeverity(ValidationErrorSeverity severity) {
+ this.severity = severity;
+ }
+
+ public ValidationEntry withSeverity(ValidationErrorSeverity severity) {
+ setSeverity(severity);
+ return this;
+ }
+
+ public String getDetailMessage() {
+ return detailMessage;
+ }
+
+ public void setDetailMessage(String detailMessage) {
+ this.detailMessage = detailMessage;
+ }
+
+ public ValidationEntry withDetailMessage(String detailMessage) {
+ setDetailMessage(detailMessage);
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return ToString.builder("ValidationEntry")
+ .add("errorId", errorId)
+ .add("severity", severity)
+ .add("detailMessage", detailMessage)
+ .build();
+ }
+}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ValidationErrorId.java b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ValidationErrorId.java
new file mode 100644
index 000000000000..37c488e11fc5
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ValidationErrorId.java
@@ -0,0 +1,34 @@
+/*
+ * 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.validation;
+
+public enum ValidationErrorId {
+ SHARED_MODELS_DIFFER(
+ "The shared models between two services differ in their definition, which causes differences in the source"
+ + " files generated by the code generator."
+ ),
+ UNKNOWN_SHAPE_MEMBER("The model references an unknown shape member."),
+ REQUEST_URI_NOT_FOUND("The request URI does not exist."),
+ ;
+
+ private final String description;
+
+ ValidationErrorId(String description) {
+ this.description = description;
+ }
+
+
+}
diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ValidationErrorSeverity.java b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ValidationErrorSeverity.java
new file mode 100644
index 000000000000..39b6b015e42a
--- /dev/null
+++ b/codegen/src/main/java/software/amazon/awssdk/codegen/validation/ValidationErrorSeverity.java
@@ -0,0 +1,22 @@
+/*
+ * 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.validation;
+
+public enum ValidationErrorSeverity {
+ // Denotes an error that MUST be addressed.
+ DANGER,
+ ;
+}
diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Partition.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Partition.java.resource
index bdded3575891..2cf9d20dc2ac 100644
--- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Partition.java.resource
+++ b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Partition.java.resource
@@ -1,5 +1,6 @@
import java.util.HashMap;
import java.util.Map;
+import java.util.regex.Pattern;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.protocols.jsoncore.JsonNode;
import software.amazon.awssdk.utils.ToString;
@@ -15,6 +16,7 @@ public class Partition {
private final String regionRegex;
private final Map regions;
private final Outputs outputs;
+ private Pattern regionPattern;
private Partition(Builder builder) {
this.id = builder.id;
@@ -31,6 +33,13 @@ public class Partition {
return regionRegex;
}
+ public boolean regionMatches(String region) {
+ if (regionPattern == null) {
+ regionPattern = Pattern.compile(regionRegex);
+ }
+ return regionPattern.matcher(region).matches();
+ }
+
public Map regions() {
return regions;
}
diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/partitions.json.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/partitions.json.resource
index a2bfa6ead490..456b07fca676 100644
--- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/partitions.json.resource
+++ b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/partitions.json.resource
@@ -17,6 +17,9 @@
"ap-east-1" : {
"description" : "Asia Pacific (Hong Kong)"
},
+ "ap-east-2" : {
+ "description" : "Asia Pacific (Taipei)"
+ },
"ap-northeast-1" : {
"description" : "Asia Pacific (Tokyo)"
},
diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RulesFunctions.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RulesFunctions.java.resource
index a6c070217a11..5cfb8b857a5a 100644
--- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RulesFunctions.java.resource
+++ b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RulesFunctions.java.resource
@@ -90,8 +90,7 @@ public class RulesFunctions {
if (matchedPartition == null) {
// try matching on region name pattern
for (Partition p : data.partitions) {
- Pattern regex = Pattern.compile(p.regionRegex());
- if (regex.matcher(regionName).matches()) {
+ if (p.regionMatches(regionName)) {
matchedPartition = p;
break;
}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java
new file mode 100644
index 000000000000..c776e0295bea
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/CodeGeneratorTest.java
@@ -0,0 +1,267 @@
+/*
+ * 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;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.codegen.internal.Jackson;
+import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel;
+import software.amazon.awssdk.codegen.model.service.ServiceModel;
+import software.amazon.awssdk.codegen.poet.ClientTestModels;
+import software.amazon.awssdk.codegen.validation.ModelInvalidException;
+import software.amazon.awssdk.codegen.validation.ModelValidator;
+import software.amazon.awssdk.codegen.validation.ValidationErrorId;
+
+public class CodeGeneratorTest {
+ private static final String VALIDATION_REPORT_NAME = "validation-report.json";
+
+ private Path outputDir;
+
+ @BeforeEach
+ void methodSetup() throws IOException {
+ outputDir = Files.createTempDirectory(null);
+ }
+
+ @AfterEach
+ void methodTeardown() throws IOException {
+ deleteDirectory(outputDir);
+ }
+
+ @Test
+ void build_cj2ModelsAndIntermediateModelSet_throws() {
+ assertThatThrownBy(() -> CodeGenerator.builder()
+ .models(C2jModels.builder().build())
+ .intermediateModel(new IntermediateModel())
+ .build())
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("Only one of");
+ }
+
+ @Test
+ void execute_emitValidationReportIsFalse_doesNotEmitValidationReport() throws IOException {
+ generateCodeFromC2jModels(ClientTestModels.awsJsonServiceC2jModels(), outputDir);
+ assertThat(Files.exists(validationReportPath(outputDir))).isFalse();
+ }
+
+ @Test
+ void execute_emitValidationReportIsTrue_emitsValidationReport() throws IOException {
+ generateCodeFromC2jModels(ClientTestModels.awsJsonServiceC2jModels(), outputDir, true, null);
+ assertThat(Files.exists(validationReportPath(outputDir))).isTrue();
+ }
+
+ @Test
+ void execute_invokesModelValidators() {
+ ModelValidator mockValidator = mock(ModelValidator.class);
+ when(mockValidator.validateModels(any())).thenReturn(Collections.emptyList());
+
+ generateCodeFromC2jModels(ClientTestModels.awsJsonServiceC2jModels(), outputDir, true,
+ Collections.singletonList(mockValidator));
+
+ verify(mockValidator).validateModels(any());
+ }
+
+ @Test
+ void execute_c2jModelsAndIntermediateModel_generateSameCode() throws IOException {
+ Path c2jModelsOutputDir = outputDir.resolve("c2jModels");
+ generateCodeFromC2jModels(ClientTestModels.awsJsonServiceC2jModels(), c2jModelsOutputDir, false, Collections.emptyList());
+
+ Path intermediateModelOutputDir = outputDir.resolve("intermediate-model");
+ generateCodeFromIntermediateModel(ClientTestModels.awsJsonServiceModels(), intermediateModelOutputDir);
+
+ List c2jModels_generatedFiles = Files.walk(c2jModelsOutputDir)
+ .sorted()
+ .map(c2jModelsOutputDir::relativize)
+ .collect(Collectors.toList());
+
+ List intermediateModels_generatedFiles = Files.walk(intermediateModelOutputDir)
+ .sorted()
+ .map(intermediateModelOutputDir::relativize)
+ .collect(Collectors.toList());
+
+ assertThat(c2jModels_generatedFiles).isNotEmpty();
+
+ // Ensure same exact set of files
+ assertThat(c2jModels_generatedFiles).isEqualTo(intermediateModels_generatedFiles);
+
+ // All files should be exactly the same
+ for (Path generatedFile : c2jModels_generatedFiles) {
+ Path c2jGenerated = c2jModelsOutputDir.resolve(generatedFile);
+ Path intermediateGenerated = intermediateModelOutputDir.resolve(generatedFile);
+
+ if (Files.isDirectory(c2jGenerated)) {
+ assertThat(Files.isDirectory(intermediateGenerated)).isTrue();
+ } else {
+ assertThat(readToString(c2jGenerated)).isEqualTo(readToString(intermediateGenerated));
+ }
+ }
+ }
+
+ @Test
+ void execute_endpointsTestReferencesUnknownOperationMember_throwsValidationError() throws IOException {
+ ModelValidator mockValidator = mock(ModelValidator.class);
+ when(mockValidator.validateModels(any())).thenReturn(Collections.emptyList());
+
+ C2jModels referenceModels = ClientTestModels.awsJsonServiceC2jModels();
+
+ C2jModels c2jModelsWithBadTest =
+ C2jModels.builder()
+ .endpointTestSuiteModel(getBrokenEndpointTestSuiteModel())
+ .customizationConfig(referenceModels.customizationConfig())
+ .serviceModel(referenceModels.serviceModel())
+ .paginatorsModel(referenceModels.paginatorsModel())
+ .build();
+
+ assertThatThrownBy(() -> generateCodeFromC2jModels(c2jModelsWithBadTest, outputDir, true,
+ Collections.singletonList(mockValidator)))
+ .hasCauseInstanceOf(ModelInvalidException.class)
+ .matches(e -> {
+ ModelInvalidException exception = (ModelInvalidException) e.getCause();
+ return exception.validationEntries().get(0).getErrorId() == ValidationErrorId.UNKNOWN_SHAPE_MEMBER;
+ });
+ }
+
+ @Test
+ void execute_operationHasNoRequestUri_throwsValidationError() throws IOException {
+ C2jModels models = C2jModels.builder()
+ .customizationConfig(CustomizationConfig.create())
+ .serviceModel(getMissingRequestUriServiceModel())
+ .build();
+
+ assertThatThrownBy(() -> generateCodeFromC2jModels(models, outputDir, true, Collections.emptyList()))
+ .isInstanceOf(ModelInvalidException.class)
+ .matches(e -> ((ModelInvalidException) e).validationEntries().get(0).getErrorId()
+ == ValidationErrorId.REQUEST_URI_NOT_FOUND);
+ }
+
+ private void generateCodeFromC2jModels(C2jModels c2jModels, Path outputDir) {
+ generateCodeFromC2jModels(c2jModels, outputDir, false, null);
+ }
+
+ private void generateCodeFromC2jModels(C2jModels c2jModels, Path outputDir,
+ boolean emitValidationReport,
+ List modelValidators) {
+ Path sources = outputDir.resolve("generated-sources").resolve("sdk");
+ Path resources = outputDir.resolve("generated-resources").resolve("sdk-resources");
+ Path tests = outputDir.resolve("generated-test-sources").resolve("sdk-tests");
+
+ CodeGenerator.builder()
+ .models(c2jModels)
+ .sourcesDirectory(sources.toAbsolutePath().toString())
+ .resourcesDirectory(resources.toAbsolutePath().toString())
+ .testsDirectory(tests.toAbsolutePath().toString())
+ .emitValidationReport(emitValidationReport)
+ .modelValidators(modelValidators)
+ .build()
+ .execute();
+ }
+
+ private void generateCodeFromIntermediateModel(IntermediateModel intermediateModel, Path outputDir) {
+ Path sources = outputDir.resolve("generated-sources").resolve("sdk");
+ Path resources = outputDir.resolve("generated-resources").resolve("sdk-resources");
+ Path tests = outputDir.resolve("generated-test-sources").resolve("sdk-tests");
+
+ CodeGenerator.builder()
+ .intermediateModel(intermediateModel)
+ .sourcesDirectory(sources.toAbsolutePath().toString())
+ .resourcesDirectory(resources.toAbsolutePath().toString())
+ .testsDirectory(tests.toAbsolutePath().toString())
+ .build()
+ .execute();
+ }
+
+ private static String readToString(Path p) throws IOException {
+ ByteBuffer bb = ByteBuffer.wrap(Files.readAllBytes(p));
+ return StandardCharsets.UTF_8.decode(bb).toString();
+ }
+
+ private static Path validationReportPath(Path root) {
+ return root.resolve(Paths.get("generated-sources", "sdk", "models", VALIDATION_REPORT_NAME));
+ }
+
+ private EndpointTestSuiteModel getBrokenEndpointTestSuiteModel() throws IOException {
+ String json = resourceAsString("incorrect-endpoint-tests.json");
+ return Jackson.load(EndpointTestSuiteModel.class, json);
+ }
+
+ private ServiceModel getMissingRequestUriServiceModel() throws IOException {
+ String json = resourceAsString("no-request-uri-operation-service.json");
+ return Jackson.load(ServiceModel.class, json);
+ }
+
+ private String resourceAsString(String name) throws IOException {
+ ByteArrayOutputStream baos;
+ try (InputStream resourceAsStream = getClass().getResourceAsStream(name)) {
+ baos = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int read;
+ while ((read = resourceAsStream.read(buffer)) != -1) {
+ baos.write(buffer, 0, read);
+ }
+ }
+ return StandardCharsets.UTF_8.decode(ByteBuffer.wrap(baos.toByteArray())).toString();
+ }
+
+ private static void deleteDirectory(Path dir) throws IOException {
+ Files.walkFileTree(dir, new FileVisitor() {
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ Files.delete(file);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+ return FileVisitResult.TERMINATE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ Files.delete(dir);
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/ArgumentModelTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/ArgumentModelTest.java
new file mode 100644
index 000000000000..107a6e6cdb66
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/ArgumentModelTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.model.intermediate;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.junit.jupiter.api.Test;
+
+public class ArgumentModelTest {
+ @Test
+ public void equals_isCorrect() {
+ EqualsVerifier.simple()
+ .forClass(ArgumentModel.class)
+ .usingGetClass()
+ .verify();
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/AuthorizerModelTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/AuthorizerModelTest.java
new file mode 100644
index 000000000000..28d8dd845412
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/AuthorizerModelTest.java
@@ -0,0 +1,26 @@
+/*
+ * 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.model.intermediate;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.junit.jupiter.api.Test;
+
+public class AuthorizerModelTest {
+ @Test
+ public void equals_isCorrect() {
+ EqualsVerifier.simple().forClass(AuthorizerModel.class).usingGetClass().verify();
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/MemberModelTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/MemberModelTest.java
new file mode 100644
index 000000000000..bd4a0859603f
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/MemberModelTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.model.intermediate;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.junit.jupiter.api.Test;
+
+public class MemberModelTest {
+ @Test
+ public void equals_isCorrect() {
+ ListModel redListModel = new ListModel();
+ redListModel.setMemberLocationName("RedLocation");
+ ListModel blueListModel = new ListModel();
+ blueListModel.setMemberLocationName("BlueLocation");
+
+ MemberModel redMemberModel = new MemberModel();
+ redMemberModel.setC2jName("RedC2jName");
+ MemberModel blueMemberModel = new MemberModel();
+ blueMemberModel.setC2jName("BlueC2jName");
+
+ EqualsVerifier.simple().forClass(MemberModel.class)
+ .withPrefabValues(ListModel.class, redListModel, blueListModel)
+ .withPrefabValues(MemberModel.class, redMemberModel, blueMemberModel)
+ .usingGetClass()
+ .verify();
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/OperationModelTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/OperationModelTest.java
new file mode 100644
index 000000000000..531d0b1aa55e
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/OperationModelTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.model.intermediate;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.junit.jupiter.api.Test;
+
+public class OperationModelTest {
+ @Test
+ void equals_isCorrect() {
+ MemberModel blueMemberModel = new MemberModel();
+ blueMemberModel.setName("blue");
+ MemberModel redMemberModel = new MemberModel();
+ redMemberModel.setName("red");
+
+ EqualsVerifier.simple()
+ .forClass(OperationModel.class)
+ .withPrefabValues(MemberModel.class, blueMemberModel, redMemberModel)
+ .usingGetClass()
+ .verify();
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/ParameterHttpMappingTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/ParameterHttpMappingTest.java
new file mode 100644
index 000000000000..cd142cb34c2c
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/ParameterHttpMappingTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.model.intermediate;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.junit.jupiter.api.Test;
+
+public class ParameterHttpMappingTest {
+ @Test
+ void equals_isCorrect() {
+ EqualsVerifier.simple()
+ .forClass(ParameterHttpMapping.class)
+ .usingGetClass()
+ .verify();
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/ReturnTypeModelTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/ReturnTypeModelTest.java
new file mode 100644
index 000000000000..53e99f514403
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/ReturnTypeModelTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.model.intermediate;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.junit.jupiter.api.Test;
+
+public class ReturnTypeModelTest {
+ @Test
+ void equals_isCorrect() {
+ EqualsVerifier.simple()
+ .forClass(ReturnTypeModel.class)
+ .usingGetClass()
+ .verify();
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/ShapeModelTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/ShapeModelTest.java
new file mode 100644
index 000000000000..08fb79681e96
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/ShapeModelTest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.model.intermediate;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.junit.jupiter.api.Test;
+
+public class ShapeModelTest {
+
+
+ @Test
+ public void equals_isCorrect() {
+ MemberModel blueMemberModel = new MemberModel();
+ blueMemberModel.setName("blue");
+ MemberModel redMemberModel = new MemberModel();
+ redMemberModel.setName("red");
+
+ EqualsVerifier.simple()
+ .forClass(ShapeModel.class)
+ .withPrefabValues(MemberModel.class, blueMemberModel, redMemberModel)
+ .usingGetClass()
+ .verify();
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/VariableModelTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/VariableModelTest.java
new file mode 100644
index 000000000000..55ea2f39123a
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/VariableModelTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.model.intermediate;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.junit.jupiter.api.Test;
+
+public class VariableModelTest {
+ @Test
+ void equals_isCorrect() {
+ EqualsVerifier.simple()
+ .forClass(VariableModel.class)
+ .usingGetClass()
+ .verify();
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/customization/ArtificialResultWrapperTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/customization/ArtificialResultWrapperTest.java
new file mode 100644
index 000000000000..aa29412a5f5f
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/customization/ArtificialResultWrapperTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.model.intermediate.customization;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.junit.jupiter.api.Test;
+
+public class ArtificialResultWrapperTest {
+ @Test
+ void equals_isCorrect() {
+ EqualsVerifier.simple()
+ .forClass(ArtificialResultWrapper.class)
+ .usingGetClass()
+ .verify();
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/customization/ShapeCustomizationInfoTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/customization/ShapeCustomizationInfoTest.java
new file mode 100644
index 000000000000..3126117f100d
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/customization/ShapeCustomizationInfoTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.model.intermediate.customization;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.junit.jupiter.api.Test;
+
+public class ShapeCustomizationInfoTest {
+ @Test
+ void equals_isCorrect() {
+ EqualsVerifier.simple()
+ .forClass(ShapeCustomizationInfo.class)
+ .usingGetClass()
+ .verify();
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/model/service/ContextParamTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/model/service/ContextParamTest.java
new file mode 100644
index 000000000000..937688b70cb4
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/model/service/ContextParamTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.model.service;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.junit.jupiter.api.Test;
+
+public class ContextParamTest {
+ @Test
+ void equals_isCorrect() {
+ EqualsVerifier.simple()
+ .forClass(ContextParam.class)
+ .usingGetClass()
+ .verify();
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategyTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategyTest.java
index 6b8756474405..cec5a7fd4bb2 100644
--- a/codegen/src/test/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategyTest.java
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategyTest.java
@@ -337,6 +337,39 @@ public void validateAllowsUnderscoresWithCustomization() {
strategy.validateCustomerVisibleNaming(model);
}
+ @Test
+ public void getSigningNameForEnvironmentVariables_convertsDashAndUppercases() {
+ when(serviceModel.getMetadata()).thenReturn(serviceMetadata);
+ when(serviceMetadata.getSigningName()).thenReturn("signing-name");
+
+ assertThat(strat.getSigningNameForEnvironmentVariables()).isEqualTo("SIGNING_NAME");
+ }
+
+ @Test
+ public void getSigningNameForSystemProperties_convertsDashAndUppercasesWords() {
+ when(serviceModel.getMetadata()).thenReturn(serviceMetadata);
+ when(serviceMetadata.getSigningName()).thenReturn("signing-name");
+
+ assertThat(strat.getSigningNameForSystemProperties()).isEqualTo("SigningName");
+ }
+
+ @Test
+ public void getSigningName_Uses_EndpointPrefix_whenSigningNameUnset() {
+ when(serviceModel.getMetadata()).thenReturn(serviceMetadata);
+ when(serviceMetadata.getSigningName()).thenReturn(null);
+ when(serviceMetadata.getEndpointPrefix()).thenReturn("EndpointPrefixFoo");
+
+ assertThat(strat.getSigningName()).isEqualTo("EndpointPrefixFoo");
+ }
+
+ @Test
+ public void getSigningName_Uses_SigningName() {
+ when(serviceModel.getMetadata()).thenReturn(serviceMetadata);
+ when(serviceMetadata.getSigningName()).thenReturn("Foo");
+
+ assertThat(strat.getSigningName()).isEqualTo("Foo");
+ }
+
@Test
public void validateServiceIdentifiersForEnvVarsAndProfileProperty() {
when(serviceModel.getMetadata()).thenReturn(serviceMetadata);
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java
index 308aa69ea487..920ee018c402 100644
--- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java
@@ -47,6 +47,17 @@ public static IntermediateModel awsJsonServiceModels() {
return new IntermediateModelBuilder(models).build();
}
+ public static C2jModels awsJsonServiceC2jModels() {
+ File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/json/service-2.json").getFile());
+ File customizationModel = new File(ClientTestModels.class.getResource("client/c2j/json/customization.config").getFile());
+ File paginatorsModel = new File(ClientTestModels.class.getResource("client/c2j/json/paginators.json").getFile());
+ return C2jModels.builder()
+ .serviceModel(getServiceModel(serviceModel))
+ .customizationConfig(getCustomizationConfig(customizationModel))
+ .paginatorsModel(getPaginatorsModel(paginatorsModel))
+ .build();
+ }
+
public static IntermediateModel cborServiceModels() {
File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/json/service-2.json").getFile());
File customizationModel = new File(ClientTestModels.class.getResource("client/c2j/cbor/customization.config").getFile());
@@ -86,6 +97,22 @@ public static IntermediateModel bearerAuthServiceModels() {
return new IntermediateModelBuilder(models).build();
}
+ public static IntermediateModel envBearerTokenServiceModels() {
+ File serviceModel = new File(ClientTestModels.class.getResource(
+ "client/c2j/json-bearer-auth/service-2.json").getFile());
+ File customizationModel = new File(ClientTestModels.class.getResource(
+ "client/c2j/json-bearer-auth/customization-env-bearer-token.config").getFile());
+ File paginatorsModel = new File(ClientTestModels.class.getResource(
+ "client/c2j/json-bearer-auth/paginators.json").getFile());
+ C2jModels models = C2jModels.builder()
+ .serviceModel(getServiceModel(serviceModel))
+ .customizationConfig(getCustomizationConfig(customizationModel))
+ .paginatorsModel(getPaginatorsModel(paginatorsModel))
+ .build();
+
+ return new IntermediateModelBuilder(models).build();
+ }
+
public static IntermediateModel restJsonServiceModels() {
File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/rest-json/service-2.json").getFile());
File customizationModel = new File(ClientTestModels.class.getResource("client/c2j/rest-json/customization.config").getFile());
@@ -159,6 +186,48 @@ public static IntermediateModel queryServiceModelsWithOverrideKnowProperties() {
return new IntermediateModelBuilder(models).build();
}
+ public static IntermediateModel queryServiceModelsWithUnknownEndpointProperties() {
+ File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query/service-2.json").getFile());
+ File waitersModel = new File(ClientTestModels.class.getResource("client/c2j/query/waiters-2.json").getFile());
+ File endpointRuleSetModel =
+ new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-rule-set-unknown-properties.json").getFile());
+ File endpointTestsModel =
+ new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-tests.json").getFile());
+
+ C2jModels models = C2jModels
+ .builder()
+ .serviceModel(getServiceModel(serviceModel))
+ .waitersModel(getWaiters(waitersModel))
+ .customizationConfig(CustomizationConfig.create())
+ .endpointRuleSetModel(getEndpointRuleSet(endpointRuleSetModel))
+ .endpointTestSuiteModel(getEndpointTestSuite(endpointTestsModel))
+ .build();
+
+ return new IntermediateModelBuilder(models).build();
+ }
+
+ public static IntermediateModel queryServiceModelsWithUriCache() {
+ File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query/service-2.json").getFile());
+ File customizationModel =
+ new File(ClientTestModels.class.getResource("client/c2j/query/customization-uri-cache.config").getFile());
+ File waitersModel = new File(ClientTestModels.class.getResource("client/c2j/query/waiters-2.json").getFile());
+ File endpointRuleSetModel =
+ new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-rule-set.json").getFile());
+ File endpointTestsModel =
+ new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-tests.json").getFile());
+
+ C2jModels models = C2jModels
+ .builder()
+ .serviceModel(getServiceModel(serviceModel))
+ .customizationConfig(getCustomizationConfig(customizationModel))
+ .waitersModel(getWaiters(waitersModel))
+ .endpointRuleSetModel(getEndpointRuleSet(endpointRuleSetModel))
+ .endpointTestSuiteModel(getEndpointTestSuite(endpointTestsModel))
+ .build();
+
+ return new IntermediateModelBuilder(models).build();
+ }
+
public static IntermediateModel queryServiceModelsEndpointAuthParamsWithAllowList() {
File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query/service-2.json").getFile());
File customizationModel =
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecTest.java
index dba6bca98c74..3e2807600928 100644
--- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecTest.java
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecTest.java
@@ -66,6 +66,12 @@ static List parameters() {
.caseName("query")
.outputFileSuffix("default-params")
.build(),
+ TestCase.builder()
+ .modelProvider(ClientTestModels::queryServiceModels)
+ .classSpecProvider(PreferredAuthSchemeProviderSpec::new)
+ .caseName("query")
+ .outputFileSuffix("preferred-provider")
+ .build(),
// query-endpoint-auth-params
TestCase.builder()
.modelProvider(ClientTestModels::queryServiceModelsEndpointAuthParamsWithAllowList)
@@ -214,6 +220,13 @@ static List parameters() {
.classSpecProvider(AuthSchemeInterceptorSpec::new)
.caseName("ops-auth-sigv4a-value")
.outputFileSuffix("interceptor")
+ .build(),
+ // service with environment bearer token enabled
+ TestCase.builder()
+ .modelProvider(ClientTestModels::envBearerTokenServiceModels)
+ .classSpecProvider(AuthSchemeInterceptorSpec::new)
+ .caseName("env-bearer-token")
+ .outputFileSuffix("interceptor")
.build()
);
}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassTest.java
index a09271f4001a..423ae5aba59a 100644
--- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassTest.java
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassTest.java
@@ -17,6 +17,7 @@
import static software.amazon.awssdk.codegen.poet.ClientTestModels.bearerAuthServiceModels;
import static software.amazon.awssdk.codegen.poet.ClientTestModels.composedClientJsonServiceModels;
+import static software.amazon.awssdk.codegen.poet.ClientTestModels.envBearerTokenServiceModels;
import static software.amazon.awssdk.codegen.poet.ClientTestModels.internalConfigModels;
import static software.amazon.awssdk.codegen.poet.ClientTestModels.operationWithNoAuth;
import static software.amazon.awssdk.codegen.poet.ClientTestModels.opsWithSigv4a;
@@ -87,6 +88,13 @@ void baseClientBuilderClassWithBearerAuth_sra() {
validateBaseClientBuilderClassGeneration(bearerAuthServiceModels(), "test-bearer-auth-client-builder-class.java", true);
}
+ @Test
+ void baseClientBuilderClassWithEnvBearerToken_sra() {
+ validateBaseClientBuilderClassGeneration(envBearerTokenServiceModels(),
+ "test-env-bearer-token-client-builder-class.java",
+ true);
+ }
+
@Test
void baseClientBuilderClassWithNoAuthOperation_sra() {
validateBaseClientBuilderClassGeneration(operationWithNoAuth(), "test-no-auth-ops-client-builder-class.java", true);
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/EnvironmentTokenSystemSettingsClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/EnvironmentTokenSystemSettingsClassTest.java
new file mode 100644
index 000000000000..3946483248a6
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/EnvironmentTokenSystemSettingsClassTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.hamcrest.MatcherAssert.assertThat;
+import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo;
+
+import org.junit.Test;
+import software.amazon.awssdk.codegen.poet.ClassSpec;
+import software.amazon.awssdk.codegen.poet.ClientTestModels;
+
+public class EnvironmentTokenSystemSettingsClassTest {
+ @Test
+ public void testEnvironmentTokenSystemSettingsClass() {
+ ClassSpec classSpec = new EnvironmentTokenSystemSettingsClass(ClientTestModels.restJsonServiceModels());
+ assertThat(classSpec, generatesTo("test-environment-token-system-settings-class.java"));
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java
new file mode 100644
index 000000000000..4fe4c9daf0bb
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ServiceVersionInfoSpecTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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 static org.hamcrest.Matchers.equalToIgnoringWhiteSpace;
+
+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.ServiceVersionInfoSpec;
+import software.amazon.awssdk.core.util.VersionInfo;
+
+public class ServiceVersionInfoSpecTest {
+
+ // Fixture test that compares generated ServiceVersionInfo class against expected output.
+ // The fixture file uses {{VERSION}} as a placeholder for the SDK version. The placeholder get
+ // replaced with actual value at test time, since the generated code injects the actual
+ // version at build time.
+ @Test
+ void testServiceVersionInfoClass() {
+ String currVersion = VersionInfo.SDK_VERSION;
+ ClassSpec serviceVersionInfoSpec = new ServiceVersionInfoSpec(ClientTestModels.restJsonServiceModels());
+
+ String expectedContent = loadFixtureFile("test-service-version-info-class.java");
+ expectedContent = expectedContent
+ .replace("{{VERSION}}", currVersion);
+
+ String actualContent = generateContent(serviceVersionInfoSpec);
+
+ 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();
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderCompiledRulesClassSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderCompiledRulesClassSpecTest.java
index 3ee5c8757a37..5bc9a1f74d75 100644
--- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderCompiledRulesClassSpecTest.java
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderCompiledRulesClassSpecTest.java
@@ -37,4 +37,18 @@ void knowPropertiesOverride() {
new EndpointProviderSpec2(ClientTestModels.queryServiceModelsWithOverrideKnowProperties());
assertThat(endpointProviderSpec, generatesTo("endpoint-provider-know-prop-override-class.java"));
}
+
+ @Test
+ void unknownEndpointProperties() {
+ ClassSpec endpointProviderSpec =
+ new EndpointProviderSpec2(ClientTestModels.queryServiceModelsWithUnknownEndpointProperties());
+ assertThat(endpointProviderSpec, generatesTo("endpoint-provider-unknown-property-class.java"));
+ }
+
+ @Test
+ void endpointProviderClassWithUriCache() {
+ ClassSpec endpointProviderSpec =
+ new EndpointProviderSpec2(ClientTestModels.queryServiceModelsWithUriCache());
+ assertThat(endpointProviderSpec, generatesTo("endpoint-provider-uri-cache-class.java"));
+ }
}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/utils/AuthUtilsTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/utils/AuthUtilsTest.java
index 66e2311978ee..f93f0172fbc9 100644
--- a/codegen/src/test/java/software/amazon/awssdk/codegen/utils/AuthUtilsTest.java
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/utils/AuthUtilsTest.java
@@ -18,6 +18,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -30,15 +31,17 @@
import software.amazon.awssdk.codegen.model.intermediate.Metadata;
import software.amazon.awssdk.codegen.model.intermediate.OperationModel;
import software.amazon.awssdk.codegen.model.service.AuthType;
+import software.amazon.awssdk.utils.CollectionUtils;
public class AuthUtilsTest {
@ParameterizedTest
@MethodSource("serviceValues")
public void testIfServiceHasBearerAuth(AuthType serviceAuthType,
+ List serviceAuthTypes,
List opAuthTypes,
Boolean expectedResult) {
- IntermediateModel model = modelWith(serviceAuthType);
+ IntermediateModel model = modelWith(serviceAuthType, serviceAuthTypes);
model.setOperations(createOperations(opAuthTypes));
assertThat(AuthUtils.usesBearerAuth(model)).isEqualTo(expectedResult);
}
@@ -47,10 +50,11 @@ private static Stream serviceValues() {
List oneBearerOp = Arrays.asList(AuthType.BEARER, AuthType.S3V4, AuthType.NONE);
List noBearerOp = Arrays.asList(AuthType.S3V4, AuthType.S3V4, AuthType.NONE);
- return Stream.of(Arguments.of(AuthType.BEARER, noBearerOp, true),
- Arguments.of(AuthType.BEARER, oneBearerOp, true),
- Arguments.of(AuthType.S3V4, noBearerOp, false),
- Arguments.of(AuthType.S3V4, oneBearerOp, true));
+ return Stream.of(Arguments.of(AuthType.BEARER, Collections.emptyList(), noBearerOp, true),
+ Arguments.of(AuthType.BEARER, Collections.emptyList(), oneBearerOp, true),
+ Arguments.of(AuthType.S3V4, Collections.emptyList(), noBearerOp, false),
+ Arguments.of(AuthType.S3V4, Collections.emptyList(), oneBearerOp, true),
+ Arguments.of(AuthType.S3V4, oneBearerOp, noBearerOp, true));
}
@ParameterizedTest
@@ -106,6 +110,12 @@ private static IntermediateModel modelWith(AuthType authType) {
return model;
}
+ private static IntermediateModel modelWith(AuthType authType, List authTypes) {
+ IntermediateModel model = modelWith(authType);
+ model.getMetadata().setAuth(authTypes);
+ return model;
+ }
+
private static Map createOperations(List opAuthTypes) {
return IntStream.range(0, opAuthTypes.size())
.boxed()
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/utils/ProtocolUtilsTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/utils/ProtocolUtilsTest.java
new file mode 100644
index 000000000000..9d714de98e4d
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/utils/ProtocolUtilsTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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 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_protocolCborV2_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");
+ }
+
+ @Test
+ public void protocolsWithCborV1_protocolJson_selectsCborV1() {
+ ServiceMetadata serviceMetadata = new ServiceMetadata();
+ serviceMetadata.setProtocols(Collections.singletonList("cbor"));
+ serviceMetadata.setProtocol("json");
+ String selectedProtocol = ProtocolUtils.resolveProtocol(serviceMetadata);
+ assertThat(selectedProtocol).isEqualTo("cbor");
+ }
+
+ private static Stream 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 protocols) {
+ ServiceMetadata serviceMetadata = new ServiceMetadata();
+ serviceMetadata.setProtocols(protocols);
+ return serviceMetadata;
+ }
+}
diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/validation/SharedModelsValidatorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/validation/SharedModelsValidatorTest.java
new file mode 100644
index 000000000000..a485956d94bc
--- /dev/null
+++ b/codegen/src/test/java/software/amazon/awssdk/codegen/validation/SharedModelsValidatorTest.java
@@ -0,0 +1,148 @@
+/*
+ * 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.validation;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
+import software.amazon.awssdk.codegen.model.intermediate.MemberModel;
+import software.amazon.awssdk.codegen.model.intermediate.Metadata;
+import software.amazon.awssdk.codegen.model.intermediate.ShapeModel;
+import software.amazon.awssdk.codegen.poet.ClientTestModels;
+
+public class SharedModelsValidatorTest {
+ private final ModelValidator validator = new SharedModelsValidator();
+
+ @Test
+ void validateModels_noTargetService_noValidationErrors() {
+ assertThat(runValidation(ClientTestModels.awsJsonServiceModels(), null)).isEmpty();
+ }
+
+ @Test
+ void validateModels_targetServiceTriviallyIdentical_noValidationErrors() {
+ assertThat(runValidation(ClientTestModels.awsJsonServiceModels(), ClientTestModels.awsJsonServiceModels())).isEmpty();
+ }
+
+ @Test
+ void validateModels_noSharedShapes_noValidationErrors() {
+ IntermediateModel target = ClientTestModels.awsJsonServiceModels();
+ Map renamedShapes = target.getShapes()
+ .entrySet()
+ .stream()
+ .collect(Collectors.toMap(e -> "Copy" + e.getKey(), Map.Entry::getValue));
+ target.setShapes(renamedShapes);
+
+ assertThat(runValidation(ClientTestModels.awsJsonServiceModels(), target)).isEmpty();
+ }
+
+ @Test
+ void validateModels_sharedShapesNotIdentical_emitsValidationError() {
+ IntermediateModel target = ClientTestModels.awsJsonServiceModels();
+ Map modifiedShapes = target.getShapes()
+ .entrySet()
+ .stream()
+ .collect(Collectors.toMap(Map.Entry::getKey,
+ e -> {
+ ShapeModel shapeModel = e.getValue();
+ shapeModel.setDeprecated(!shapeModel.isDeprecated());
+ return shapeModel;
+ }));
+
+ target.setShapes(modifiedShapes);
+
+ List validationEntries = runValidation(ClientTestModels.awsJsonServiceModels(), target);
+
+ assertThat(validationEntries).hasSize(modifiedShapes.size());
+
+ assertThat(validationEntries).allMatch(e -> e.getErrorId() == ValidationErrorId.SHARED_MODELS_DIFFER
+ && e.getSeverity() == ValidationErrorSeverity.DANGER);
+ }
+
+ @Test
+ void validateModels_shapesDontHaveSameMemberNames_emitsValidationError() {
+ IntermediateModel fooService = new IntermediateModel();
+ fooService.setMetadata(new Metadata().withServiceName("Foo"));
+
+ IntermediateModel barService = new IntermediateModel();
+ barService.setMetadata(new Metadata().withServiceName("Bar"));
+
+ String shapeName = "TestShape";
+
+ ShapeModel shape1 = new ShapeModel();
+ MemberModel member1 = new MemberModel();
+ member1.setName("Shape1Member");
+ shape1.setMembers(Arrays.asList(member1));
+
+ ShapeModel shape2 = new ShapeModel();
+ MemberModel member2 = new MemberModel();
+ member2.setName("Shape2Member");
+ shape2.setMembers(Arrays.asList(member2));
+
+ Map fooServiceShapes = new HashMap<>();
+ fooServiceShapes.put(shapeName, shape1);
+ fooService.setShapes(fooServiceShapes);
+
+ Map barServiceShapes = new HashMap<>();
+ barServiceShapes.put(shapeName, shape2);
+ barService.setShapes(barServiceShapes);
+
+ List validationEntries = runValidation(fooService, barService);
+
+ assertThat(validationEntries).hasSize(1);
+ }
+
+ @Test
+ void validateModels_shapesDontHaveSameMembers_emitsValidationError() {
+ IntermediateModel fooService = new IntermediateModel();
+ fooService.setMetadata(new Metadata().withServiceName("Foo"));
+
+ IntermediateModel barService = new IntermediateModel();
+ barService.setMetadata(new Metadata().withServiceName("Bar"));
+
+ String shapeName = "TestShape";
+ ShapeModel shape1 = new ShapeModel();
+
+ ShapeModel shape2 = new ShapeModel();
+ shape2.setMembers(Arrays.asList(new MemberModel(), new MemberModel()));
+
+ Map fooServiceShapes = new HashMap<>();
+ fooServiceShapes.put(shapeName, shape1);
+ fooService.setShapes(fooServiceShapes);
+
+ Map barServiceShapes = new HashMap<>();
+ barServiceShapes.put(shapeName, shape2);
+ barService.setShapes(barServiceShapes);
+
+ List validationEntries = runValidation(fooService, barService);
+
+ assertThat(validationEntries).hasSize(1);
+ }
+
+ private List runValidation(IntermediateModel m1, IntermediateModel m2) {
+ ModelValidationContext ctx = ModelValidationContext.builder()
+ .intermediateModel(m1)
+ .shareModelsTarget(m2)
+ .build();
+
+ return validator.validateModels(ctx);
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/incorrect-endpoint-tests.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/incorrect-endpoint-tests.json
new file mode 100644
index 000000000000..861ba12cf3c5
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/incorrect-endpoint-tests.json
@@ -0,0 +1,26 @@
+{
+ "testCases": [
+ {
+ "documentation": "Test references undefined operation member",
+ "expect": {
+ "error": "Some error"
+ },
+ "operationInputs": [
+ {
+ "builtInParams": {
+ "AWS::Region": "us-east-1"
+ },
+ "operationName": "APostOperation",
+ "operationParams": {
+ "Foo": "bar"
+ }
+ }
+ ],
+ "params": {
+ "Region": "us-east-1",
+ "UseFIPS": false,
+ "UseDualStack": false
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/no-request-uri-operation-service.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/no-request-uri-operation-service.json
new file mode 100644
index 000000000000..d7caffad37e0
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/no-request-uri-operation-service.json
@@ -0,0 +1,43 @@
+{
+ "version": "2.0",
+ "metadata": {
+ "apiVersion": "2010-05-08",
+ "endpointPrefix": "json-service-endpoint",
+ "globalEndpoint": "json-service.amazonaws.com",
+ "protocol": "rest-json",
+ "serviceAbbreviation": "Rest Json Service",
+ "serviceFullName": "Some Service That Uses Rest-Json Protocol",
+ "serviceId": "Rest Json Service",
+ "signingName": "json-service",
+ "signatureVersion": "v4",
+ "uid": "json-service-2010-05-08",
+ "xmlNamespace": "https://json-service.amazonaws.com/doc/2010-05-08/"
+ },
+ "operations": {
+ "OperationWithUriMappedParam": {
+ "name": "OperationWithUriMappedParam",
+ "http": {
+ "method": "GET"
+ },
+ "input": {
+ "shape": "OperationWithUriMappedParamRequest"
+ }
+ }
+ },
+ "shapes": {
+ "OperationWithUriMappedParamRequest": {
+ "type": "structure",
+ "members": {
+ "StringMember": {
+ "shape": "String",
+ "location": "uri",
+ "locationName": "stringMember"
+ }
+ }
+ },
+ "String": {
+ "type": "string"
+ }
+ },
+ "documentation": "A service that is implemented using the rest-json protocol"
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/env-bearer-token-auth-scheme-interceptor.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/env-bearer-token-auth-scheme-interceptor.java
new file mode 100644
index 000000000000..a7f8a8e8d336
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/env-bearer-token-auth-scheme-interceptor.java
@@ -0,0 +1,164 @@
+package software.amazon.awssdk.services.json.auth.scheme.internal;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.core.SdkRequest;
+import software.amazon.awssdk.core.SelectedAuthScheme;
+import software.amazon.awssdk.core.exception.SdkException;
+import software.amazon.awssdk.core.interceptor.Context;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute;
+import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
+import software.amazon.awssdk.core.internal.util.MetricUtils;
+import software.amazon.awssdk.core.metrics.CoreMetric;
+import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
+import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.http.auth.spi.signer.HttpSigner;
+import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
+import software.amazon.awssdk.identity.spi.Identity;
+import software.amazon.awssdk.identity.spi.IdentityProvider;
+import software.amazon.awssdk.identity.spi.IdentityProviders;
+import software.amazon.awssdk.identity.spi.ResolveIdentityRequest;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
+import software.amazon.awssdk.metrics.MetricCollector;
+import software.amazon.awssdk.metrics.SdkMetric;
+import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeParams;
+import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider;
+import software.amazon.awssdk.utils.Logger;
+import software.amazon.awssdk.utils.Validate;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class JsonAuthSchemeInterceptor implements ExecutionInterceptor {
+ private static Logger LOG = Logger.loggerFor(JsonAuthSchemeInterceptor.class);
+
+ @Override
+ public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) {
+ List authOptions = resolveAuthOptions(context, executionAttributes);
+ SelectedAuthScheme extends Identity> selectedAuthScheme = selectAuthScheme(authOptions, executionAttributes);
+ putSelectedAuthScheme(executionAttributes, selectedAuthScheme);
+ recordEnvironmentTokenBusinessMetric(selectedAuthScheme, executionAttributes);
+ }
+
+ private List resolveAuthOptions(Context.BeforeExecution context, ExecutionAttributes executionAttributes) {
+ JsonAuthSchemeProvider authSchemeProvider = Validate.isInstanceOf(JsonAuthSchemeProvider.class,
+ executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER),
+ "Expected an instance of JsonAuthSchemeProvider");
+ JsonAuthSchemeParams params = authSchemeParams(context.request(), executionAttributes);
+ return authSchemeProvider.resolveAuthScheme(params);
+ }
+
+ private SelectedAuthScheme extends Identity> selectAuthScheme(List authOptions,
+ ExecutionAttributes executionAttributes) {
+ MetricCollector metricCollector = executionAttributes.getAttribute(SdkExecutionAttribute.API_CALL_METRIC_COLLECTOR);
+ Map> authSchemes = executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES);
+ IdentityProviders identityProviders = executionAttributes.getAttribute(SdkInternalExecutionAttribute.IDENTITY_PROVIDERS);
+ List> discardedReasons = new ArrayList<>();
+ for (AuthSchemeOption authOption : authOptions) {
+ AuthScheme> authScheme = authSchemes.get(authOption.schemeId());
+ SelectedAuthScheme extends Identity> selectedAuthScheme = trySelectAuthScheme(authOption, authScheme,
+ identityProviders, discardedReasons, metricCollector, executionAttributes);
+ if (selectedAuthScheme != null) {
+ if (!discardedReasons.isEmpty()) {
+ LOG.debug(() -> String.format("%s auth will be used, discarded: '%s'", authOption.schemeId(),
+ discardedReasons.stream().map(Supplier::get).collect(Collectors.joining(", "))));
+ }
+ return selectedAuthScheme;
+ }
+ }
+ throw SdkException
+ .builder()
+ .message(
+ "Failed to determine how to authenticate the user: "
+ + discardedReasons.stream().map(Supplier::get).collect(Collectors.joining(", "))).build();
+ }
+
+ private JsonAuthSchemeParams authSchemeParams(SdkRequest request, ExecutionAttributes executionAttributes) {
+ String operation = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME);
+ JsonAuthSchemeParams.Builder builder = JsonAuthSchemeParams.builder().operation(operation);
+ return builder.build();
+ }
+
+ private SelectedAuthScheme trySelectAuthScheme(AuthSchemeOption authOption, AuthScheme authScheme,
+ IdentityProviders identityProviders, List> discardedReasons, MetricCollector metricCollector,
+ ExecutionAttributes executionAttributes) {
+ if (authScheme == null) {
+ discardedReasons.add(() -> String.format("'%s' is not enabled for this request.", authOption.schemeId()));
+ return null;
+ }
+ IdentityProvider identityProvider = authScheme.identityProvider(identityProviders);
+ if (identityProvider == null) {
+ discardedReasons
+ .add(() -> String.format("'%s' does not have an identity provider configured.", authOption.schemeId()));
+ return null;
+ }
+ HttpSigner signer;
+ try {
+ signer = authScheme.signer();
+ } catch (RuntimeException e) {
+ discardedReasons.add(() -> String.format("'%s' signer could not be retrieved: %s", authOption.schemeId(),
+ e.getMessage()));
+ return null;
+ }
+ ResolveIdentityRequest.Builder identityRequestBuilder = ResolveIdentityRequest.builder();
+ authOption.forEachIdentityProperty(identityRequestBuilder::putProperty);
+ CompletableFuture extends T> identity;
+ SdkMetric metric = getIdentityMetric(identityProvider);
+ if (metric == null) {
+ identity = identityProvider.resolveIdentity(identityRequestBuilder.build());
+ } else {
+ identity = MetricUtils.reportDuration(() -> identityProvider.resolveIdentity(identityRequestBuilder.build()),
+ metricCollector, metric);
+ }
+ return new SelectedAuthScheme<>(identity, signer, authOption);
+ }
+
+ private SdkMetric getIdentityMetric(IdentityProvider> identityProvider) {
+ Class> identityType = identityProvider.identityType();
+ if (identityType == AwsCredentialsIdentity.class) {
+ return CoreMetric.CREDENTIALS_FETCH_DURATION;
+ }
+ if (identityType == TokenIdentity.class) {
+ return CoreMetric.TOKEN_FETCH_DURATION;
+ }
+ return null;
+ }
+
+ private void putSelectedAuthScheme(ExecutionAttributes attributes,
+ SelectedAuthScheme selectedAuthScheme) {
+ SelectedAuthScheme> existingAuthScheme = attributes.getAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME);
+ if (existingAuthScheme != null) {
+ AuthSchemeOption.Builder selectedOption = selectedAuthScheme.authSchemeOption().toBuilder();
+ existingAuthScheme.authSchemeOption().forEachIdentityProperty(selectedOption::putIdentityPropertyIfAbsent);
+ existingAuthScheme.authSchemeOption().forEachSignerProperty(selectedOption::putSignerPropertyIfAbsent);
+ selectedAuthScheme = new SelectedAuthScheme<>(selectedAuthScheme.identity(), selectedAuthScheme.signer(),
+ selectedOption.build());
+ }
+ attributes.putAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME, selectedAuthScheme);
+ }
+
+ private void recordEnvironmentTokenBusinessMetric(SelectedAuthScheme selectedAuthScheme,
+ ExecutionAttributes executionAttributes) {
+ String tokenFromEnv = executionAttributes.getAttribute(SdkInternalExecutionAttribute.TOKEN_CONFIGURED_FROM_ENV);
+ if (selectedAuthScheme != null && selectedAuthScheme.authSchemeOption().schemeId().equals(BearerAuthScheme.SCHEME_ID)
+ && selectedAuthScheme.identity().isDone()) {
+ if (selectedAuthScheme.identity().getNow(null) instanceof TokenIdentity) {
+ TokenIdentity configuredToken = (TokenIdentity) selectedAuthScheme.identity().getNow(null);
+ if (configuredToken.token().equals(tokenFromEnv)) {
+ executionAttributes.getAttribute(SdkInternalExecutionAttribute.BUSINESS_METRICS).addMetric(
+ BusinessMetricFeatureId.BEARER_SERVICE_ENV_VARS.value());
+ }
+ }
+ }
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-preferred-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-preferred-provider.java
new file mode 100644
index 000000000000..279142374e6b
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-preferred-provider.java
@@ -0,0 +1,51 @@
+package software.amazon.awssdk.services.query.auth.scheme.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams;
+import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider;
+import software.amazon.awssdk.utils.CollectionUtils;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class PreferredQueryAuthSchemeProvider implements QueryAuthSchemeProvider {
+ private final QueryAuthSchemeProvider delegate;
+
+ private final List authSchemePreference;
+
+ public PreferredQueryAuthSchemeProvider(QueryAuthSchemeProvider delegate, List authSchemePreference) {
+ this.delegate = delegate;
+ this.authSchemePreference = authSchemePreference != null ? authSchemePreference : Collections.emptyList();
+ }
+
+ /**
+ * Resolve the auth schemes based on the given set of parameters.
+ */
+ @Override
+ public List resolveAuthScheme(QueryAuthSchemeParams params) {
+ List candidateAuthSchemes = delegate.resolveAuthScheme(params);
+ if (CollectionUtils.isNullOrEmpty(authSchemePreference)) {
+ return candidateAuthSchemes;
+ }
+ List authSchemes = new ArrayList<>();
+ authSchemePreference.forEach(preferredSchemeId -> {
+ candidateAuthSchemes
+ .stream()
+ .filter(candidate -> {
+ String candidateSchemeName = candidate.schemeId().contains("#") ? candidate.schemeId().split("#")[1]
+ : candidate.schemeId();
+ return candidateSchemeName.equals(preferredSchemeId);
+ }).findFirst().ifPresent(authSchemes::add);
+ });
+ candidateAuthSchemes.forEach(candidate -> {
+ if (!authSchemes.contains(candidate)) {
+ authSchemes.add(candidate);
+ }
+ });
+ return authSchemes;
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-provider.java
index a4f84dc2665a..cdbc7c4c24d0 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-provider.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-provider.java
@@ -1,18 +1,3 @@
-/*
- * 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.services.query.auth.scheme;
import java.util.List;
@@ -22,6 +7,7 @@
import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider;
import software.amazon.awssdk.services.query.auth.scheme.internal.DefaultQueryAuthSchemeProvider;
+import software.amazon.awssdk.services.query.auth.scheme.internal.PreferredQueryAuthSchemeProvider;
/**
* An auth scheme provider for Query service. The auth scheme provider takes a set of parameters using
@@ -50,4 +36,11 @@ default List resolveAuthScheme(Consumer authSchemePreference) {
+ return new PreferredQueryAuthSchemeProvider(defaultProvider(), authSchemePreference);
+ }
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-provider.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-provider.java
index a4f84dc2665a..cdbc7c4c24d0 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-provider.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-provider.java
@@ -1,18 +1,3 @@
-/*
- * 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.services.query.auth.scheme;
import java.util.List;
@@ -22,6 +7,7 @@
import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption;
import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider;
import software.amazon.awssdk.services.query.auth.scheme.internal.DefaultQueryAuthSchemeProvider;
+import software.amazon.awssdk.services.query.auth.scheme.internal.PreferredQueryAuthSchemeProvider;
/**
* An auth scheme provider for Query service. The auth scheme provider takes a set of parameters using
@@ -50,4 +36,11 @@ default List resolveAuthScheme(Consumer authSchemePreference) {
+ return new PreferredQueryAuthSchemeProvider(defaultProvider(), authSchemePreference);
+ }
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-bearer-auth-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-bearer-auth-client-builder-class.java
index 4dee534fba41..ee8f9a73d3e5 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-bearer-auth-client-builder-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-bearer-auth-client-builder-class.java
@@ -10,6 +10,7 @@
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.auth.credentials.TokenUtils;
import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
+import software.amazon.awssdk.awscore.auth.AuthSchemePreferenceResolver;
import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider;
@@ -59,14 +60,15 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c
- .option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
- .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
- .lazyOption(AwsClientOption.TOKEN_PROVIDER,
- p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
- .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider()));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config))
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .lazyOption(AwsClientOption.TOKEN_PROVIDER,
+ p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider());
+ });
}
@Override
@@ -77,7 +79,7 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new JsonRequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
@@ -93,21 +95,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
});
builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
- .serviceProfileProperty("json_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
+ .serviceProfileProperty("json_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
return builder.build();
}
@@ -126,7 +128,14 @@ public B authSchemeProvider(JsonAuthSchemeProvider authSchemeProvider) {
return thisBuilder();
}
- private JsonAuthSchemeProvider defaultAuthSchemeProvider() {
+ private JsonAuthSchemeProvider defaultAuthSchemeProvider(SdkClientConfiguration config) {
+ AuthSchemePreferenceResolver authSchemePreferenceProvider = AuthSchemePreferenceResolver.builder()
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME)).build();
+ List preferences = authSchemePreferenceProvider.resolveAuthSchemePreference();
+ if (!preferences.isEmpty()) {
+ return JsonAuthSchemeProvider.defaultProvider(preferences);
+ }
return JsonAuthSchemeProvider.defaultProvider();
}
@@ -196,6 +205,6 @@ private List internalPlugins(SdkClientConfiguration config) {
protected static void validateClientOptions(SdkClientConfiguration c) {
Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER),
- "The 'tokenProvider' must be configured in the client builder.");
+ "The 'tokenProvider' must be configured in the client builder.");
}
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-class.java
index 83b6266466fd..a0bdac67d04d 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-class.java
@@ -12,6 +12,7 @@
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.auth.credentials.TokenUtils;
import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
+import software.amazon.awssdk.awscore.auth.AuthSchemePreferenceResolver;
import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider;
@@ -70,15 +71,16 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c
- .option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
- .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
- .option(SdkClientOption.SERVICE_CONFIGURATION, ServiceConfiguration.builder().build())
- .lazyOption(AwsClientOption.TOKEN_PROVIDER,
- p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
- .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider()));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config))
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .option(SdkClientOption.SERVICE_CONFIGURATION, ServiceConfiguration.builder().build())
+ .lazyOption(AwsClientOption.TOKEN_PROVIDER,
+ p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider());
+ });
}
@Override
@@ -89,82 +91,82 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new JsonRequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS));
ServiceConfiguration.Builder serviceConfigBuilder = ((ServiceConfiguration) config
- .option(SdkClientOption.SERVICE_CONFIGURATION)).toBuilder();
+ .option(SdkClientOption.SERVICE_CONFIGURATION)).toBuilder();
serviceConfigBuilder.profileFile(serviceConfigBuilder.profileFileSupplier() != null ? serviceConfigBuilder
- .profileFileSupplier() : config.option(SdkClientOption.PROFILE_FILE_SUPPLIER));
+ .profileFileSupplier() : config.option(SdkClientOption.PROFILE_FILE_SUPPLIER));
serviceConfigBuilder.profileName(serviceConfigBuilder.profileName() != null ? serviceConfigBuilder.profileName() : config
- .option(SdkClientOption.PROFILE_NAME));
+ .option(SdkClientOption.PROFILE_NAME));
if (serviceConfigBuilder.dualstackEnabled() != null) {
Validate.validState(
- config.option(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED) == null,
- "Dualstack has been configured on both ServiceConfiguration and the client/global level. Please limit dualstack configuration to one location.");
+ config.option(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED) == null,
+ "Dualstack has been configured on both ServiceConfiguration and the client/global level. Please limit dualstack configuration to one location.");
} else {
serviceConfigBuilder.dualstackEnabled(config.option(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED));
}
if (serviceConfigBuilder.fipsModeEnabled() != null) {
Validate.validState(
- config.option(AwsClientOption.FIPS_ENDPOINT_ENABLED) == null,
- "Fips has been configured on both ServiceConfiguration and the client/global level. Please limit fips configuration to one location.");
+ config.option(AwsClientOption.FIPS_ENDPOINT_ENABLED) == null,
+ "Fips has been configured on both ServiceConfiguration and the client/global level. Please limit fips configuration to one location.");
} else {
serviceConfigBuilder.fipsModeEnabled(config.option(AwsClientOption.FIPS_ENDPOINT_ENABLED));
}
if (serviceConfigBuilder.useArnRegionEnabled() != null) {
Validate.validState(
- clientContextParams.get(JsonClientContextParams.USE_ARN_REGION) == null,
- "UseArnRegion has been configured on both ServiceConfiguration and the client/global level. Please limit UseArnRegion configuration to one location.");
+ clientContextParams.get(JsonClientContextParams.USE_ARN_REGION) == null,
+ "UseArnRegion has been configured on both ServiceConfiguration and the client/global level. Please limit UseArnRegion configuration to one location.");
} else {
serviceConfigBuilder.useArnRegionEnabled(clientContextParams.get(JsonClientContextParams.USE_ARN_REGION));
}
if (serviceConfigBuilder.multiRegionEnabled() != null) {
Validate.validState(
- clientContextParams.get(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS) == null,
- "DisableMultiRegionAccessPoints has been configured on both ServiceConfiguration and the client/global level. Please limit DisableMultiRegionAccessPoints configuration to one location.");
+ clientContextParams.get(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS) == null,
+ "DisableMultiRegionAccessPoints has been configured on both ServiceConfiguration and the client/global level. Please limit DisableMultiRegionAccessPoints configuration to one location.");
} else if (clientContextParams.get(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS) != null) {
serviceConfigBuilder.multiRegionEnabled(!clientContextParams
- .get(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS));
+ .get(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS));
}
if (serviceConfigBuilder.pathStyleAccessEnabled() != null) {
Validate.validState(
- clientContextParams.get(JsonClientContextParams.FORCE_PATH_STYLE) == null,
- "ForcePathStyle has been configured on both ServiceConfiguration and the client/global level. Please limit ForcePathStyle configuration to one location.");
+ clientContextParams.get(JsonClientContextParams.FORCE_PATH_STYLE) == null,
+ "ForcePathStyle has been configured on both ServiceConfiguration and the client/global level. Please limit ForcePathStyle configuration to one location.");
} else {
serviceConfigBuilder.pathStyleAccessEnabled(clientContextParams.get(JsonClientContextParams.FORCE_PATH_STYLE));
}
if (serviceConfigBuilder.accelerateModeEnabled() != null) {
Validate.validState(
- clientContextParams.get(JsonClientContextParams.ACCELERATE) == null,
- "Accelerate has been configured on both ServiceConfiguration and the client/global level. Please limit Accelerate configuration to one location.");
+ clientContextParams.get(JsonClientContextParams.ACCELERATE) == null,
+ "Accelerate has been configured on both ServiceConfiguration and the client/global level. Please limit Accelerate configuration to one location.");
} else {
serviceConfigBuilder.accelerateModeEnabled(clientContextParams.get(JsonClientContextParams.ACCELERATE));
}
Boolean checksumValidationEnabled = serviceConfigBuilder.checksumValidationEnabled();
if (checksumValidationEnabled != null) {
Validate.validState(
- config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION) == null,
- "Checksum behavior has been configured on both ServiceConfiguration and the client/global level. Please limit checksum behavior configuration to one location.");
+ config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION) == null,
+ "Checksum behavior has been configured on both ServiceConfiguration and the client/global level. Please limit checksum behavior configuration to one location.");
Validate.validState(
- config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION) == null,
- "Checksum behavior has been configured on both ServiceConfiguration and the client/global level. Please limit checksum behavior configuration to one location.");
+ config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION) == null,
+ "Checksum behavior has been configured on both ServiceConfiguration and the client/global level. Please limit checksum behavior configuration to one location.");
if (checksumValidationEnabled) {
config = config.toBuilder()
- .option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_SUPPORTED)
- .option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_SUPPORTED).build();
+ .option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_SUPPORTED)
+ .option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_SUPPORTED).build();
} else {
config = config.toBuilder()
- .option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_REQUIRED)
- .option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_REQUIRED).build();
+ .option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_REQUIRED)
+ .option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_REQUIRED).build();
}
}
ServiceConfiguration finalServiceConfig = serviceConfigBuilder.build();
clientContextParams.put(JsonClientContextParams.USE_ARN_REGION, finalServiceConfig.useArnRegionEnabled());
clientContextParams.put(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS,
- !finalServiceConfig.multiRegionEnabled());
+ !finalServiceConfig.multiRegionEnabled());
clientContextParams.put(JsonClientContextParams.FORCE_PATH_STYLE, finalServiceConfig.pathStyleAccessEnabled());
clientContextParams.put(JsonClientContextParams.ACCELERATE, finalServiceConfig.accelerateModeEnabled());
SdkClientConfiguration.Builder builder = config.toBuilder();
@@ -189,21 +191,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
}
builder.option(SdkClientOption.SERVICE_CONFIGURATION, finalServiceConfig);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
- .serviceProfileProperty("json_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
+ .serviceProfileProperty("json_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
SdkClientConfiguration clientConfig = config;
builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig));
@@ -225,7 +227,14 @@ public B authSchemeProvider(JsonAuthSchemeProvider authSchemeProvider) {
return thisBuilder();
}
- private JsonAuthSchemeProvider defaultAuthSchemeProvider() {
+ private JsonAuthSchemeProvider defaultAuthSchemeProvider(SdkClientConfiguration config) {
+ AuthSchemePreferenceResolver authSchemePreferenceProvider = AuthSchemePreferenceResolver.builder()
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME)).build();
+ List preferences = authSchemePreferenceProvider.resolveAuthSchemePreference();
+ if (!preferences.isEmpty()) {
+ return JsonAuthSchemeProvider.defaultProvider(preferences);
+ }
return JsonAuthSchemeProvider.defaultProvider();
}
@@ -327,9 +336,9 @@ private RequestChecksumCalculation resolveRequestChecksumCalculation(SdkClientCo
RequestChecksumCalculation configuredChecksumCalculation = config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION);
if (configuredChecksumCalculation == null) {
configuredChecksumCalculation = RequestChecksumCalculationResolver.create()
- .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(config.option(SdkClientOption.PROFILE_NAME))
- .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve();
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME))
+ .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve();
}
return configuredChecksumCalculation;
}
@@ -338,15 +347,15 @@ private ResponseChecksumValidation resolveResponseChecksumValidation(SdkClientCo
ResponseChecksumValidation configuredChecksumValidation = config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION);
if (configuredChecksumValidation == null) {
configuredChecksumValidation = ResponseChecksumValidationResolver.create()
- .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(config.option(SdkClientOption.PROFILE_NAME))
- .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve();
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME))
+ .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve();
}
return configuredChecksumValidation;
}
protected static void validateClientOptions(SdkClientConfiguration c) {
Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER),
- "The 'tokenProvider' must be configured in the client builder.");
+ "The 'tokenProvider' must be configured in the client builder.");
}
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-endpoints-auth-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-endpoints-auth-params.java
index 80511b9556ce..360d3664eaad 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-endpoints-auth-params.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-endpoints-auth-params.java
@@ -10,6 +10,7 @@
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.auth.credentials.TokenUtils;
import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
+import software.amazon.awssdk.awscore.auth.AuthSchemePreferenceResolver;
import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider;
@@ -68,14 +69,15 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c
- .option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
- .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
- .lazyOption(AwsClientOption.TOKEN_PROVIDER,
- p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
- .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider()));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config))
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .lazyOption(AwsClientOption.TOKEN_PROVIDER,
+ p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider());
+ });
}
@Override
@@ -143,7 +145,14 @@ public B authSchemeProvider(QueryAuthSchemeProvider authSchemeProvider) {
return thisBuilder();
}
- private QueryAuthSchemeProvider defaultAuthSchemeProvider() {
+ private QueryAuthSchemeProvider defaultAuthSchemeProvider(SdkClientConfiguration config) {
+ AuthSchemePreferenceResolver authSchemePreferenceProvider = AuthSchemePreferenceResolver.builder()
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME)).build();
+ List preferences = authSchemePreferenceProvider.resolveAuthSchemePreference();
+ if (!preferences.isEmpty()) {
+ return QueryAuthSchemeProvider.defaultProvider(preferences);
+ }
return QueryAuthSchemeProvider.defaultProvider();
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-internal-defaults-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-internal-defaults-class.java
index e7a2428380aa..9b143b9ccd69 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-internal-defaults-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-internal-defaults-class.java
@@ -8,6 +8,7 @@
import java.util.function.Consumer;
import software.amazon.awssdk.annotations.Generated;
import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.awscore.auth.AuthSchemePreferenceResolver;
import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider;
@@ -55,10 +56,12 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
- .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config))
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false);
+ });
}
@Override
@@ -77,7 +80,7 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new JsonRequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
@@ -93,21 +96,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
});
builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
- .serviceProfileProperty("json_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
+ .serviceProfileProperty("json_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
return builder.build();
}
@@ -126,7 +129,14 @@ public B authSchemeProvider(JsonAuthSchemeProvider authSchemeProvider) {
return thisBuilder();
}
- private JsonAuthSchemeProvider defaultAuthSchemeProvider() {
+ private JsonAuthSchemeProvider defaultAuthSchemeProvider(SdkClientConfiguration config) {
+ AuthSchemePreferenceResolver authSchemePreferenceProvider = AuthSchemePreferenceResolver.builder()
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME)).build();
+ List preferences = authSchemePreferenceProvider.resolveAuthSchemePreference();
+ if (!preferences.isEmpty()) {
+ return JsonAuthSchemeProvider.defaultProvider(preferences);
+ }
return JsonAuthSchemeProvider.defaultProvider();
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-composed-sync-default-client-builder.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-composed-sync-default-client-builder.java
index 6baf26fa580e..117e19038881 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-composed-sync-default-client-builder.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-composed-sync-default-client-builder.java
@@ -10,6 +10,7 @@
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.auth.credentials.TokenUtils;
import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
+import software.amazon.awssdk.awscore.auth.AuthSchemePreferenceResolver;
import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider;
@@ -65,15 +66,16 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c
- .option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
- .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
- .option(SdkClientOption.SERVICE_CONFIGURATION, ServiceConfiguration.builder().build())
- .lazyOption(AwsClientOption.TOKEN_PROVIDER,
- p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
- .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider()));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config))
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .option(SdkClientOption.SERVICE_CONFIGURATION, ServiceConfiguration.builder().build())
+ .lazyOption(AwsClientOption.TOKEN_PROVIDER,
+ p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider());
+ });
}
@Override
@@ -84,17 +86,17 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new JsonRequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS));
ServiceConfiguration.Builder serviceConfigBuilder = ((ServiceConfiguration) config
- .option(SdkClientOption.SERVICE_CONFIGURATION)).toBuilder();
+ .option(SdkClientOption.SERVICE_CONFIGURATION)).toBuilder();
serviceConfigBuilder.profileFile(serviceConfigBuilder.profileFileSupplier() != null ? serviceConfigBuilder
- .profileFileSupplier() : config.option(SdkClientOption.PROFILE_FILE_SUPPLIER));
+ .profileFileSupplier() : config.option(SdkClientOption.PROFILE_FILE_SUPPLIER));
serviceConfigBuilder.profileName(serviceConfigBuilder.profileName() != null ? serviceConfigBuilder.profileName() : config
- .option(SdkClientOption.PROFILE_NAME));
+ .option(SdkClientOption.PROFILE_NAME));
ServiceConfiguration finalServiceConfig = serviceConfigBuilder.build();
SdkClientConfiguration.Builder builder = config.toBuilder();
builder.lazyOption(SdkClientOption.IDENTITY_PROVIDERS, c -> {
@@ -112,21 +114,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
builder.option(SdkClientOption.SERVICE_CONFIGURATION, finalServiceConfig);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
- .serviceProfileProperty("json_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
+ .serviceProfileProperty("json_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
SdkClientConfiguration clientConfig = config;
builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig));
@@ -148,7 +150,14 @@ public B authSchemeProvider(JsonAuthSchemeProvider authSchemeProvider) {
return thisBuilder();
}
- private JsonAuthSchemeProvider defaultAuthSchemeProvider() {
+ private JsonAuthSchemeProvider defaultAuthSchemeProvider(SdkClientConfiguration config) {
+ AuthSchemePreferenceResolver authSchemePreferenceProvider = AuthSchemePreferenceResolver.builder()
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME)).build();
+ List preferences = authSchemePreferenceProvider.resolveAuthSchemePreference();
+ if (!preferences.isEmpty()) {
+ return JsonAuthSchemeProvider.defaultProvider(preferences);
+ }
return JsonAuthSchemeProvider.defaultProvider();
}
@@ -246,9 +255,9 @@ private RequestChecksumCalculation resolveRequestChecksumCalculation(SdkClientCo
RequestChecksumCalculation configuredChecksumCalculation = config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION);
if (configuredChecksumCalculation == null) {
configuredChecksumCalculation = RequestChecksumCalculationResolver.create()
- .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(config.option(SdkClientOption.PROFILE_NAME))
- .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve();
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME))
+ .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve();
}
return configuredChecksumCalculation;
}
@@ -257,15 +266,15 @@ private ResponseChecksumValidation resolveResponseChecksumValidation(SdkClientCo
ResponseChecksumValidation configuredChecksumValidation = config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION);
if (configuredChecksumValidation == null) {
configuredChecksumValidation = ResponseChecksumValidationResolver.create()
- .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(config.option(SdkClientOption.PROFILE_NAME))
- .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve();
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME))
+ .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve();
}
return configuredChecksumValidation;
}
protected static void validateClientOptions(SdkClientConfiguration c) {
Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER),
- "The 'tokenProvider' must be configured in the client builder.");
+ "The 'tokenProvider' must be configured in the client builder.");
}
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-env-bearer-token-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-env-bearer-token-client-builder-class.java
new file mode 100644
index 000000000000..48ecf08535fa
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-env-bearer-token-client-builder-class.java
@@ -0,0 +1,227 @@
+package software.amazon.awssdk.services.json;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Consumer;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.auth.credentials.TokenUtils;
+import software.amazon.awssdk.auth.token.credentials.StaticTokenProvider;
+import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
+import software.amazon.awssdk.awscore.auth.AuthSchemePreferenceResolver;
+import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
+import software.amazon.awssdk.awscore.client.config.AwsClientOption;
+import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider;
+import software.amazon.awssdk.awscore.retry.AwsRetryStrategy;
+import software.amazon.awssdk.core.SdkPlugin;
+import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
+import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
+import software.amazon.awssdk.core.client.config.SdkClientOption;
+import software.amazon.awssdk.core.interceptor.ClasspathInterceptorChainFactory;
+import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
+import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
+import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
+import software.amazon.awssdk.core.retry.RetryMode;
+import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme;
+import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme;
+import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
+import software.amazon.awssdk.identity.spi.IdentityProvider;
+import software.amazon.awssdk.identity.spi.IdentityProviders;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
+import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption;
+import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption;
+import software.amazon.awssdk.retries.api.RetryStrategy;
+import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider;
+import software.amazon.awssdk.services.json.auth.scheme.internal.JsonAuthSchemeInterceptor;
+import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider;
+import software.amazon.awssdk.services.json.endpoints.internal.JsonRequestSetEndpointInterceptor;
+import software.amazon.awssdk.services.json.endpoints.internal.JsonResolveEndpointInterceptor;
+import software.amazon.awssdk.services.json.internal.EnvironmentTokenSystemSettings;
+import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder;
+import software.amazon.awssdk.utils.CollectionUtils;
+import software.amazon.awssdk.utils.Validate;
+
+/**
+ * Internal base class for {@link DefaultJsonClientBuilder} and {@link DefaultJsonAsyncClientBuilder}.
+ */
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+abstract class DefaultJsonBaseClientBuilder, C> extends AwsDefaultClientBuilder {
+ private final Map> additionalAuthSchemes = new HashMap<>();
+
+ @Override
+ protected final String serviceEndpointPrefix() {
+ return "json-service-endpoint";
+ }
+
+ @Override
+ protected final String serviceName() {
+ return "Json";
+ }
+
+ @Override
+ protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .lazyOption(AwsClientOption.TOKEN_PROVIDER,
+ p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider());
+ Optional tokenFromEnv = new EnvironmentTokenSystemSettings().getStringValue();
+ if (tokenFromEnv.isPresent() && config.option(SdkClientOption.AUTH_SCHEME_PROVIDER) == null
+ && config.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER) == null) {
+ c.option(SdkClientOption.AUTH_SCHEME_PROVIDER,
+ JsonAuthSchemeProvider.defaultProvider(Collections.singletonList("httpBearerAuth")));
+ c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, StaticTokenProvider.create(tokenFromEnv::get));
+ c.option(
+ SdkClientOption.EXECUTION_ATTRIBUTES,
+ ExecutionAttributes.builder()
+ .put(SdkInternalExecutionAttribute.TOKEN_CONFIGURED_FROM_ENV, tokenFromEnv.get()).build());
+ } else {
+ c.option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config));
+ }
+ });
+ }
+
+ @Override
+ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) {
+ List endpointInterceptors = new ArrayList<>();
+ endpointInterceptors.add(new JsonAuthSchemeInterceptor());
+ endpointInterceptors.add(new JsonResolveEndpointInterceptor());
+ endpointInterceptors.add(new JsonRequestSetEndpointInterceptor());
+ ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
+ List interceptors = interceptorFactory
+ .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
+ List additionalInterceptors = new ArrayList<>();
+ interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
+ interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS));
+ SdkClientConfiguration.Builder builder = config.toBuilder();
+ builder.lazyOption(SdkClientOption.IDENTITY_PROVIDERS, c -> {
+ IdentityProviders.Builder result = IdentityProviders.builder();
+ IdentityProvider> tokenIdentityProvider = c.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER);
+ if (tokenIdentityProvider != null) {
+ result.putIdentityProvider(tokenIdentityProvider);
+ }
+ return result.build();
+ });
+ builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
+ builder.lazyOptionIfAbsent(
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
+ .serviceProfileProperty("json_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
+ return builder.build();
+ }
+
+ @Override
+ protected final String signingName() {
+ return "json-service";
+ }
+
+ private JsonEndpointProvider defaultEndpointProvider() {
+ return JsonEndpointProvider.defaultProvider();
+ }
+
+ public B authSchemeProvider(JsonAuthSchemeProvider authSchemeProvider) {
+ clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER, authSchemeProvider);
+ return thisBuilder();
+ }
+
+ private JsonAuthSchemeProvider defaultAuthSchemeProvider(SdkClientConfiguration config) {
+ AuthSchemePreferenceResolver authSchemePreferenceProvider = AuthSchemePreferenceResolver.builder()
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME)).build();
+ List preferences = authSchemePreferenceProvider.resolveAuthSchemePreference();
+ if (!preferences.isEmpty()) {
+ return JsonAuthSchemeProvider.defaultProvider(preferences);
+ }
+ return JsonAuthSchemeProvider.defaultProvider();
+ }
+
+ @Override
+ public B putAuthScheme(AuthScheme> authScheme) {
+ additionalAuthSchemes.put(authScheme.schemeId(), authScheme);
+ return thisBuilder();
+ }
+
+ private Map> authSchemes() {
+ Map> schemes = new HashMap<>(2 + this.additionalAuthSchemes.size());
+ BearerAuthScheme bearerAuthScheme = BearerAuthScheme.create();
+ schemes.put(bearerAuthScheme.schemeId(), bearerAuthScheme);
+ NoAuthAuthScheme noAuthAuthScheme = NoAuthAuthScheme.create();
+ schemes.put(noAuthAuthScheme.schemeId(), noAuthAuthScheme);
+ schemes.putAll(this.additionalAuthSchemes);
+ return schemes;
+ }
+
+ private IdentityProvider extends TokenIdentity> defaultTokenProvider() {
+ return DefaultAwsTokenProvider.create();
+ }
+
+ @Override
+ protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
+ List internalPlugins = internalPlugins(config);
+ List externalPlugins = plugins();
+ if (internalPlugins.isEmpty() && externalPlugins.isEmpty()) {
+ return config;
+ }
+ List plugins = CollectionUtils.mergeLists(internalPlugins, externalPlugins);
+ SdkClientConfiguration.Builder configuration = config.toBuilder();
+ JsonServiceClientConfigurationBuilder serviceConfigBuilder = new JsonServiceClientConfigurationBuilder(configuration);
+ for (SdkPlugin plugin : plugins) {
+ plugin.configureClient(serviceConfigBuilder);
+ }
+ updateRetryStrategyClientConfiguration(configuration);
+ return configuration.build();
+ }
+
+ private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) {
+ ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder();
+ RetryMode retryMode = builder.retryMode();
+ if (retryMode != null) {
+ configuration.option(SdkClientOption.RETRY_STRATEGY, AwsRetryStrategy.forRetryMode(retryMode));
+ } else {
+ Consumer> configurator = builder.retryStrategyConfigurator();
+ if (configurator != null) {
+ RetryStrategy.Builder, ?> defaultBuilder = AwsRetryStrategy.defaultRetryStrategy().toBuilder();
+ configurator.accept(defaultBuilder);
+ configuration.option(SdkClientOption.RETRY_STRATEGY, defaultBuilder.build());
+ } else {
+ RetryStrategy retryStrategy = builder.retryStrategy();
+ if (retryStrategy != null) {
+ configuration.option(SdkClientOption.RETRY_STRATEGY, retryStrategy);
+ }
+ }
+ }
+ configuration.option(SdkClientOption.CONFIGURED_RETRY_MODE, null);
+ configuration.option(SdkClientOption.CONFIGURED_RETRY_STRATEGY, null);
+ configuration.option(SdkClientOption.CONFIGURED_RETRY_CONFIGURATOR, null);
+ }
+
+ private List internalPlugins(SdkClientConfiguration config) {
+ return Collections.emptyList();
+ }
+
+ protected static void validateClientOptions(SdkClientConfiguration c) {
+ Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER),
+ "The 'tokenProvider' must be configured in the client builder.");
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-multi-auth-sigv4a-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-multi-auth-sigv4a-client-builder-class.java
index 1e5d47f1235c..75faf2cad7a8 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-multi-auth-sigv4a-client-builder-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-multi-auth-sigv4a-client-builder-class.java
@@ -8,6 +8,7 @@
import java.util.function.Consumer;
import software.amazon.awssdk.annotations.Generated;
import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.awscore.auth.AuthSchemePreferenceResolver;
import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider;
@@ -43,7 +44,7 @@
@Generated("software.amazon.awssdk:codegen")
@SdkInternalApi
abstract class DefaultDatabaseBaseClientBuilder, C> extends
- AwsDefaultClientBuilder {
+ AwsDefaultClientBuilder {
private final Map> additionalAuthSchemes = new HashMap<>();
@Override
@@ -58,10 +59,12 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
- .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config))
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false);
+ });
}
@Override
@@ -72,7 +75,7 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new DatabaseRequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/database/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/database/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
@@ -88,21 +91,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
});
builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase")
- .serviceProfileProperty("database_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase")
+ .serviceProfileProperty("database_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
return builder.build();
}
@@ -121,7 +124,14 @@ public B authSchemeProvider(DatabaseAuthSchemeProvider authSchemeProvider) {
return thisBuilder();
}
- private DatabaseAuthSchemeProvider defaultAuthSchemeProvider() {
+ private DatabaseAuthSchemeProvider defaultAuthSchemeProvider(SdkClientConfiguration config) {
+ AuthSchemePreferenceResolver authSchemePreferenceProvider = AuthSchemePreferenceResolver.builder()
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME)).build();
+ List preferences = authSchemePreferenceProvider.resolveAuthSchemePreference();
+ if (!preferences.isEmpty()) {
+ return DatabaseAuthSchemeProvider.defaultProvider(preferences);
+ }
return DatabaseAuthSchemeProvider.defaultProvider();
}
@@ -153,7 +163,7 @@ protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
List plugins = CollectionUtils.mergeLists(internalPlugins, externalPlugins);
SdkClientConfiguration.Builder configuration = config.toBuilder();
DatabaseServiceClientConfigurationBuilder serviceConfigBuilder = new DatabaseServiceClientConfigurationBuilder(
- configuration);
+ configuration);
for (SdkPlugin plugin : plugins) {
plugin.configureClient(serviceConfigBuilder);
}
@@ -193,7 +203,7 @@ protected static void validateClientOptions(SdkClientConfiguration c) {
public B sigv4aSigningRegionSet(RegionSet sigv4aSigningRegionSet) {
clientConfiguration.option(AwsClientOption.AWS_SIGV4A_SIGNING_REGION_SET,
- sigv4aSigningRegionSet == null ? Collections.emptySet() : sigv4aSigningRegionSet.asSet());
+ sigv4aSigningRegionSet == null ? Collections.emptySet() : sigv4aSigningRegionSet.asSet());
return thisBuilder();
}
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-ops-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-ops-client-builder-class.java
index 74e0b6ce2709..72d4f526bfb3 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-ops-client-builder-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-ops-client-builder-class.java
@@ -8,6 +8,9 @@
import java.util.function.Consumer;
import software.amazon.awssdk.annotations.Generated;
import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.auth.credentials.TokenUtils;
+import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
+import software.amazon.awssdk.awscore.auth.AuthSchemePreferenceResolver;
import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider;
@@ -25,6 +28,7 @@
import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme;
import software.amazon.awssdk.identity.spi.IdentityProvider;
import software.amazon.awssdk.identity.spi.IdentityProviders;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption;
import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption;
import software.amazon.awssdk.retries.api.RetryStrategy;
@@ -35,6 +39,7 @@
import software.amazon.awssdk.services.database.endpoints.internal.DatabaseResolveEndpointInterceptor;
import software.amazon.awssdk.services.database.internal.DatabaseServiceClientConfigurationBuilder;
import software.amazon.awssdk.utils.CollectionUtils;
+import software.amazon.awssdk.utils.Validate;
/**
* Internal base class for {@link DefaultDatabaseClientBuilder} and {@link DefaultDatabaseAsyncClientBuilder}.
@@ -42,7 +47,7 @@
@Generated("software.amazon.awssdk:codegen")
@SdkInternalApi
abstract class DefaultDatabaseBaseClientBuilder, C> extends
- AwsDefaultClientBuilder {
+ AwsDefaultClientBuilder {
private final Map> additionalAuthSchemes = new HashMap<>();
@Override
@@ -57,10 +62,15 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
- .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config))
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .lazyOption(AwsClientOption.TOKEN_PROVIDER,
+ p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider());
+ });
}
@Override
@@ -71,7 +81,7 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new DatabaseRequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/database/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/database/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
@@ -79,6 +89,10 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
SdkClientConfiguration.Builder builder = config.toBuilder();
builder.lazyOption(SdkClientOption.IDENTITY_PROVIDERS, c -> {
IdentityProviders.Builder result = IdentityProviders.builder();
+ IdentityProvider> tokenIdentityProvider = c.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER);
+ if (tokenIdentityProvider != null) {
+ result.putIdentityProvider(tokenIdentityProvider);
+ }
IdentityProvider> credentialsIdentityProvider = c.get(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER);
if (credentialsIdentityProvider != null) {
result.putIdentityProvider(credentialsIdentityProvider);
@@ -87,21 +101,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
});
builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase")
- .serviceProfileProperty("database_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase")
+ .serviceProfileProperty("database_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
return builder.build();
}
@@ -120,7 +134,14 @@ public B authSchemeProvider(DatabaseAuthSchemeProvider authSchemeProvider) {
return thisBuilder();
}
- private DatabaseAuthSchemeProvider defaultAuthSchemeProvider() {
+ private DatabaseAuthSchemeProvider defaultAuthSchemeProvider(SdkClientConfiguration config) {
+ AuthSchemePreferenceResolver authSchemePreferenceProvider = AuthSchemePreferenceResolver.builder()
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME)).build();
+ List preferences = authSchemePreferenceProvider.resolveAuthSchemePreference();
+ if (!preferences.isEmpty()) {
+ return DatabaseAuthSchemeProvider.defaultProvider(preferences);
+ }
return DatabaseAuthSchemeProvider.defaultProvider();
}
@@ -142,6 +163,10 @@ private Map> authSchemes() {
return schemes;
}
+ private IdentityProvider extends TokenIdentity> defaultTokenProvider() {
+ return DefaultAwsTokenProvider.create();
+ }
+
@Override
protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
List internalPlugins = internalPlugins(config);
@@ -152,7 +177,7 @@ protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
List plugins = CollectionUtils.mergeLists(internalPlugins, externalPlugins);
SdkClientConfiguration.Builder configuration = config.toBuilder();
DatabaseServiceClientConfigurationBuilder serviceConfigBuilder = new DatabaseServiceClientConfigurationBuilder(
- configuration);
+ configuration);
for (SdkPlugin plugin : plugins) {
plugin.configureClient(serviceConfigBuilder);
}
@@ -188,5 +213,7 @@ private List internalPlugins(SdkClientConfiguration config) {
}
protected static void validateClientOptions(SdkClientConfiguration c) {
+ Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER),
+ "The 'tokenProvider' must be configured in the client builder.");
}
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-service-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-service-client-builder-class.java
index 8a42dcba4138..0be9c031d828 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-service-client-builder-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-no-auth-service-client-builder-class.java
@@ -8,6 +8,7 @@
import java.util.function.Consumer;
import software.amazon.awssdk.annotations.Generated;
import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.awscore.auth.AuthSchemePreferenceResolver;
import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider;
@@ -39,7 +40,7 @@
@Generated("software.amazon.awssdk:codegen")
@SdkInternalApi
abstract class DefaultDatabaseBaseClientBuilder, C> extends
- AwsDefaultClientBuilder {
+ AwsDefaultClientBuilder {
private final Map> additionalAuthSchemes = new HashMap<>();
@Override
@@ -54,10 +55,12 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
- .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config))
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false);
+ });
}
@Override
@@ -68,7 +71,7 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new DatabaseRequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/database/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/database/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
@@ -80,21 +83,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
});
builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase")
- .serviceProfileProperty("database_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase")
+ .serviceProfileProperty("database_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
return builder.build();
}
@@ -113,7 +116,14 @@ public B authSchemeProvider(DatabaseAuthSchemeProvider authSchemeProvider) {
return thisBuilder();
}
- private DatabaseAuthSchemeProvider defaultAuthSchemeProvider() {
+ private DatabaseAuthSchemeProvider defaultAuthSchemeProvider(SdkClientConfiguration config) {
+ AuthSchemePreferenceResolver authSchemePreferenceProvider = AuthSchemePreferenceResolver.builder()
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME)).build();
+ List preferences = authSchemePreferenceProvider.resolveAuthSchemePreference();
+ if (!preferences.isEmpty()) {
+ return DatabaseAuthSchemeProvider.defaultProvider(preferences);
+ }
return DatabaseAuthSchemeProvider.defaultProvider();
}
@@ -141,7 +151,7 @@ protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
List plugins = CollectionUtils.mergeLists(internalPlugins, externalPlugins);
SdkClientConfiguration.Builder configuration = config.toBuilder();
DatabaseServiceClientConfigurationBuilder serviceConfigBuilder = new DatabaseServiceClientConfigurationBuilder(
- configuration);
+ configuration);
for (SdkPlugin plugin : plugins) {
plugin.configureClient(serviceConfigBuilder);
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-query-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-query-client-builder-class.java
index 724eb838439d..19b8d5abbae1 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-query-client-builder-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-query-client-builder-class.java
@@ -10,6 +10,7 @@
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.auth.credentials.TokenUtils;
import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
+import software.amazon.awssdk.awscore.auth.AuthSchemePreferenceResolver;
import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider;
@@ -66,14 +67,15 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c
- .option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider())
- .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
- .lazyOption(AwsClientOption.TOKEN_PROVIDER,
- p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
- .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider()));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config))
+ .option(SdkClientOption.AUTH_SCHEMES, authSchemes())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .lazyOption(AwsClientOption.TOKEN_PROVIDER,
+ p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider());
+ });
}
@Override
@@ -141,7 +143,14 @@ public B authSchemeProvider(QueryAuthSchemeProvider authSchemeProvider) {
return thisBuilder();
}
- private QueryAuthSchemeProvider defaultAuthSchemeProvider() {
+ private QueryAuthSchemeProvider defaultAuthSchemeProvider(SdkClientConfiguration config) {
+ AuthSchemePreferenceResolver authSchemePreferenceProvider = AuthSchemePreferenceResolver.builder()
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME)).build();
+ List preferences = authSchemePreferenceProvider.resolveAuthSchemePreference();
+ if (!preferences.isEmpty()) {
+ return QueryAuthSchemeProvider.defaultProvider(preferences);
+ }
return QueryAuthSchemeProvider.defaultProvider();
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-bearer-auth-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-bearer-auth-client-builder-class.java
index 9895ae765031..c7932ab9f7c6 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-bearer-auth-client-builder-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-bearer-auth-client-builder-class.java
@@ -53,13 +53,14 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c
- .option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
- .lazyOption(AwsClientOption.TOKEN_PROVIDER,
- p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
- .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider())
- .option(SdkAdvancedClientOption.TOKEN_SIGNER, defaultTokenSigner()));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .lazyOption(AwsClientOption.TOKEN_PROVIDER,
+ p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider())
+ .option(SdkAdvancedClientOption.TOKEN_SIGNER, defaultTokenSigner());
+ });
}
@Override
@@ -69,7 +70,7 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new JsonRequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
@@ -85,21 +86,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
});
builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
- .serviceProfileProperty("json_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
+ .serviceProfileProperty("json_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
return builder.build();
}
@@ -167,8 +168,8 @@ private List internalPlugins(SdkClientConfiguration config) {
protected static void validateClientOptions(SdkClientConfiguration c) {
Validate.notNull(c.option(SdkAdvancedClientOption.TOKEN_SIGNER),
- "The 'overrideConfiguration.advancedOption[TOKEN_SIGNER]' must be configured in the client builder.");
+ "The 'overrideConfiguration.advancedOption[TOKEN_SIGNER]' must be configured in the client builder.");
Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER),
- "The 'tokenProvider' must be configured in the client builder.");
+ "The 'tokenProvider' must be configured in the client builder.");
}
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-class.java
index 6013da8b2ea5..2eca7dfdcf2c 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-class.java
@@ -64,15 +64,16 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c
- .option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
- .option(SdkClientOption.SERVICE_CONFIGURATION, ServiceConfiguration.builder().build())
- .lazyOption(AwsClientOption.TOKEN_PROVIDER,
- p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
- .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider())
- .option(SdkAdvancedClientOption.TOKEN_SIGNER, defaultTokenSigner()));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .option(SdkClientOption.SERVICE_CONFIGURATION, ServiceConfiguration.builder().build())
+ .lazyOption(AwsClientOption.TOKEN_PROVIDER,
+ p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider())
+ .option(SdkAdvancedClientOption.TOKEN_SIGNER, defaultTokenSigner());
+ });
}
@Override
@@ -82,82 +83,82 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new JsonRequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS));
ServiceConfiguration.Builder serviceConfigBuilder = ((ServiceConfiguration) config
- .option(SdkClientOption.SERVICE_CONFIGURATION)).toBuilder();
+ .option(SdkClientOption.SERVICE_CONFIGURATION)).toBuilder();
serviceConfigBuilder.profileFile(serviceConfigBuilder.profileFileSupplier() != null ? serviceConfigBuilder
- .profileFileSupplier() : config.option(SdkClientOption.PROFILE_FILE_SUPPLIER));
+ .profileFileSupplier() : config.option(SdkClientOption.PROFILE_FILE_SUPPLIER));
serviceConfigBuilder.profileName(serviceConfigBuilder.profileName() != null ? serviceConfigBuilder.profileName() : config
- .option(SdkClientOption.PROFILE_NAME));
+ .option(SdkClientOption.PROFILE_NAME));
if (serviceConfigBuilder.dualstackEnabled() != null) {
Validate.validState(
- config.option(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED) == null,
- "Dualstack has been configured on both ServiceConfiguration and the client/global level. Please limit dualstack configuration to one location.");
+ config.option(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED) == null,
+ "Dualstack has been configured on both ServiceConfiguration and the client/global level. Please limit dualstack configuration to one location.");
} else {
serviceConfigBuilder.dualstackEnabled(config.option(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED));
}
if (serviceConfigBuilder.fipsModeEnabled() != null) {
Validate.validState(
- config.option(AwsClientOption.FIPS_ENDPOINT_ENABLED) == null,
- "Fips has been configured on both ServiceConfiguration and the client/global level. Please limit fips configuration to one location.");
+ config.option(AwsClientOption.FIPS_ENDPOINT_ENABLED) == null,
+ "Fips has been configured on both ServiceConfiguration and the client/global level. Please limit fips configuration to one location.");
} else {
serviceConfigBuilder.fipsModeEnabled(config.option(AwsClientOption.FIPS_ENDPOINT_ENABLED));
}
if (serviceConfigBuilder.useArnRegionEnabled() != null) {
Validate.validState(
- clientContextParams.get(JsonClientContextParams.USE_ARN_REGION) == null,
- "UseArnRegion has been configured on both ServiceConfiguration and the client/global level. Please limit UseArnRegion configuration to one location.");
+ clientContextParams.get(JsonClientContextParams.USE_ARN_REGION) == null,
+ "UseArnRegion has been configured on both ServiceConfiguration and the client/global level. Please limit UseArnRegion configuration to one location.");
} else {
serviceConfigBuilder.useArnRegionEnabled(clientContextParams.get(JsonClientContextParams.USE_ARN_REGION));
}
if (serviceConfigBuilder.multiRegionEnabled() != null) {
Validate.validState(
- clientContextParams.get(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS) == null,
- "DisableMultiRegionAccessPoints has been configured on both ServiceConfiguration and the client/global level. Please limit DisableMultiRegionAccessPoints configuration to one location.");
+ clientContextParams.get(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS) == null,
+ "DisableMultiRegionAccessPoints has been configured on both ServiceConfiguration and the client/global level. Please limit DisableMultiRegionAccessPoints configuration to one location.");
} else if (clientContextParams.get(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS) != null) {
serviceConfigBuilder.multiRegionEnabled(!clientContextParams
- .get(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS));
+ .get(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS));
}
if (serviceConfigBuilder.pathStyleAccessEnabled() != null) {
Validate.validState(
- clientContextParams.get(JsonClientContextParams.FORCE_PATH_STYLE) == null,
- "ForcePathStyle has been configured on both ServiceConfiguration and the client/global level. Please limit ForcePathStyle configuration to one location.");
+ clientContextParams.get(JsonClientContextParams.FORCE_PATH_STYLE) == null,
+ "ForcePathStyle has been configured on both ServiceConfiguration and the client/global level. Please limit ForcePathStyle configuration to one location.");
} else {
serviceConfigBuilder.pathStyleAccessEnabled(clientContextParams.get(JsonClientContextParams.FORCE_PATH_STYLE));
}
if (serviceConfigBuilder.accelerateModeEnabled() != null) {
Validate.validState(
- clientContextParams.get(JsonClientContextParams.ACCELERATE) == null,
- "Accelerate has been configured on both ServiceConfiguration and the client/global level. Please limit Accelerate configuration to one location.");
+ clientContextParams.get(JsonClientContextParams.ACCELERATE) == null,
+ "Accelerate has been configured on both ServiceConfiguration and the client/global level. Please limit Accelerate configuration to one location.");
} else {
serviceConfigBuilder.accelerateModeEnabled(clientContextParams.get(JsonClientContextParams.ACCELERATE));
}
Boolean checksumValidationEnabled = serviceConfigBuilder.checksumValidationEnabled();
if (checksumValidationEnabled != null) {
Validate.validState(
- config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION) == null,
- "Checksum behavior has been configured on both ServiceConfiguration and the client/global level. Please limit checksum behavior configuration to one location.");
+ config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION) == null,
+ "Checksum behavior has been configured on both ServiceConfiguration and the client/global level. Please limit checksum behavior configuration to one location.");
Validate.validState(
- config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION) == null,
- "Checksum behavior has been configured on both ServiceConfiguration and the client/global level. Please limit checksum behavior configuration to one location.");
+ config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION) == null,
+ "Checksum behavior has been configured on both ServiceConfiguration and the client/global level. Please limit checksum behavior configuration to one location.");
if (checksumValidationEnabled) {
config = config.toBuilder()
- .option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_SUPPORTED)
- .option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_SUPPORTED).build();
+ .option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_SUPPORTED)
+ .option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_SUPPORTED).build();
} else {
config = config.toBuilder()
- .option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_REQUIRED)
- .option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_REQUIRED).build();
+ .option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_REQUIRED)
+ .option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_REQUIRED).build();
}
}
ServiceConfiguration finalServiceConfig = serviceConfigBuilder.build();
clientContextParams.put(JsonClientContextParams.USE_ARN_REGION, finalServiceConfig.useArnRegionEnabled());
clientContextParams.put(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS,
- !finalServiceConfig.multiRegionEnabled());
+ !finalServiceConfig.multiRegionEnabled());
clientContextParams.put(JsonClientContextParams.FORCE_PATH_STYLE, finalServiceConfig.pathStyleAccessEnabled());
clientContextParams.put(JsonClientContextParams.ACCELERATE, finalServiceConfig.accelerateModeEnabled());
SdkClientConfiguration.Builder builder = config.toBuilder();
@@ -182,21 +183,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
}
builder.option(SdkClientOption.SERVICE_CONFIGURATION, finalServiceConfig);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
- .serviceProfileProperty("json_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
+ .serviceProfileProperty("json_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
SdkClientConfiguration clientConfig = config;
builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig));
@@ -301,9 +302,9 @@ private RequestChecksumCalculation resolveRequestChecksumCalculation(SdkClientCo
RequestChecksumCalculation configuredChecksumCalculation = config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION);
if (configuredChecksumCalculation == null) {
configuredChecksumCalculation = RequestChecksumCalculationResolver.create()
- .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(config.option(SdkClientOption.PROFILE_NAME))
- .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve();
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME))
+ .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve();
}
return configuredChecksumCalculation;
}
@@ -312,19 +313,19 @@ private ResponseChecksumValidation resolveResponseChecksumValidation(SdkClientCo
ResponseChecksumValidation configuredChecksumValidation = config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION);
if (configuredChecksumValidation == null) {
configuredChecksumValidation = ResponseChecksumValidationResolver.create()
- .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(config.option(SdkClientOption.PROFILE_NAME))
- .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve();
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME))
+ .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve();
}
return configuredChecksumValidation;
}
protected static void validateClientOptions(SdkClientConfiguration c) {
Validate.notNull(c.option(SdkAdvancedClientOption.SIGNER),
- "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder.");
+ "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder.");
Validate.notNull(c.option(SdkAdvancedClientOption.TOKEN_SIGNER),
- "The 'overrideConfiguration.advancedOption[TOKEN_SIGNER]' must be configured in the client builder.");
+ "The 'overrideConfiguration.advancedOption[TOKEN_SIGNER]' must be configured in the client builder.");
Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER),
- "The 'tokenProvider' must be configured in the client builder.");
+ "The 'tokenProvider' must be configured in the client builder.");
}
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-endpoints-auth-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-endpoints-auth-params.java
index 52c27dfcc8ac..4a8a346f1c76 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-endpoints-auth-params.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-endpoints-auth-params.java
@@ -61,14 +61,15 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c
- .option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
- .lazyOption(AwsClientOption.TOKEN_PROVIDER,
- p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
- .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider())
- .option(SdkAdvancedClientOption.TOKEN_SIGNER, defaultTokenSigner()));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .lazyOption(AwsClientOption.TOKEN_PROVIDER,
+ p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider())
+ .option(SdkAdvancedClientOption.TOKEN_SIGNER, defaultTokenSigner());
+ });
}
@Override
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-internal-defaults-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-internal-defaults-class.java
index 12dec5b9986d..4f1e5bbd8e0d 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-internal-defaults-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-internal-defaults-class.java
@@ -50,9 +50,11 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false);
+ });
}
@Override
@@ -70,7 +72,7 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new JsonRequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
@@ -86,21 +88,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
});
builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
- .serviceProfileProperty("json_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
+ .serviceProfileProperty("json_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
return builder.build();
}
@@ -164,6 +166,6 @@ private List internalPlugins(SdkClientConfiguration config) {
protected static void validateClientOptions(SdkClientConfiguration c) {
Validate.notNull(c.option(SdkAdvancedClientOption.SIGNER),
- "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder.");
+ "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder.");
}
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-sync-default-client-builder.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-sync-default-client-builder.java
index 52f9d10e821f..778b676c4975 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-sync-default-client-builder.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-sync-default-client-builder.java
@@ -59,15 +59,16 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c
- .option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
- .option(SdkClientOption.SERVICE_CONFIGURATION, ServiceConfiguration.builder().build())
- .lazyOption(AwsClientOption.TOKEN_PROVIDER,
- p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
- .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider())
- .option(SdkAdvancedClientOption.TOKEN_SIGNER, defaultTokenSigner()));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .option(SdkClientOption.SERVICE_CONFIGURATION, ServiceConfiguration.builder().build())
+ .lazyOption(AwsClientOption.TOKEN_PROVIDER,
+ p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider())
+ .option(SdkAdvancedClientOption.TOKEN_SIGNER, defaultTokenSigner());
+ });
}
@Override
@@ -77,17 +78,17 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new JsonRequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/json/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS));
ServiceConfiguration.Builder serviceConfigBuilder = ((ServiceConfiguration) config
- .option(SdkClientOption.SERVICE_CONFIGURATION)).toBuilder();
+ .option(SdkClientOption.SERVICE_CONFIGURATION)).toBuilder();
serviceConfigBuilder.profileFile(serviceConfigBuilder.profileFileSupplier() != null ? serviceConfigBuilder
- .profileFileSupplier() : config.option(SdkClientOption.PROFILE_FILE_SUPPLIER));
+ .profileFileSupplier() : config.option(SdkClientOption.PROFILE_FILE_SUPPLIER));
serviceConfigBuilder.profileName(serviceConfigBuilder.profileName() != null ? serviceConfigBuilder.profileName() : config
- .option(SdkClientOption.PROFILE_NAME));
+ .option(SdkClientOption.PROFILE_NAME));
ServiceConfiguration finalServiceConfig = serviceConfigBuilder.build();
SdkClientConfiguration.Builder builder = config.toBuilder();
builder.lazyOption(SdkClientOption.IDENTITY_PROVIDERS, c -> {
@@ -105,21 +106,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
builder.option(SdkClientOption.SERVICE_CONFIGURATION, finalServiceConfig);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
- .serviceProfileProperty("json_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson")
+ .serviceProfileProperty("json_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
SdkClientConfiguration clientConfig = config;
builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig));
@@ -220,9 +221,9 @@ private RequestChecksumCalculation resolveRequestChecksumCalculation(SdkClientCo
RequestChecksumCalculation configuredChecksumCalculation = config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION);
if (configuredChecksumCalculation == null) {
configuredChecksumCalculation = RequestChecksumCalculationResolver.create()
- .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(config.option(SdkClientOption.PROFILE_NAME))
- .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve();
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME))
+ .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve();
}
return configuredChecksumCalculation;
}
@@ -231,19 +232,19 @@ private ResponseChecksumValidation resolveResponseChecksumValidation(SdkClientCo
ResponseChecksumValidation configuredChecksumValidation = config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION);
if (configuredChecksumValidation == null) {
configuredChecksumValidation = ResponseChecksumValidationResolver.create()
- .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(config.option(SdkClientOption.PROFILE_NAME))
- .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve();
+ .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(config.option(SdkClientOption.PROFILE_NAME))
+ .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve();
}
return configuredChecksumValidation;
}
protected static void validateClientOptions(SdkClientConfiguration c) {
Validate.notNull(c.option(SdkAdvancedClientOption.SIGNER),
- "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder.");
+ "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder.");
Validate.notNull(c.option(SdkAdvancedClientOption.TOKEN_SIGNER),
- "The 'overrideConfiguration.advancedOption[TOKEN_SIGNER]' must be configured in the client builder.");
+ "The 'overrideConfiguration.advancedOption[TOKEN_SIGNER]' must be configured in the client builder.");
Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER),
- "The 'tokenProvider' must be configured in the client builder.");
+ "The 'tokenProvider' must be configured in the client builder.");
}
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-service-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-service-client-builder-class.java
index ddd2b3427e71..eb724ba82245 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-service-client-builder-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-service-client-builder-class.java
@@ -54,9 +54,11 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false);
+ });
}
@Override
@@ -66,7 +68,7 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new H2RequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/h2/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/h2/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
@@ -82,21 +84,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
});
builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_H2_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlH2")
- .serviceProfileProperty("h2_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_H2_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlH2")
+ .serviceProfileProperty("h2_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
return builder.build();
}
@@ -118,7 +120,7 @@ private H2EndpointProvider defaultEndpointProvider() {
protected final AttributeMap serviceHttpConfig() {
AttributeMap result = AttributeMap.empty();
return result.merge(AttributeMap.builder().put(SdkHttpConfigurationOption.PROTOCOL, Protocol.HTTP2)
- .put(SdkHttpConfigurationOption.PROTOCOL_NEGOTIATION, ProtocolNegotiation.ALPN).build());
+ .put(SdkHttpConfigurationOption.PROTOCOL_NEGOTIATION, ProtocolNegotiation.ALPN).build());
}
@Override
@@ -167,6 +169,6 @@ private List internalPlugins(SdkClientConfiguration config) {
protected static void validateClientOptions(SdkClientConfiguration c) {
Validate.notNull(c.option(SdkAdvancedClientOption.SIGNER),
- "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder.");
+ "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder.");
}
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-usePriorKnowledgeForH2-service-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-usePriorKnowledgeForH2-service-client-builder-class.java
index a296652d9b41..a9dcec96847e 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-usePriorKnowledgeForH2-service-client-builder-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-usePriorKnowledgeForH2-service-client-builder-class.java
@@ -53,9 +53,11 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false);
+ });
}
@Override
@@ -65,7 +67,7 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new H2RequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/h2/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/h2/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
@@ -81,21 +83,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
});
builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_H2_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlH2")
- .serviceProfileProperty("h2_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_H2_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlH2")
+ .serviceProfileProperty("h2_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
return builder.build();
}
@@ -165,6 +167,6 @@ private List internalPlugins(SdkClientConfiguration config) {
protected static void validateClientOptions(SdkClientConfiguration c) {
Validate.notNull(c.option(SdkAdvancedClientOption.SIGNER),
- "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder.");
+ "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder.");
}
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-ops-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-ops-client-builder-class.java
index 4c7699ac4c6d..5ec8c0facf9a 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-ops-client-builder-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-ops-client-builder-class.java
@@ -6,7 +6,10 @@
import java.util.function.Consumer;
import software.amazon.awssdk.annotations.Generated;
import software.amazon.awssdk.annotations.SdkInternalApi;
+import software.amazon.awssdk.auth.credentials.TokenUtils;
import software.amazon.awssdk.auth.signer.Aws4Signer;
+import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider;
+import software.amazon.awssdk.auth.token.signer.aws.BearerTokenSigner;
import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder;
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider;
@@ -22,6 +25,7 @@
import software.amazon.awssdk.core.signer.Signer;
import software.amazon.awssdk.identity.spi.IdentityProvider;
import software.amazon.awssdk.identity.spi.IdentityProviders;
+import software.amazon.awssdk.identity.spi.TokenIdentity;
import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption;
import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption;
import software.amazon.awssdk.retries.api.RetryStrategy;
@@ -38,7 +42,7 @@
@Generated("software.amazon.awssdk:codegen")
@SdkInternalApi
abstract class DefaultDatabaseBaseClientBuilder, C> extends
- AwsDefaultClientBuilder {
+ AwsDefaultClientBuilder {
@Override
protected final String serviceEndpointPrefix() {
return "database-service-endpoint";
@@ -51,9 +55,15 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .lazyOption(AwsClientOption.TOKEN_PROVIDER,
+ p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider())
+ .option(SdkAdvancedClientOption.TOKEN_SIGNER, defaultTokenSigner());
+ });
}
@Override
@@ -63,7 +73,7 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new DatabaseRequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/database/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/database/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
@@ -71,6 +81,10 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
SdkClientConfiguration.Builder builder = config.toBuilder();
builder.lazyOption(SdkClientOption.IDENTITY_PROVIDERS, c -> {
IdentityProviders.Builder result = IdentityProviders.builder();
+ IdentityProvider> tokenIdentityProvider = c.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER);
+ if (tokenIdentityProvider != null) {
+ result.putIdentityProvider(tokenIdentityProvider);
+ }
IdentityProvider> credentialsIdentityProvider = c.get(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER);
if (credentialsIdentityProvider != null) {
result.putIdentityProvider(credentialsIdentityProvider);
@@ -79,21 +93,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
});
builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase")
- .serviceProfileProperty("database_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase")
+ .serviceProfileProperty("database_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
return builder.build();
}
@@ -111,6 +125,14 @@ private DatabaseEndpointProvider defaultEndpointProvider() {
return DatabaseEndpointProvider.defaultProvider();
}
+ private IdentityProvider extends TokenIdentity> defaultTokenProvider() {
+ return DefaultAwsTokenProvider.create();
+ }
+
+ private Signer defaultTokenSigner() {
+ return BearerTokenSigner.create();
+ }
+
@Override
protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
List internalPlugins = internalPlugins(config);
@@ -121,7 +143,7 @@ protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
List plugins = CollectionUtils.mergeLists(internalPlugins, externalPlugins);
SdkClientConfiguration.Builder configuration = config.toBuilder();
DatabaseServiceClientConfigurationBuilder serviceConfigBuilder = new DatabaseServiceClientConfigurationBuilder(
- configuration);
+ configuration);
for (SdkPlugin plugin : plugins) {
plugin.configureClient(serviceConfigBuilder);
}
@@ -158,6 +180,10 @@ private List internalPlugins(SdkClientConfiguration config) {
protected static void validateClientOptions(SdkClientConfiguration c) {
Validate.notNull(c.option(SdkAdvancedClientOption.SIGNER),
- "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder.");
+ "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder.");
+ Validate.notNull(c.option(SdkAdvancedClientOption.TOKEN_SIGNER),
+ "The 'overrideConfiguration.advancedOption[TOKEN_SIGNER]' must be configured in the client builder.");
+ Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER),
+ "The 'tokenProvider' must be configured in the client builder.");
}
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-service-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-service-client-builder-class.java
index a5aedee94c63..6a8e2290d918 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-service-client-builder-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-service-client-builder-class.java
@@ -33,7 +33,7 @@
@Generated("software.amazon.awssdk:codegen")
@SdkInternalApi
abstract class DefaultDatabaseBaseClientBuilder, C> extends
- AwsDefaultClientBuilder {
+ AwsDefaultClientBuilder {
@Override
protected final String serviceEndpointPrefix() {
return "database-service-endpoint";
@@ -46,8 +46,10 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider()).option(
- SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider()).option(
+ SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false);
+ });
}
@Override
@@ -57,7 +59,7 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
endpointInterceptors.add(new DatabaseRequestSetEndpointInterceptor());
ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory();
List interceptors = interceptorFactory
- .getInterceptors("software/amazon/awssdk/services/database/execution.interceptors");
+ .getInterceptors("software/amazon/awssdk/services/database/execution.interceptors");
List additionalInterceptors = new ArrayList<>();
interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors);
interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors);
@@ -69,21 +71,21 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
});
builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors);
builder.lazyOptionIfAbsent(
- SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
- c -> AwsClientEndpointProvider
- .builder()
- .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE")
- .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase")
- .serviceProfileProperty("database_service")
- .serviceEndpointPrefix(serviceEndpointPrefix())
- .defaultProtocol("https")
- .region(c.get(AwsClientOption.AWS_REGION))
- .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
- .profileName(c.get(SdkClientOption.PROFILE_NAME))
- .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
- c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
- .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
- .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
+ SdkClientOption.CLIENT_ENDPOINT_PROVIDER,
+ c -> AwsClientEndpointProvider
+ .builder()
+ .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE")
+ .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase")
+ .serviceProfileProperty("database_service")
+ .serviceEndpointPrefix(serviceEndpointPrefix())
+ .defaultProtocol("https")
+ .region(c.get(AwsClientOption.AWS_REGION))
+ .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER))
+ .profileName(c.get(SdkClientOption.PROFILE_NAME))
+ .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,
+ c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))
+ .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED))
+ .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build());
builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true);
return builder.build();
}
@@ -107,7 +109,7 @@ protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) {
List plugins = CollectionUtils.mergeLists(internalPlugins, externalPlugins);
SdkClientConfiguration.Builder configuration = config.toBuilder();
DatabaseServiceClientConfigurationBuilder serviceConfigBuilder = new DatabaseServiceClientConfigurationBuilder(
- configuration);
+ configuration);
for (SdkPlugin plugin : plugins) {
plugin.configureClient(serviceConfigBuilder);
}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-query-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-query-client-builder-class.java
index df04abcb8bef..2ef919b3671f 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-query-client-builder-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-query-client-builder-class.java
@@ -60,14 +60,15 @@ protected final String serviceName() {
@Override
protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) {
- return config.merge(c -> c
- .option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
- .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
- .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
- .lazyOption(AwsClientOption.TOKEN_PROVIDER,
- p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
- .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider())
- .option(SdkAdvancedClientOption.TOKEN_SIGNER, defaultTokenSigner()));
+ return config.merge(c -> {
+ c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider())
+ .option(SdkAdvancedClientOption.SIGNER, defaultSigner())
+ .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false)
+ .lazyOption(AwsClientOption.TOKEN_PROVIDER,
+ p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER)))
+ .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider())
+ .option(SdkAdvancedClientOption.TOKEN_SIGNER, defaultTokenSigner());
+ });
}
@Override
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/json-bearer-auth/customization-env-bearer-token.config b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/json-bearer-auth/customization-env-bearer-token.config
new file mode 100644
index 000000000000..2edb12c857bc
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/json-bearer-auth/customization-env-bearer-token.config
@@ -0,0 +1,3 @@
+{
+ "enableEnvironmentBearerToken": true
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/customization-uri-cache.config b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/customization-uri-cache.config
new file mode 100644
index 000000000000..75393cba13cf
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/customization-uri-cache.config
@@ -0,0 +1,37 @@
+{
+ "authPolicyActions" : {
+ "skip" : true
+ },
+ "skipEndpointTests": {
+ "test case 4": "Does not work"
+ },
+ "endpointParameters": {
+ "CustomEndpointArray": {
+ "required": false,
+ "documentation": "Parameter from the customization config",
+ "type": "StringArray"
+ },
+ "ArnList": {
+ "required": false,
+ "documentation": "Parameter from the customization config",
+ "type": "StringArray"
+ }
+ },
+ "customOperationContextParams": [
+ {
+ "operationName": "OperationWithCustomizedOperationContextParam",
+ "operationContextParamsMap": {
+ "customEndpointArray": {
+ "path": "ListMember.StringList[*].LeafString"
+ }
+ }
+ }
+ ],
+ "preClientExecutionRequestCustomizer": {
+ "OperationWithCustomMember": {
+ "methodName": "dummyRequestModifier",
+ "className": "software.amazon.awssdk.codegen.internal.UtilsTest"
+ }
+ },
+ "enableEndpointProviderUriCaching": true
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-rule-set-unknown-properties.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-rule-set-unknown-properties.json
new file mode 100644
index 000000000000..ddc397230298
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-rule-set-unknown-properties.json
@@ -0,0 +1,46 @@
+{
+ "version": "1.0",
+ "parameters": {
+ "Endpoint": {
+ "builtIn": "SDK::Endpoint",
+ "required": false,
+ "documentation": "Override the endpoint used to send this request",
+ "type": "String"
+ }
+ },
+ "rules": [
+ {
+ "conditions": [
+ {
+ "fn": "isSet",
+ "argv": [
+ {
+ "ref": "Endpoint"
+ }
+ ]
+ }
+ ],
+ "rules": [
+ {
+ "conditions": [],
+ "endpoint": {
+ "url": {
+ "ref": "Endpoint"
+ },
+ "properties": {
+ "unknownProperty": "value"
+ },
+ "headers": {}
+ },
+ "type": "endpoint"
+ }
+ ],
+ "type": "tree"
+ },
+ {
+ "conditions": [],
+ "error": "Invalid Configuration: Missing Endpoint",
+ "type": "error"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/rpcv2/service-2.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/rpcv2/service-2.json
index 7120326e77ec..d9c2b68b4b6e 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/rpcv2/service-2.json
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/rpcv2/service-2.json
@@ -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",
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/specs/test-service-version-info-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/specs/test-service-version-info-class.java
new file mode 100644
index 000000000000..ab582d908e73
--- /dev/null
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/specs/test-service-version-info-class.java
@@ -0,0 +1,17 @@
+package software.amazon.awssdk.services.json.internal;
+
+import java.lang.String;
+import software.amazon.awssdk.annotations.Generated;
+import software.amazon.awssdk.annotations.SdkInternalApi;
+
+@Generated("software.amazon.awssdk:codegen")
+@SdkInternalApi
+public final class ServiceVersionInfo {
+ /**
+ * Returns the current version for the AWS SDK in which this class is running.
+ */
+ public static final String VERSION = "{{VERSION}}";
+
+ private ServiceVersionInfo() {
+ }
+}
diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-aws-json-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-aws-json-async-client-class.java
index 7298068aa6ad..62fc9a6420b1 100644
--- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-aws-json-async-client-class.java
+++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-aws-json-async-client-class.java
@@ -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.ServiceVersionInfo;
import software.amazon.awssdk.services.json.model.APostOperationRequest;
import software.amazon.awssdk.services.json.model.APostOperationResponse;
import software.amazon.awssdk.services.json.model.APostOperationWithOutputRequest;
@@ -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, "Json_Service" + "#" + ServiceVersionInfo.VERSION).build();
this.protocolFactory = init(AwsJsonProtocolFactory.builder()).build();
this.executor = clientConfiguration.option(SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR);
}
@@ -189,9 +191,23 @@ public CompletableFuture aPostOperation(APostOperationRe
HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(
operationMetadata, APostOperationResponse::builder);
-
+ Function> exceptionMetadataMapper = errorCode -> {
+ if (errorCode == null) {
+ return Optional.empty();
+ }
+ switch (errorCode) {
+ case "InvalidInputException":
+ return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400)
+ .exceptionBuilderSupplier(InvalidInputException::builder).build());
+ case "ServiceFaultException":
+ return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500)
+ .exceptionBuilderSupplier(ServiceFaultException::builder).build());
+ default:
+ return Optional.empty();
+ }
+ };
HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory,
- operationMetadata);
+ operationMetadata, exceptionMetadataMapper);
String hostPrefix = "{StringMember}-foo.";
HostnameValidator.validateHostnameCompliant(aPostOperationRequest.stringMember(), "StringMember",
"aPostOperationRequest");
@@ -257,9 +273,23 @@ public CompletableFuture aPostOperationWithOut
HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(
operationMetadata, APostOperationWithOutputResponse::builder);
-
+ Function> exceptionMetadataMapper = errorCode -> {
+ if (errorCode == null) {
+ return Optional.empty();
+ }
+ switch (errorCode) {
+ case "InvalidInputException":
+ return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400)
+ .exceptionBuilderSupplier(InvalidInputException::builder).build());
+ case "ServiceFaultException":
+ return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500)
+ .exceptionBuilderSupplier(ServiceFaultException::builder).build());
+ default:
+ return Optional.empty();
+ }
+ };
HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory,
- operationMetadata);
+ operationMetadata, exceptionMetadataMapper);
CompletableFuture executeFuture = clientHandler
.execute(new ClientExecutionParams()
@@ -338,8 +368,23 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest
HttpResponseHandler errorEventResponseHandler = createErrorResponseHandler(protocolFactory,
operationMetadata, eventstreamExceptionMetadataMapper);
+ Function> exceptionMetadataMapper = errorCode -> {
+ if (errorCode == null) {
+ return Optional.empty();
+ }
+ switch (errorCode) {
+ case "InvalidInputException":
+ return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400)
+ .exceptionBuilderSupplier(InvalidInputException::builder).build());
+ case "ServiceFaultException":
+ return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500)
+ .exceptionBuilderSupplier(ServiceFaultException::builder).build());
+ default:
+ return Optional.empty();
+ }
+ };
HttpResponseHandler