24
24
import software .amazon .awssdk .annotations .SdkInternalApi ;
25
25
import software .amazon .awssdk .core .SdkField ;
26
26
import software .amazon .awssdk .core .SdkPojo ;
27
+ import software .amazon .awssdk .core .exception .SdkClientException ;
27
28
import software .amazon .awssdk .services .s3 .model .AbortMultipartUploadRequest ;
28
29
import software .amazon .awssdk .services .s3 .model .ChecksumType ;
29
30
import software .amazon .awssdk .services .s3 .model .CompleteMultipartUploadRequest ;
@@ -53,12 +54,104 @@ public final class SdkPojoConversionUtils {
53
54
new HashSet <>(Arrays .asList ("ChecksumSHA1" , "ChecksumSHA256" , "ContentMD5" , "ChecksumCRC32C" , "ChecksumCRC32" ,
54
55
"ChecksumCRC64NVME" , "ContentLength" ));
55
56
57
+ private static final Set <String > PUT_OBJECT_TO_UPLOAD_PART_ALLOWED_FIELDS = new HashSet <>(Arrays .asList (
58
+ "ACL" ,
59
+ "Bucket" ,
60
+ "CacheControl" ,
61
+ "ContentDisposition" ,
62
+ "ContentEncoding" ,
63
+ "ContentLanguage" ,
64
+ "ContentLength" ,
65
+ "ContentMD5" ,
66
+ "ContentType" ,
67
+ "ChecksumAlgorithm" ,
68
+ "ChecksumCRC32" ,
69
+ "ChecksumCRC32C" ,
70
+ "ChecksumCRC64NVME" ,
71
+ "ChecksumSHA1" ,
72
+ "ChecksumSHA256" ,
73
+ "Expires" ,
74
+ "IfMatch" ,
75
+ "IfNoneMatch" ,
76
+ "GrantFullControl" ,
77
+ "GrantRead" ,
78
+ "GrantReadACP" ,
79
+ "GrantWriteACP" ,
80
+ "Key" ,
81
+ "WriteOffsetBytes" ,
82
+ "Metadata" ,
83
+ "ServerSideEncryption" ,
84
+ "StorageClass" ,
85
+ "WebsiteRedirectLocation" ,
86
+ "SSECustomerAlgorithm" ,
87
+ "SSECustomerKey" ,
88
+ "SSECustomerKeyMD5" ,
89
+ "SSEKMSKeyId" ,
90
+ "SSEKMSEncryptionContext" ,
91
+ "BucketKeyEnabled" ,
92
+ "RequestPayer" ,
93
+ "Tagging" ,
94
+ "ObjectLockMode" ,
95
+ "ObjectLockRetainUntilDate" ,
96
+ "ObjectLockLegalHoldStatus" ,
97
+ "ExpectedBucketOwner"
98
+ ));
99
+
100
+ private static final Set <String > COPY_OBJECT_TO_COPY_OBJECT_ALLOWED_FIELDS = new HashSet <>(Arrays .asList (
101
+ "ACL" ,
102
+ "CacheControl" ,
103
+ "ChecksumAlgorithm" ,
104
+ "ContentDisposition" ,
105
+ "ContentEncoding" ,
106
+ "ContentLanguage" ,
107
+ "ContentType" ,
108
+ "CopySource" ,
109
+ "CopySourceIfMatch" ,
110
+ "CopySourceIfModifiedSince" ,
111
+ "CopySourceIfNoneMatch" ,
112
+ "CopySourceIfUnmodifiedSince" ,
113
+ "CopySourceSSECustomerAlgorithm" ,
114
+ "CopySourceSSECustomerKey" ,
115
+ "CopySourceSSECustomerKeyMD5" ,
116
+ "DestinationBucket" ,
117
+ "DestinationKey" ,
118
+ "Expires" ,
119
+ "GrantFullControl" ,
120
+ "GrantRead" ,
121
+ "GrantReadACP" ,
122
+ "GrantWriteACP" ,
123
+ "Metadata" ,
124
+ "MetadataDirective" ,
125
+ "TaggingDirective" ,
126
+ "ServerSideEncryption" ,
127
+ "SourceBucket" ,
128
+ "SourceKey" ,
129
+ "SourceVersionId" ,
130
+ "StorageClass" ,
131
+ "WebsiteRedirectLocation" ,
132
+ "SSECustomerAlgorithm" ,
133
+ "SSECustomerKey" ,
134
+ "SSECustomerKeyMD5" ,
135
+ "SSEKMSKeyId" ,
136
+ "SSEKMSEncryptionContext" ,
137
+ "BucketKeyEnabled" ,
138
+ "RequestPayer" ,
139
+ "Tagging" ,
140
+ "ObjectLockMode" ,
141
+ "ObjectLockRetainUntilDate" ,
142
+ "ObjectLockLegalHoldStatus" ,
143
+ "ExpectedBucketOwner" ,
144
+ "ExpectedSourceBucketOwner"
145
+ ));
146
+
147
+
56
148
private SdkPojoConversionUtils () {
57
149
}
58
150
59
151
public static UploadPartRequest toUploadPartRequest (PutObjectRequest putObjectRequest , int partNumber , String uploadId ) {
60
152
61
153
UploadPartRequest .Builder builder = UploadPartRequest .builder ();
154
+ validateRequestFields (putObjectRequest , PUT_OBJECT_TO_UPLOAD_PART_ALLOWED_FIELDS );
62
155
setSdkFields (builder , putObjectRequest , PUT_OBJECT_REQUEST_TO_UPLOAD_PART_FIELDS_TO_IGNORE );
63
156
return builder .uploadId (uploadId ).partNumber (partNumber ).build ();
64
157
}
@@ -67,6 +160,7 @@ public static CompleteMultipartUploadRequest toCompleteMultipartUploadRequest(Pu
67
160
String uploadId , CompletedPart [] parts ,
68
161
long contentLength ) {
69
162
CompleteMultipartUploadRequest .Builder builder = CompleteMultipartUploadRequest .builder ();
163
+ validateRequestFields (putObjectRequest , PUT_OBJECT_TO_UPLOAD_PART_ALLOWED_FIELDS );
70
164
setSdkFields (builder , putObjectRequest );
71
165
72
166
builder .mpuObjectSize (contentLength );
@@ -81,6 +175,7 @@ public static CompleteMultipartUploadRequest toCompleteMultipartUploadRequest(Pu
81
175
public static CreateMultipartUploadRequest toCreateMultipartUploadRequest (PutObjectRequest putObjectRequest ) {
82
176
83
177
CreateMultipartUploadRequest .Builder builder = CreateMultipartUploadRequest .builder ();
178
+ validateRequestFields (putObjectRequest , PUT_OBJECT_TO_UPLOAD_PART_ALLOWED_FIELDS );
84
179
setSdkFields (builder , putObjectRequest );
85
180
86
181
if (S3ChecksumUtils .checksumValueSpecified (putObjectRequest )) {
@@ -130,29 +225,14 @@ public static CompletedPart toCompletedPart(Part part) {
130
225
131
226
public static ListPartsRequest toListPartsRequest (String uploadId , PutObjectRequest putObjectRequest ) {
132
227
ListPartsRequest .Builder builder = ListPartsRequest .builder ();
228
+ validateRequestFields (putObjectRequest , PUT_OBJECT_TO_UPLOAD_PART_ALLOWED_FIELDS );
133
229
setSdkFields (builder , putObjectRequest );
134
230
return builder .uploadId (uploadId ).build ();
135
231
}
136
232
137
- private static void setSdkFields (SdkPojo targetBuilder , SdkPojo sourceObject ) {
138
- setSdkFields (targetBuilder , sourceObject , new HashSet <>());
139
- }
140
-
141
- private static void setSdkFields (SdkPojo targetBuilder , SdkPojo sourceObject , Set <String > fieldsToIgnore ) {
142
- Map <String , Object > sourceFields = retrieveSdkFields (sourceObject , sourceObject .sdkFields ());
143
- List <SdkField <?>> targetSdkFields = targetBuilder .sdkFields ();
144
-
145
- for (SdkField <?> field : targetSdkFields ) {
146
- if (fieldsToIgnore .contains (field .memberName ())) {
147
- continue ;
148
- }
149
- field .set (targetBuilder , sourceFields .getOrDefault (field .memberName (), null ));
150
- }
151
- }
152
-
153
233
public static CreateMultipartUploadRequest toCreateMultipartUploadRequest (CopyObjectRequest copyObjectRequest ) {
154
234
CreateMultipartUploadRequest .Builder builder = CreateMultipartUploadRequest .builder ();
155
-
235
+ validateRequestFields ( copyObjectRequest , COPY_OBJECT_TO_COPY_OBJECT_ALLOWED_FIELDS );
156
236
setSdkFields (builder , copyObjectRequest );
157
237
builder .bucket (copyObjectRequest .destinationBucket ());
158
238
builder .key (copyObjectRequest .destinationKey ());
@@ -180,6 +260,7 @@ private static CopyObjectResult toCopyObjectResult(CompleteMultipartUploadRespon
180
260
181
261
public static AbortMultipartUploadRequest .Builder toAbortMultipartUploadRequest (CopyObjectRequest copyObjectRequest ) {
182
262
AbortMultipartUploadRequest .Builder builder = AbortMultipartUploadRequest .builder ();
263
+ validateRequestFields (copyObjectRequest , COPY_OBJECT_TO_COPY_OBJECT_ALLOWED_FIELDS );
183
264
setSdkFields (builder , copyObjectRequest );
184
265
builder .bucket (copyObjectRequest .destinationBucket ());
185
266
builder .key (copyObjectRequest .destinationKey ());
@@ -188,6 +269,7 @@ public static AbortMultipartUploadRequest.Builder toAbortMultipartUploadRequest(
188
269
189
270
public static AbortMultipartUploadRequest .Builder toAbortMultipartUploadRequest (PutObjectRequest putObjectRequest ) {
190
271
AbortMultipartUploadRequest .Builder builder = AbortMultipartUploadRequest .builder ();
272
+ validateRequestFields (putObjectRequest , PUT_OBJECT_TO_UPLOAD_PART_ALLOWED_FIELDS );
191
273
setSdkFields (builder , putObjectRequest );
192
274
return builder ;
193
275
}
@@ -225,4 +307,40 @@ private static Map<String, Object> retrieveSdkFields(SdkPojo sourceObject, List<
225
307
field .getValueOrDefault (sourceObject )),
226
308
Map ::putAll );
227
309
}
310
+
311
+ private static void setSdkFields (SdkPojo targetBuilder , SdkPojo sourceObject ) {
312
+ setSdkFields (targetBuilder , sourceObject , new HashSet <>());
313
+ }
314
+
315
+ private static void setSdkFields (SdkPojo targetBuilder , SdkPojo sourceObject , Set <String > fieldsToIgnore ) {
316
+ Map <String , Object > sourceFields = retrieveSdkFields (sourceObject , sourceObject .sdkFields ());
317
+ List <SdkField <?>> targetSdkFields = targetBuilder .sdkFields ();
318
+
319
+ for (SdkField <?> field : targetSdkFields ) {
320
+ if (fieldsToIgnore .contains (field .memberName ())) {
321
+ continue ;
322
+ }
323
+ field .set (targetBuilder , sourceFields .getOrDefault (field .memberName (), null ));
324
+ }
325
+ }
326
+
327
+ private static void validateRequestFields (SdkPojo sourceObject , Set <String > allowedFields ) {
328
+ Set <String > invalidFields = new HashSet <>();
329
+
330
+ for (SdkField <?> sourceField : sourceObject .sdkFields ()) {
331
+ String fieldName = sourceField .memberName ();
332
+ Object rawValue = sourceField .getValueOrDefault (sourceObject );
333
+
334
+ if (rawValue != null && !allowedFields .contains (fieldName )) {
335
+ invalidFields .add (fieldName );
336
+ }
337
+ }
338
+
339
+ if (!invalidFields .isEmpty ()) {
340
+ throw SdkClientException .create (
341
+ String .format ("The following fields are not allowed: %s" ,
342
+ String .join (", " , invalidFields ))
343
+ );
344
+ }
345
+ }
228
346
}
0 commit comments