@@ -54,7 +54,7 @@ public final class ResponseCookie extends HttpCookie {
54
54
/**
55
55
* Private constructor. See {@link #from(String, String)}.
56
56
*/
57
- private ResponseCookie (String name , String value , Duration maxAge , @ Nullable String domain ,
57
+ private ResponseCookie (String name , @ Nullable String value , Duration maxAge , @ Nullable String domain ,
58
58
@ Nullable String path , boolean secure , boolean httpOnly , @ Nullable String sameSite ) {
59
59
60
60
super (name , value );
@@ -128,6 +128,19 @@ public String getSameSite() {
128
128
return this .sameSite ;
129
129
}
130
130
131
+ /**
132
+ * Return a builder pre-populated with values from {@code "this"} instance.
133
+ * @since 6.0
134
+ */
135
+ public ResponseCookieBuilder mutate () {
136
+ return new DefaultResponseCookieBuilder (getName (), getValue (), false )
137
+ .maxAge (this .maxAge )
138
+ .domain (this .domain )
139
+ .path (this .path )
140
+ .secure (this .secure )
141
+ .httpOnly (this .httpOnly )
142
+ .sameSite (this .sameSite );
143
+ }
131
144
132
145
@ Override
133
146
public boolean equals (@ Nullable Object other ) {
@@ -179,6 +192,18 @@ public String toString() {
179
192
}
180
193
181
194
195
+ /**
196
+ * Factory method to obtain a builder for a server-defined cookie, given its
197
+ * name only, and where the value as well as other attributes can be set
198
+ * later via builder methods.
199
+ * @param name the cookie name
200
+ * @return a builder to create the cookie with
201
+ * @since 6.0
202
+ */
203
+ public static ResponseCookieBuilder from (final String name ) {
204
+ return new DefaultResponseCookieBuilder (name , null , false );
205
+ }
206
+
182
207
/**
183
208
* Factory method to obtain a builder for a server-defined cookie that starts
184
209
* with a name-value pair and may also include attributes.
@@ -187,7 +212,7 @@ public String toString() {
187
212
* @return a builder to create the cookie with
188
213
*/
189
214
public static ResponseCookieBuilder from (final String name , final String value ) {
190
- return from (name , value , false );
215
+ return new DefaultResponseCookieBuilder (name , value , false );
191
216
}
192
217
193
218
/**
@@ -201,90 +226,7 @@ public static ResponseCookieBuilder from(final String name, final String value)
201
226
* @since 5.2.5
202
227
*/
203
228
public static ResponseCookieBuilder fromClientResponse (final String name , final String value ) {
204
- return from (name , value , true );
205
- }
206
-
207
-
208
- private static ResponseCookieBuilder from (final String name , final String value , boolean lenient ) {
209
-
210
- return new ResponseCookieBuilder () {
211
-
212
- private Duration maxAge = Duration .ofSeconds (-1 );
213
-
214
- @ Nullable
215
- private String domain ;
216
-
217
- @ Nullable
218
- private String path ;
219
-
220
- private boolean secure ;
221
-
222
- private boolean httpOnly ;
223
-
224
- @ Nullable
225
- private String sameSite ;
226
-
227
- @ Override
228
- public ResponseCookieBuilder maxAge (Duration maxAge ) {
229
- this .maxAge = maxAge ;
230
- return this ;
231
- }
232
-
233
- @ Override
234
- public ResponseCookieBuilder maxAge (long maxAgeSeconds ) {
235
- this .maxAge = maxAgeSeconds >= 0 ? Duration .ofSeconds (maxAgeSeconds ) : Duration .ofSeconds (-1 );
236
- return this ;
237
- }
238
-
239
- @ Override
240
- public ResponseCookieBuilder domain (@ Nullable String domain ) {
241
- this .domain = initDomain (domain );
242
- return this ;
243
- }
244
-
245
- @ Nullable
246
- private String initDomain (@ Nullable String domain ) {
247
- if (lenient && StringUtils .hasLength (domain )) {
248
- String str = domain .trim ();
249
- if (str .startsWith ("\" " ) && str .endsWith ("\" " )) {
250
- if (str .substring (1 , str .length () - 1 ).trim ().isEmpty ()) {
251
- return null ;
252
- }
253
- }
254
- }
255
- return domain ;
256
- }
257
-
258
- @ Override
259
- public ResponseCookieBuilder path (@ Nullable String path ) {
260
- this .path = path ;
261
- return this ;
262
- }
263
-
264
- @ Override
265
- public ResponseCookieBuilder secure (boolean secure ) {
266
- this .secure = secure ;
267
- return this ;
268
- }
269
-
270
- @ Override
271
- public ResponseCookieBuilder httpOnly (boolean httpOnly ) {
272
- this .httpOnly = httpOnly ;
273
- return this ;
274
- }
275
-
276
- @ Override
277
- public ResponseCookieBuilder sameSite (@ Nullable String sameSite ) {
278
- this .sameSite = sameSite ;
279
- return this ;
280
- }
281
-
282
- @ Override
283
- public ResponseCookie build () {
284
- return new ResponseCookie (name , value , this .maxAge , this .domain , this .path ,
285
- this .secure , this .httpOnly , this .sameSite );
286
- }
287
- };
229
+ return new DefaultResponseCookieBuilder (name , value , true );
288
230
}
289
231
290
232
@@ -293,6 +235,12 @@ public ResponseCookie build() {
293
235
*/
294
236
public interface ResponseCookieBuilder {
295
237
238
+ /**
239
+ * Set the cookie value.
240
+ * @since 6.0
241
+ */
242
+ ResponseCookieBuilder value (@ Nullable String value );
243
+
296
244
/**
297
245
* Set the cookie "Max-Age" attribute.
298
246
*
@@ -429,4 +377,106 @@ public static void validatePath(@Nullable String path) {
429
377
}
430
378
}
431
379
380
+
381
+ /**
382
+ * Default implementation of {@link ResponseCookieBuilder}.
383
+ */
384
+ private static class DefaultResponseCookieBuilder implements ResponseCookieBuilder {
385
+
386
+ private final String name ;
387
+
388
+ @ Nullable
389
+ private String value ;
390
+
391
+ private final boolean lenient ;
392
+
393
+ private Duration maxAge = Duration .ofSeconds (-1 );
394
+
395
+ @ Nullable
396
+ private String domain ;
397
+
398
+ @ Nullable
399
+ private String path ;
400
+
401
+ private boolean secure ;
402
+
403
+ private boolean httpOnly ;
404
+
405
+ @ Nullable
406
+ private String sameSite ;
407
+
408
+ public DefaultResponseCookieBuilder (String name , @ Nullable String value , boolean lenient ) {
409
+ this .name = name ;
410
+ this .value = value ;
411
+ this .lenient = lenient ;
412
+ }
413
+
414
+ @ Override
415
+ public ResponseCookieBuilder value (@ Nullable String value ) {
416
+ this .value = value ;
417
+ return this ;
418
+ }
419
+
420
+ @ Override
421
+ public ResponseCookieBuilder maxAge (Duration maxAge ) {
422
+ this .maxAge = maxAge ;
423
+ return this ;
424
+ }
425
+
426
+ @ Override
427
+ public ResponseCookieBuilder maxAge (long maxAgeSeconds ) {
428
+ this .maxAge = (maxAgeSeconds >= 0 ? Duration .ofSeconds (maxAgeSeconds ) : Duration .ofSeconds (-1 ));
429
+ return this ;
430
+ }
431
+
432
+ @ Override
433
+ public ResponseCookieBuilder domain (@ Nullable String domain ) {
434
+ this .domain = initDomain (domain );
435
+ return this ;
436
+ }
437
+
438
+ @ Nullable
439
+ private String initDomain (@ Nullable String domain ) {
440
+ if (this .lenient && StringUtils .hasLength (domain )) {
441
+ String str = domain .trim ();
442
+ if (str .startsWith ("\" " ) && str .endsWith ("\" " )) {
443
+ if (str .substring (1 , str .length () - 1 ).trim ().isEmpty ()) {
444
+ return null ;
445
+ }
446
+ }
447
+ }
448
+ return domain ;
449
+ }
450
+
451
+ @ Override
452
+ public ResponseCookieBuilder path (@ Nullable String path ) {
453
+ this .path = path ;
454
+ return this ;
455
+ }
456
+
457
+ @ Override
458
+ public ResponseCookieBuilder secure (boolean secure ) {
459
+ this .secure = secure ;
460
+ return this ;
461
+ }
462
+
463
+ @ Override
464
+ public ResponseCookieBuilder httpOnly (boolean httpOnly ) {
465
+ this .httpOnly = httpOnly ;
466
+ return this ;
467
+ }
468
+
469
+ @ Override
470
+ public ResponseCookieBuilder sameSite (@ Nullable String sameSite ) {
471
+ this .sameSite = sameSite ;
472
+ return this ;
473
+ }
474
+
475
+ @ Override
476
+ public ResponseCookie build () {
477
+ return new ResponseCookie (this .name , this .value , this .maxAge ,
478
+ this .domain , this .path , this .secure , this .httpOnly , this .sameSite );
479
+ }
480
+ }
481
+
432
482
}
0 commit comments