Skip to content

Commit 55e7a53

Browse files
joerg1985diemol
andauthored
[java] removed usage of FileBackedOutputStream in the client (#13308)
* [java] removed usage of FileBackedOutputStream in the client * [java] removed usage of FileBackedOutputStream in the client --------- Co-authored-by: Diego Molina <[email protected]>
1 parent 4cfe983 commit 55e7a53

File tree

13 files changed

+137
-198
lines changed

13 files changed

+137
-198
lines changed

java/src/org/openqa/selenium/devtools/idealized/Network.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import static java.nio.charset.StandardCharsets.UTF_8;
2222
import static java.util.logging.Level.WARNING;
2323

24-
import java.io.ByteArrayInputStream;
25-
import java.io.InputStream;
2624
import java.net.URI;
2725
import java.net.URISyntaxException;
2826
import java.util.Base64;
@@ -293,13 +291,13 @@ protected HttpResponse createHttpResponse(
293291
String body,
294292
Boolean bodyIsBase64Encoded,
295293
List<Map.Entry<String, String>> headers) {
296-
Supplier<InputStream> content;
294+
Contents.Supplier content;
297295

298296
if (body == null) {
299297
content = Contents.empty();
300298
} else if (bodyIsBase64Encoded != null && bodyIsBase64Encoded) {
301299
byte[] decoded = Base64.getDecoder().decode(body);
302-
content = () -> new ByteArrayInputStream(decoded);
300+
content = Contents.bytes(decoded);
303301
} else {
304302
content = Contents.string(body, UTF_8);
305303
}

java/src/org/openqa/selenium/grid/data/SessionRequest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import org.openqa.selenium.json.TypeToken;
4242
import org.openqa.selenium.remote.Dialect;
4343
import org.openqa.selenium.remote.NewSessionPayload;
44-
import org.openqa.selenium.remote.http.Contents;
4544
import org.openqa.selenium.remote.http.HttpRequest;
4645

4746
public class SessionRequest {
@@ -61,7 +60,7 @@ public SessionRequest(RequestId requestId, HttpRequest request, Instant enqueued
6160
this.enqueued = Require.nonNull("Enqueued time", enqueued);
6261
Require.nonNull("Request", request);
6362

64-
try (NewSessionPayload payload = NewSessionPayload.create(Contents.reader(request))) {
63+
try (NewSessionPayload payload = NewSessionPayload.create(request.getContent())) {
6564
desiredCapabilities =
6665
payload.stream()
6766
.filter(capabilities -> !capabilities.asMap().isEmpty())

java/src/org/openqa/selenium/netty/server/RequestConverter.java

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import java.util.List;
4545
import java.util.logging.Logger;
4646
import org.openqa.selenium.internal.Debug;
47+
import org.openqa.selenium.remote.http.Contents;
4748
import org.openqa.selenium.remote.http.HttpMethod;
4849
import org.openqa.selenium.remote.http.HttpRequest;
4950
import org.openqa.selenium.remote.http.HttpResponse;
@@ -55,6 +56,7 @@ class RequestConverter extends SimpleChannelInboundHandler<HttpObject> {
5556
private static final List<io.netty.handler.codec.http.HttpMethod> SUPPORTED_METHODS =
5657
Arrays.asList(DELETE, GET, POST, OPTIONS);
5758
private volatile FileBackedOutputStream buffer;
59+
private volatile int length;
5860
private volatile HttpRequest request;
5961

6062
@Override
@@ -91,6 +93,7 @@ protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Ex
9193
AttributeKey.HTTP_FLAVOR.getKey(), nettyRequest.protocolVersion().majorVersion());
9294

9395
buffer = null;
96+
length = -1;
9497
}
9598

9699
if (msg instanceof HttpContent) {
@@ -100,10 +103,12 @@ protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Ex
100103
if (nBytes > 0) {
101104
if (buffer == null) {
102105
buffer = new FileBackedOutputStream(3 * 1024 * 1024, true);
106+
length = 0;
103107
}
104108

105109
try {
106110
buf.readBytes(buffer, nBytes);
111+
length += nBytes;
107112
} finally {
108113
buf.release();
109114
}
@@ -114,29 +119,31 @@ protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Ex
114119

115120
if (buffer != null) {
116121
ByteSource source = buffer.asByteSource();
122+
int len = length;
117123

118124
request.setContent(
119-
() -> {
120-
try {
121-
return source.openBufferedStream();
122-
} catch (IOException e) {
123-
throw new UncheckedIOException(e);
125+
new Contents.Supplier() {
126+
@Override
127+
public InputStream get() {
128+
try {
129+
return source.openBufferedStream();
130+
} catch (IOException e) {
131+
throw new UncheckedIOException(e);
132+
}
133+
}
134+
135+
@Override
136+
public int length() {
137+
return len;
138+
}
139+
140+
@Override
141+
public void close() throws IOException {
142+
buffer.reset();
124143
}
125144
});
126145
} else {
127-
request.setContent(
128-
() ->
129-
new InputStream() {
130-
@Override
131-
public int read() throws IOException {
132-
return -1;
133-
}
134-
135-
@Override
136-
public int read(byte[] b, int off, int len) throws IOException {
137-
return -1;
138-
}
139-
});
146+
request.setContent(Contents.empty());
140147
}
141148

142149
ctx.fireChannelRead(request);

java/src/org/openqa/selenium/remote/NewSessionPayload.java

Lines changed: 17 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,10 @@
2121
import static org.openqa.selenium.json.Json.LIST_OF_MAPS_TYPE;
2222
import static org.openqa.selenium.json.Json.MAP_TYPE;
2323

24-
import com.google.common.io.FileBackedOutputStream;
2524
import java.io.Closeable;
2625
import java.io.IOException;
27-
import java.io.InputStreamReader;
28-
import java.io.OutputStreamWriter;
2926
import java.io.Reader;
30-
import java.io.StringReader;
3127
import java.io.UncheckedIOException;
32-
import java.io.Writer;
3328
import java.util.Collection;
3429
import java.util.Collections;
3530
import java.util.HashMap;
@@ -50,32 +45,19 @@
5045
import org.openqa.selenium.json.Json;
5146
import org.openqa.selenium.json.JsonInput;
5247
import org.openqa.selenium.json.JsonOutput;
48+
import org.openqa.selenium.remote.http.Contents;
5349

5450
public class NewSessionPayload implements Closeable {
5551

5652
private static final Dialect DEFAULT_DIALECT = Dialect.W3C;
5753
private static final Predicate<String> ACCEPTED_W3C_PATTERNS = new AcceptedW3CCapabilityKeys();
5854

5955
private final Json json = new Json();
60-
private final FileBackedOutputStream backingStore;
56+
private final Contents.Supplier supplier;
6157
private final Set<Dialect> dialects;
6258

63-
private NewSessionPayload(Reader source) {
64-
// Dedicate up to 10% of all RAM or 20% of available RAM (whichever is smaller) to storing this
65-
// payload.
66-
int threshold =
67-
(int)
68-
Math.min(
69-
Integer.MAX_VALUE,
70-
Math.min(
71-
Runtime.getRuntime().freeMemory() / 5, Runtime.getRuntime().maxMemory() / 10));
72-
73-
backingStore = new FileBackedOutputStream(threshold);
74-
try (Writer writer = new OutputStreamWriter(backingStore, UTF_8)) {
75-
source.transferTo(writer);
76-
} catch (IOException e) {
77-
throw new UncheckedIOException(e);
78-
}
59+
private NewSessionPayload(Contents.Supplier supplier) {
60+
this.supplier = supplier;
7961

8062
Set<Dialect> dialects = new LinkedHashSet<>();
8163
try {
@@ -89,12 +71,6 @@ private NewSessionPayload(Reader source) {
8971
} catch (IOException e) {
9072
throw new UncheckedIOException(e);
9173
}
92-
93-
try {
94-
source.close();
95-
} catch (IOException e) {
96-
// Ignore
97-
}
9874
}
9975

10076
public static NewSessionPayload create(Capabilities caps) {
@@ -120,12 +96,15 @@ public static NewSessionPayload create(Map<String, ?> source) {
12096
Require.precondition(
12197
source.containsKey("capabilities"), "New session payload must contain capabilities");
12298

123-
String json = new Json().toJson(Require.nonNull("Payload", source));
124-
return new NewSessionPayload(new StringReader(json));
99+
return new NewSessionPayload(Contents.asJson(Require.nonNull("Payload", source)));
100+
}
101+
102+
public static NewSessionPayload create(Contents.Supplier supplier) {
103+
return new NewSessionPayload(supplier);
125104
}
126105

127-
public static NewSessionPayload create(Reader source) {
128-
return new NewSessionPayload(source);
106+
public Contents.Supplier getSupplier() {
107+
return supplier;
129108
}
130109

131110
private void validate() throws IOException {
@@ -213,8 +192,7 @@ public void writeTo(Appendable appendable) throws IOException {
213192
}
214193

215194
private void writeMetaData(JsonOutput out) throws IOException {
216-
try (Reader reader =
217-
new InputStreamReader(backingStore.asByteSource().openBufferedStream(), UTF_8);
195+
try (Reader reader = Contents.reader(supplier, UTF_8);
218196
JsonInput input = json.newInput(reader)) {
219197
input.beginObject();
220198
while (input.hasNext()) {
@@ -253,8 +231,7 @@ public Set<Dialect> getDownstreamDialects() {
253231
public Map<String, Object> getMetadata() {
254232
Set<String> ignoredMetadataKeys = Set.of("capabilities");
255233

256-
try (Reader reader =
257-
new InputStreamReader(backingStore.asByteSource().openBufferedStream(), UTF_8);
234+
try (Reader reader = Contents.reader(supplier, UTF_8);
258235
JsonInput input = json.newInput(reader)) {
259236
Map<String, Object> toReturn = new LinkedHashMap<>();
260237

@@ -284,7 +261,7 @@ public Map<String, Object> getMetadata() {
284261
@Override
285262
public void close() {
286263
try {
287-
backingStore.reset();
264+
supplier.close();
288265
} catch (IOException e) {
289266
throw new UncheckedIOException(e);
290267
}
@@ -324,8 +301,7 @@ private Stream<Map<String, Object>> getW3C() throws IOException {
324301
}
325302

326303
private boolean isW3C() throws IOException {
327-
try (Reader reader =
328-
new InputStreamReader(backingStore.asByteSource().openBufferedStream(), UTF_8);
304+
try (Reader reader = Contents.reader(supplier, UTF_8);
329305
JsonInput input = json.newInput(reader)) {
330306
input.beginObject();
331307
while (input.hasNext()) {
@@ -341,8 +317,7 @@ private boolean isW3C() throws IOException {
341317
}
342318

343319
private Map<String, Object> getAlwaysMatch() throws IOException {
344-
try (Reader reader =
345-
new InputStreamReader(backingStore.asByteSource().openBufferedStream(), UTF_8);
320+
try (Reader reader = Contents.reader(supplier, UTF_8);
346321
JsonInput input = json.newInput(reader)) {
347322
input.beginObject();
348323
while (input.hasNext()) {
@@ -367,8 +342,7 @@ private Map<String, Object> getAlwaysMatch() throws IOException {
367342
}
368343

369344
private Collection<Map<String, Object>> getFirstMatches() throws IOException {
370-
try (Reader reader =
371-
new InputStreamReader(backingStore.asByteSource().openBufferedStream(), UTF_8);
345+
try (Reader reader = Contents.reader(supplier, UTF_8);
372346
JsonInput input = json.newInput(reader)) {
373347
input.beginObject();
374348
while (input.hasNext()) {

java/src/org/openqa/selenium/remote/ProtocolHandshake.java

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,16 @@
1717

1818
package org.openqa.selenium.remote;
1919

20-
import static java.nio.charset.StandardCharsets.UTF_8;
2120
import static java.util.Collections.singleton;
2221
import static org.openqa.selenium.json.Json.JSON_UTF_8;
2322
import static org.openqa.selenium.remote.CapabilityType.PROXY;
2423
import static org.openqa.selenium.remote.http.Contents.string;
2524

26-
import com.google.common.io.CountingOutputStream;
27-
import com.google.common.io.FileBackedOutputStream;
2825
import java.io.IOException;
29-
import java.io.InputStream;
30-
import java.io.OutputStreamWriter;
31-
import java.io.Writer;
3226
import java.util.Collection;
3327
import java.util.Map;
3428
import java.util.Objects;
3529
import java.util.function.Function;
36-
import java.util.function.Supplier;
3730
import java.util.logging.Level;
3831
import java.util.logging.Logger;
3932
import java.util.stream.Stream;
@@ -45,6 +38,7 @@
4538
import org.openqa.selenium.internal.Require;
4639
import org.openqa.selenium.json.Json;
4740
import org.openqa.selenium.json.JsonException;
41+
import org.openqa.selenium.remote.http.Contents;
4842
import org.openqa.selenium.remote.http.HttpHandler;
4943
import org.openqa.selenium.remote.http.HttpHeader;
5044
import org.openqa.selenium.remote.http.HttpMethod;
@@ -78,36 +72,17 @@ public Result createSession(HttpHandler client, Command command) throws IOExcept
7872

7973
public Either<SessionNotCreatedException, Result> createSession(
8074
HttpHandler client, NewSessionPayload payload) throws IOException {
81-
int threshold = (int) Math.min(Runtime.getRuntime().freeMemory() / 10, Integer.MAX_VALUE);
82-
FileBackedOutputStream os = new FileBackedOutputStream(threshold, true);
83-
84-
try (CountingOutputStream counter = new CountingOutputStream(os);
85-
Writer writer = new OutputStreamWriter(counter, UTF_8)) {
86-
payload.writeTo(writer);
87-
Supplier<InputStream> contentSupplier =
88-
() -> {
89-
try {
90-
return os.asByteSource().openBufferedStream();
91-
} catch (IOException e) {
92-
throw new RuntimeException(e);
93-
}
94-
};
95-
return createSession(client, contentSupplier, counter.getCount());
96-
}
75+
return createSession(client, payload.getSupplier());
9776
}
9877

9978
private Either<SessionNotCreatedException, Result> createSession(
100-
HttpHandler client, Supplier<InputStream> contentSupplier, long size) {
79+
HttpHandler client, Contents.Supplier contentSupplier) {
10180
// Create the http request and send it
10281
HttpRequest request = new HttpRequest(HttpMethod.POST, "/session");
10382

10483
HttpResponse response;
10584
long start = System.currentTimeMillis();
10685

107-
// Setting the CONTENT_LENGTH will allow a http client implementation not to read the data in
108-
// memory. Usually the payload is small and buffering it to memory is okay, except for a new
109-
// session e.g. with profiles.
110-
request.setHeader(HttpHeader.ContentLength.getName(), String.valueOf(size));
11186
request.setHeader(HttpHeader.ContentType.getName(), JSON_UTF_8);
11287
request.setContent(contentSupplier);
11388

java/src/org/openqa/selenium/remote/http/BUILD.bazel

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ java_export(
1717
"//java:auto-service",
1818
"//java/src/org/openqa/selenium:core",
1919
"//java/src/org/openqa/selenium/json",
20-
artifact("com.google.guava:guava"),
2120
artifact("dev.failsafe:failsafe"),
2221
],
2322
)

0 commit comments

Comments
 (0)