com.turbospaces.boot.test.AbstractSpringBootTestContextBootstrapper Maven / Gradle / Ivy
package com.turbospaces.boot.test;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.apache.commons.lang3.concurrent.ConcurrentException;
import org.apache.commons.lang3.concurrent.LazyInitializer;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.test.context.SpringBootContextLoader;
import org.springframework.boot.test.context.SpringBootTestContextBootstrapper;
import org.springframework.cloud.SmartCloud;
import org.springframework.cloud.service.ServiceInfo;
import org.springframework.cloud.service.UriBasedServiceInfo;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.kafka.test.EmbeddedKafkaBroker;
import org.springframework.kafka.test.EmbeddedKafkaZKBroker;
import org.springframework.kafka.test.core.BrokerAddress;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextLoader;
import com.google.common.collect.Iterables;
import com.google.common.net.HostAndPort;
import com.turbospaces.boot.AbstractBootstrap;
import com.turbospaces.cfg.ApplicationConfig;
import com.turbospaces.cfg.ApplicationProperties;
import com.turbospaces.ups.KafkaServiceInfo;
import com.turbospaces.ups.RawServiceInfo;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public abstract class AbstractSpringBootTestContextBootstrapper
extends SpringBootTestContextBootstrapper
implements SmartCloud {
static {
System.setProperty("ebean.registerShutdownHook", Boolean.FALSE.toString());
}
private final Map services = new HashMap<>();
private final LazyInitializer props = new LazyInitializer() {
@Override
protected T initialize() throws ConcurrentException {
try {
return createProps();
} catch (Exception err) {
throw new ConcurrentException(err);
}
}
};
@Override
protected ContextLoader resolveContextLoader(Class> testClass, List configAttributesList) {
return new SpringBootContextLoader() {
@Override
protected SpringApplication getSpringApplication() {
for (;;) {
try {
T delegate = props.get();
//
// ~ pass as property and let cloud connector to pick up it via property
//
for (ServiceInfo info : services.values()) {
String uri = null;
if (info instanceof UriBasedServiceInfo) {
uri = ((UriBasedServiceInfo) info).getUri();
} else if (info instanceof RawServiceInfo raw) {
uri = raw.toByteSource().asCharSource(StandardCharsets.UTF_8).read();
} else {
throw new IllegalArgumentException();
}
delegate.cfg().setLocalProperty(String.format("service.%s.uri", info.getId()), uri);
}
return new ConfigurableApplicationBootstrap(delegate);
} catch (Throwable err) {
ExceptionUtils.wrapAndThrow(err);
}
}
}
};
}
protected abstract T createProps() throws Exception;
@Override
public void addUps(ServiceInfo info) {
services.put(info.getId(), info);
}
@Override
public boolean removeUps(String id) {
if (props.isInitialized()) {
try {
T delegate = props.get();
ApplicationConfig cfg = delegate.cfg();
cfg.clearLocalProperty(String.format("service.%s.uri", id));
return Objects.nonNull(services.remove(id));
} catch (ConcurrentException err) {
ExceptionUtils.wrapAndThrow(err);
}
}
return false;
}
public static RawServiceInfo genRawServiceInfo(String id) throws Exception {
byte[] data = new byte[64];
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.nextBytes(data);
return new RawServiceInfo(id, data);
}
private static class ConfigurableApplicationBootstrap extends AbstractBootstrap {
protected ConfigurableApplicationBootstrap(T props) throws Throwable {
super(props);
}
@Override
protected void applyInitializers(ConfigurableApplicationContext context) {
super.applyInitializers(context);
if (context.containsBean(EmbeddedKafkaBroker.BEAN_NAME)) {
EmbeddedKafkaZKBroker broker = (EmbeddedKafkaZKBroker) context.getBeanFactory().getSingleton(EmbeddedKafkaBroker.BEAN_NAME);
if (Objects.nonNull(broker)) {
if (Objects.nonNull(broker.getBrokerAddresses())) {
BrokerAddress address = Iterables.getOnlyElement(Arrays.asList(broker.getBrokerAddresses()));
KafkaServiceInfo ksi = new KafkaServiceInfo(HostAndPort.fromParts(address.getHost(), address.getPort()));
addUps(ksi);
}
}
}
}
}
}