Skip to content
66 changes: 66 additions & 0 deletions client/src/main/java/io/split/client/ApiKeyCounter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.split.client;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ConcurrentHashMultiset;
import com.google.common.collect.Multiset;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ApiKeyCounter {

private static final Logger _log = LoggerFactory.getLogger(ApiKeyCounter.class);
private static final Multiset<String> USED_API_KEYS = ConcurrentHashMultiset.create();

private ApiKeyCounter() {}

public static ApiKeyCounter getApiKeyCounterInstance() {
return ApyKeyCounterHolder.INSTANCE;
}

//Inner class to provide instance of class
private static class ApyKeyCounterHolder
{
private static final ApiKeyCounter INSTANCE = new ApiKeyCounter();
}

public void add(String apiKey) {
String message;
if (USED_API_KEYS.contains(apiKey)) {
message = String.format("factory instantiation: You already have %s with this API Key. " +
"We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing " +
"it throughout your application.",
USED_API_KEYS.count(apiKey) == 1 ? "1 factory" : String.format("%s factories", USED_API_KEYS.count(apiKey)));
_log.warn(message);
} else if (!USED_API_KEYS.isEmpty()) {
message = "factory instantiation: You already have an instance of the Split factory. " +
"Make sure you definitely want this additional instance. We recommend keeping only one instance of " +
"the factory at all times (Singleton pattern) and reusing it throughout your application.“";
_log.warn(message);
}
USED_API_KEYS.add(apiKey);
}

public void remove(String apiKey) {
USED_API_KEYS.remove(apiKey);
}

/**
* Just for test
* @param apiKey
* @return
*/
@VisibleForTesting
boolean isApiKeyPresent(String apiKey) {
return USED_API_KEYS.contains(apiKey);
}

/**
* Just for test
* @param apiKey
* @return
*/
@VisibleForTesting
int getCount(String apiKey) {
return USED_API_KEYS.count(apiKey);
}
}
22 changes: 4 additions & 18 deletions client/src/main/java/io/split/client/SplitFactoryImpl.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package io.split.client;

import com.google.common.collect.ConcurrentHashMultiset;
import com.google.common.collect.Multiset;
import io.split.client.impressions.AsynchronousImpressionListener;
import io.split.client.impressions.ImpressionListener;
import io.split.client.impressions.ImpressionsManagerImpl;
Expand Down Expand Up @@ -62,31 +60,19 @@ public class SplitFactoryImpl implements SplitFactory {
private final static long SSE_CONNECT_TIMEOUT = 30000;
private final static long SSE_SOCKET_TIMEOUT = 70000;

private static final Multiset<String> USED_API_TOKENS = ConcurrentHashMultiset.create();
private static Random RANDOM = new Random();

private final SplitClient _client;
private final SplitManager _manager;
private final Runnable destroyer;
private final String _apiToken;
private boolean isTerminated = false;
private final ApiKeyCounter _apiKeyCounter;

public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyntaxException {
_apiToken = apiToken;

if (USED_API_TOKENS.contains(apiToken)) {
String message = String.format("factory instantiation: You already have %s with this API Key. " +
"We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing " +
"it throughout your application.",
USED_API_TOKENS.count(apiToken) == 1 ? "1 factory" : String.format("%s factories", USED_API_TOKENS.count(apiToken)));
_log.warn(message);
} else if (!USED_API_TOKENS.isEmpty()) {
String message = "factory instantiation: You already have an instance of the Split factory. " +
"Make sure you definitely want this additional instance. We recommend keeping only one instance of " +
"the factory at all times (Singleton pattern) and reusing it throughout your application.“";
_log.warn(message);
}
USED_API_TOKENS.add(apiToken);
_apiKeyCounter = ApiKeyCounter.getApiKeyCounterInstance();
_apiKeyCounter.add(apiToken);

if (config.blockUntilReady() == -1) {
//BlockUntilReady not been set
Expand Down Expand Up @@ -214,7 +200,7 @@ public void destroy() {
synchronized (SplitFactoryImpl.class) {
if (!isTerminated) {
destroyer.run();
USED_API_TOKENS.remove(_apiToken);
_apiKeyCounter.remove(_apiToken);
isTerminated = true;
}
}
Expand Down
50 changes: 50 additions & 0 deletions client/src/test/java/io/split/client/ApiKeyCounterTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package io.split.client;

import junit.framework.TestCase;
import org.junit.Test;

public class ApiKeyCounterTest extends TestCase {

private static final String FIRST_KEY = "KEYNUMBER1";
private static final String SECOND_KEY = "KEYNUMBER2";

@Test
public void testAddingNewToken() {
ApiKeyCounter.getApiKeyCounterInstance().add(FIRST_KEY);
assertTrue(ApiKeyCounter.getApiKeyCounterInstance().isApiKeyPresent(FIRST_KEY));

ApiKeyCounter.getApiKeyCounterInstance().remove(FIRST_KEY);
}

@Test
public void testAddingExistingToken() {
ApiKeyCounter.getApiKeyCounterInstance().add(FIRST_KEY);
ApiKeyCounter.getApiKeyCounterInstance().add(FIRST_KEY);

assertTrue(ApiKeyCounter.getApiKeyCounterInstance().isApiKeyPresent(FIRST_KEY));
assertEquals(2, ApiKeyCounter.getApiKeyCounterInstance().getCount(FIRST_KEY));
ApiKeyCounter.getApiKeyCounterInstance().remove(FIRST_KEY);
ApiKeyCounter.getApiKeyCounterInstance().remove(FIRST_KEY);
}

@Test
public void testRemovingToken() {
ApiKeyCounter.getApiKeyCounterInstance().add(FIRST_KEY);
ApiKeyCounter.getApiKeyCounterInstance().remove(FIRST_KEY);

assertFalse(ApiKeyCounter.getApiKeyCounterInstance().isApiKeyPresent(FIRST_KEY));
assertEquals(0, ApiKeyCounter.getApiKeyCounterInstance().getCount(FIRST_KEY));
}

@Test
public void testAddingNonExistingToken() {
ApiKeyCounter.getApiKeyCounterInstance().add(FIRST_KEY);
ApiKeyCounter.getApiKeyCounterInstance().add(SECOND_KEY);

assertTrue(ApiKeyCounter.getApiKeyCounterInstance().isApiKeyPresent(FIRST_KEY));
assertEquals(1, ApiKeyCounter.getApiKeyCounterInstance().getCount(FIRST_KEY));
assertEquals(1, ApiKeyCounter.getApiKeyCounterInstance().getCount(SECOND_KEY));
ApiKeyCounter.getApiKeyCounterInstance().remove(FIRST_KEY);
ApiKeyCounter.getApiKeyCounterInstance().remove(SECOND_KEY);
}
}