Skip to content

Commit 4eb3cd0

Browse files
author
Petr Vales
committed
extract authentication strategy from GoodData class
* introduce GoodDataEndpoint, class encapsulating GoodData host, port and protocol * introduce Authentication interface, it allows developer to implement new authentication strategy * provide two implementation of new Authentication interface, sst and login + passport
1 parent 9bdb274 commit 4eb3cd0

File tree

10 files changed

+397
-55
lines changed

10 files changed

+397
-55
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Copyright (C) 2004-2016, GoodData(R) Corporation. All rights reserved.
3+
* This source code is licensed under the BSD-style license found in the
4+
* LICENSE.txt file in the root directory of this source tree.
5+
*/
6+
package com.gooddata;
7+
8+
import org.apache.http.client.HttpClient;
9+
import org.apache.http.impl.client.HttpClientBuilder;
10+
11+
/**
12+
* User authentication strategy. See https://developer.gooddata.com/api#/reference/authentication/log-in
13+
*/
14+
public interface Authentication {
15+
16+
/**
17+
* Authenticate user
18+
* @param endpoint GoodData Platform's endpoint
19+
* @param httpClientBuilder http client builder
20+
* @return Http client with provided authentication means
21+
*/
22+
HttpClient createHttpClient(final GoodDataEndpoint endpoint, final HttpClientBuilder httpClientBuilder);
23+
24+
}

src/main/java/com/gooddata/GoodData.java

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,15 @@
1212
import com.gooddata.md.maintenance.ExportImportService;
1313
import com.gooddata.notification.NotificationService;
1414
import com.gooddata.util.ResponseErrorHandler;
15+
import com.gooddata.authentication.LoginPasswordAuthentication;
1516
import com.gooddata.warehouse.WarehouseService;
1617
import com.gooddata.dataset.DatasetService;
1718
import com.gooddata.gdc.DataStoreService;
1819
import com.gooddata.gdc.GdcService;
19-
import com.gooddata.http.client.GoodDataHttpClient;
20-
import com.gooddata.http.client.LoginSSTRetrievalStrategy;
21-
import com.gooddata.http.client.SSTRetrievalStrategy;
2220
import com.gooddata.md.MetadataService;
2321
import com.gooddata.model.ModelService;
2422
import com.gooddata.project.ProjectService;
2523
import com.gooddata.report.ReportService;
26-
import org.apache.http.HttpHost;
2724
import org.apache.http.client.HttpClient;
2825
import org.apache.http.client.config.RequestConfig;
2926
import org.apache.http.config.SocketConfig;
@@ -37,7 +34,7 @@
3734

3835
import java.util.Arrays;
3936

40-
import static com.gooddata.util.Validate.notEmpty;
37+
import static com.gooddata.util.Validate.notNull;
4138
import static java.util.Collections.singletonMap;
4239
import static org.apache.http.util.VersionInfo.loadVersionInfo;
4340

@@ -58,9 +55,9 @@ public class GoodData {
5855

5956
public static final String GDC_REQUEST_ID_HEADER = "X-GDC-REQUEST";
6057

61-
protected static final String PROTOCOL = "https";
62-
protected static final int PORT = 443;
63-
protected static final String HOSTNAME = "secure.gooddata.com";
58+
protected static final String PROTOCOL = GoodDataEndpoint.PROTOCOL;
59+
protected static final int PORT = GoodDataEndpoint.PORT;
60+
protected static final String HOSTNAME = GoodDataEndpoint.HOSTNAME;
6461
private static final String UNKNOWN_VERSION = "UNKNOWN";
6562

6663
private static final int RESTAPI_VERSION = 1;
@@ -167,21 +164,43 @@ public GoodData(String hostname, String login, String password, int port, GoodDa
167164
* @param settings additional settings
168165
*/
169166
protected GoodData(String hostname, String login, String password, int port, String protocol, GoodDataSettings settings) {
170-
notEmpty(hostname, "hostname");
171-
notEmpty(login, "login");
172-
notEmpty(password, "password");
173-
notEmpty(protocol, "protocol");
174-
httpClient = createHttpClient(login, password, hostname, port, protocol,
175-
createHttpClientBuilder(settings));
167+
this(
168+
new GoodDataEndpoint(hostname, port, protocol),
169+
new LoginPasswordAuthentication(login, password),
170+
settings
171+
);
172+
}
176173

177-
restTemplate = createRestTemplate(hostname, httpClient, port, protocol);
174+
/**
175+
* Create instance configured to communicate with GoodData Platform running on given endpoint and using
176+
* given http client factory.
177+
*
178+
* @param endpoint GoodData Platform's endpoint
179+
* @param authentication authentication
180+
*/
181+
protected GoodData(GoodDataEndpoint endpoint, Authentication authentication) {
182+
this(endpoint, authentication, new GoodDataSettings());
183+
}
184+
185+
/**
186+
* Create instance configured to communicate with GoodData Platform running on given endpoint and using
187+
* given http client factory.
188+
*
189+
* @param endpoint GoodData Platform's endpoint
190+
* @param authentication authentication
191+
* @param settings additional settings
192+
*/
193+
protected GoodData(GoodDataEndpoint endpoint, Authentication authentication, GoodDataSettings settings) {
194+
httpClient = authentication.createHttpClient(endpoint, createHttpClientBuilder(settings));
195+
196+
restTemplate = createRestTemplate(endpoint, httpClient);
178197

179198
accountService = new AccountService(getRestTemplate());
180199
projectService = new ProjectService(getRestTemplate(), accountService);
181200
metadataService = new MetadataService(getRestTemplate());
182201
modelService = new ModelService(getRestTemplate());
183202
gdcService = new GdcService(getRestTemplate());
184-
dataStoreService = new DataStoreService(getHttpClient(), getRestTemplate(), gdcService, new HttpHost(hostname, port, protocol).toURI());
203+
dataStoreService = new DataStoreService(getHttpClient(), getRestTemplate(), gdcService, endpoint.toUri());
185204
datasetService = new DatasetService(getRestTemplate(), dataStoreService);
186205
reportService = new ReportService(getRestTemplate());
187206
processService = new ProcessService(getRestTemplate(), accountService, dataStoreService);
@@ -192,10 +211,16 @@ protected GoodData(String hostname, String login, String password, int port, Str
192211
featureFlagService = new FeatureFlagService(restTemplate);
193212
}
194213

195-
private RestTemplate createRestTemplate(String hostname, HttpClient httpClient, int port, String protocol) {
214+
static RestTemplate createRestTemplate(GoodDataEndpoint endpoint, HttpClient httpClient) {
215+
notNull(endpoint, "endpoint");
216+
notNull(httpClient, "httpClient");
196217

197218
final UriPrefixingClientHttpRequestFactory factory = new UriPrefixingClientHttpRequestFactory(
198-
new HttpComponentsClientHttpRequestFactory(httpClient), hostname, port, protocol);
219+
new HttpComponentsClientHttpRequestFactory(httpClient),
220+
endpoint.getHostname(),
221+
endpoint.getPort(),
222+
endpoint.getProtocol()
223+
);
199224
final RestTemplate restTemplate = new RestTemplate(factory);
200225
restTemplate.setInterceptors(Arrays.<ClientHttpRequestInterceptor>asList(
201226
new HeaderSettingRequestInterceptor(singletonMap("Accept", getAcceptHeaderValue()))));
@@ -229,18 +254,10 @@ private HttpClientBuilder createHttpClientBuilder(final GoodDataSettings setting
229254
* Set accept header (application/json by default) and append rest api versioning information which is mandatory
230255
* for some resources.
231256
*/
232-
private String getAcceptHeaderValue(){
257+
private static String getAcceptHeaderValue(){
233258
return MediaType.APPLICATION_JSON_VALUE + ";version=" + RESTAPI_VERSION;
234259
}
235260

236-
protected HttpClient createHttpClient(final String login, final String password, final String hostname,
237-
final int port, final String protocol, final HttpClientBuilder builder) {
238-
final HttpHost host = new HttpHost(hostname, port, protocol);
239-
final HttpClient httpClient = builder.build();
240-
final SSTRetrievalStrategy strategy = new LoginSSTRetrievalStrategy(login, password);
241-
return new GoodDataHttpClient(httpClient, host, strategy);
242-
}
243-
244261
private String getUserAgent() {
245262
final Package pkg = Package.getPackage("com.gooddata");
246263
final String clientVersion = pkg != null && pkg.getImplementationVersion() != null
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/**
2+
* Copyright (C) 2004-2016, GoodData(R) Corporation. All rights reserved.
3+
* This source code is licensed under the BSD-style license found in the
4+
* LICENSE.txt file in the root directory of this source tree.
5+
*/
6+
package com.gooddata;
7+
8+
import org.apache.http.HttpHost;
9+
10+
import static com.gooddata.util.Validate.notEmpty;
11+
12+
/**
13+
* GoodData Platform endpoint represented by host, port and protocol
14+
*/
15+
public class GoodDataEndpoint {
16+
17+
public static final String PROTOCOL = "https";
18+
public static final int PORT = 443;
19+
public static final String HOSTNAME = "secure.gooddata.com";
20+
21+
private final String hostname;
22+
private final int port;
23+
private final String protocol;
24+
25+
/**
26+
* Create GoodData endpoint for given hostname, port and protocol
27+
* @param hostname GoodData Platform's host name (e.g. secure.gooddata.com)
28+
* @param port GoodData Platform's API port (e.g. 443)
29+
* @param protocol GoodData Platform's API protocol (e.g. https)
30+
*/
31+
public GoodDataEndpoint(final String hostname, final int port, final String protocol) {
32+
this.hostname = notEmpty(hostname, "hostname");
33+
this.port = port;
34+
this.protocol = notEmpty(protocol, "protocol");
35+
}
36+
37+
/**
38+
* Create GoodData endpoint for given hostname, port using HTTPS protocol
39+
* @param hostname GoodData Platform's host name (e.g. secure.gooddata.com)
40+
* @param port GoodData Platform's API port (e.g. 443)
41+
*/
42+
public GoodDataEndpoint(String hostname, int port) {
43+
this(hostname, port, PROTOCOL);
44+
}
45+
46+
/**
47+
* Create GoodData endpoint for given hostname using 443 port and HTTPS protocol
48+
* @param hostname GoodData Platform's host name (e.g. secure.gooddata.com)
49+
*/
50+
public GoodDataEndpoint(String hostname) {
51+
this(hostname, PORT, PROTOCOL);
52+
}
53+
54+
/**
55+
* Create GoodData endpoint for given hostname using 443 port and HTTPS protocol and secure.gooddata.com hostname
56+
*/
57+
public GoodDataEndpoint() {
58+
this(HOSTNAME, PORT, PROTOCOL);
59+
}
60+
61+
/**
62+
* @return the host URI, as a string.
63+
*/
64+
public String toUri() {
65+
return new HttpHost(hostname, port, protocol).toURI();
66+
}
67+
68+
/**
69+
* @return GoodData Platform's host name (e.g. secure.gooddata.com)
70+
*/
71+
public String getHostname() {
72+
return hostname;
73+
}
74+
75+
/**
76+
* @return GoodData Platform's API port (e.g. 443)
77+
*/
78+
public int getPort() {
79+
return port;
80+
}
81+
82+
/**
83+
* @return GoodData Platform's API protocol (e.g. https)
84+
*/
85+
public String getProtocol() {
86+
return protocol;
87+
}
88+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Copyright (C) 2004-2016, GoodData(R) Corporation. All rights reserved.
3+
* This source code is licensed under the BSD-style license found in the
4+
* LICENSE.txt file in the root directory of this source tree.
5+
*/
6+
package com.gooddata.authentication;
7+
8+
import com.gooddata.GoodDataEndpoint;
9+
import com.gooddata.Authentication;
10+
import com.gooddata.http.client.GoodDataHttpClient;
11+
import com.gooddata.http.client.LoginSSTRetrievalStrategy;
12+
import com.gooddata.http.client.SSTRetrievalStrategy;
13+
import org.apache.http.HttpHost;
14+
import org.apache.http.client.HttpClient;
15+
import org.apache.http.impl.client.HttpClientBuilder;
16+
17+
import static com.gooddata.util.Validate.notEmpty;
18+
import static com.gooddata.util.Validate.notNull;
19+
20+
/**
21+
* Login and password authentication
22+
*/
23+
public class LoginPasswordAuthentication implements Authentication {
24+
25+
private final String login;
26+
private final String password;
27+
28+
/**
29+
* Create login password authentication
30+
*
31+
* @param login login
32+
* @param password password
33+
*/
34+
public LoginPasswordAuthentication(final String login, final String password) {
35+
this.login = notEmpty(login, "login");
36+
this.password = notEmpty(password, "password");
37+
}
38+
39+
@Override
40+
public HttpClient createHttpClient(final GoodDataEndpoint endpoint, final HttpClientBuilder builder) {
41+
notNull(endpoint, "endpoint");
42+
notNull(builder, "builder");
43+
44+
final HttpClient httpClient = builder.build();
45+
final SSTRetrievalStrategy strategy = new LoginSSTRetrievalStrategy(login, password);
46+
final HttpHost httpHost = new HttpHost(endpoint.getHostname(), endpoint.getPort(), endpoint.getProtocol());
47+
return new GoodDataHttpClient(httpClient, httpHost, strategy);
48+
}
49+
50+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Copyright (C) 2004-2016, GoodData(R) Corporation. All rights reserved.
3+
* This source code is licensed under the BSD-style license found in the
4+
* LICENSE.txt file in the root directory of this source tree.
5+
*/
6+
package com.gooddata.authentication;
7+
8+
import com.gooddata.GoodDataEndpoint;
9+
import com.gooddata.Authentication;
10+
import com.gooddata.http.client.GoodDataHttpClient;
11+
import com.gooddata.http.client.SSTRetrievalStrategy;
12+
import com.gooddata.http.client.SimpleSSTRetrievalStrategy;
13+
import org.apache.http.HttpHost;
14+
import org.apache.http.client.HttpClient;
15+
import org.apache.http.impl.client.HttpClientBuilder;
16+
17+
import static com.gooddata.util.Validate.notEmpty;
18+
import static com.gooddata.util.Validate.notNull;
19+
20+
/**
21+
* SST authentication, see https://developer.gooddata.com/article/gooddata-token-types#Authentication
22+
*/
23+
public class SstAuthentication implements Authentication {
24+
25+
private final String sst;
26+
27+
/**
28+
* Create SST authentication
29+
* @param sst sst
30+
*/
31+
public SstAuthentication(final String sst) {
32+
this.sst = notEmpty(sst, "sst");
33+
}
34+
35+
@Override
36+
public HttpClient createHttpClient(final GoodDataEndpoint endpoint, final HttpClientBuilder builder) {
37+
notNull(endpoint, "endpoint");
38+
notNull(builder, "builder");
39+
40+
final HttpClient httpClient = builder.build();
41+
final SSTRetrievalStrategy strategy = new SimpleSSTRetrievalStrategy(sst);
42+
final HttpHost httpHost = new HttpHost(endpoint.getHostname(), endpoint.getPort(), endpoint.getProtocol());
43+
return new GoodDataHttpClient(httpClient, httpHost, strategy);
44+
}
45+
}

src/test/java/com/gooddata/AbstractGoodDataAT.java

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,13 @@
55
*/
66
package com.gooddata;
77

8-
import com.gooddata.http.client.GoodDataHttpClient;
9-
import com.gooddata.http.client.LoginSSTRetrievalStrategy;
10-
import com.gooddata.http.client.SSTRetrievalStrategy;
118
import com.gooddata.md.Attribute;
129
import com.gooddata.md.Metric;
1310
import com.gooddata.md.ScheduledMail;
1411
import com.gooddata.md.report.Report;
1512
import com.gooddata.md.report.ReportDefinition;
1613
import com.gooddata.project.Project;
17-
import org.apache.http.HttpHost;
14+
import com.gooddata.authentication.LoginPasswordAuthentication;
1815
import org.apache.http.client.HttpClient;
1916
import org.apache.http.impl.client.HttpClientBuilder;
2017
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
@@ -30,20 +27,22 @@ public abstract class AbstractGoodDataAT {
3027
"sdktest " + new LocalDate() + " " + System.getenv("BUILD_NUMBER");
3128

3229
protected static final GoodData gd =
33-
new GoodData(getProperty("host"), getProperty("login"), getProperty("pass")) {
34-
/**
35-
* had to be overriden to access connectionManager, to test how many connections were not closed
36-
*/
37-
@Override
38-
protected HttpClient createHttpClient(String login, String password, String hostname, int port, String protocol, HttpClientBuilder builder) {
39-
PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager();
40-
final HttpHost host = new HttpHost(hostname, port, protocol);
41-
final HttpClient httpClient = builder.setConnectionManager(httpClientConnectionManager).build();
42-
final SSTRetrievalStrategy strategy = new LoginSSTRetrievalStrategy(httpClient, host, login, password);
43-
connManager = httpClientConnectionManager;
44-
return new GoodDataHttpClient(httpClient, strategy);
45-
}
46-
};
30+
new GoodData(
31+
new GoodDataEndpoint(getProperty("host")),
32+
new LoginPasswordAuthentication(getProperty("login"), getProperty("pass")) {
33+
/**
34+
* had to be overriden to access connectionManager, to test how many connections were not closed
35+
*/
36+
@Override
37+
public HttpClient createHttpClient(final GoodDataEndpoint endpoint, final HttpClientBuilder builder) {
38+
PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager();
39+
final HttpClientBuilder builderWithManager = builder.setConnectionManager(httpClientConnectionManager);
40+
connManager = httpClientConnectionManager;
41+
42+
return super.createHttpClient(endpoint, builderWithManager);
43+
}
44+
});
45+
4746

4847
protected static PoolingHttpClientConnectionManager connManager;
4948

0 commit comments

Comments
 (0)