package io.graceland.plugin;
import javax.servlet.Filter;
import com.codahale.metrics.health.HealthCheck;
import com.google.common.base.Preconditions;
import com.google.inject.AbstractModule;
import com.google.inject.multibindings.Multibinder;
import io.dropwizard.Bundle;
import io.dropwizard.cli.Command;
import io.dropwizard.lifecycle.Managed;
import io.dropwizard.servlets.tasks.Task;
import io.graceland.configuration.Configuration;
import io.graceland.configuration.ConfigurationBinder;
import io.graceland.dropwizard.Configurator;
import io.graceland.dropwizard.Initializer;
import io.graceland.filter.FilterBinder;
import io.graceland.inject.Graceland;
import io.graceland.inject.TypeLiterals;
/**
* This abstract class should be used to create most plugins. It contains helpful functions such as
* {@link #bindJerseyComponent(Object)} and {@link #bindTask(io.dropwizard.servlets.tasks.Task)} that will build out
* the necessary multi-binders and use the necessary annotations.
*/
public abstract class AbstractPlugin
extends AbstractModule
implements Plugin {
private Multibinder<Object> jerseyBinder = null;
private Multibinder<Managed> managedBinder = null;
private Multibinder<Class<? extends Managed>> managedClassBinder = null;
private Multibinder<HealthCheck> healthCheckBinder = null;
private Multibinder<Class<? extends HealthCheck>> healthCheckClassBinder = null;
private Multibinder<Task> taskBinder = null;
private Multibinder<Class<? extends Task>> taskClassBinder = null;
private Multibinder<Bundle> bundleBinder = null;
private Multibinder<Class<? extends Bundle>> bundleClassBinder = null;
private Multibinder<Command> commandBinder = null;
private Multibinder<Class<? extends Command>> commandClassBinder = null;
private Multibinder<Initializer> initializerBinder = null;
private Multibinder<Class<? extends Initializer>> initializerClassBinder = null;
private Multibinder<Configurator> configuratorBinder = null;
private Multibinder<Class<? extends Configurator>> configuratorClassBinder = null;
private boolean bindersBuilt = false;
private void buildBinders() {
if (!bindersBuilt) {
jerseyBinder = Multibinder.newSetBinder(binder(), Object.class, Graceland.class);
managedBinder = Multibinder.newSetBinder(binder(), Managed.class, Graceland.class);
managedClassBinder = Multibinder.newSetBinder(binder(), TypeLiterals.ManagedClass, Graceland.class);
healthCheckBinder = Multibinder.newSetBinder(binder(), HealthCheck.class, Graceland.class);
healthCheckClassBinder = Multibinder.newSetBinder(binder(), TypeLiterals.HealthCheckClass, Graceland.class);
taskBinder = Multibinder.newSetBinder(binder(), Task.class, Graceland.class);
taskClassBinder = Multibinder.newSetBinder(binder(), TypeLiterals.TaskClass, Graceland.class);
bundleBinder = Multibinder.newSetBinder(binder(), Bundle.class, Graceland.class);
bundleClassBinder = Multibinder.newSetBinder(binder(), TypeLiterals.BundleClass, Graceland.class);
commandBinder = Multibinder.newSetBinder(binder(), Command.class, Graceland.class);
commandClassBinder = Multibinder.newSetBinder(binder(), TypeLiterals.CommandClass, Graceland.class);
initializerBinder = Multibinder.newSetBinder(binder(), Initializer.class, Graceland.class);
initializerClassBinder = Multibinder.newSetBinder(binder(), TypeLiterals.InitializerClass, Graceland.class);
configuratorBinder = Multibinder.newSetBinder(binder(), Configurator.class, Graceland.class);
configuratorClassBinder = Multibinder.newSetBinder(binder(), TypeLiterals.ConfiguratorClass, Graceland.class);
bindersBuilt = true;
}
}
// ========================
// Helper Binding Functions
// ========================
/**
* Add a resource to the graceland platform.
* <p/>
* There are two ways of adding a resource:
* <ul>
* <li><strong>Instance</strong> - bind an instance of a resource directly.</li>
* <li><strong>Class</strong> - bind a class of a resource, and it will be built by the {@link com.google.inject.Injector}.</li>
* </ul>
*
* @param resource The resource to add, either a {@link java.lang.Class} or an instance.
*/
protected void bindJerseyComponent(Object resource) {
Preconditions.checkNotNull(resource, "Resource cannot be null.");
buildBinders();
jerseyBinder.addBinding().toInstance(resource);
}
protected void bindManaged(Managed managed) {
Preconditions.checkNotNull(managed, "Managed Object cannot be null.");
buildBinders();
managedBinder.addBinding().toInstance(managed);
}
protected void bindManaged(Class<? extends Managed> managedClass) {
Preconditions.checkNotNull(managedClass, "Managed Class cannot be null.");
buildBinders();
managedClassBinder.addBinding().toInstance(managedClass);
}
protected void bindHealthCheck(HealthCheck healthCheck) {
Preconditions.checkNotNull(healthCheck, "Health Check cannot be null.");
buildBinders();
healthCheckBinder.addBinding().toInstance(healthCheck);
}
protected void bindHealthCheck(Class<? extends HealthCheck> healthCheckClass) {
Preconditions.checkNotNull(healthCheckClass, "Health Check Class cannot be null.");
buildBinders();
healthCheckClassBinder.addBinding().toInstance(healthCheckClass);
}
protected void bindTask(Task task) {
Preconditions.checkNotNull(task, "Task cannot be null.");
buildBinders();
taskBinder.addBinding().toInstance(task);
}
protected void bindTask(Class<? extends Task> taskClass) {
Preconditions.checkNotNull(taskClass, "Task Class cannot be null.");
buildBinders();
taskClassBinder.addBinding().toInstance(taskClass);
}
protected void bindBundle(Bundle bundle) {
Preconditions.checkNotNull(bundle, "Bundle cannot be null.");
buildBinders();
bundleBinder.addBinding().toInstance(bundle);
}
protected void bindBundle(Class<? extends Bundle> bundleClass) {
Preconditions.checkNotNull(bundleClass, "Bundle Class cannot be null.");
buildBinders();
bundleClassBinder.addBinding().toInstance(bundleClass);
}
protected void bindCommand(Command command) {
Preconditions.checkNotNull(command, "Command cannot be null.");
buildBinders();
commandBinder.addBinding().toInstance(command);
}
protected void bindCommand(Class<? extends Command> commandClass) {
Preconditions.checkNotNull(commandClass, "Command Class cannot be null.");
buildBinders();
commandClassBinder.addBinding().toInstance(commandClass);
}
protected void bindInitializer(Initializer initializer) {
Preconditions.checkNotNull(initializer, "Initializer cannot be null.");
buildBinders();
initializerBinder.addBinding().toInstance(initializer);
}
protected void bindInitializer(Class<? extends Initializer> initializerClass) {
Preconditions.checkNotNull(initializerClass, "Initializer Class cannot be null.");
buildBinders();
initializerClassBinder.addBinding().toInstance(initializerClass);
}
protected void bindConfigurator(Configurator configurator) {
Preconditions.checkNotNull(configurator, "Configurator cannot be null.");
buildBinders();
configuratorBinder.addBinding().toInstance(configurator);
}
protected void bindConfigurator(Class<? extends Configurator> configuratorClass) {
Preconditions.checkNotNull(configuratorClass, "Configurator Class cannot be null.");
buildBinders();
configuratorClassBinder.addBinding().toInstance(configuratorClass);
}
protected <T extends Configuration> ConfigurationBinder<T> bindConfiguration(Class<T> configurationClass) {
Preconditions.checkNotNull(configurationClass, "Configuration Class cannot be null.");
return ConfigurationBinder.forClass(configurationClass, binder());
}
protected FilterBinder buildFilter(Filter filter) {
Preconditions.checkNotNull(filter, "Filter cannot be null.");
buildBinders();
return FilterBinder.forInstance(binder(), filter);
}
protected FilterBinder buildFilter(Class<? extends Filter> filterClass) {
Preconditions.checkNotNull(filterClass, "Filter Class cannot be null.");
buildBinders();
return FilterBinder.forClass(binder(), filterClass);
}
}