package com.netflix.governator; import java.util.Arrays; import java.util.Collections; import java.util.List; import javax.inject.Inject; import javax.inject.Provider; import javax.inject.Singleton; import com.google.inject.ProvisionException; import com.netflix.governator.annotations.Configuration; import com.netflix.governator.configuration.ConfigurationDocumentation; import com.netflix.governator.configuration.ConfigurationMapper; import com.netflix.governator.configuration.ConfigurationProvider; import com.netflix.governator.lifecycle.LifecycleMethods; /** * Feature to enable @Configuration annotation processing. * * To enable install the ConfigurationModule. * * <pre> * {@code * install(new ConfigurationModule()); * } * </pre> * @author elandau * */ @Singleton public class ConfigurationLifecycleFeature implements LifecycleFeature { private static class Mapper { private ConfigurationMapper mapper; private ConfigurationProvider configurationProvider; private ConfigurationDocumentation configurationDocumentation; @Inject Mapper(ConfigurationMapper mapper, ConfigurationProvider configurationProvider, ConfigurationDocumentation configurationDocumentation) { this.mapper = mapper; this.configurationProvider = configurationProvider; this.configurationDocumentation = configurationDocumentation; } private void mapConfiguration(Object obj, LifecycleMethods methods) throws Exception { mapper.mapConfiguration(configurationProvider, configurationDocumentation, obj, methods); } } private volatile Provider<Mapper> mapper; @Inject public void initialize(Provider<Mapper> state) { this.mapper = state; } @Override public List<LifecycleAction> getActionsForType(final Class<?> type) { final LifecycleMethods methods = new LifecycleMethods(type); if (methods.annotatedFields(Configuration.class).length > 0) { return Arrays.<LifecycleAction>asList(new LifecycleAction() { @Override public void call(Object obj) throws Exception { if (mapper == null) { throw new ProvisionException("Trying to map fields of type " + type.getName() + " before ConfigurationLifecycleFeature was fully initialized by the injector"); } try { mapper.get().mapConfiguration(obj, methods); } catch (Exception e) { throw new ProvisionException("Failed to map configuration for type " + type.getName(), e); } } }); } else { return Collections.emptyList(); } } @Override public String toString() { return "ConfigurationLifecycleFeature[]"; } }