2323import com .google .common .collect .ImmutableList ;
2424import com .google .common .collect .ImmutableMap ;
2525
26- import io . appium . java_client . remote . AndroidMobileCapabilityType ;
27- import io . appium . java_client . remote . MobileCapabilityType ;
26+ import com . google . gson . Gson ;
27+ import com . google . gson . GsonBuilder ;
2828import io .appium .java_client .service .local .flags .ServerArgument ;
2929
3030import org .apache .commons .io .IOUtils ;
3131import org .apache .commons .lang3 .StringUtils ;
3232import org .apache .commons .lang3 .SystemUtils ;
3333import org .apache .commons .validator .routines .InetAddressValidator ;
3434import org .openqa .selenium .Capabilities ;
35- import org .openqa .selenium .Platform ;
3635import org .openqa .selenium .os .ExecutableFinder ;
3736import org .openqa .selenium .remote .BrowserType ;
3837import org .openqa .selenium .remote .DesiredCapabilities ;
5453import java .util .concurrent .TimeUnit ;
5554import java .util .function .Function ;
5655
57-
5856public final class AppiumServiceBuilder
5957 extends DriverService .Builder <AppiumDriverLocalService , AppiumServiceBuilder > {
6058
@@ -73,8 +71,6 @@ public final class AppiumServiceBuilder
7371 private static final String NODE_PATH = "NODE_BINARY_PATH" ;
7472
7573 public static final String BROADCAST_IP_ADDRESS = "0.0.0.0" ;
76- private static final List <String > PATH_CAPABILITIES = ImmutableList .of (AndroidMobileCapabilityType .KEYSTORE_PATH ,
77- AndroidMobileCapabilityType .CHROMEDRIVER_EXECUTABLE , MobileCapabilityType .APP );
7874 private static final Path APPIUM_PATH_SUFFIX = Paths .get ("appium" , "build" , "lib" , "main.js" );
7975 public static final int DEFAULT_APPIUM_PORT = 4723 ;
8076 private final Map <String , String > serverArguments = new HashMap <>();
@@ -300,79 +296,15 @@ private void loadPathToMainScript() {
300296 this .appiumJS = findMainScript ();
301297 }
302298
303- private String parseCapabilitiesIfWindows () {
304- String result = StringUtils .EMPTY ;
305-
306- if (capabilities != null ) {
307- Map <String , ?> capabilitiesMap = capabilities .asMap ();
308- Set <? extends Map .Entry <String , ?>> entries = capabilitiesMap .entrySet ();
309-
310- for (Map .Entry <String , ?> entry : entries ) {
311- Object value = entry .getValue ();
312-
313- if (value == null ) {
314- continue ;
315- }
316-
317- if (String .class .isAssignableFrom (value .getClass ())) {
318- if (PATH_CAPABILITIES .contains (entry .getKey ())) {
319- value = "\\ \" " + String .valueOf (value ).replace ("\\ " , "/" ) + "\\ \" " ;
320- } else {
321- value = "\\ \" " + value + "\\ \" " ;
322- }
323- } else {
324- value = String .valueOf (value );
325- }
326-
327- String key = "\\ \" " + entry .getKey () + "\\ \" " ;
328- if (StringUtils .isBlank (result )) {
329- result = key + ": " + value ;
330- } else {
331- result = result + ", " + key + ": " + value ;
332- }
333- }
334- }
335-
336- return "{" + result + "}" ;
337- }
338-
339- private String parseCapabilitiesIfUNIX () {
340- String result = StringUtils .EMPTY ;
341-
342- if (capabilities != null ) {
343- Map <String , ?> capabilitiesMap = capabilities .asMap ();
344- Set <? extends Map .Entry <String , ?>> entries = capabilitiesMap .entrySet ();
345-
346- for (Map .Entry <String , ?> entry : entries ) {
347- Object value = entry .getValue ();
348-
349- if (value == null ) {
350- continue ;
351- }
352-
353- if (String .class .isAssignableFrom (value .getClass ())) {
354- value = "\" " + value + "\" " ;
355- } else {
356- value = String .valueOf (value );
357- }
358-
359- String key = "\" " + entry .getKey () + "\" " ;
360- if (StringUtils .isBlank (result )) {
361- result = key + ": " + value ;
362- } else {
363- result = result + ", " + key + ": " + value ;
364- }
365- }
366- }
367-
368- return "{" + result + "}" ;
369- }
370-
371- private String parseCapabilities () {
372- if (Platform .getCurrent ().is (Platform .WINDOWS )) {
373- return parseCapabilitiesIfWindows ();
374- }
375- return parseCapabilitiesIfUNIX ();
299+ private String capabilitiesToCmdlineArg () {
300+ Gson gson = new GsonBuilder ()
301+ .disableHtmlEscaping ()
302+ .serializeNulls ()
303+ .create ();
304+ // Selenium internally uses org.apache.commons.exec.CommandLine
305+ // which has the following known bug in its arguments parser:
306+ // https://issues.apache.org/jira/browse/EXEC-54
307+ return gson .toJson (capabilities .asMap ());
376308 }
377309
378310 @ Override
@@ -418,7 +350,7 @@ protected ImmutableList<String> createArgs() {
418350
419351 if (capabilities != null ) {
420352 argList .add ("--default-capabilities" );
421- argList .add (parseCapabilities ());
353+ argList .add (capabilitiesToCmdlineArg ());
422354 }
423355
424356 return new ImmutableList .Builder <String >().addAll (argList ).build ();
0 commit comments