0
# Content Handling
1
2
Comprehensive content utilities for converting between different formats (strings, bytes, JSON) with charset support and streaming capabilities for HTTP message content management.
3
4
## Capabilities
5
6
### Contents Utility Class
7
8
Central utility class providing static methods for creating, converting, and manipulating HTTP message content with support for multiple formats and character encodings.
9
10
```java { .api }
11
/**
12
* Utility class for HTTP content handling and conversion
13
* Provides static methods for creating and converting content suppliers
14
*/
15
public class Contents {
16
/**
17
* Creates empty content supplier with zero length
18
* @return Empty Contents.Supplier
19
*/
20
public static Supplier empty();
21
22
/**
23
* Creates UTF-8 encoded string content supplier
24
* @param value Character sequence to convert
25
* @return Contents.Supplier for UTF-8 string
26
*/
27
public static Supplier utf8String(CharSequence value);
28
29
/**
30
* Creates string content supplier with specified charset
31
* @param value Character sequence to convert
32
* @param charset Character encoding to use
33
* @return Contents.Supplier for encoded string
34
*/
35
public static Supplier string(CharSequence value, Charset charset);
36
37
/**
38
* Creates content supplier from byte array
39
* Makes defensive copy of input array
40
* @param bytes Byte array to use as content
41
* @return Contents.Supplier for byte data
42
*/
43
public static Supplier bytes(byte[] bytes);
44
45
/**
46
* Converts content supplier to byte array
47
* @param supplier Contents.Supplier to convert
48
* @return Byte array containing all content
49
*/
50
public static byte[] bytes(Supplier supplier);
51
52
/**
53
* Converts content supplier to UTF-8 string
54
* @param supplier Contents.Supplier to convert
55
* @return String decoded using UTF-8
56
*/
57
public static String utf8String(Supplier supplier);
58
59
/**
60
* Converts content supplier to string with specified charset
61
* @param supplier Contents.Supplier to convert
62
* @param charset Character encoding for decoding
63
* @return String decoded using specified charset
64
*/
65
public static String string(Supplier supplier, Charset charset);
66
67
/**
68
* Extracts string content from HTTP message using detected encoding
69
* Uses Content-Type header to determine charset, defaults to UTF-8
70
* @param message HTTP message to extract content from
71
* @return String content using detected encoding
72
*/
73
public static String string(HttpMessage<?> message);
74
75
/**
76
* Creates UTF-8 reader from content supplier
77
* @param supplier Contents.Supplier to read from
78
* @return Reader for UTF-8 content
79
*/
80
public static Reader utf8Reader(Supplier supplier);
81
82
/**
83
* Creates reader from content supplier with specified charset
84
* @param supplier Contents.Supplier to read from
85
* @param charset Character encoding for reading
86
* @return Reader for content with specified encoding
87
*/
88
public static Reader reader(Supplier supplier, Charset charset);
89
90
/**
91
* Creates reader from HTTP message using detected encoding
92
* Uses Content-Type header to determine charset
93
* @param message HTTP message to create reader for
94
* @return Reader using detected charset
95
*/
96
public static Reader reader(HttpMessage<?> message);
97
98
/**
99
* Converts object to JSON content supplier
100
* Serializes object using JSON serialization
101
* @param obj Object to serialize as JSON
102
* @return Contents.Supplier for JSON content
103
*/
104
public static Supplier asJson(Object obj);
105
106
/**
107
* Deserializes JSON content from HTTP message
108
* @param message HTTP message containing JSON content
109
* @param typeOfT Type to deserialize JSON into
110
* @return Deserialized object of specified type
111
*/
112
public static <T> T fromJson(HttpMessage<?> message, Type typeOfT);
113
114
/**
115
* Converts file to Base64 encoded string
116
* @param input File to encode
117
* @return Base64 encoded string representation
118
*/
119
public static String string(File input);
120
}
121
```
122
123
**Usage Examples:**
124
125
```java
126
import org.openqa.selenium.remote.http.*;
127
import java.nio.charset.StandardCharsets;
128
import java.io.File;
129
import java.util.Map;
130
131
// Create different types of content
132
Contents.Supplier emptyContent = Contents.empty();
133
Contents.Supplier textContent = Contents.utf8String("Hello World");
134
Contents.Supplier latinContent = Contents.string("Café", StandardCharsets.ISO_8859_1);
135
Contents.Supplier binaryContent = Contents.bytes("Binary data".getBytes());
136
137
// Set content on HTTP messages
138
HttpRequest request = new HttpRequest(HttpMethod.POST, "/api/data");
139
request.setContent(textContent);
140
request.addHeader("Content-Type", "text/plain; charset=UTF-8");
141
142
// Convert content to different formats
143
Contents.Supplier jsonData = Contents.asJson(Map.of(
144
"name", "John Doe",
145
"age", 30,
146
"active", true
147
));
148
149
byte[] jsonBytes = Contents.bytes(jsonData);
150
String jsonString = Contents.utf8String(jsonData);
151
152
System.out.println("JSON as string: " + jsonString);
153
System.out.println("JSON size: " + jsonBytes.length + " bytes");
154
155
// Extract content from responses
156
HttpResponse response = client.execute(request);
157
String responseText = Contents.string(response); // Uses detected charset
158
byte[] responseBytes = Contents.bytes(response.getContent());
159
160
// Work with readers for streaming
161
Reader reader = Contents.reader(response);
162
BufferedReader buffered = new BufferedReader(reader);
163
String line;
164
while ((line = buffered.readLine()) != null) {
165
System.out.println("Line: " + line);
166
}
167
reader.close();
168
```
169
170
### Contents.Supplier Interface
171
172
Interface extending both `Supplier<InputStream>` and `AutoCloseable` for providing HTTP content with length information and resource management.
173
174
```java { .api }
175
/**
176
* Content supplier interface providing InputStream and resource management
177
* Extends Supplier<InputStream> and AutoCloseable for proper resource handling
178
*/
179
public interface Supplier extends java.util.function.Supplier<InputStream>, AutoCloseable {
180
/**
181
* Gets the content length in bytes
182
* @return Content length, or -1 if unknown
183
*/
184
int length();
185
186
/**
187
* Closes resources associated with this supplier
188
* Should be called when content is no longer needed
189
* @throws IOException if an I/O error occurs
190
*/
191
void close() throws IOException;
192
}
193
```
194
195
**Usage Examples:**
196
197
```java
198
import org.openqa.selenium.remote.http.*;
199
import java.io.InputStream;
200
import java.io.IOException;
201
202
// Create content supplier
203
Contents.Supplier supplier = Contents.utf8String("Sample content for length testing");
204
205
// Check content length
206
int contentLength = supplier.length();
207
System.out.println("Content length: " + contentLength + " bytes");
208
209
// Use as InputStream supplier
210
try (InputStream inputStream = supplier.get()) {
211
byte[] buffer = new byte[1024];
212
int bytesRead = inputStream.read(buffer);
213
System.out.println("Read " + bytesRead + " bytes");
214
} catch (IOException e) {
215
System.err.println("Error reading content: " + e.getMessage());
216
} finally {
217
supplier.close(); // Always close resources
218
}
219
220
// Use with try-with-resources for automatic cleanup
221
try (Contents.Supplier autoCloseSupplier = Contents.utf8String("Auto-close content")) {
222
InputStream stream = autoCloseSupplier.get();
223
// Use stream...
224
} // Automatically closes supplier
225
226
// Custom supplier implementation
227
Contents.Supplier customSupplier = new Contents.Supplier() {
228
private final byte[] data = "Custom data".getBytes();
229
230
@Override
231
public InputStream get() {
232
return new ByteArrayInputStream(data);
233
}
234
235
@Override
236
public int length() {
237
return data.length;
238
}
239
240
@Override
241
public void close() {
242
// Custom cleanup if needed
243
System.out.println("Custom supplier closed");
244
}
245
};
246
```
247
248
## Content Conversion Examples
249
250
### String Content Handling
251
252
```java
253
import org.openqa.selenium.remote.http.*;
254
import java.nio.charset.StandardCharsets;
255
256
// Create string content with different encodings
257
String message = "Hello, 世界! Café";
258
259
Contents.Supplier utf8Content = Contents.utf8String(message);
260
Contents.Supplier latinContent = Contents.string(message, StandardCharsets.ISO_8859_1);
261
Contents.Supplier utf16Content = Contents.string(message, StandardCharsets.UTF_16);
262
263
// Set on HTTP request
264
HttpRequest request = new HttpRequest(HttpMethod.PUT, "/messages");
265
request.setContent(utf8Content);
266
request.addHeader("Content-Type", "text/plain; charset=UTF-8");
267
268
// Convert back to string
269
String retrievedUtf8 = Contents.utf8String(utf8Content);
270
String retrievedLatin = Contents.string(latinContent, StandardCharsets.ISO_8859_1);
271
272
System.out.println("UTF-8: " + retrievedUtf8);
273
System.out.println("Latin-1: " + retrievedLatin);
274
275
// Extract from HTTP response with automatic charset detection
276
HttpResponse response = client.execute(request);
277
String responseContent = Contents.string(response); // Uses Content-Type charset
278
```
279
280
### Binary Content Handling
281
282
```java
283
import org.openqa.selenium.remote.http.*;
284
import java.io.File;
285
import java.io.FileInputStream;
286
import java.io.IOException;
287
288
// Handle binary data
289
byte[] imageData = loadImageFile();
290
Contents.Supplier binaryContent = Contents.bytes(imageData);
291
292
// Set binary content on request
293
HttpRequest uploadRequest = new HttpRequest(HttpMethod.POST, "/upload");
294
uploadRequest.setContent(binaryContent);
295
uploadRequest.addHeader("Content-Type", "image/jpeg");
296
297
// Extract binary data from response
298
HttpResponse uploadResponse = client.execute(uploadRequest);
299
byte[] responseData = Contents.bytes(uploadResponse.getContent());
300
301
System.out.println("Uploaded " + imageData.length + " bytes");
302
System.out.println("Response " + responseData.length + " bytes");
303
304
// File to Base64 conversion
305
File document = new File("document.pdf");
306
String base64Document = Contents.string(document);
307
308
HttpRequest documentRequest = new HttpRequest(HttpMethod.POST, "/documents");
309
documentRequest.setContent(Contents.utf8String(base64Document));
310
documentRequest.addHeader("Content-Type", "text/plain");
311
312
private byte[] loadImageFile() throws IOException {
313
File imageFile = new File("image.jpg");
314
try (FileInputStream fis = new FileInputStream(imageFile)) {
315
return fis.readAllBytes();
316
}
317
}
318
```
319
320
### JSON Content Handling
321
322
```java
323
import org.openqa.selenium.remote.http.*;
324
import java.lang.reflect.ParameterizedType;
325
import java.lang.reflect.Type;
326
import java.util.Map;
327
import java.util.List;
328
329
// Create JSON content from objects
330
Map<String, Object> userData = Map.of(
331
"id", 123,
332
"name", "John Doe",
333
"email", "john@example.com",
334
"roles", List.of("user", "admin"),
335
"active", true
336
);
337
338
Contents.Supplier jsonContent = Contents.asJson(userData);
339
340
// Send JSON request
341
HttpRequest jsonRequest = new HttpRequest(HttpMethod.POST, "/users");
342
jsonRequest.setContent(jsonContent);
343
jsonRequest.addHeader("Content-Type", "application/json");
344
345
HttpResponse jsonResponse = client.execute(jsonRequest);
346
347
// Deserialize JSON response
348
Map<String, Object> responseMap = Contents.fromJson(jsonResponse, Map.class);
349
System.out.println("Created user ID: " + responseMap.get("id"));
350
351
// Deserialize to custom types using anonymous ParameterizedType
352
Type listType = new ParameterizedType() {
353
public Type[] getActualTypeArguments() { return new Type[]{Map.class}; }
354
public Type getRawType() { return List.class; }
355
public Type getOwnerType() { return null; }
356
};
357
List<Map<String, Object>> userList = Contents.fromJson(jsonResponse, listType);
358
359
// Complex object serialization
360
UserData user = new UserData("Jane Doe", "jane@example.com");
361
Contents.Supplier userJson = Contents.asJson(user);
362
363
HttpRequest createUser = new HttpRequest(HttpMethod.POST, "/users");
364
createUser.setContent(userJson);
365
366
HttpResponse createResponse = client.execute(createUser);
367
UserData createdUser = Contents.fromJson(createResponse, UserData.class);
368
369
System.out.println("Created user: " + createdUser.getName());
370
371
// Custom serialization class
372
public static class UserData {
373
private String name;
374
private String email;
375
376
public UserData(String name, String email) {
377
this.name = name;
378
this.email = email;
379
}
380
381
// Getters and setters...
382
public String getName() { return name; }
383
public String getEmail() { return email; }
384
}
385
```
386
387
### Stream-based Content Processing
388
389
```java
390
import org.openqa.selenium.remote.http.*;
391
import java.io.*;
392
import java.nio.charset.StandardCharsets;
393
394
// Process large content using readers
395
HttpResponse largeResponse = client.execute(request);
396
397
try (Reader reader = Contents.reader(largeResponse);
398
BufferedReader buffered = new BufferedReader(reader)) {
399
400
String line;
401
int lineCount = 0;
402
while ((line = buffered.readLine()) != null) {
403
processLine(line);
404
lineCount++;
405
406
if (lineCount % 1000 == 0) {
407
System.out.println("Processed " + lineCount + " lines");
408
}
409
}
410
411
System.out.println("Total lines processed: " + lineCount);
412
}
413
414
// Create reader with specific charset
415
try (Reader utf16Reader = Contents.reader(response.getContent(), StandardCharsets.UTF_16)) {
416
char[] buffer = new char[1024];
417
int charsRead;
418
while ((charsRead = utf16Reader.read(buffer)) != -1) {
419
String chunk = new String(buffer, 0, charsRead);
420
processChunk(chunk);
421
}
422
}
423
424
// Stream binary content
425
Contents.Supplier binarySupplier = Contents.bytes(largeBinaryData);
426
try (InputStream stream = binarySupplier.get();
427
BufferedInputStream buffered = new BufferedInputStream(stream)) {
428
429
byte[] buffer = new byte[8192];
430
int bytesRead;
431
long totalBytes = 0;
432
433
while ((bytesRead = buffered.read(buffer)) != -1) {
434
processBinaryChunk(buffer, bytesRead);
435
totalBytes += bytesRead;
436
}
437
438
System.out.println("Processed " + totalBytes + " bytes");
439
} finally {
440
binarySupplier.close();
441
}
442
443
private void processLine(String line) { /* process text line */ }
444
private void processChunk(String chunk) { /* process text chunk */ }
445
private void processBinaryChunk(byte[] data, int length) { /* process binary data */ }
446
```
447
448
## Content Type Detection
449
450
```java
451
import org.openqa.selenium.remote.http.*;
452
import java.nio.charset.Charset;
453
import java.nio.charset.StandardCharsets;
454
455
// Automatic charset detection from Content-Type header
456
HttpResponse response = client.execute(request);
457
458
// Response has "Content-Type: text/html; charset=ISO-8859-1"
459
String content = Contents.string(response); // Uses ISO-8859-1 automatically
460
461
// Manual charset handling
462
Charset detectedCharset = response.getContentEncoding(); // ISO-8859-1
463
String manualContent = Contents.string(response.getContent(), detectedCharset);
464
465
// Override charset detection
466
String utf8Content = Contents.utf8String(response.getContent()); // Force UTF-8
467
468
// Set proper Content-Type when sending
469
HttpRequest request = new HttpRequest(HttpMethod.POST, "/submit");
470
request.setContent(Contents.string("Content with special chars: café", StandardCharsets.UTF_8));
471
request.addHeader("Content-Type", "text/plain; charset=UTF-8");
472
473
// Multiple charset handling
474
Contents.Supplier utf8Data = Contents.utf8String("UTF-8 content: 你好");
475
Contents.Supplier latinData = Contents.string("Latin-1 content: café", StandardCharsets.ISO_8859_1);
476
477
request.setContent(utf8Data);
478
request.setHeader("Content-Type", "text/plain; charset=UTF-8");
479
```