Skip to content

Commit 4877fec

Browse files
author
Harshit Vasu
committed
Merge branch 'master' of github.com:jenkinsci/browserstack-integration-plugin into Add-support-for-DSL-with-and-without-local-parameters
2 parents a016553 + 176c2ff commit 4877fec

17 files changed

+338
-134
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ hs_err_pid*
2222
.project
2323
.settings/
2424
/bin/
25+
.vscode/

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
<p align="center">
2+
<a href="https://browserstack.com"><img alt="BrowserStack Logo" src="https://d98b8t1nnulk5.cloudfront.net/production/images/layout/logo-invoice.svg"></a>
3+
</p>
4+
15
# Overview
26
[BrowserStack](https://browserstack.com) gives instant access to 2000+ real mobile devices and browsers that enables developers to test their websites and mobile applications without requiring to install or maintain an internal lab of virtual machines, devices, or emulators.
37

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
</parent>
1111

1212
<artifactId>browserstack-integration</artifactId>
13-
<version>1.1.10-SNAPSHOT</version>
13+
<version>1.2.1-SNAPSHOT</version>
1414
<packaging>hpi</packaging>
1515

1616
<name>BrowserStack</name>
@@ -150,13 +150,13 @@
150150
<dependency>
151151
<groupId>com.browserstack</groupId>
152152
<artifactId>automate-client-java</artifactId>
153-
<version>0.6</version>
153+
<version>0.7</version>
154154
</dependency>
155155

156156
<dependency>
157157
<groupId>com.browserstack</groupId>
158158
<artifactId>browserstack-local-java</artifactId>
159-
<version>1.0.3</version>
159+
<version>1.0.6</version>
160160
</dependency>
161161

162162
<dependency>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.browserstack.automate.ci.common.clienthandler;
2+
3+
import com.browserstack.appautomate.AppAutomateClient;
4+
import com.browserstack.automate.AutomateClient;
5+
import com.browserstack.automate.ci.common.enums.ProjectType;
6+
import com.browserstack.automate.ci.common.proxysettings.JenkinsProxySettings;
7+
import com.browserstack.client.BrowserStackClient;
8+
9+
import javax.annotation.Nonnull;
10+
import javax.annotation.Nullable;
11+
import java.io.PrintStream;
12+
13+
public class ClientHandler {
14+
15+
/**
16+
* Returns BrowserStackClient based on Project, i.e Automate or App Automate.
17+
* Also decides and sets the proxy for the client
18+
* @param project ProjectType
19+
* @param username Username of BrowserStack
20+
* @param accessKey Access Key of BrowserStack
21+
* @param customProxy Custom Proxy String
22+
* @param logger Logger
23+
* @return BrowserStackClient
24+
*/
25+
public static BrowserStackClient getBrowserStackClient(@Nonnull final ProjectType project, @Nonnull final String username,
26+
@Nonnull final String accessKey, @Nullable final String customProxy,
27+
@Nullable final PrintStream logger) {
28+
BrowserStackClient client = decideAndGetClient(project, username, accessKey);
29+
30+
JenkinsProxySettings proxy;
31+
if (customProxy != null) {
32+
proxy = new JenkinsProxySettings(customProxy, logger);
33+
} else {
34+
proxy = new JenkinsProxySettings(logger);
35+
}
36+
37+
if (proxy.hasProxy()) {
38+
client.setProxy(proxy.getHost(), proxy.getPort(), proxy.getUsername(), proxy.getPassword());
39+
}
40+
41+
return client;
42+
}
43+
44+
/**
45+
* Initializes BrowserStack client based on project type
46+
* @param project ProjectType
47+
* @param username Username of BrowserStack
48+
* @param accessKey Access Key of BrowserStack
49+
* @return BrowserStackClient
50+
*/
51+
private static BrowserStackClient decideAndGetClient(@Nonnull final ProjectType project, @Nonnull final String username, @Nonnull final String accessKey) {
52+
if (project == ProjectType.APP_AUTOMATE) {
53+
return new AppAutomateClient(username, accessKey);
54+
}
55+
56+
return new AutomateClient(username, accessKey);
57+
}
58+
}
Lines changed: 184 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,219 @@
11
package com.browserstack.automate.ci.common.proxysettings;
22

3+
import com.browserstack.automate.ci.common.Tools;
34
import hudson.ProxyConfiguration;
5+
import hudson.Util;
46
import jenkins.model.Jenkins;
57

8+
import javax.annotation.Nonnull;
9+
import javax.annotation.Nullable;
10+
import java.io.PrintStream;
611
import java.net.InetSocketAddress;
712
import java.net.Proxy;
8-
import java.util.regex.Matcher;
9-
import java.util.regex.Pattern;
13+
import java.net.URL;
14+
15+
import static com.browserstack.automate.ci.common.logger.PluginLogger.log;
16+
import static com.browserstack.automate.ci.common.logger.PluginLogger.logDebug;
17+
1018
public class JenkinsProxySettings {
1119

1220
private static final ProxyConfiguration jenkinsProxy = Jenkins.getInstanceOrNull() != null ? Jenkins.getInstanceOrNull().proxy : null;
13-
private static final String protocol = "https";
14-
private static String proxyHost;
15-
private static int proxyPort;
16-
private static String proxyUser;
17-
private static String proxyPassword;
18-
static {
19-
final String systemProxyHost = System.getProperty(protocol + ".proxyHost");
20-
final int systemProxyPort = Integer.parseInt(System.getProperty(protocol + ".proxyPort", "0"));
21-
final String systemProxyUser = System.getProperty(protocol + ".proxyUser");
22-
final String systemProxyPassword = System.getProperty(protocol + ".proxyPassword");
23-
if(systemProxyHost!=null && systemProxyPort!=0){
24-
proxyHost = systemProxyHost;
25-
proxyPort = systemProxyPort;
26-
if(systemProxyUser!=null && systemProxyPassword!=null){
27-
proxyUser = systemProxyUser;
28-
proxyPassword = systemProxyPassword;
21+
22+
private static final String jarProxyHost = System.getProperty("https.proxyHost");
23+
private static final int jarProxyPort = Integer.parseInt(System.getProperty("https.proxyPort", "443"));
24+
private static final String jarProxyUser = System.getProperty("https.proxyUser");
25+
private static final String jarProxyPassword = System.getProperty("https.proxyPassword");
26+
27+
private static final String systemHttpProxyEnv = System.getenv("http_proxy");
28+
private static final String systemHttpsProxyEnv = System.getenv("https_proxy");
29+
30+
private String finalProxyHost;
31+
private int finalProxyPort;
32+
private String finalProxyUsername;
33+
private String finalProxyPassword;
34+
35+
private boolean hasProxy;
36+
37+
private transient PrintStream logger;
38+
39+
/**
40+
* Constructor for JenkinsProxySettings with Priority for Custom Proxy
41+
*
42+
* @param customProxy Custom Proxy String
43+
* @param logger Logger
44+
*/
45+
public JenkinsProxySettings(@Nonnull final String customProxy, @Nullable PrintStream logger) {
46+
this.logger = logger;
47+
decideJenkinsProxy(customProxy);
48+
}
49+
50+
/**
51+
* Constructor for JenkinsProxySettings
52+
*
53+
* @param logger Logger
54+
*/
55+
public JenkinsProxySettings(@Nullable PrintStream logger) {
56+
this.logger = logger;
57+
decideJenkinsProxy(null);
58+
}
59+
60+
/**
61+
* Verifies the format of the Proxy String
62+
*
63+
* @param proxyString String
64+
* @param proxyType Type/Source of Proxy
65+
* @return
66+
*/
67+
private URL verifyAndGetProxyURL(final String proxyString, final String proxyType) {
68+
try {
69+
final URL proxyUrl = new URL(proxyString);
70+
if (proxyUrl.getHost() != null && proxyUrl.getHost().length() == 0)
71+
throw new Error("Empty host in proxy");
72+
73+
String userInfo = proxyUrl.getUserInfo();
74+
if (userInfo != null) {
75+
if (userInfo.split(":").length != 2) {
76+
throw new Error("Invalid authentication params in proxy");
77+
}
2978
}
79+
80+
return proxyUrl;
81+
} catch (Exception e) {
82+
if (logger != null)
83+
logDebug(logger, String.format("Invalid Proxy String: %s, Proxy Type: %s. Error: %s", proxyString, proxyType, e.toString()));
84+
return null;
3085
}
86+
}
3187

32-
if(proxyHost==null && proxyPort==0 && jenkinsProxy!=null){
33-
final String host = jenkinsProxy.name;
34-
final int port = jenkinsProxy.port;
35-
final String user = jenkinsProxy.getUserName();
36-
final String password = jenkinsProxy.getPassword();
37-
if(host!=null && port!=0){
38-
proxyHost = host;
39-
proxyPort = port;
40-
if(user!=null && password!=null){
41-
proxyUser = user;
42-
proxyPassword = password;
43-
}
88+
/**
89+
* Decides Proxy for the Plugin. Priority:
90+
* 0. Custom Proxy passed as input
91+
* 1. `https_proxy` Environment Variable
92+
* 2. `http_proxy` Environment Variable
93+
* 3. Jenkins Proxy Configuration
94+
* 4. JAR Proxy arguments, i.e. `https.proxyHost` etc.
95+
*
96+
* @param customProxyString Custom Proxy String
97+
*/
98+
private void decideJenkinsProxy(final String customProxyString) {
99+
URL proxyUrl = null;
100+
101+
// Verifies the custom proxy string
102+
if (customProxyString != null) {
103+
proxyUrl = verifyAndGetProxyURL(customProxyString, "ENV_VAR");
104+
}
105+
106+
// Looks for System level `https_proxy`. If not, looks for `http_proxy`
107+
if (proxyUrl == null && getSystemProxyString() != null) {
108+
proxyUrl = verifyAndGetProxyURL(getSystemProxyString(), "SYSTEM_ENV_VAR");
109+
}
110+
111+
// Looks for Jenkins Proxy
112+
if (proxyUrl == null && jenkinsProxy != null) {
113+
this.finalProxyHost = jenkinsProxy.name;
114+
this.finalProxyPort = jenkinsProxy.port;
115+
116+
if (Util.fixEmpty(jenkinsProxy.getUserName()) != null && Util.fixEmpty(jenkinsProxy.getPassword()) != null) {
117+
this.finalProxyUsername = jenkinsProxy.getUserName();
118+
this.finalProxyPassword = jenkinsProxy.getPassword();
44119
}
45120
}
46-
if(proxyHost==null && proxyPort==0){
47-
String proxyEnv = System.getenv("https_proxy");
48-
String authRegex = "(https:\\/\\/)(.+):(.+)@(.+):(\\d+)";
49-
String basicRegex = "(https:\\/\\/)(.+):(\\d+)";
50-
51-
if(proxyEnv!=null && proxyEnv.matches(authRegex)){
52-
Pattern r = Pattern.compile(authRegex);
53-
Matcher m = r.matcher(proxyEnv);
54-
final String envHost = m.group(1);
55-
final int envPort = Integer.parseInt(m.group(2));
56-
final String envUser = m.group(3);
57-
final String envPassword = m.group(4);
58-
if(envHost!=null && envPort!=0){
59-
proxyHost = envHost;
60-
proxyPort = envPort;
61-
if(envUser!=null && envPassword!=null){
62-
proxyUser = envUser;
63-
proxyPassword = envPassword;
64-
}
65-
}
121+
122+
// Looks for JAR Proxy Arguments
123+
if (proxyUrl == null && this.finalProxyHost == null && jarProxyHost != null) {
124+
this.finalProxyHost = jarProxyHost;
125+
this.finalProxyPort = jarProxyPort;
126+
127+
if (Util.fixEmpty(jarProxyUser) != null && Util.fixEmpty(jarProxyPassword) != null) {
128+
this.finalProxyUsername = jarProxyUser;
129+
this.finalProxyPassword = jarProxyPassword;
66130
}
67-
else if(proxyEnv!=null && proxyEnv.matches(basicRegex)) {
68-
Pattern r = Pattern.compile(authRegex);
69-
Matcher m = r.matcher(proxyEnv);
70-
final String envHost = m.group(1);
71-
final int envPort = Integer.parseInt(m.group(2));
72-
if(envHost!=null && envPort!=0){
73-
proxyHost = envHost;
74-
proxyPort = envPort;
75-
}
131+
}
132+
133+
// Utilises the proxyUrl set by Env Vars if Jenkins & Jar Proxy are absent
134+
if (proxyUrl != null) {
135+
this.finalProxyHost = proxyUrl.getHost();
136+
this.finalProxyPort = proxyUrl.getPort() == -1 ? proxyUrl.getDefaultPort() : proxyUrl.getPort();
137+
138+
final String userInfo = proxyUrl.getUserInfo();
139+
140+
if (userInfo != null) {
141+
String[] userInfoArray = userInfo.split(":");
142+
this.finalProxyUsername = userInfoArray[0];
143+
this.finalProxyPassword = userInfoArray[1];
76144
}
77145
}
146+
147+
// Logging and final boolean set
148+
if (this.finalProxyHost != null && this.finalProxyPort != 0) {
149+
this.hasProxy = true;
150+
151+
String proxyDataToLog = "Host: " + this.getHost() + ", Port: " + this.getPort();
152+
if (this.hasAuth()) {
153+
proxyDataToLog += ", Username: " + this.getUsername() + ", Password: " + Tools.maskString(this.getPassword());
154+
}
155+
156+
if (logger != null) log(logger, "Proxy Selected for BrowserStack Plugin: " + proxyDataToLog);
157+
} else {
158+
this.hasProxy = false;
159+
160+
if (logger != null) log(logger, "No Proxy Selected for BrowserStack Plugin");
161+
}
78162
}
79163

80-
public static Proxy getJenkinsProxy() {
81-
return (proxyHost != null && proxyPort != 0) ? new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)) : null;
164+
165+
/**
166+
* Returns the proxy string from System level env vars. Priority:
167+
* 1. `https_proxy`
168+
* 2. `http_proxy`
169+
* If no value exists, returns null
170+
*
171+
* @return String/null
172+
*/
173+
private String getSystemProxyString() {
174+
return systemHttpsProxyEnv == null ? systemHttpProxyEnv : systemHttpsProxyEnv;
82175
}
83176

84-
public static String getHost() {
85-
return proxyHost;
177+
/**
178+
* Returns Jenkins proxy configuration in Proxy object
179+
*
180+
* @return Proxy object
181+
*/
182+
public Proxy getJenkinsProxy() {
183+
if (this.hasProxy()) {
184+
return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(this.finalProxyHost, this.finalProxyPort));
185+
}
186+
187+
return Proxy.NO_PROXY;
86188
}
87189

88-
public static int getPort() {
89-
return proxyPort;
190+
public String getHost() {
191+
return this.finalProxyHost;
90192
}
91193

92-
public static String getUsername() {
93-
return proxyUser;
194+
public int getPort() {
195+
return this.finalProxyPort;
94196
}
95197

96-
public static String getPassword() {
97-
return proxyPassword;
198+
public String getUsername() {
199+
if (this.finalProxyUsername != null && this.finalProxyUsername.length() != 0)
200+
return this.finalProxyUsername;
201+
202+
return null;
98203
}
99204

100-
public static ProxyConfiguration getProxyConfig() {
101-
return jenkinsProxy;
205+
public String getPassword() {
206+
if (this.finalProxyPassword != null && this.finalProxyPassword.length() != 0)
207+
return this.finalProxyPassword;
208+
209+
return null;
102210
}
103211

104-
public static boolean hasProxy() {
105-
return getHost() != null && getPort() != 0;
212+
public boolean hasAuth() {
213+
return ((this.getUsername() != null) && (this.getPassword() != null));
106214
}
107215

216+
public boolean hasProxy() {
217+
return this.hasProxy;
218+
}
108219
}

0 commit comments

Comments
 (0)