From 12cb9d9b6e117274340e8c73f40b0fa7a11396ba Mon Sep 17 00:00:00 2001 From: Sergey Tikhomirov Date: Sun, 30 Jul 2017 01:57:56 +0300 Subject: [PATCH 1/5] #655 FIX --- .../io/appium/java_client/AppiumDriver.java | 3 +- .../io/appium/java_client/MobileCommand.java | 3 +- .../java_client/android/AndroidDriver.java | 4 +- .../io/appium/java_client/ios/IOSDriver.java | 4 +- .../remote/AppiumCommandExecutor.java | 136 ++--------- .../remote/AppiumProtocolHandShake.java | 217 ------------------ .../java_client/windows/WindowsDriver.java | 4 +- 7 files changed, 32 insertions(+), 339 deletions(-) delete mode 100644 src/main/java/io/appium/java_client/remote/AppiumProtocolHandShake.java diff --git a/src/main/java/io/appium/java_client/AppiumDriver.java b/src/main/java/io/appium/java_client/AppiumDriver.java index 54bf7708e..0a51b5271 100644 --- a/src/main/java/io/appium/java_client/AppiumDriver.java +++ b/src/main/java/io/appium/java_client/AppiumDriver.java @@ -42,6 +42,7 @@ import org.openqa.selenium.remote.DriverCommand; import org.openqa.selenium.remote.ErrorHandler; import org.openqa.selenium.remote.ExecuteMethod; +import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.html5.RemoteLocationContext; import org.openqa.selenium.remote.http.HttpClient; @@ -82,7 +83,7 @@ public class AppiumDriver * @param capabilities take a look * at {@link org.openqa.selenium.Capabilities} */ - public AppiumDriver(AppiumCommandExecutor executor, Capabilities capabilities) { + public AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, capabilities); this.executeMethod = new AppiumExecutionMethod(this); locationContext = new RemoteLocationContext(executeMethod); diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 40a131a0e..7ab77cc90 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableMap; import org.apache.commons.lang3.StringUtils; +import org.openqa.selenium.remote.CommandInfo; import org.openqa.selenium.remote.http.HttpMethod; import java.time.Duration; @@ -79,7 +80,7 @@ public class MobileCommand { protected static final String SET_SETTINGS; protected static final String GET_CURRENT_PACKAGE; - public static final Map commandRepository; + public static final Map commandRepository; static { RESET = "reset"; diff --git a/src/main/java/io/appium/java_client/android/AndroidDriver.java b/src/main/java/io/appium/java_client/android/AndroidDriver.java index 0bfe0974e..fc29f9ecb 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -24,12 +24,12 @@ import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.FindsByAndroidUIAutomator; import io.appium.java_client.PressesKeyCode; -import io.appium.java_client.remote.AppiumCommandExecutor; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import org.openqa.selenium.Capabilities; import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; @@ -58,7 +58,7 @@ public class AndroidDriver * @param capabilities take a look * at {@link org.openqa.selenium.Capabilities} */ - public AndroidDriver(AppiumCommandExecutor executor, Capabilities capabilities) { + public AndroidDriver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, substituteMobilePlatform(capabilities, ANDROID_PLATFORM)); } diff --git a/src/main/java/io/appium/java_client/ios/IOSDriver.java b/src/main/java/io/appium/java_client/ios/IOSDriver.java index 0394264d8..995c6370c 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -24,7 +24,6 @@ import io.appium.java_client.FindsByIosNSPredicate; import io.appium.java_client.FindsByIosUIAutomation; import io.appium.java_client.HidesKeyboardWithKeyName; -import io.appium.java_client.remote.AppiumCommandExecutor; import io.appium.java_client.remote.MobilePlatform; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; @@ -32,6 +31,7 @@ import org.openqa.selenium.Capabilities; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.DriverCommand; +import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.Response; import org.openqa.selenium.remote.http.HttpClient; import org.openqa.selenium.security.Credentials; @@ -64,7 +64,7 @@ public class IOSDriver * @param capabilities take a look * at {@link org.openqa.selenium.Capabilities} */ - public IOSDriver(AppiumCommandExecutor executor, Capabilities capabilities) { + public IOSDriver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, substituteMobilePlatform(capabilities, IOS_PLATFORM)); } diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index 18a928fa8..a47043b20 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -16,29 +16,17 @@ package io.appium.java_client.remote; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Throwables.getRootCause; import static com.google.common.base.Throwables.throwIfUnchecked; -import static org.openqa.selenium.remote.DriverCommand.GET_ALL_SESSIONS; -import static org.openqa.selenium.remote.DriverCommand.NEW_SESSION; -import static org.openqa.selenium.remote.DriverCommand.QUIT; -import io.appium.java_client.AppiumCommandInfo; -import org.openqa.selenium.NoSuchSessionException; -import org.openqa.selenium.SessionNotCreatedException; -import org.openqa.selenium.UnsupportedCommandException; +import com.google.common.base.Throwables; + import org.openqa.selenium.WebDriverException; import org.openqa.selenium.remote.Command; -import org.openqa.selenium.remote.CommandCodec; -import org.openqa.selenium.remote.CommandExecutor; -import org.openqa.selenium.remote.Dialect; +import org.openqa.selenium.remote.CommandInfo; import org.openqa.selenium.remote.DriverCommand; -import org.openqa.selenium.remote.HttpSessionId; +import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.Response; -import org.openqa.selenium.remote.ResponseCodec; import org.openqa.selenium.remote.http.HttpClient; -import org.openqa.selenium.remote.http.HttpRequest; -import org.openqa.selenium.remote.http.HttpResponse; import org.openqa.selenium.remote.internal.ApacheHttpClient; import org.openqa.selenium.remote.service.DriverService; @@ -47,124 +35,44 @@ import java.net.URL; import java.util.Map; -public class AppiumCommandExecutor implements CommandExecutor { +public class AppiumCommandExecutor extends HttpCommandExecutor { - private final URL remoteServer; - private final HttpClient client; - private final Map additionalCommands; - private CommandCodec commandCodec; - private ResponseCodec responseCodec; - private DriverService service; + private final DriverService service; - /** - * Cretes an instance that sends requests and receives responses. - * - * @param additionalCommands is the mapped command repository - * @param addressOfRemoteServer is the url to connect to the Appium remote/local server - * @param httpClientFactory is the http client factory - */ - public AppiumCommandExecutor(Map additionalCommands, - URL addressOfRemoteServer, HttpClient.Factory httpClientFactory) { - checkNotNull(addressOfRemoteServer); - remoteServer = addressOfRemoteServer; - this.additionalCommands = additionalCommands; - this.client = httpClientFactory.createClient(remoteServer); + public AppiumCommandExecutor(Map additionalCommands, + URL addressOfRemoteServer, HttpClient.Factory httpClientFactory) { + super(additionalCommands, addressOfRemoteServer, httpClientFactory); + service = null; } - public AppiumCommandExecutor(Map additionalCommands, DriverService service, - HttpClient.Factory httpClientFactory) { - this(additionalCommands, service.getUrl(), httpClientFactory); + public AppiumCommandExecutor(Map additionalCommands, DriverService service, + HttpClient.Factory httpClientFactory) { + super(additionalCommands, service.getUrl(), httpClientFactory); this.service = service; } - public AppiumCommandExecutor(Map additionalCommands, - URL addressOfRemoteServer) { + public AppiumCommandExecutor(Map additionalCommands, + URL addressOfRemoteServer) { this(additionalCommands, addressOfRemoteServer, new ApacheHttpClient.Factory()); } - public AppiumCommandExecutor(Map additionalCommands, - DriverService service) { + public AppiumCommandExecutor(Map additionalCommands, + DriverService service) { this(additionalCommands, service, new ApacheHttpClient.Factory()); } - public URL getAddressOfRemoteServer() { - return remoteServer; - } - - private Response doExecute(Command command) throws IOException, WebDriverException { - if (command.getSessionId() == null) { - if (QUIT.equals(command.getName())) { - return new Response(); - } - if (!GET_ALL_SESSIONS.equals(command.getName()) - && !NEW_SESSION.equals(command.getName())) { - throw new NoSuchSessionException( - "Session ID is null. Using WebDriver after calling quit()?"); - } - } - - if (NEW_SESSION.equals(command.getName())) { - if (commandCodec != null) { - throw new SessionNotCreatedException("Session already exists"); - } - AppiumProtocolHandShake handshake = new AppiumProtocolHandShake(); - AppiumProtocolHandShake.Result result = handshake.createSession(client, command); - Dialect dialect = result.getDialect(); - commandCodec = dialect.getCommandCodec(); - - additionalCommands.forEach((key, value) -> { - checkNotNull(key); - checkNotNull(value); - commandCodec.defineCommand(key, value.getMethod(), value.getUrl()); - } ); - - responseCodec = dialect.getResponseCodec(); - return result.createResponse(); - } - - if (commandCodec == null || responseCodec == null) { - throw new WebDriverException( - "No command or response codec has been defined. Unable to proceed"); - } - - HttpRequest httpRequest = commandCodec.encode(command); - try { - HttpResponse httpResponse = client.execute(httpRequest, true); - - Response response = responseCodec.decode(httpResponse); - if (response.getSessionId() == null) { - if (httpResponse.getTargetHost() != null) { - response.setSessionId(HttpSessionId.getSessionId(httpResponse.getTargetHost())); - } else { - response.setSessionId(command.getSessionId().toString()); - } - } - if (QUIT.equals(command.getName())) { - client.close(); - } - return response; - } catch (UnsupportedCommandException e) { - if (e.getMessage() == null || "".equals(e.getMessage())) { - throw new UnsupportedOperationException( - "No information from server. Command name was: " + command.getName(), - e.getCause()); - } - throw e; - } - } - @Override public Response execute(Command command) throws IOException, WebDriverException { if (DriverCommand.NEW_SESSION.equals(command.getName()) && service != null) { service.start(); } try { - return doExecute(command); + return super.execute(command); } catch (Throwable t) { - Throwable rootCause = getRootCause(t); + Throwable rootCause = Throwables.getRootCause(t); if (rootCause instanceof ConnectException - && rootCause.getMessage().contains("Connection refused") - && service != null) { + && rootCause.getMessage().contains("Connection refused") + && service != null) { if (service.isRunning()) { throw new WebDriverException("The session is closed!", t); } @@ -182,4 +90,4 @@ private Response doExecute(Command command) throws IOException, WebDriverExcepti } } -} +} \ No newline at end of file diff --git a/src/main/java/io/appium/java_client/remote/AppiumProtocolHandShake.java b/src/main/java/io/appium/java_client/remote/AppiumProtocolHandShake.java deleted file mode 100644 index 12dab4d39..000000000 --- a/src/main/java/io/appium/java_client/remote/AppiumProtocolHandShake.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.appium.java_client.remote; - -import static com.google.common.base.Charsets.UTF_8; -import static com.google.common.net.HttpHeaders.CONTENT_LENGTH; -import static com.google.common.net.HttpHeaders.CONTENT_TYPE; -import static com.google.common.net.MediaType.JSON_UTF_8; -import static java.util.Optional.ofNullable; -import static org.openqa.selenium.remote.ErrorCodes.SESSION_NOT_CREATED; -import static org.openqa.selenium.remote.ErrorCodes.SUCCESS; - -import com.google.common.base.Preconditions; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -import org.openqa.selenium.Capabilities; -import org.openqa.selenium.SessionNotCreatedException; -import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.remote.BeanToJsonConverter; -import org.openqa.selenium.remote.Command; -import org.openqa.selenium.remote.DesiredCapabilities; -import org.openqa.selenium.remote.Dialect; -import org.openqa.selenium.remote.ErrorHandler; -import org.openqa.selenium.remote.JsonException; -import org.openqa.selenium.remote.JsonToBeanConverter; -import org.openqa.selenium.remote.Response; -import org.openqa.selenium.remote.SessionId; -import org.openqa.selenium.remote.http.HttpClient; -import org.openqa.selenium.remote.http.HttpMethod; -import org.openqa.selenium.remote.http.HttpRequest; -import org.openqa.selenium.remote.http.HttpResponse; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -class AppiumProtocolHandShake { - - public Result createSession(HttpClient client, Command command) - throws IOException, WebDriverException { - - Capabilities desired = ofNullable((Capabilities) command.getParameters().get("desiredCapabilities")) - .orElseGet(DesiredCapabilities::new); - - Capabilities required = ofNullable((Capabilities) command.getParameters().get("requiredCapabilities")) - .orElseGet(DesiredCapabilities::new); - - JsonParser parser = new JsonParser(); - JsonElement des = parser.parse(new BeanToJsonConverter().convert(desired)); - JsonElement req = parser.parse(new BeanToJsonConverter().convert(required)); - - JsonObject jsonObject = new JsonObject(); - - amendW3CParameters(jsonObject, des, req); - amendOssParamters(jsonObject, des, req); - Optional result = createSession(client, jsonObject); - - return ofNullable(result.orElseGet(() -> { - JsonObject jsonObject1 = new JsonObject(); - amendOssParamters(jsonObject1, des, req); - - try { - return createSession(client, jsonObject1).orElseGet(() -> { - JsonObject jsonObject2 = new JsonObject(); - amendW3CParameters(jsonObject2, des, req); - - try { - return createSession(client, jsonObject2).orElse(null); - } catch (IOException e) { - throw new WebDriverException(e); - } - }); - } catch (IOException e) { - throw new WebDriverException(e); - } - })).orElseThrow(() -> new SessionNotCreatedException( - String.format( - "Unable to create new remote session. " - + "desired capabilities = %s, required capabilities = %s", - desired, - required))); - } - - private Optional createSession(HttpClient client, JsonObject params) - throws IOException { - // Create the http request and send it - HttpRequest request = new HttpRequest(HttpMethod.POST, "/session"); - String content = params.toString(); - byte[] data = content.getBytes(UTF_8); - - request.setHeader(CONTENT_LENGTH, String.valueOf(data.length)); - request.setHeader(CONTENT_TYPE, JSON_UTF_8.toString()); - request.setContent(data); - HttpResponse response = client.execute(request, true); - - Map jsonBlob = new HashMap<>(); - String resultString = response.getContentString(); - try { - jsonBlob = new JsonToBeanConverter().convert(Map.class, resultString); - } catch (ClassCastException e) { - return Optional.empty(); - } catch (JsonException e) { - // Fine. Handle that below - } - - // If the result looks positive, return the result. - Object sessionId = jsonBlob.get("sessionId"); - Object value = jsonBlob.get("value"); - Object w3cError = jsonBlob.get("error"); - Object ossStatus = jsonBlob.get("status"); - Map capabilities = null; - if (value != null && value instanceof Map) { - capabilities = (Map) value; - } else if (value != null && value instanceof Capabilities) { - capabilities = ((Capabilities) capabilities).asMap(); - } - - if (response.getStatus() == HttpURLConnection.HTTP_OK - && sessionId != null && capabilities != null) { - Dialect dialect = ossStatus == null ? Dialect.W3C : Dialect.OSS; - return Optional.of( - new Result(dialect, String.valueOf(sessionId), capabilities)); - } - - // If the result was an error that we believe has to do with the remote end failing to start the - // session, create an exception and throw it. - Response tempResponse = null; - if ("session not created".equals(w3cError)) { - tempResponse = new Response(null); - tempResponse.setStatus(SESSION_NOT_CREATED); - tempResponse.setValue(jsonBlob); - } else if ( - ossStatus instanceof Number - && ((Number) ossStatus).intValue() == SESSION_NOT_CREATED) { - tempResponse = new Response(null); - tempResponse.setStatus(SESSION_NOT_CREATED); - tempResponse.setValue(jsonBlob); - } - - if (tempResponse != null) { - new ErrorHandler().throwIfResponseFailed(tempResponse, 0); - } - - // Otherwise, just return empty. - return Optional.empty(); - } - - private void amendW3CParameters(JsonObject jsonObject, JsonElement desired, - JsonElement required) { - JsonArray result = new JsonArray(); - JsonObject desiredJson = new JsonObject(); - JsonObject requiredJson = new JsonObject(); - - desiredJson.add("desiredCapabilities", desired); - requiredJson.add("requiredCapabilities", required); - - result.add(desiredJson); - result.add(requiredJson); - - jsonObject.add("capabilities", result); - } - - private void amendOssParamters( - JsonObject jsonObject, JsonElement desired, - JsonElement required) { - jsonObject.add("desiredCapabilities", desired); - jsonObject.add("requiredCapabilities", required); - } - - public class Result { - private final Dialect dialect; - private final Map capabilities; - private final SessionId sessionId; - - private Result(Dialect dialect, String sessionId, Map capabilities) { - this.dialect = dialect; - this.sessionId = new SessionId(Preconditions.checkNotNull(sessionId)); - this.capabilities = capabilities; - } - - public Dialect getDialect() { - return dialect; - } - - public Response createResponse() { - Response response = new Response(sessionId); - response.setValue(capabilities); - response.setStatus(SUCCESS); - return response; - } - - @Override - public String toString() { - return String.format("%s: %s", dialect, capabilities); - } - } -} diff --git a/src/main/java/io/appium/java_client/windows/WindowsDriver.java b/src/main/java/io/appium/java_client/windows/WindowsDriver.java index 97cb366cc..5c03692ec 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsDriver.java +++ b/src/main/java/io/appium/java_client/windows/WindowsDriver.java @@ -22,11 +22,11 @@ import io.appium.java_client.FindsByWindowsAutomation; import io.appium.java_client.HidesKeyboardWithKeyName; import io.appium.java_client.PressesKeyCode; -import io.appium.java_client.remote.AppiumCommandExecutor; import io.appium.java_client.service.local.AppiumDriverLocalService; import io.appium.java_client.service.local.AppiumServiceBuilder; import org.openqa.selenium.Capabilities; import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.HttpCommandExecutor; import org.openqa.selenium.remote.http.HttpClient; import java.net.URL; @@ -35,7 +35,7 @@ public class WindowsDriver extends AppiumDriver implements PressesKeyCode, HidesKeyboardWithKeyName, FindsByWindowsAutomation { - public WindowsDriver(AppiumCommandExecutor executor, Capabilities capabilities) { + public WindowsDriver(HttpCommandExecutor executor, Capabilities capabilities) { super(executor, substituteMobilePlatform(capabilities, WINDOWS)); } From f5ee59565c9086a87b2089b7c843ac028c51d311 Mon Sep 17 00:00:00 2001 From: Sergey Tikhomirov Date: Fri, 4 Aug 2017 01:14:24 +0300 Subject: [PATCH 2/5] Improvement with optional --- .../remote/AppiumCommandExecutor.java | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index a47043b20..fd3c91f49 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -17,7 +17,9 @@ package io.appium.java_client.remote; import static com.google.common.base.Throwables.throwIfUnchecked; +import static java.util.Optional.ofNullable; +import com.google.common.base.Function; import com.google.common.base.Throwables; import org.openqa.selenium.WebDriverException; @@ -61,9 +63,15 @@ public AppiumCommandExecutor(Map additionalCommands, this(additionalCommands, service, new ApacheHttpClient.Factory()); } - @Override public Response execute(Command command) throws IOException, WebDriverException { - if (DriverCommand.NEW_SESSION.equals(command.getName()) && service != null) { - service.start(); + @Override public Response execute(Command command) throws WebDriverException { + if (DriverCommand.NEW_SESSION.equals(command.getName())) { + ofNullable(service).ifPresent(driverService -> { + try { + driverService.start(); + } catch (IOException e) { + throw new WebDriverException(e.getMessage(), e); + } + }); } try { @@ -71,15 +79,14 @@ public AppiumCommandExecutor(Map additionalCommands, } catch (Throwable t) { Throwable rootCause = Throwables.getRootCause(t); if (rootCause instanceof ConnectException - && rootCause.getMessage().contains("Connection refused") - && service != null) { - if (service.isRunning()) { - throw new WebDriverException("The session is closed!", t); - } + && rootCause.getMessage().contains("Connection refused")) { + throw ofNullable(service).map((Function) service -> { + if (service.isRunning()) { + return new WebDriverException("The session is closed!", rootCause); + } - if (!service.isRunning()) { - throw new WebDriverException("The appium server has accidentally died!", t); - } + return new WebDriverException("The appium server has accidentally died!", rootCause); + }).orElse(new WebDriverException(rootCause.getMessage(), rootCause)); } throwIfUnchecked(t); throw new WebDriverException(t); From 5996661e2a514fab07bb7ff9a0671e061c76b724 Mon Sep 17 00:00:00 2001 From: Sergey Tikhomirov Date: Fri, 4 Aug 2017 19:33:11 +0300 Subject: [PATCH 3/5] service field was turned into serviceOptional --- .../remote/AppiumCommandExecutor.java | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index fd3c91f49..fb3d985f4 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -16,10 +16,12 @@ package io.appium.java_client.remote; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Throwables.throwIfUnchecked; import static java.util.Optional.ofNullable; import com.google.common.base.Function; +import com.google.common.base.Supplier; import com.google.common.base.Throwables; import org.openqa.selenium.WebDriverException; @@ -36,22 +38,31 @@ import java.net.ConnectException; import java.net.URL; import java.util.Map; +import java.util.Optional; public class AppiumCommandExecutor extends HttpCommandExecutor { - private final DriverService service; + private final Optional serviceOptional; - public AppiumCommandExecutor(Map additionalCommands, - URL addressOfRemoteServer, HttpClient.Factory httpClientFactory) { - super(additionalCommands, addressOfRemoteServer, httpClientFactory); - service = null; + private AppiumCommandExecutor(Map additionalCommands, DriverService service, + URL addressOfRemoteServer, + HttpClient.Factory httpClientFactory) { + super(additionalCommands, + ofNullable(service) + .map((Function) DriverService::getUrl) + .orElse(addressOfRemoteServer), httpClientFactory); + serviceOptional = ofNullable(service); } public AppiumCommandExecutor(Map additionalCommands, DriverService service, HttpClient.Factory httpClientFactory) { - super(additionalCommands, service.getUrl(), httpClientFactory); - this.service = service; + this(additionalCommands, checkNotNull(service), null, httpClientFactory); } + public AppiumCommandExecutor(Map additionalCommands, + URL addressOfRemoteServer, HttpClient.Factory httpClientFactory) { + this(additionalCommands, null, checkNotNull(addressOfRemoteServer), httpClientFactory); + } + public AppiumCommandExecutor(Map additionalCommands, URL addressOfRemoteServer) { @@ -65,7 +76,7 @@ public AppiumCommandExecutor(Map additionalCommands, @Override public Response execute(Command command) throws WebDriverException { if (DriverCommand.NEW_SESSION.equals(command.getName())) { - ofNullable(service).ifPresent(driverService -> { + serviceOptional.ifPresent(driverService -> { try { driverService.start(); } catch (IOException e) { @@ -80,21 +91,20 @@ public AppiumCommandExecutor(Map additionalCommands, Throwable rootCause = Throwables.getRootCause(t); if (rootCause instanceof ConnectException && rootCause.getMessage().contains("Connection refused")) { - throw ofNullable(service).map((Function) service -> { + throw serviceOptional.map((Function) service -> { if (service.isRunning()) { return new WebDriverException("The session is closed!", rootCause); } return new WebDriverException("The appium server has accidentally died!", rootCause); - }).orElse(new WebDriverException(rootCause.getMessage(), rootCause)); + }).orElseGet((Supplier) () -> new WebDriverException(rootCause.getMessage(), rootCause)); } throwIfUnchecked(t); throw new WebDriverException(t); } finally { - if (DriverCommand.QUIT.equals(command.getName()) && service != null) { - service.stop(); + if (DriverCommand.QUIT.equals(command.getName())) { + serviceOptional.ifPresent(DriverService::stop); } } } - } \ No newline at end of file From b83b090f747d1d61c8376a7a57acb78d019f41e9 Mon Sep 17 00:00:00 2001 From: Sergey Tikhomirov Date: Fri, 4 Aug 2017 19:41:35 +0300 Subject: [PATCH 4/5] check style issues were fixed --- .../io/appium/java_client/remote/AppiumCommandExecutor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index fb3d985f4..baa8306fb 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -58,6 +58,7 @@ public AppiumCommandExecutor(Map additionalCommands, Driver HttpClient.Factory httpClientFactory) { this(additionalCommands, checkNotNull(service), null, httpClientFactory); } + public AppiumCommandExecutor(Map additionalCommands, URL addressOfRemoteServer, HttpClient.Factory httpClientFactory) { this(additionalCommands, null, checkNotNull(addressOfRemoteServer), httpClientFactory); @@ -97,7 +98,8 @@ public AppiumCommandExecutor(Map additionalCommands, } return new WebDriverException("The appium server has accidentally died!", rootCause); - }).orElseGet((Supplier) () -> new WebDriverException(rootCause.getMessage(), rootCause)); + }).orElseGet((Supplier) () -> + new WebDriverException(rootCause.getMessage(), rootCause)); } throwIfUnchecked(t); throw new WebDriverException(t); From dd15bc0e7ef1fae3936792534a05b81e03a6c899 Mon Sep 17 00:00:00 2001 From: Sergey Tikhomirov Date: Sat, 5 Aug 2017 01:04:59 +0300 Subject: [PATCH 5/5] removal of the unnecessary casting --- .../appium/java_client/remote/AppiumCommandExecutor.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java index baa8306fb..b62e99e01 100644 --- a/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java +++ b/src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java @@ -20,7 +20,6 @@ import static com.google.common.base.Throwables.throwIfUnchecked; import static java.util.Optional.ofNullable; -import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.base.Throwables; @@ -49,7 +48,7 @@ private AppiumCommandExecutor(Map additionalCommands, Drive HttpClient.Factory httpClientFactory) { super(additionalCommands, ofNullable(service) - .map((Function) DriverService::getUrl) + .map(DriverService::getUrl) .orElse(addressOfRemoteServer), httpClientFactory); serviceOptional = ofNullable(service); } @@ -58,7 +57,7 @@ public AppiumCommandExecutor(Map additionalCommands, Driver HttpClient.Factory httpClientFactory) { this(additionalCommands, checkNotNull(service), null, httpClientFactory); } - + public AppiumCommandExecutor(Map additionalCommands, URL addressOfRemoteServer, HttpClient.Factory httpClientFactory) { this(additionalCommands, null, checkNotNull(addressOfRemoteServer), httpClientFactory); @@ -92,7 +91,7 @@ public AppiumCommandExecutor(Map additionalCommands, Throwable rootCause = Throwables.getRootCause(t); if (rootCause instanceof ConnectException && rootCause.getMessage().contains("Connection refused")) { - throw serviceOptional.map((Function) service -> { + throw serviceOptional.map(service -> { if (service.isRunning()) { return new WebDriverException("The session is closed!", rootCause); }