package org.rakam.plugin;
import com.google.inject.Binder;
import com.google.inject.name.Names;
import io.airlift.configuration.ConfigDefaults;
import io.airlift.configuration.ConfigurationAwareModule;
import io.airlift.configuration.ConfigurationFactory;
import javax.validation.constraints.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static io.airlift.configuration.ConfigBinder.configBinder;
import static io.airlift.configuration.ConfigurationModule.bindConfig;
public abstract class RakamModule
implements ConfigurationAwareModule
{
private ConfigurationFactory configurationFactory;
private Binder binder;
@Override
public synchronized void setConfigurationFactory(ConfigurationFactory configurationFactory)
{
this.configurationFactory = checkNotNull(configurationFactory, "configurationFactory is null");
}
@Override
public final synchronized void configure(Binder binder)
{
checkState(this.binder == null, "re-entry not allowed");
this.binder = checkNotNull(binder, "binder is null");
try {
setup(binder);
}
finally {
this.binder = null;
}
}
protected synchronized <T> T buildConfigObject(Class<T> configClass)
{
bindConfig(binder).to(configClass);
return configurationFactory.build(configClass);
}
protected synchronized String getConfig(String config)
{
String value = configurationFactory.getProperties().get(config);
configurationFactory.consumeProperty(config);
return value;
}
protected synchronized <T> T buildConfigObject(Class<T> configClass, String prefix)
{
configBinder(binder).bindConfig(configClass,
prefix != null ? Names.named(prefix) : null, prefix);
try {
Method method = configurationFactory.getClass().getDeclaredMethod(
"build", Class.class,
String.class, ConfigDefaults.class);
method.setAccessible(true);
Object invoke = method.invoke(configurationFactory, configClass, prefix, ConfigDefaults.noDefaults());
Field instance = invoke.getClass().getDeclaredField("instance");
instance.setAccessible(true);
return (T) instance.get(invoke);
}
catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | NoSuchFieldException e) {
throw new IllegalStateException("Internal error related to airlift.configuration library", e);
}
}
protected synchronized void install(RakamModule module)
{
module.setConfigurationFactory(configurationFactory);
binder.install(module);
}
protected abstract void setup(Binder binder);
@NotNull
public abstract String name();
public abstract String description();
}