Skip to content

Commit

Permalink
Merge pull request #86 from magx2/4.0.x
Browse files Browse the repository at this point in the history
4.0.x
  • Loading branch information
magx2 authored May 31, 2020
2 parents fb3cf99 + 8eb607d commit b7f1954
Show file tree
Hide file tree
Showing 11 changed files with 293 additions and 91 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ dependencies {
implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVersion

compileOnly "org.projectlombok:lombok:$lombokVersion"
testImplementation "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"

swaggerCodegen 'io.swagger.codegen.v3:swagger-codegen-cli:3.0.5' // or Swagger Codegen V3

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ApiClientFactorySpec extends Specification {
def token = "MTA1YzRhYWRiNzcyYTI0NzliNmMxZTM0MTkwNGM4NGYzYjY0YjBmZjBkYTUxZGVhNDg1NmYyODc1NDM3NDQxOA.aHR0cHM6Ly9zdnI0LnN1cGxhLm9yZw=="

when:
def client = ApiClientFactory.INSTANCE.newApiClient(token, Mock(ApiUsageStatisticsSetter.class))
def client = ApiClientFactory.INSTANCE.newApiClient(token)

then:
client.getHttpClient()
Expand All @@ -45,29 +45,14 @@ class ApiClientFactorySpec extends Specification {
.anyMatch { it == ApiUsageStatisticsInterceptor.class }
}

def "should not add ApiUsageStatisticsInterceptor to interceptors"() {
given:
def token = "MTA1YzRhYWRiNzcyYTI0NzliNmMxZTM0MTkwNGM4NGYzYjY0YjBmZjBkYTUxZGVhNDg1NmYyODc1NDM3NDQxOA.aHR0cHM6Ly9zdnI0LnN1cGxhLm9yZw=="

when:
def client = ApiClientFactory.INSTANCE.newApiClient(token, (ApiUsageStatisticsSetter) null)

then:
!client.getHttpClient()
.interceptors()
.stream()
.map { it.getClass() }
.anyMatch { it == ApiUsageStatisticsInterceptor.class }
}

@Unroll
def "should not verify SSL if property is set to `#property`"(property) {
given:
def token = "MTA1YzRhYWRiNzcyYTI0NzliNmMxZTM0MTkwNGM4NGYzYjY0YjBmZjBkYTUxZGVhNDg1NmYyODc1NDM3NDQxOA.aHR0cHM6Ly9zdnI0LnN1cGxhLm9yZw=="
System.setProperty("jSuplaApi.noVerifyingSsl", property)

when:
def client = ApiClientFactory.INSTANCE.newApiClient(token, (ApiUsageStatisticsSetter) null)
def client = ApiClientFactory.INSTANCE.newApiClient(token)

then:
!client.verifyingSsl
Expand All @@ -83,7 +68,7 @@ class ApiClientFactorySpec extends Specification {
System.setProperty("jSuplaApi.noVerifyingSsl", property)

when:
def client = ApiClientFactory.INSTANCE.newApiClient(token, (ApiUsageStatisticsSetter) null)
def client = ApiClientFactory.INSTANCE.newApiClient(token)

then:
client.verifyingSsl
Expand All @@ -99,7 +84,7 @@ class ApiClientFactorySpec extends Specification {
System.clearProperty("jSuplaApi.noVerifyingSsl")

when:
def client = ApiClientFactory.INSTANCE.newApiClient(token, (ApiUsageStatisticsSetter) null)
def client = ApiClientFactory.INSTANCE.newApiClient(token)

then:
client.verifyingSsl
Expand Down
4 changes: 0 additions & 4 deletions src/main/java/pl/grzeslowski/jsupla/api/Api.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ static Api getInstance(String token) {
return new ApiImpl(token);
}

static Api getInstance(String token, String url) {
return new ApiImpl(token, url);
}

DeviceApi getDeviceApi();

ChannelApi getChannelApi();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,19 @@ public static String getApiVersion() {
/**
* Creates new {@link ApiClient} with given OAuth token and server URL.
*
* @param oAuthToken to authorize
* @param url server base URL
* @param apiUsageStatisticsSetter object to st {@link pl.grzeslowski.jsupla.api.Api.ApiUsageStatistics}
* @param oAuthToken to authorize
* @param url server base URL
* @return new {@link ApiClient} with configured authorization and base path
*/
ApiClient newApiClient(String oAuthToken, String url, ApiUsageStatisticsSetter apiUsageStatisticsSetter) {
private ApiClient newApiClient(String oAuthToken, String url) {
ApiClient client = new ApiClient();
client.setUserAgent("magx2/jSuplaApi");
OAuth password = (OAuth) client.getAuthentication("BearerAuth");
password.setAccessToken(oAuthToken);
client.setBasePath(url + "/api/v" + API_VERSION);
final List<Interceptor> interceptors = client.getHttpClient().interceptors();
interceptors.add(new OneLineHttpLoggingInterceptor(ApiImpl.getLog()::trace, BODY));
if (apiUsageStatisticsSetter != null) {
interceptors.add(new ApiUsageStatisticsInterceptor(apiUsageStatisticsSetter));
}
interceptors.add(new ApiUsageStatisticsInterceptor(ApiUsageStatisticsCollector.INSTANCE.newTokenBound(oAuthToken)));
if (Boolean.getBoolean("jSuplaApi.noVerifyingSsl")) {
client.setVerifyingSsl(false);
}
Expand All @@ -48,11 +45,10 @@ ApiClient newApiClient(String oAuthToken, String url, ApiUsageStatisticsSetter a
/**
* Creates new {@link ApiClient} with given OAuth token.
*
* @param oAuthToken to authorize
* @param apiUsageStatisticsSetter object to st {@link pl.grzeslowski.jsupla.api.Api.ApiUsageStatistics}
* @param oAuthToken to authorize
* @return new {@link ApiClient} with configured authorization and base path
*/
ApiClient newApiClient(String oAuthToken, ApiUsageStatisticsSetter apiUsageStatisticsSetter) {
ApiClient newApiClient(String oAuthToken) {
String[] split = oAuthToken.split("\\.");
if (split.length < 2) {
throw new IllegalArgumentException("OAuth token does not contain '.' (dot)! Token: " + oAuthToken);
Expand All @@ -61,31 +57,6 @@ ApiClient newApiClient(String oAuthToken, ApiUsageStatisticsSetter apiUsageStati
}
String urlBase64 = split[1];
String url = new String(Base64.getDecoder().decode(urlBase64));
return newApiClient(oAuthToken, url, apiUsageStatisticsSetter);
}

/**
* Creates new {@link ApiClient} with given OAuth token and server URL.
*
* @param oAuthToken to authorize
* @param url server base URL
* @return new {@link ApiClient} with configured authorization and base path
* @deprecated use {@link ApiClientFactory#newApiClient(String, String, ApiUsageStatisticsSetter)}
*/
@Deprecated
ApiClient newApiClient(String oAuthToken, String url) {
return newApiClient(oAuthToken, url, null);
}

/**
* Creates new {@link ApiClient} with given OAuth token.
*
* @param oAuthToken to authorize
* @return new {@link ApiClient} with configured authorization and base path
* @deprecated use {@link ApiClientFactory#newApiClient(String, ApiUsageStatisticsSetter)}
*/
@Deprecated
ApiClient newApiClient(String oAuthToken) {
return newApiClient(oAuthToken, (ApiUsageStatisticsSetter) null);
return newApiClient(oAuthToken, url);
}
}
42 changes: 13 additions & 29 deletions src/main/java/pl/grzeslowski/jsupla/api/internal/ApiImpl.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package pl.grzeslowski.jsupla.api.internal;

import io.swagger.client.ApiClient;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import pl.grzeslowski.jsupla.api.Api;
Expand All @@ -11,51 +10,49 @@
import pl.grzeslowski.jsupla.api.LocationApi;
import pl.grzeslowski.jsupla.api.ServerInfoApi;

import java.time.ZonedDateTime;
import java.util.Optional;

import static pl.grzeslowski.jsupla.api.internal.ApiClientFactory.INSTANCE;

@Slf4j
public final class ApiImpl implements Api, ApiUsageStatisticsSetter {
private final ApiClient apiClient;
private ApiUsageStatistics apiUsageStatistics;

public ApiImpl(String token, String url) {
this.apiClient = INSTANCE.newApiClient(token, url, this);
}
public final class ApiImpl implements Api {
private final String token;

public ApiImpl(String token) {
this.apiClient = INSTANCE.newApiClient(token, this);
this.token = token;
}

static Logger getLog() {
return log;
}

private ApiClient newApiClient() {
return INSTANCE.newApiClient(token);
}

@Override
public DeviceApi getDeviceApi() {
return new DeviceApiImpl(apiClient);
return new DeviceApiImpl(newApiClient());
}

@Override
public ChannelApi getChannelApi() {
return new ChannelApiImpl(apiClient);
return new ChannelApiImpl(newApiClient());
}

@Override
public ChannelGroupApi getChannelGroupApi() {
return new ChannelApiImpl(apiClient);
return new ChannelApiImpl(newApiClient());
}

@Override
public LocationApi getLocationApi() {
return new LocationApiImpl(apiClient);
return new LocationApiImpl(newApiClient());
}

@Override
public ServerInfoApi getServerInfoApi() {
return new ServerInfoApiImpl(apiClient);
return new ServerInfoApiImpl(newApiClient());
}

@Override
Expand All @@ -65,19 +62,6 @@ public String getApiVersion() {

@Override
public Optional<ApiUsageStatistics> getApiUsageStatistics() {
return Optional.ofNullable(apiUsageStatistics);
}

@Override
public void setApiUsageStatistics(final ApiUsageStatistics apiUsageStatistics) {
this.apiUsageStatistics = apiUsageStatistics;
}

@Value
static class ApiUsageStatisticsImpl implements ApiUsageStatistics {
ZonedDateTime lastUpdateDate;
int limit;
int remainingLimit;
ZonedDateTime resetDate;
return ApiUsageStatisticsCollector.INSTANCE.getStatistics(token);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package pl.grzeslowski.jsupla.api.internal;

import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import pl.grzeslowski.jsupla.api.Api;

import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import static lombok.AccessLevel.PRIVATE;

@NoArgsConstructor(access = PRIVATE)
final class ApiUsageStatisticsCollector {
static final ApiUsageStatisticsCollector INSTANCE = new ApiUsageStatisticsCollector();
private final ConcurrentMap<String, Api.ApiUsageStatistics> cache = new ConcurrentHashMap<>();

TokenBound newTokenBound(@NonNull String token) {
return new TokenBound(token);
}

void putStatistics(@NonNull String token, @NonNull Api.ApiUsageStatistics apiUsageStatistics) {
cache.put(token, apiUsageStatistics);
}

Optional<Api.ApiUsageStatistics> getStatistics(@NonNull String token) {
return Optional.ofNullable(cache.getOrDefault(token, null));
}

@ToString
@RequiredArgsConstructor
final class TokenBound implements ApiUsageStatisticsSetter {
@NonNull private final String token;

@Override
public void setApiUsageStatistics(final Api.ApiUsageStatistics apiUsageStatistics) {
putStatistics(token, apiUsageStatistics);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.Response;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import pl.grzeslowski.jsupla.api.Api;
Expand All @@ -20,6 +22,7 @@

import static java.util.Optional.empty;
import static java.util.Optional.of;
import static lombok.AccessLevel.PRIVATE;

@Slf4j
@RequiredArgsConstructor
Expand Down Expand Up @@ -49,7 +52,7 @@ private Optional<Api.ApiUsageStatistics> buildApiUsageStatistics(final Headers h
final Optional<ZonedDateTime> resetDate = parseResetDate(headers, url);

if (limit.isPresent() && remainingLimit.isPresent() && resetDate.isPresent()) {
return of(new ApiImpl.ApiUsageStatisticsImpl(
return of(new ApiUsageStatisticsImpl(
ZonedDateTime.now(ZoneId.of("UTC")),
limit.get(),
remainingLimit.get(),
Expand Down Expand Up @@ -91,4 +94,13 @@ private Optional<Integer> parseIntFromHeader(final Headers headers, final String
return Optional.empty();
}
}

@Value
@AllArgsConstructor(access = PRIVATE)
static class ApiUsageStatisticsImpl implements Api.ApiUsageStatistics {
ZonedDateTime lastUpdateDate;
int limit;
int remainingLimit;
ZonedDateTime resetDate;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.logging.HttpLoggingInterceptor;
import lombok.val;

import java.io.IOException;

Expand Down Expand Up @@ -30,7 +31,20 @@ private static final class StringBuilderLogger implements HttpLoggingInterceptor

@Override
public void log(final String message) {
stringBuilder.append("\t").append(message).append("\n");
final String parsedMessage;
if (message.startsWith("Authorization")) {
val noAuth = message.substring(15);
val space = noAuth.indexOf(" ");
if (space > -1) {
val type = noAuth.substring(0, space);
parsedMessage = "Authorization: " + type + " <SECRET>";
} else {
parsedMessage = "Authorization: <SECRET>";
}
} else {
parsedMessage = message;
}
stringBuilder.append("\t").append(parsedMessage).append("\n");
}

String wholeMessage() {
Expand Down
Loading

0 comments on commit b7f1954

Please sign in to comment.