package com.netflix.governator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import com.google.inject.Module;
import com.google.inject.util.Modules;
import com.netflix.governator.annotations.SuppressLifecycleUninitialized;
import com.netflix.governator.internal.DefaultPropertySource;
import com.netflix.governator.internal.GovernatorFeatureSet;
import com.netflix.governator.internal.ModulesEx;
import com.netflix.governator.spi.ModuleListTransformer;
import com.netflix.governator.spi.ModuleTransformer;
import com.netflix.governator.spi.PropertySource;
import com.netflix.governator.spi.LifecycleListener;
/**
* Main entry point for creating a LifecycleInjector with guice extensions such as
* support for @PostConstruct, @PreDestroy annotations and LifecycleListener.
*
* Example:
* <code>
new Governator()
.addModules(
new ArchaiusGovernatorModule(),
new JettyModule(),
new JerseyServletModule() {
{@literal @}@Override
protected void configureServlets() {
serve("/*").with(GuiceContainer.class);
bind(GuiceContainer.class).asEagerSingleton();
bind(HelloWorldApp.class).asEagerSingleton();
}
}
)
.run()
.awaitTermination();
* </code>
*
* @deprecated 2015-12-13 Use {@link InjectorBuilder} instead
*/
@Deprecated
public class Governator {
protected Set<String> profiles = new LinkedHashSet<>();
protected List<Module> modules = new ArrayList<>();
protected List<ModuleListTransformer> transformers = new ArrayList<>();
protected List<Module> overrideModules = new ArrayList<>();
protected IdentityHashMap<GovernatorFeature<?>, Object> featureOverrides = new IdentityHashMap<>();
// This is a hack to make sure that if archaius is used at some point we make use
// of the bridge so any access to the legacy Archaius1 API is actually backed by
// the Archaius2 implementation
static {
System.setProperty("archaius.default.configuration.class", "com.netflix.archaius.bridge.StaticAbstractConfiguration");
System.setProperty("archaius.default.deploymentContext.class", "com.netflix.archaius.bridge.StaticDeploymentContext");
}
@Singleton
@SuppressLifecycleUninitialized
class GovernatorFeatureSetImpl implements GovernatorFeatureSet {
private final IdentityHashMap<GovernatorFeature<?>, Object> featureOverrides;
@Inject
private PropertySource properties = new DefaultPropertySource();
@Inject
public GovernatorFeatureSetImpl(IdentityHashMap<GovernatorFeature<?>, Object> featureOverrides) {
this.featureOverrides = featureOverrides;
}
@SuppressWarnings("unchecked")
@Override
public <T> T get(GovernatorFeature<T> feature) {
return featureOverrides.containsKey(feature)
? (T) featureOverrides.get(feature)
: (T) properties.get(feature.getKey(), feature.getType(), feature.getDefaultValue());
}
}
/**
* Add Guice modules to Governator.
*
* @param modules Guice modules to add.
* @return this
*/
public Governator addModules(Module ... modules) {
if (modules != null) {
this.modules.addAll(Arrays.asList(modules));
}
return this;
}
/**
* Add Guice modules to Governator.
*
* @param modules Guice modules to add.
* @return this
*/
public Governator addModules(List<Module> modules) {
if (modules != null) {
this.modules.addAll(modules);
}
return this;
}
/**
* Add a runtime profile. Profiles are processed by the conditional binding {@literal @}ConditionalOnProfile and
* are injectable as {@literal @}Profiles Set{@literal <}String{@literal >}.
*
* @param profile A profile
* @return this
*/
public Governator addProfile(String profile) {
if (profile != null) {
this.profiles.add(profile);
}
return this;
}
/**
* Add a runtime profiles. Profiles are processed by the conditional binding {@literal @}ConditionalOnProfile and
* are injectable as {@literal @}Profiles Set{@literal <}String{@literal >}.
*
* @param profiles Set of profiles
* @return this
*/
public Governator addProfiles(String... profiles) {
if (profiles != null) {
this.profiles.addAll(Arrays.asList(profiles));
}
return this;
}
/**
* Add a runtime profiles. Profiles are processed by the conditional binding {@literal @}ConditionalOnProfile and
* are injectable as {@literal @}Profiles Set{@literal <}String{@literal >}.
*
* @param profiles Set of profiles
* @return this
*/
public Governator addProfiles(Collection<String> profiles) {
if (profiles != null) {
this.profiles.addAll(profiles);
}
return this;
}
/**
* Enable the specified feature
* @param feature Boolean feature to enable
* @return this
*/
public Governator enableFeature(GovernatorFeature<Boolean> feature) {
return setFeature(feature, true);
}
/**
* Enable or disable the specified feature
* @param feature Boolean feature to disable
* @return this
*/
public Governator enableFeature(GovernatorFeature<Boolean> feature, boolean enabled) {
return setFeature(feature, enabled);
}
/**
* Disable the specified feature
* @param feature Boolean feature to enable/disable
* @return this
*/
public Governator disableFeature(GovernatorFeature<Boolean> feature) {
return setFeature(feature, false);
}
/**
* Set a feature
* @param feature Feature to set
* @return this
*/
public <T> Governator setFeature(GovernatorFeature<T> feature, T value) {
this.featureOverrides.put(feature, value);
return this;
}
/**
* Add a ModuleListTransformer that will be invoked on the final list of modules
* prior to creating the injectors. Multiple transformers may be added with each
* transforming the result of the previous one.
*
* @param transformer A transformer
* @return this
*/
public Governator addModuleListTransformer(ModuleListTransformer transformer) {
if (transformer != null) {
this.transformers.add(transformer);
}
return this;
}
/**
* Add override modules for any modules add via addModules or that are
* conditionally loaded. This is useful for testing or when an application
* absolutely needs to override a binding to fix a binding problem in the
* code modules
* @param modules Modules that will be applied as overrides to modules
* @return this
*/
public Governator addOverrideModules(Module ... modules) {
if (modules != null) {
this.overrideModules.addAll(Arrays.asList(modules));
}
return this;
}
/**
* Add override modules for any modules add via addModules or that are
* conditionally loaded. This is useful for testing or when an application
* absolutely needs to override a binding to fix a binding problem in the
* code modules
* @param modules Modules that will be applied as overrides to modules
* @return this
*/
public Governator addOverrideModules(List<Module> modules) {
if (modules != null) {
this.overrideModules.addAll(modules);
}
return this;
}
/**
* @deprecated Call new Governator().addModules(modules).run() instead.
*/
@Deprecated
public LifecycleInjector createInjector(Module ... modules) {
return new Governator().addModules(modules).run();
}
/**
* @deprecated Call new Governator().addModules(modules).run() instead.
*/
public LifecycleInjector createInjector(Collection<Module> modules) {
return new Governator().addModules(new ArrayList<Module>(modules)).run();
}
/**
* Create the injector and call any LifecycleListeners
* @return the LifecycleInjector for this run
*/
public LifecycleInjector run() {
return run(ModulesEx.emptyModule(), new String[]{});
}
public LifecycleInjector run(final String[] args) {
return run(ModulesEx.emptyModule(), args);
}
public LifecycleInjector run(final Class<? extends LifecycleListener> mainClass) {
return run(mainClass, new String[]{});
}
public LifecycleInjector run(LifecycleListener mainClass) {
return run(ModulesEx.fromInstance(mainClass), new String[]{});
}
public LifecycleInjector run(LifecycleListener mainClass, final String[] args) {
return run(ModulesEx.fromInstance(mainClass), args);
}
public LifecycleInjector run(final Class<? extends LifecycleListener> mainClass, final String[] args) {
return run(ModulesEx.fromEagerSingleton(mainClass), args);
}
/**
* Create the injector and call any LifecycleListeners
* @param args - Runtime parameter (from main) injectable as {@literal @}Arguments String[]
* @return the LifecycleInjector for this run
*/
private LifecycleInjector run(Module externalModule, final String[] args) {
return InjectorBuilder
.fromModules(modules)
.combineWith(externalModule)
.map(new ModuleTransformer() {
@Override
public Module transform(Module module) {
List<Module> modulesToTransform = Collections.singletonList(module);
for (ModuleListTransformer transformer : transformers) {
modulesToTransform = transformer.transform(Collections.unmodifiableList(modulesToTransform));
}
return Modules.combine(modulesToTransform);
}
})
.overrideWith(overrideModules)
.createInjector(new LifecycleInjectorCreator()
.withArguments(args)
.withFeatures(featureOverrides)
.withProfiles(profiles));
}
}