Skip to content

Commit e0e5ae0

Browse files
Merge pull request #682 from TikhomirovSergey/w3c_compatibility_issue_fix
#655 FIX
2 parents 46a821a + dd15bc0 commit e0e5ae0

File tree

7 files changed

+64
-353
lines changed

7 files changed

+64
-353
lines changed

src/main/java/io/appium/java_client/AppiumDriver.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.openqa.selenium.remote.DriverCommand;
4343
import org.openqa.selenium.remote.ErrorHandler;
4444
import org.openqa.selenium.remote.ExecuteMethod;
45+
import org.openqa.selenium.remote.HttpCommandExecutor;
4546
import org.openqa.selenium.remote.Response;
4647
import org.openqa.selenium.remote.html5.RemoteLocationContext;
4748
import org.openqa.selenium.remote.http.HttpClient;
@@ -82,7 +83,7 @@ public class AppiumDriver<T extends WebElement>
8283
* @param capabilities take a look
8384
* at {@link org.openqa.selenium.Capabilities}
8485
*/
85-
public AppiumDriver(AppiumCommandExecutor executor, Capabilities capabilities) {
86+
public AppiumDriver(HttpCommandExecutor executor, Capabilities capabilities) {
8687
super(executor, capabilities);
8788
this.executeMethod = new AppiumExecutionMethod(this);
8889
locationContext = new RemoteLocationContext(executeMethod);

src/main/java/io/appium/java_client/MobileCommand.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.google.common.collect.ImmutableMap;
2020

2121
import org.apache.commons.lang3.StringUtils;
22+
import org.openqa.selenium.remote.CommandInfo;
2223
import org.openqa.selenium.remote.http.HttpMethod;
2324

2425
import java.time.Duration;
@@ -79,7 +80,7 @@ public class MobileCommand {
7980
protected static final String SET_SETTINGS;
8081
protected static final String GET_CURRENT_PACKAGE;
8182

82-
public static final Map<String, AppiumCommandInfo> commandRepository;
83+
public static final Map<String, CommandInfo> commandRepository;
8384

8485
static {
8586
RESET = "reset";

src/main/java/io/appium/java_client/android/AndroidDriver.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@
2424
import io.appium.java_client.CommandExecutionHelper;
2525
import io.appium.java_client.FindsByAndroidUIAutomator;
2626
import io.appium.java_client.PressesKeyCode;
27-
import io.appium.java_client.remote.AppiumCommandExecutor;
2827
import io.appium.java_client.remote.MobilePlatform;
2928
import io.appium.java_client.service.local.AppiumDriverLocalService;
3029
import io.appium.java_client.service.local.AppiumServiceBuilder;
3130
import org.openqa.selenium.Capabilities;
3231
import org.openqa.selenium.WebElement;
32+
import org.openqa.selenium.remote.HttpCommandExecutor;
3333
import org.openqa.selenium.remote.http.HttpClient;
3434

3535
import java.net.URL;
@@ -58,7 +58,7 @@ public class AndroidDriver<T extends WebElement>
5858
* @param capabilities take a look
5959
* at {@link org.openqa.selenium.Capabilities}
6060
*/
61-
public AndroidDriver(AppiumCommandExecutor executor, Capabilities capabilities) {
61+
public AndroidDriver(HttpCommandExecutor executor, Capabilities capabilities) {
6262
super(executor, substituteMobilePlatform(capabilities, ANDROID_PLATFORM));
6363
}
6464

src/main/java/io/appium/java_client/ios/IOSDriver.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@
2424
import io.appium.java_client.FindsByIosNSPredicate;
2525
import io.appium.java_client.FindsByIosUIAutomation;
2626
import io.appium.java_client.HidesKeyboardWithKeyName;
27-
import io.appium.java_client.remote.AppiumCommandExecutor;
2827
import io.appium.java_client.remote.MobilePlatform;
2928
import io.appium.java_client.service.local.AppiumDriverLocalService;
3029
import io.appium.java_client.service.local.AppiumServiceBuilder;
3130
import org.openqa.selenium.Alert;
3231
import org.openqa.selenium.Capabilities;
3332
import org.openqa.selenium.WebElement;
3433
import org.openqa.selenium.remote.DriverCommand;
34+
import org.openqa.selenium.remote.HttpCommandExecutor;
3535
import org.openqa.selenium.remote.Response;
3636
import org.openqa.selenium.remote.http.HttpClient;
3737
import org.openqa.selenium.security.Credentials;
@@ -64,7 +64,7 @@ public class IOSDriver<T extends WebElement>
6464
* @param capabilities take a look
6565
* at {@link org.openqa.selenium.Capabilities}
6666
*/
67-
public IOSDriver(AppiumCommandExecutor executor, Capabilities capabilities) {
67+
public IOSDriver(HttpCommandExecutor executor, Capabilities capabilities) {
6868
super(executor, substituteMobilePlatform(capabilities, IOS_PLATFORM));
6969
}
7070

src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java

Lines changed: 54 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -17,169 +17,95 @@
1717
package io.appium.java_client.remote;
1818

1919
import static com.google.common.base.Preconditions.checkNotNull;
20-
import static com.google.common.base.Throwables.getRootCause;
2120
import static com.google.common.base.Throwables.throwIfUnchecked;
22-
import static org.openqa.selenium.remote.DriverCommand.GET_ALL_SESSIONS;
23-
import static org.openqa.selenium.remote.DriverCommand.NEW_SESSION;
24-
import static org.openqa.selenium.remote.DriverCommand.QUIT;
25-
26-
import io.appium.java_client.AppiumCommandInfo;
27-
import org.openqa.selenium.NoSuchSessionException;
28-
import org.openqa.selenium.SessionNotCreatedException;
29-
import org.openqa.selenium.UnsupportedCommandException;
21+
import static java.util.Optional.ofNullable;
22+
23+
import com.google.common.base.Supplier;
24+
import com.google.common.base.Throwables;
25+
3026
import org.openqa.selenium.WebDriverException;
3127
import org.openqa.selenium.remote.Command;
32-
import org.openqa.selenium.remote.CommandCodec;
33-
import org.openqa.selenium.remote.CommandExecutor;
34-
import org.openqa.selenium.remote.Dialect;
28+
import org.openqa.selenium.remote.CommandInfo;
3529
import org.openqa.selenium.remote.DriverCommand;
36-
import org.openqa.selenium.remote.HttpSessionId;
30+
import org.openqa.selenium.remote.HttpCommandExecutor;
3731
import org.openqa.selenium.remote.Response;
38-
import org.openqa.selenium.remote.ResponseCodec;
3932
import org.openqa.selenium.remote.http.HttpClient;
40-
import org.openqa.selenium.remote.http.HttpRequest;
41-
import org.openqa.selenium.remote.http.HttpResponse;
4233
import org.openqa.selenium.remote.internal.ApacheHttpClient;
4334
import org.openqa.selenium.remote.service.DriverService;
4435

4536
import java.io.IOException;
4637
import java.net.ConnectException;
4738
import java.net.URL;
4839
import java.util.Map;
40+
import java.util.Optional;
4941

50-
public class AppiumCommandExecutor implements CommandExecutor {
51-
52-
private final URL remoteServer;
53-
private final HttpClient client;
54-
private final Map<String, AppiumCommandInfo> additionalCommands;
55-
private CommandCodec<HttpRequest> commandCodec;
56-
private ResponseCodec<HttpResponse> responseCodec;
57-
private DriverService service;
58-
59-
/**
60-
* Cretes an instance that sends requests and receives responses.
61-
*
62-
* @param additionalCommands is the mapped command repository
63-
* @param addressOfRemoteServer is the url to connect to the Appium remote/local server
64-
* @param httpClientFactory is the http client factory
65-
*/
66-
public AppiumCommandExecutor(Map<String, AppiumCommandInfo> additionalCommands,
67-
URL addressOfRemoteServer, HttpClient.Factory httpClientFactory) {
68-
checkNotNull(addressOfRemoteServer);
69-
remoteServer = addressOfRemoteServer;
70-
this.additionalCommands = additionalCommands;
71-
this.client = httpClientFactory.createClient(remoteServer);
72-
}
42+
public class AppiumCommandExecutor extends HttpCommandExecutor {
7343

74-
public AppiumCommandExecutor(Map<String, AppiumCommandInfo> additionalCommands, DriverService service,
75-
HttpClient.Factory httpClientFactory) {
76-
this(additionalCommands, service.getUrl(), httpClientFactory);
77-
this.service = service;
78-
}
44+
private final Optional<DriverService> serviceOptional;
7945

80-
public AppiumCommandExecutor(Map<String, AppiumCommandInfo> additionalCommands,
81-
URL addressOfRemoteServer) {
82-
this(additionalCommands, addressOfRemoteServer, new ApacheHttpClient.Factory());
46+
private AppiumCommandExecutor(Map<String, CommandInfo> additionalCommands, DriverService service,
47+
URL addressOfRemoteServer,
48+
HttpClient.Factory httpClientFactory) {
49+
super(additionalCommands,
50+
ofNullable(service)
51+
.map(DriverService::getUrl)
52+
.orElse(addressOfRemoteServer), httpClientFactory);
53+
serviceOptional = ofNullable(service);
8354
}
8455

85-
public AppiumCommandExecutor(Map<String, AppiumCommandInfo> additionalCommands,
86-
DriverService service) {
87-
this(additionalCommands, service, new ApacheHttpClient.Factory());
56+
public AppiumCommandExecutor(Map<String, CommandInfo> additionalCommands, DriverService service,
57+
HttpClient.Factory httpClientFactory) {
58+
this(additionalCommands, checkNotNull(service), null, httpClientFactory);
8859
}
8960

90-
public URL getAddressOfRemoteServer() {
91-
return remoteServer;
61+
public AppiumCommandExecutor(Map<String, CommandInfo> additionalCommands,
62+
URL addressOfRemoteServer, HttpClient.Factory httpClientFactory) {
63+
this(additionalCommands, null, checkNotNull(addressOfRemoteServer), httpClientFactory);
9264
}
9365

94-
private Response doExecute(Command command) throws IOException, WebDriverException {
95-
if (command.getSessionId() == null) {
96-
if (QUIT.equals(command.getName())) {
97-
return new Response();
98-
}
99-
if (!GET_ALL_SESSIONS.equals(command.getName())
100-
&& !NEW_SESSION.equals(command.getName())) {
101-
throw new NoSuchSessionException(
102-
"Session ID is null. Using WebDriver after calling quit()?");
103-
}
104-
}
105-
106-
if (NEW_SESSION.equals(command.getName())) {
107-
if (commandCodec != null) {
108-
throw new SessionNotCreatedException("Session already exists");
109-
}
110-
AppiumProtocolHandShake handshake = new AppiumProtocolHandShake();
111-
AppiumProtocolHandShake.Result result = handshake.createSession(client, command);
112-
Dialect dialect = result.getDialect();
113-
commandCodec = dialect.getCommandCodec();
114-
115-
additionalCommands.forEach((key, value) -> {
116-
checkNotNull(key);
117-
checkNotNull(value);
118-
commandCodec.defineCommand(key, value.getMethod(), value.getUrl());
119-
} );
120-
121-
responseCodec = dialect.getResponseCodec();
122-
return result.createResponse();
123-
}
12466

125-
if (commandCodec == null || responseCodec == null) {
126-
throw new WebDriverException(
127-
"No command or response codec has been defined. Unable to proceed");
128-
}
67+
public AppiumCommandExecutor(Map<String, CommandInfo> additionalCommands,
68+
URL addressOfRemoteServer) {
69+
this(additionalCommands, addressOfRemoteServer, new ApacheHttpClient.Factory());
70+
}
12971

130-
HttpRequest httpRequest = commandCodec.encode(command);
131-
try {
132-
HttpResponse httpResponse = client.execute(httpRequest, true);
133-
134-
Response response = responseCodec.decode(httpResponse);
135-
if (response.getSessionId() == null) {
136-
if (httpResponse.getTargetHost() != null) {
137-
response.setSessionId(HttpSessionId.getSessionId(httpResponse.getTargetHost()));
138-
} else {
139-
response.setSessionId(command.getSessionId().toString());
140-
}
141-
}
142-
if (QUIT.equals(command.getName())) {
143-
client.close();
144-
}
145-
return response;
146-
} catch (UnsupportedCommandException e) {
147-
if (e.getMessage() == null || "".equals(e.getMessage())) {
148-
throw new UnsupportedOperationException(
149-
"No information from server. Command name was: " + command.getName(),
150-
e.getCause());
151-
}
152-
throw e;
153-
}
72+
public AppiumCommandExecutor(Map<String, CommandInfo> additionalCommands,
73+
DriverService service) {
74+
this(additionalCommands, service, new ApacheHttpClient.Factory());
15475
}
15576

156-
@Override public Response execute(Command command) throws IOException, WebDriverException {
157-
if (DriverCommand.NEW_SESSION.equals(command.getName()) && service != null) {
158-
service.start();
77+
@Override public Response execute(Command command) throws WebDriverException {
78+
if (DriverCommand.NEW_SESSION.equals(command.getName())) {
79+
serviceOptional.ifPresent(driverService -> {
80+
try {
81+
driverService.start();
82+
} catch (IOException e) {
83+
throw new WebDriverException(e.getMessage(), e);
84+
}
85+
});
15986
}
16087

16188
try {
162-
return doExecute(command);
89+
return super.execute(command);
16390
} catch (Throwable t) {
164-
Throwable rootCause = getRootCause(t);
91+
Throwable rootCause = Throwables.getRootCause(t);
16592
if (rootCause instanceof ConnectException
166-
&& rootCause.getMessage().contains("Connection refused")
167-
&& service != null) {
168-
if (service.isRunning()) {
169-
throw new WebDriverException("The session is closed!", t);
170-
}
171-
172-
if (!service.isRunning()) {
173-
throw new WebDriverException("The appium server has accidentally died!", t);
174-
}
93+
&& rootCause.getMessage().contains("Connection refused")) {
94+
throw serviceOptional.map(service -> {
95+
if (service.isRunning()) {
96+
return new WebDriverException("The session is closed!", rootCause);
97+
}
98+
99+
return new WebDriverException("The appium server has accidentally died!", rootCause);
100+
}).orElseGet((Supplier<WebDriverException>) () ->
101+
new WebDriverException(rootCause.getMessage(), rootCause));
175102
}
176103
throwIfUnchecked(t);
177104
throw new WebDriverException(t);
178105
} finally {
179-
if (DriverCommand.QUIT.equals(command.getName()) && service != null) {
180-
service.stop();
106+
if (DriverCommand.QUIT.equals(command.getName())) {
107+
serviceOptional.ifPresent(DriverService::stop);
181108
}
182109
}
183110
}
184-
185-
}
111+
}

0 commit comments

Comments
 (0)