Skip to content

Commit

Permalink
[java] Reworking ProtocolHandshake to return either result or an exce…
Browse files Browse the repository at this point in the history
…ption, and reworking RemoteWebDriverBuilder to use FileBackedOutputStream to form request to remote server.
  • Loading branch information
barancev committed Feb 22, 2021
1 parent fd7a4b6 commit 6baf2b8
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 41 deletions.
51 changes: 28 additions & 23 deletions java/client/src/org/openqa/selenium/remote/ProtocolHandshake.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,37 +59,39 @@ public Result createSession(HttpHandler client, Command command) throws IOExcept
Capabilities desired = (Capabilities) command.getParameters().get("desiredCapabilities");
desired = desired == null ? new ImmutableCapabilities() : desired;

try (NewSessionPayload payload = NewSessionPayload.create(desired)) {
Either<WebDriverException, Result> result = createSession(client, payload);

if (result.isRight()) {
Result toReturn = result.right();
LOG.info(String.format("Detected dialect: %s", toReturn.dialect));
return toReturn;
} else {
throw new SessionNotCreatedException(
String.format("Unable to create new remote session with desired capabilities = %s", desired),
result.left());
}
}
}

public Either<WebDriverException, Result> createSession(HttpHandler client, NewSessionPayload payload) throws IOException {
int threshold = (int) Math.min(Runtime.getRuntime().freeMemory() / 10, Integer.MAX_VALUE);
FileBackedOutputStream os = new FileBackedOutputStream(threshold);
try (
CountingOutputStream counter = new CountingOutputStream(os);
Writer writer = new OutputStreamWriter(counter, UTF_8);
NewSessionPayload payload = NewSessionPayload.create(desired)) {

try (CountingOutputStream counter = new CountingOutputStream(os);
Writer writer = new OutputStreamWriter(counter, UTF_8)) {
payload.writeTo(writer);

try (InputStream rawIn = os.asByteSource().openBufferedStream();
BufferedInputStream contentStream = new BufferedInputStream(rawIn)) {
Either<String, Result> result = createSession(client, contentStream, counter.getCount());

if (result.isRight()) {
Result toReturn = result.right();
LOG.info(String.format("Detected dialect: %s", toReturn.dialect));
return toReturn;
} else {
throw new SessionNotCreatedException(
String.format(
"Unable to create new remote session. Reason: %s, " +
"desired capabilities = %s",
result.right(), desired));
}
return createSession(client, contentStream, counter.getCount());
}
} finally {
os.reset();
}
}

Either<String, Result> createSession(HttpHandler client, InputStream newSessionBlob, long size) {
private Either<WebDriverException, Result> createSession(HttpHandler client, InputStream newSessionBlob, long size) {
// Create the http request and send it
HttpRequest request = new HttpRequest(HttpMethod.POST, "/session");

Expand All @@ -109,8 +111,8 @@ Either<String, Result> createSession(HttpHandler client, InputStream newSessionB
try {
blob = new Json().toType(string(response), Map.class);
} catch (JsonException e) {
throw new WebDriverException(
"Unable to parse remote response: " + string(response), e);
return Either.left(new WebDriverException(
"Unable to parse remote response: " + string(response), e));
}

InitialHandshakeResponse initialResponse = new InitialHandshakeResponse(
Expand All @@ -119,7 +121,9 @@ Either<String, Result> createSession(HttpHandler client, InputStream newSessionB
blob);

if (initialResponse.getStatusCode() != 200) {
return Either.left(blob.get("message").toString());
return Either.left(new WebDriverException(
String.format("Server response code %s, message: %s",
initialResponse.getStatusCode(), blob.get("message").toString())));
}

return Stream.of(
Expand All @@ -128,8 +132,9 @@ Either<String, Result> createSession(HttpHandler client, InputStream newSessionB
.map(func -> func.apply(initialResponse))
.filter(Objects::nonNull)
.findFirst()
.<Either<String, Result>>map(Either::right)
.orElseGet(() -> Either.left("Handshake response does not match any supported protocol"));
.<Either<WebDriverException, Result>>map(Either::right)
.orElseGet(() -> Either.left(
new WebDriverException("Handshake response does not match any supported protocol")));
}

public static class Result {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.openqa.selenium.ImmutableCapabilities;
import org.openqa.selenium.SessionNotCreatedException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebDriverInfo;
import org.openqa.selenium.internal.Either;
import org.openqa.selenium.internal.Require;
Expand All @@ -35,7 +36,6 @@
import org.openqa.selenium.remote.http.HttpResponse;
import org.openqa.selenium.remote.service.DriverService;

import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.UncheckedIOException;
Expand All @@ -56,7 +56,6 @@
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.logging.Level.WARNING;
import static org.openqa.selenium.internal.Debug.getDebugLogLevel;
import static org.openqa.selenium.remote.DriverCommand.QUIT;
Expand Down Expand Up @@ -358,18 +357,18 @@ private WebDriver getRemoteDriver() {
.andThen(new AddWebDriverSpecHeaders())
.andThen(new ErrorFilter()));

byte[] payload = getPayloadUtf8Bytes();
Either<String, ProtocolHandshake.Result> result = new ProtocolHandshake().createSession(
handler,
new ByteArrayInputStream(payload),
payload.length);
Either<WebDriverException, ProtocolHandshake.Result> result = null;
try {
result = new ProtocolHandshake().createSession(handler, getPayload());
} catch (IOException e) {
throw new SessionNotCreatedException("Unable to create new remote session.", e);
}

if (result.isRight()) {
CommandExecutor executor = result.map(res -> createExecutor(handler, res));
return new RemoteWebDriver(executor, new ImmutableCapabilities());
} else {
throw new SessionNotCreatedException(
String.format("Unable to create new remote session. Reason: %s", result.left()));
throw new SessionNotCreatedException("Unable to create new remote session", result.left());
}
}

Expand Down Expand Up @@ -454,7 +453,7 @@ private Set<String> getClobberedCapabilities() {
.collect(Collectors.toSet());
}

private byte[] getPayloadUtf8Bytes() {
private NewSessionPayload getPayload() {
Map<String, Object> roughPayload = new TreeMap<>(metadata);

Map<String, Object> w3cCaps = new TreeMap<>();
Expand All @@ -463,14 +462,7 @@ private byte[] getPayloadUtf8Bytes() {
w3cCaps.put("firstMatch", requestedCapabilities);
}
roughPayload.put("capabilities", w3cCaps);

try (NewSessionPayload payload = NewSessionPayload.create(roughPayload)) {
StringBuilder json = new StringBuilder();
payload.writeTo(json);
return json.toString().getBytes(UTF_8);
} catch (IOException e) {
throw new SessionNotCreatedException("Unable to create session roughPayload", e);
}
return NewSessionPayload.create(roughPayload);
}

private static class CloseHttpClientFilter implements Filter {
Expand Down

0 comments on commit 6baf2b8

Please sign in to comment.